/*static char *SCCSID = "@(#)cmgetarg.c	6.2 91/02/22";*/
/* static char *SCCSID = "@(#)cmgetarg.c	6.2 91/02/22"; */

/*********************************************************************/
/*	 IBM/Microsoft Confidential				     */
/*								     */
/*	 Copyright (c) IBM Corporation 1987, 1989		     */
/*	 Copyright (c) Microsoft Corporation 1987, 1989 	     */
/*								     */
/*	 All Rights Reserved					     */
/*********************************************************************/

/********** START OF SPECIFICATIONS ******** IBM CONFIDENTIAL ********/
/*								     */
/* SOURCE FILE NAME: CMGETARG					     */
/*								     */
/* DESCRIPTIVE NAME: GET COMMAND ARGUMENT AND CHECK VALIDITY	     */
/*								     */
/* FUNCTION:							     */
/*								     */
/*     Get operator's key-inned command arguments and break them     */
/*     down into minimun argument units. And also do brief check     */
/*     on drive, other arguments and DOS version		     */
/*								     */
/*     An original arguments are broken down into one of the follow- */
/*     ing three units. 					     */
/*								     */
/*     1) drive argument unit					     */
/*								     */
/*	  two-character string. the 1st is an alphabetic letter      */
/*	  (a-z or A-Z), it is followed by a colon":".                */
/*	  A blank and any other character are not allowed to be      */
/*	  between them. 					     */
/*								     */
/*	  ex)	  valid     d:					     */
/*		  invalid   dd: or d :				     */
/*								     */
/*     2) switch argument unit					     */
/*								     */
/*	  two or more character string. it starts with a swiching    */
/*	  character ( in US verison, slash "/")   and terminate with */
/*	  a blank or a comma"," or the next switching character.     */
/*	  Any blanks are allowed to exit between the preceding	     */
/*	  switching character and the 2nd character of the switch    */
/*	  argument string. But these blanks are eliminated when      */
/*	  generating a switch argument unit.			     */
/*								     */
/*	  ex)	 valid	  /abc	or  / abc			     */
/*			  /a:	or  / a:     -> a: is not drive      */
/*						in this case	     */
/*		 invalid  // or / / or /,			     */
/*								     */
/*     3) general argument unit 				     */
/*								     */
/*	  A character string other than the above ones. 	     */
/*	  It starts just after a  drive argument unit "d",           */
/*	  a comma "," and a blank.                                   */
/*								     */
/*	  ex)  str1,str2 str3 a:str4  ->  4 general arg units of     */
/*					  "str1", "str2", "str3"     */
/*					  and "str4".                */
/*								     */
/*     - A character string between two double-quotaions("...")      */
/*	 is not devided by a blank character in it. But any key      */
/*	 characters like comma, colon, switch-character devide	     */
/*	 this string if they are found in the string.		     */
/*								     */
/*     - The genearated argument unit strings are set in	     */
/*	 *newargv[], and the total number of the argument units      */
/*	 is set in *newargc. If a command has no parameter,	     */
/*	 *newargc would be zero.				     */
/*								     */
/*     - C-program does not handle double-byte space character	     */
/*	 set (8140H). So if this character set is found in a	     */
/*	 original command line, this routine handle it the same      */
/*	 as 2 space characters. 				     */
/*	 That means that an user of this common routine need not     */
/*	 care about handling of DBCS space.			     */
/*								     */
/* NOTES:							     */
/*								     */
/* ENTRY POINTS:						     */
/*								     */
/*	       COMGETARG - get command argument check varidity	     */
/*								     */
/* EXTERNAL REFERENCE:						     */
/*								     */
/*	       DOSQCURDISK    - query current disk		     */
/*								     */
/*	       comcheckdosver - verify DOS version		     */
/*	       com_strupr     - convert to uppercase		     */
/*	       com_strcmpi    - compare string without		     */
/*				regard to case			     */
/* RELEASE:							     */
/*								     */
/*   VERSION	  DATE		 REASON 			     */
/*								     */
/*     1.00    03/10/1986      initial version			     */
/*     1.01    03/11/1986      define external pointer to invalid    */
/*			       argument string (CORA's request)      */
/*     1.02    03/19/1986      switch argument bug fix		     */
/*     1.03    03/20/1986      1st argument bug fix		     */
/*     1.04    03/21/1986      do not support double quotations      */
/*     1.05    03/25/1986    - change "int" to "unsigned"            */
/*			     - delete ASSGN/JOIN/SUBST check logic   */
/*			     - chagne "tolower" to "toupper"         */
/*			     - check DOS version by calling	     */
/*			       "comcheckdosver"                      */
/*			     - mix model support		     */
/*     2.00    03/26/1986      initial version for driver 1	     */
/*     2.01    03/28/1986      fix a bug of drive check errror	     */
/*     2.02    04/01/1986      fix a bug of 1st invalid switch arg   */
/*     2.03    04/08/1986      fix a bug in handling /// and ////    */
/*     3.00    04/15/1986    - the first intigration version	     */
/*     3.01    05/01/1986    - add two more error include files.     */
/*			       <utlerror.h> and <error2.h>	     */
/*     3.02    05/17/1986    - use DBCS support common routines      */
/*			       ( call internal emulating func.)      */
/*			     - fix bug in "cm_invalid_parm_pointer"  */
/*			     - fix bug in setting "drive_error_flag" */
/*     3.03    05/23/1986    - call DBCS common routines	     */
/*     3.04    05/27/1986      DCR#	      (drive # change)	     */
/*     3.05    06/17/1986    - enable SCCSID tag		     */
/*     3.06    06/27/1986    - change "trace.exe" to "trace"         */
/*			     - delete check_command routine	     */
/*     3.07    06/30/1986    - replace "doscall.h" with "doscalls.h" */
/*     3.08    07/24/1986    - bug fix: reset two error flags on     */
/*			       entry. (syntax error, drive error)    */
/*     3.09    08/04/1986      disable drive/switch character	     */
/*			       processing for TRACE command.	     */
/*     4.00    10/03/1986    - allow "/a:" as valid switch parameter */
/*			       for CP/DOS 1.1			     */
/*     4.01    12/09/1986    - add macro for debug		     */
/*     4.02    01/09/1987    - handle DBCS space char (8140h)	     */
/*     4.03    01/26/1987    - '/n:9/n' is not handled in the same   */
/*			       way as for '/n:9 /n'.                 */
/*     4.04    01/30/1987    - initialize static variable on entry   */
/*     4.05    02/06/1987    - eliminate compile warnings for	     */
/*			       option -W2 -DLINT_ARGS		     */
/*     4.06    02/13/1987    - identify TRACE command by flag "cm_   */
/*			       trace_cmd_flg".                       */
/*     4.07    02/16/1987    - change global variable to static.     */
/*     5.00    07/25/1988      Bruice Bailey			     */
/*			     - Moving switch statement "BLANK:"      */
/*			       before the switch statment	     */
/*			       "other_character:".  The "BLANK:"     */
/*			       statement was before the "COMMA:"     */
/*			       originally. This change is needed     */
/*			       for PTM1389 to allow blanks in the    */
/*			       command line arguments. For example:  */
/*				  \V:" LABEL NAME"                   */
/*				  now will be returned with BLANKS   */
/*				  in there.  Before the change	     */
/*				  \V:"LABELNAME" will be returned.   */
/*								     */
/*     5.01    08/04/1988      Cora Yang			     */
/*			       If the comgetarg was called from      */
/*			       a dynamic module intead of from	     */
/*			       a regular "C" program, the BLANKs     */
/*			       needed to be stripe off. i.e.	     */
/*			       passing: 			     */
/*				   E:*.* /F:1			     */
/*			       The following will be returned if     */
/*			       the change is not made in	     */
/*			       "SETNEWARGV".                         */
/*				   "E:" "*.* " "F:" "1 "             */
/*								     */
/*     DCR 687	10/10/89       cwl - Don't parse on comma            */
/*								     */
/* B001 02/20/91 fgw  B718926: warning messages for C6 compiles      */
/*********************************************************************/
#include <doscall.h>		       /* DOS call			    */
#include <comsub.h>		       /* common subroutine		    */

#include <error.h>		       /* error code			    */
#include <error2.h>		       /*				    */
#include <utlerror.h>		       /*				    */

#include <string.h>		       /* C run time func		    */
#include <stdio.h>
#include <stdlib.h>

#include "cmdebug.h"                   /* macro for debug                   */
/*
 *   constant definition
 */
#define OK	      0 		    /* successful return code	    */
#define YES	      0 		    /* value to be set in response  */
#define NO	      1 		    /* data area on exit.	    */
#define ON	      1 		    /* flag ON			    */
#define OFF	      0 		    /*	    OFF 		    */
#define IDENTICAL     0 		    /*				    */
/*
 * argument checking state constant
 */
#define DEFAULT 0
#define DRIVE	1
#define GENERAL 2
#define SWITCH	3
/*
 * character constant
 */
#define COMMA ','
#define BLANK ' '
#define COLON ':'
#define HEX_81 0x81
#define HEX_40 0x40
#define NULLC  '\0'                      /* ;BN001; */

/*
 *  internal routine
 */
  int checkdrive(char); 		 /* check specified drive letter */
  void setnewargv(char **, char *);	 /* put analized data into buffer */

/*
 *  external variable define
 */
 unsigned cm_invalid_parm_pointer = 0 ;/* points to array including first */
				       /* invalid arguemt		  */
 char cm_trace_cmd_flg = OFF;	       /* trace cmd flag (default: OFF)   */

/*
 * static data define	( COMGETARG )
 */
static
 unsigned argcharbf_ptr;	       /* pointer of argcharbf[]	    */
static
 unsigned newargv_ptr;		       /* new argument array pointer	    */
static
 unsigned startarg_ptr; 	       /* pointer of 1st char of a arg unit */
static
 unsigned newargc_ctr;		       /* counter of new argument units     */
static
 char	  drivenumber;		       /* current drive number		    */
static
 unsigned long			       /* current logical drive-map area    */
	 logicaldrivenumber;	       /*				    */
static
 char	  checking_state = DEFAULT;    /* argument checking state	    */
static
 char	  syntax_error_flag = OFF;     /* ON : invalid argument found	    */
static
 char	  drive_error_flag = OFF;      /* ON : invalid drive found	    */
static
 char	  invalid_parm_flag = OFF;     /* ON : invalid parm detected before */
static
 char	  previous_char = COMMA;       /* previous character		    */
static
 char	  current_char = COMMA;        /* current character		    */
static
 char	  switcharg_flag = OFF;        /* ON : in process of switch argument*/
/*********************************************************************/
/*								     */
/* SUBROUTINE NAME:  comgetarg					     */
/*								     */
/* DESCRIPTIVE NAME: get command argument and check validity	     */
/*		     ( entry routine of this module )		     */
/*								     */
/* FUNCTION:							     */
/*								     */
/*     - Verify DOS version.					     */
/*     - analize common arguemt and break down into minimum argument */
/*	 units. 						     */
/*								     */
/* NOTES:							     */
/*								     */
/*     In this version, the switch character is not different	     */
/*     in a different country. So it is always set to "/".           */
/*								     */
/*								     */
/* ENTRY POINT:  comgetarg					     */
/*   LINKAGE  :  call near					     */
/*								     */
/* INPUT:   int *argc	  - pointer to total number of command	     */
/*			    argument.				     */
/*	    char *argv[]  - pointer array of command argument	     */
/*			    strings.				     */
/*	    char						     */
/*	      *newargv[]  - pointer array of brown down argument     */
/*			    unit strings.			     */
/*	    int 						     */
/*	     newargv_size - depth of pointer array of brown down     */
/*			    argument strings			     */
/*	    char						     */
/*	      *argcharbf  - pointer to brown down argument unit      */
/*			    character buffer.			     */
/*	    int 						     */
/*	    argcharbf_size					     */
/*			  - size of argument character buffer	     */
/*								     */
/*	    char						     */
/*	    *default_drive - pointer to current default dirve name   */
/*								     */
/*	    char						     */
/*	      *switch_char - switching character will be set here.   */
/*								     */
/* EXIT-NORMAL: 						     */
/*   RETURN CODE SYMBOL:  OK					     */
/*								     */
/* EXIT-ERROR:							     */
/*   RETURN CODE SYMBOL:					     */
/*								     */
/*	   ERROR_INVALID_DOSVER     - invalid DOS version	     */
/*	   ERROR_INVALID_PARAMETER  - invalid command parameter      */
/*	   ERROR_INVALID_DRIVE	    - invalid drive		     */
/*	   ERROR_UCOM_BUFFER_LENGTH - defined buffer not big enough  */
/*								     */
/* EFFECTS:							     */
/*								     */
/* INTERNAL REFERENCES: 					     */
/*   ROUTINES:							     */
/*	       checkdrive   - check validity of drive		     */
/*	       setnewargv   - set pointer array of generated argument*/
/*			      unit strings.			     */
/*	       setrespchar  - set allowable response character and   */
/*			      switching character.		     */
/*								     */
/* EXTERNAL REFERENCES: 					     */
/*   ROUTINES: DOSQCURDISK    - get logical drive status	     */
/*	       comcheckdosver - verify DOS version		     */
/*								     */
/*	       com_strcmpi    - compare strings without regard to    */
/*				case.				     */
/******************* END OF SPECIFICATIONS ***************************/
unsigned
comgetarg(argc, argv, newargv, newargv_size, argcharbf,
	  argcharbf_size,default_drive, switch_char)
unsigned *argc; 	   /* total number of argument variable 	 */
char **argv;		   /* pointer array of original argument strings */
char **newargv; 	   /* pointer array of broken down argument units*/
unsigned newargv_size;	   /* depth of pointer array			 */
char *argcharbf;	   /* pointer of argument unit character buffer  */
unsigned argcharbf_size;   /* size of character buffer			 */
char *default_drive;	   /* where a default drive name will be set	 */
char *switch_char;	   /* where a switch character will be set	 */
{
  int i,j;			       /* pointer of argv[i][j] 	*/
  int rc;			       /* return code			*/
/*
 * set initial value
 */
  syntax_error_flag = OFF;		  /* clear error flag		     */
  drive_error_flag = OFF;		  /*				     */
  *switch_char = '/';                     /* switch char is always "/"       */

  argcharbf_ptr =			  /* initialize poiters to 0	     */
  newargv_ptr = 			  /*			   (ptm 1756)*/
  startarg_ptr =			  /*				     */
  newargc_ctr = 			  /*				     */
  cm_invalid_parm_pointer = 0;		  /*				     */

/*
 * DOS version check
 *
 */
 DCALL(COMCHECKDOSVER); 		  /*				     */
 if ((rc = comcheckdosver()) != OK) {	  /* correct DOS version?	     */
   DRETCD;				  /*				     */
   return(rc);				  /*  no -> error return	     */
 }					  /*				     */
 DRETCD;				  /*				     */

/*
 * get default drive name
 */
  DCALL(DOSQCURDISK);			  /*				     */
  if ((rc =				  /*				     */
	DOSQCURDISK((unsigned far *)	  /* get logical drive and current   */
		    &drivenumber,	  /* drive			     */
		    (unsigned long far *) /* get logical drive and current   */
		    &logicaldrivenumber)) /* drive			     */
				  != OK) {/*				     */
    DRETCD;				  /*				     */
    return(rc); 			  /*				     */
  }					  /*				     */
  DRETCD;				  /*				     */
  *default_drive = drivenumber + 'A'-1;   /* convert drive number to drive   */
					  /* name ( upper case )	     */
/*
 *  break down into argument units and check the validity
 */
    i = 1;				     /* point to 1st parm arg string */
    j = 0;				     /* point to 1st char in arg stri*/
    while (i < *argc) { 		     /* 			     */
      if ( argcharbf_ptr >=		     /* defined buffer overflow?     */
	     (argcharbf_size - 2 ) ||	     /*   Y -> error return	     */
	   newargv_ptr >=		     /* 			     */
	     (newargv_size - 2)) {	     /* 			     */
	return(ERROR_UCOM_BUFFER_LENGTH);    /* 			     */
      } 				     /* 			     */
      current_char = argv[i][j++];	     /* get a char from original argu*/
      switch ((unsigned char)current_char) { /* 			     */
      case COLON:			     /********************************/
	if (cm_trace_cmd_flg == ON)	     /* executing cmd is "trace"?    */
	  goto other_character; 	     /*  yes -> other char process   */
	argcharbf[argcharbf_ptr++]	     /* 			     */
	  = current_char;		     /* 			     */
	switch (checking_state) {	     /* 			     */
	case DRIVE:			     /* 			     */
	  if (checkdrive(previous_char)      /*  valid drive name?	     */
				   != OK) {  /*   no-> set error flag	     */
	    drive_error_flag = ON;	     /* 			     */
	  }				     /* 			     */
	  setnewargv(newargv, argcharbf);    /* put drive arg unit	     */
	  break;			     /* 			     */
	case SWITCH:			     /********************************/
	case DEFAULT:			     /* 			     */
	case GENERAL:			     /* 			     */
	  if (switcharg_flag == OFF) {	     /* if not in switch arg process,*/
	    syntax_error_flag = ON;	     /*   -> syntax error.	     */
	  }				     /* 			     */
	  setnewargv(newargv, argcharbf);    /* put drive arg unit	     */
	  break;			     /* 			     */
	}				     /* 			     */
	break;				     /* 			     */
					     /* 			     */
      case HEX_81:			     /* DBCS space character check   */
	  if (argv[i][j] == HEX_40) {	     /*  DBCS space char?(8140h)     */
	    j++;			     /*   then, point to next char.  */
	    current_char = previous_char;    /*   ingore Hex_81.	     */
	    switch (checking_state) {	     /* 			     */
	    case DRIVE: 		     /*  State is DRIVE,GENERAL,     */
	    case GENERAL:		     /*  Then make new arguement.    */
	      setnewargv(newargv,argcharbf); /* 			     */
	    }				     /* 			     */
	    break;			     /* 			     */
	  }				     /* 			     */
	  goto other_character; 	     /* if not DBCS space, handle    */
					     /* as ordinary character.	     */
      case '\0':                             /********************************/
	  i++;				     /* point to the next arg stirg  */
	  j = 0;			     /* reset pointer of argument    */
/*    case COMMA:      DCR 687		*/   /* 			     */
	  switch (checking_state) {	     /* 			     */
	  case DRIVE:			     /* 			     */
	  case GENERAL: 		     /* 			     */
	    setnewargv(newargv,argcharbf);   /* 			     */
	    break;			     /* 			     */
	  case SWITCH:			     /* 			     */
	      syntax_error_flag = ON;	     /* "/," is syntax error         */
	      argcharbf[argcharbf_ptr++]     /* 			     */
		= current_char; 	     /* 			     */
	      setnewargv(newargv,argcharbf); /* 			     */
	      break;			     /* 			     */
	  case DEFAULT: 		     /* 			     */
	    break;			     /* 			     */
	  }				     /* 			     */
	break;				     /********************************/
					     /* string			     */
      case BLANK:			     /* 			     */
	  if (checking_state == SWITCH) {    /* 			     */
	    break;			     /* switch arg unit?	     */
	  }				     /*   -> ingnore null	     */
other_character:			     /* character other than	     */
      default:				     /* comma, blank, colon, and     */
	if (current_char == *switch_char     /* switching characters are     */
	    && cm_trace_cmd_flg == OFF) {    /* process here.		     */
	  switch (checking_state) {	     /* 			     */
	  case DEFAULT: 		     /*  when called in "TRACE"      */
	    argcharbf[argcharbf_ptr++]	     /*  command, switch character   */
	      = current_char;		     /*  is handled as non special   */
	    checking_state = SWITCH;	     /*  character.		     */
	    switcharg_flag = ON;	     /*  set switch arg flag	     */
	    break;			     /* 			     */
	  case DRIVE:			     /* 			     */
	  case GENERAL: 		     /* 			     */
	    setnewargv(newargv, argcharbf);  /* put general arg 	     */
	    argcharbf[argcharbf_ptr++]	     /* 			     */
	      = current_char;		     /* 			     */
	    checking_state = SWITCH;	     /* set switch checking state    */
	    switcharg_flag = ON;	     /* set switch arg flag	     */
	    break;			     /* 			     */
	  case SWITCH:			     /* "//" is syntax error         */
	     syntax_error_flag = ON;	     /* set syntax error	     */
	     argcharbf[argcharbf_ptr++]      /* 			     */
	       = current_char;		     /* 			     */
	     setnewargv(newargv, argcharbf); /* put general arg 	     */
	  }				     /* 			     */
	break;				     /* 			     */
	}				     /* 			     */
	else {				     /* 			     */
	  argcharbf[argcharbf_ptr++]	     /* 			     */
	    = current_char;		     /* 			     */
	  switch (checking_state) {	     /* 			     */
	  case DEFAULT: 		     /* 			     */
	       checking_state = DRIVE;	     /* 			     */
	       break;			     /* 			     */
	  case DRIVE:			     /* 			     */
	  case SWITCH:			     /* 			     */
	       checking_state = GENERAL;     /* 			     */
	       break;			     /* 			     */
	  case GENERAL: 		     /* 			     */
	       break;			     /* 			     */
	  }				     /* 			     */
	break;				     /* 			     */
	}				     /* 			     */
      } 				     /* 			     */
      previous_char = current_char;	     /* update previous char	     */
    }					     /* 			     */
    if (checking_state == SWITCH) {	     /* if switch arg unit not comp- */
      setnewargv(newargv, argcharbf);	     /* leted, put last char to      */
    }					     /* newargv[].		     */
    *argc = newargc_ctr;		     /* set total no of new arg unit */
    if (syntax_error_flag != OK) {	     /* invalid parameter found      */
      return(ERROR_INVALID_PARAMETER);	     /*   yes -> error return	     */
    }					     /* 			     */
    if (drive_error_flag != OK) {	     /* invalid drive found	     */
      return(ERROR_INVALID_DRIVE);	     /*   yes -> error found	     */
    }					     /* 			     */
    return(OK); 			     /* normal return		     */
}
/*********************************************************************/
/*								     */
/* SUBROUTINE NAME:  checkdrive 				     */
/*								     */
/* DESCRIPTIVE NAME: check validity of specified drive name	     */
/*								     */
/* FUNCTION:  check if a specified drive name is defined as	     */
/*	      a logical drive. if not, return the error code.	     */
/* NOTES:							     */
/*								     */
/* ENTRY POINT:  checkdirve					     */
/*   LINKAGE  :  call near					     */
/*								     */
/* INPUT:   char drivename - a drive name to be checked 	     */
/*								     */
/* EXIT-NORMAL: 						     */
/*   RETURN CODE SYMBOL:  OK					     */
/*								     */
/* EXIT-ERROR:							     */
/*   RETURN CODE SYMBOL:  ERROR_INVALID_DRIVE			     */
/*								     */
/* EFFECTS:							     */
/*								     */
/* INTERNAL REFERENCES:   none					     */
/*   ROUTINES:							     */
/*								     */
/* EXTERNAL REFERENCES: 					     */
/*   ROUTINES:							     */
/*		com_strupr - convert to uppercase		     */
/*								     */
/*								     */
/******************* END OF SPECIFICATIONS ***************************/
int
checkdrive(drivename)
char drivename; 			/* a character of drive name	   */
{					/*				   */
  unsigned long rcvdrivenumber; 	/* drive number which is specified */
  char work_string[2];			/* temporary arrary for conversion */

  work_string[1] = NULLC;		/* ;BC001;			   */
  work_string[0] = drivename;		/*				   */
  DCALL(COM_STRUPR);			/*				   */
  com_strupr(work_string);		/* converts to uppercase	   */
  DRET; 				/*				   */
  drivename = work_string[0];		/*				   */
  if (drivename < 'A' ||                /* an alphabet?                    */
      'Z' < drivename) {                /*  no -> invalid drive error      */
    return(ERROR_INVALID_DRIVE);	/*				   */
  }					/*				   */
 drivename -= 'A';                      /*                                 */
 rcvdrivenumber = 1;			/* create specified drive map	   */
 rcvdrivenumber <<= drivename;		/*				   */
 if ((rcvdrivenumber &= 		/*  specified a logical drive?	   */
      logicaldrivenumber) == 0) {	/*				   */
   return(ERROR_INVALID_DRIVE); 	/*  no -> invalid drive error	   */
 }					/*				   */
 return(OK);
}
/*********************************************************************/
/*								     */
/* SUBROUTINE NAME:  setnewargv 				     */
/*								     */
/* DESCRIPTIVE NAME: set a found argument unit			     */
/*								     */
/* FUNCTION:  terminate the current argument unit checking and	     */
/*	      set the begining address of this argument unit	     */
/*	      string in the pointer array of argument unit	     */
/*	      strings.						     */
/*								     */
/* NOTES:							     */
/*								     */
/* ENTRY POINT:  setnewargv					     */
/*   LINKAGE  :  call near					     */
/*								     */
/* INPUT:							     */
/*	 char *newargv[]  - pointer array of generated argument      */
/*			    unit strings.			     */
/*	 char *argcharbf  - pointer of character buffer of generated */
/*			    argument units.			     */
/* EXIT-NORMAL: 						     */
/*   RETURN CODE SYMBOL:  NONE					     */
/*								     */
/* EXIT-ERROR:							     */
/*   RETURN CODE SYMBOL:  NONE					     */
/*								     */
/* EFFECTS:							     */
/*								     */
/* INTERNAL REFERENCES:       none				     */
/*   ROUTINES:							     */
/*								     */
/* EXTERNAL REFERENCES: 					     */
/*   ROUTINES:							     */
/*								     */
/******************* END OF SPECIFICATIONS ***************************/
void
setnewargv(newargv, argcharbf)
char *newargv[];
char *argcharbf;
{

  if (invalid_parm_flag == OFF &&      /* invalid parm or	    */
      (syntax_error_flag != OFF ||     /* invalid drive detected    */
       drive_error_flag != OFF)) {     /* for the first time ?	    */
    cm_invalid_parm_pointer =	       /*  yes -> set inv string    */
			newargc_ctr;   /*	  pointer	    */
    invalid_parm_flag = ON;	       /* set inv parm flag	    */
  }				       /*			    */
  argcharbf_ptr--;		       /* point at the last char    */
  while ( argcharbf[argcharbf_ptr] == BLANK ) {    /* looping util not BLANKS	*/
     argcharbf_ptr--;
  }
  argcharbf[++argcharbf_ptr] = NULLC;  /* ;BC001; terminate with null */
  newargc_ctr++;		       /* increment counter	    */
  checking_state = DEFAULT;	       /* set DEFAULT checkig state */
  newargv[newargv_ptr++]	       /* set arg unit pointer	    */
    = &argcharbf[startarg_ptr];        /*			    */
  startarg_ptr = (++argcharbf_ptr);    /* set pointer to 1st char   */
  switcharg_flag = OFF; 	       /* clear flag of switch arg  */
}
