From:	MERC::"uunet!WKUVX1.BITNET!FILESERV-Mgr" 12-JUN-1992 15:01:55.55
To:	galaxy::gleeve
CC:	
Subj:	FGREP.05_OF_06

-+-+-+-+-+-+-+-+ START OF PART 5 -+-+-+-+-+-+-+-+
X**  Given a filespec, this function parses that filespec out and searches fo
Vr
X** the file---or, if the filespec has wildcard characters in it, the files--
V-
X** associated with the filespec.  It returns a newly-allocated vector of fil
Ve-
X** specs that are also newly-allocated.  This function can be used to find o
Vnly
X** the first file that matches the filespec or all the files that match it.
V  In
X** the latter case, this function will also provide a count of the files tha
Vt
X** were found.
X**  Filespecs returned by this function are in lowercase, to approximate the
X** "look and feel" of GNU.
X**  This function is used by shell_mung(), and is also handy for general use
V.
X**--------------------------------------------------------------------------
V---
X** Usage
X** `7E`7E`7E`7E`7E
X**  This function returns a vector---that is, a pointer to pointers.  Thus y
Vou
X** will need to declare this function and a vector like this:
X**
X**      extern char **  shell_glob();
X**
X**      char **  filespec_v;
X**
X**  To find only the first match of a wildcarded filespec, or just to get th
Ve
X** fully-parsed filespec of a given filespec, call shell_glob() with NULL as
X** its second parameter.  For example, if you call it like this:
X**
X**      static int const  filespec = "*.c";
X**      char **  filespec_v;
X**              ...
X**      filespec_v = shell_glob(filespec,NULL);
X**
X** The value in `60filespec_v`5B0`5D' will be (for example) "dev:`5Bdir`5Dba
Vr.c;".  Note
X** that the character string pointer is the content of the vector, not the
X** vector itself.
X**  With this usage, `60filespec_v' points to a pointer (actually an array o
Vf one
X** pointer, which is the same thing).  When used to get a number of filespec
Vs,
X** it points to an array of pointers.
X**  To get all the filespecs that match a filespec, use an address of an
X** integer as shell_glob()'s second parameter, as in this example:
X**
X**      static int const  filespec = "*.c";
X**      int  filespec_count;
X**      char **  filespec_v;
X**              ...
X**      filespec_v = shell_glob(filespec,&filespec_count);
X**
X** The result of this would be (for example),
X**
X**      filespec_count = 3,
X**      filespec_v`5B0`5D = "dev:`5Bdir`5Dbar.c",
X**      filespec_v`5B1`5D = "dev:`5Bdir`5Dbaz.c", and
X**      filespec_v`5B2`5D = "dev:`5Bdir`5Dfoo.c".
X**
X**  In either type of usage, both the vector and the character strings are i
Vn
X** newly-allocated memory.
X**  VMS globbing entails a feature that allows one to fill in parts of a fil
Ve-
X** spec with default values.  This feature can be used by shell_glob() using
X** `60shell_default', a global character string.  Use of this character stri
Vng is
X** optional, and it is initially set to NULL, meaning no default filespec is
X** used.  To use it, you need to declare it like this:
X**
X**      globalref char *  shell_default;
X**
X**  The most frequent use of a default filespec in VMS is to provide a defau
Vlt
X** filetype, as shown in this example:
X**
X**      static int const  filespec = "*.c";
X**      int  filespec_count;
X**      char **  filespec_v;
X**              ...
X**      shell_default = ".c";
X**      filespec_v = shell_glob(filespec,&filespec_count);
X**
X** If `60user_string' (which is, of course, a character string) is (for exam
Vple)
X** "foo*", a filespec without a filetype, shell_glob() will look for all fil
Ves
X** whose filespecs match "foo*.c".  If `60user_string' were "foo*.h", a file
Vspec
X** that has a filetype, the default filespec ".c" is ignored and shell_glob(
V)
X** will look for all files whose filespecs match "foo*.h".
X**  Default filespecs can include devices, directories, filenames, filetypes
V,
X** and version numbers.  Wildcards can be used in filenames, filetypes, and
X** version numbers.  To turn default filespecs off, just set `60shell_defaul
Vt'
X** back to NULL.
X**  If the given filespec cannot be globbed, shell_glob() will simply return
X** a filespec vector with an array of one pointer, pointing to the unglobbab
Vle
X** given filespec.  The given filespec, therefore, should be something that
X** will stick around for as long as you expect to use the filespec vector.
V  In
X** particular, don't call shell_glob() from a function using an automatic
X** character string variable of that function and expect the string to still
V be
X** available when you've exited that function.
X**--------------------------------------------------------------------------
V---
X** Calling Sequence
X** `7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E
X** filespec_v = shell_glob(given_filespec,filespec_count_p);
X**--------------------------------------------------------------------------
V---
X** Formal Arguments     Description
X** `7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E     `7E`7E`7E`7E`7E`7E`7
VE`7E`7E`7E`7E
X** given_filespec       Filespec "as given"---that is, as typed on the comma
Vnd
X**                      line.  This is what we parse and search for.
X** filespec_count_p     Pointer to an integer that is to receive a count of
X**                      filespecs found that match `60given_filespec'.  If N
VULL,
X**                      indicates that we're only to search for the first fi
Vle
X**                      that matches `60given_filespec'.
X**--------------------------------------------------------------------------
V---
X** Implicit Input       Description
X** `7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E       `7E`7E`7E`7E`7E`7E`7E`7E
V`7E`7E`7E
X** shell_default        This global variable is a character string of a defa
Vult
X**                      filespec.  If NULL, no default filespec is used.
X**--------------------------------------------------------------------------
V---
X** Implicit Outputs:    None
X**--------------------------------------------------------------------------
V---
X** Return Value
X** `7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E
X**  Returns a vector of pointers to newly-parsed filespecs.
X**--------------------------------------------------------------------------
V---
X** Side Effects
X** `7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E
X**  Memory is allocated for the filespec vector and for the filespecs that i
Vt
X** points to.
X**--------------------------------------------------------------------------
V---
X*/
Xchar **
Xshell_glob(given_filespec,filespec_count_p)
X char *  given_filespec;
X int *  filespec_count_p;
X`7B
X  /* --- LOCAL VARIABLES --- */
X
X  register char *  character_p;         /* General-purpose character pointer
V,
X                                        ** used to convert filespecs to
X                                        ** lowercase.
X                                        */
X  register char  * expanded_filespec;`09/* v1.2-004 */
X                                        /* Buffer to hold the expanded files
Vpec
X                                        ** from a call to sys$parse().
X                                        */
X  register int  filespec_count = 0;     /* Count of filespecs that sys$searc
Vh()
X                                        ** finds.
X                                        */
X  register char **  filespec_v = NULL;  /* Vector of pointers to filespecs t
Vhat
X                                        ** sys$search() finds.  Allocated an
Vd
X                                        ** reallocated as filespecs are foun
Vd.
X                                        */
X  static char *our_path;                /* The default device and directory
X                                        ** path.  Initialized the first time
X                                        ** this function is called.
X                                        */
X  register char * resultant_filespec;`09/* v1.2-004 */
X                                        /* Buffer to hold a resultant filesp
Vec
X                                        ** from a call to sys$search().
X                                        */
X  register int  status;                 /* Status codes returned from calls
V to
X                                        ** sys$parse() and sys$search().
X                                        */
X  struct FAB  fab = cc$rms_fab;         /* RMS file access block.
X                                        */
X  struct NAM  nam = cc$rms_nam;         /* RMS name block.
X                                        */
X
X  /* --- INITIALIZE PATH --- */
X
X  resultant_filespec = xmalloc(NAM$C_MAXRSS + 1);`09/* v1.2-004 */
X  expanded_filespec = xmalloc(NAM$C_MAXRSS + 1);`09/* v1.2-004 */
X  if (our_path == NULL)
X   (char *) our_path = getenv("PATH");`09`09`09/* v1.2-004 */
X   /* our_path = getenv("PATH"); */
X
X  /* --- INITIALIZE FAB AND NAM --- */
X
X  if (shell_default != NULL)
X  `7B
X    fab.fab$l_dna = shell_default;
X    fab.fab$b_dns = strlen(shell_default);
X  `7D
X  fab.fab$l_fna = given_filespec;
X  fab.fab$b_fns = strlen(given_filespec);
X  fab.fab$l_nam = &nam;
X  nam.nam$l_esa = expanded_filespec;`09`09/* v1.2-004 */
X  nam.nam$b_ess = NAM$C_MAXRSS;
X  nam.nam$l_rsa = resultant_filespec;`09`09/* v1.2-004 */
X  nam.nam$b_rss = NAM$C_MAXRSS;
X
X  /* --- PARSE OUT THE GIVEN FILESPEC --- */
X
X  if ((status = sys$parse(&fab)) == RMS$_NORMAL)
X  `7B
X    /* --- SEARCH FOR FILE OR FILES --- */
X
X    while ((status = sys$search(&fab)) == RMS$_NORMAL)
X    `7B
X      filespec_v = ((filespec_v == NULL) ? xmalloc(sizeof (char *)) :
X       xrealloc(filespec_v,(filespec_count + 1) * sizeof (char *)));
X
X      nam.nam$l_rsa`5Bnam.nam$b_rsl`5D = '\0';
X      for (character_p = nam.nam$l_rsa; *character_p; ++character_p)
X       *character_p = _tolower(*character_p);`09`09/* v1.2-004 */
X
X      if (strncmp(nam.nam$l_rsa,our_path,nam.nam$b_dev + nam.nam$b_dir) == 0
V)
X      `7B
X        filespec_v`5Bfilespec_count`5D = xmalloc(
X          (int) (nam.nam$b_rsl - nam.nam$b_dev - nam.nam$b_dir) + 1
X        );
X        strcpy(filespec_v`5Bfilespec_count`5D,nam.nam$l_name);
X      `7D
X      else if (strncmp(nam.nam$l_rsa,our_path,nam.nam$b_dev) == 0)
X      `7B
X        filespec_v`5Bfilespec_count`5D = xmalloc(
X          (int) (nam.nam$b_rsl - nam.nam$b_dev) + 1
X        );
X        strcpy(filespec_v`5Bfilespec_count`5D,nam.nam$l_dir);
X      `7D
X      else
X      `7B
X        filespec_v`5Bfilespec_count`5D = xmalloc((int) nam.nam$b_rsl + 1);
X        strcpy(filespec_v`5Bfilespec_count`5D,nam.nam$l_rsa);
X      `7D
X
X      if (filespec_count_p == NULL)
X       break;
X      ++filespec_count;
X
X    `7D /* sys$search() while */
X
X    /* --- UPDATE FILESPEC COUNT AND RETURN FILESPEC VECTOR --- */
X
X    if ((status == RMS$_NORMAL) `7C`7C (status == RMS$_NMF))
X    `7B
X      if (filespec_count_p)
X       *filespec_count_p = filespec_count;
X      return filespec_v;
X    `7D
X
X  `7D /* sys$parse() if */
X
X  /* --- RETURN VECTOR REFERRING TO GIVEN FILESPEC --- */
X
X  /* If we get here, we either could not parse the given filespec or could
X  ** not find it.  In such cases we simply return a vector that refers to
X  ** the given filespec.
X  */
X  filespec_v = xmalloc(sizeof (char *));
X  filespec_v`5B0`5D = given_filespec;
X  if (filespec_count_p)
X   *filespec_count_p = 1;
X  return filespec_v;
X
X`7D /* shell_glob() */
X
X/* shell_mung()
X**--------------------------------------------------------------------------
V---
X** Functional Description
X** `7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E
X**  Given a description of the command line that invoked a program from the
X** main() function's `60argc' and `60argv' variables, this function changes
V those
X** variables to reflect wildcard matching of filespecs in that command line
X** and changes standard IO file pointers `60stderr', `60stdin', and `60stdou
Vt' to
X** reflect any IO redirection requested in that command line.
X**--------------------------------------------------------------------------
V---
X** Usage
X** `7E`7E`7E`7E`7E
X**  Since shell_mung() is written for programs running VAX C programs under
V the
X** DCL CLI on VMS, a call to shell_mung() should be predicated on these thin
Vgs:
X**
X**      #if defined(VAXC) && defined(VMS)
X**        if (!shell$is_shell())
X**         shell_mung(&argc,&argv,...,...);
X**      #endif
X**
X** One should call shell_mung() before doing anything else---in particular,
X** before anything is done with `60argc', `60argv', and parts of the standar
Vd IO
X** library.
X**  The first and second arguments to shell_mung() should always be addresse
Vs
X** of `60argc' and `60argv', respectively.  The third and fourth arguments r
Vequire
X** a bit more thought.  Before they are explained, though, we have to define
X** some terms.
X**  A "parameter" is a position-dependent command line argument that isn't a
Vn
X** IO redirection (those start with '<' or '>'), an option or an option valu
Ve.
X** An "option" is similar to a DCL qualifier, except that it starts with '-'
V or
X** '+' instead of '/'.  A "value" is a string that follows certain options.
X** Which options have values is something that varies from program to progra
Vm.
X** A value in DCL is indicated with a equal sign (e.g. /qualifier=value), bu
Vt
X** here it can either be concatenated to an option (e.g. -ovalue) or appear
V as
X** an argument following the option (e.g. -o value).  "Globbing," as mention
Ved
X** above, is to parse wildcarded filespecs and match them with existing file
Vs.
X** A "mung" is a legume used in Indian cooking, often after being shelled.
X**  The third argument to shell_mung() is the number of the parameter where
V we
X** expect filespecs to appear---in other words, the parameters we expect to
X** need globbing.  A GNU-shell-like command language interpreter will glob a
Vny
X** argument that has a wildcard character in it, unless that argument is put
V in
X** single quotes.  DCL doesn't glob arguments, and though you can put argume
Vnts
X** in double quotes to pass them through exactly as typed, by the time VAX C
X** has processed them into `60argv' strings, the double quotes have been str
Vipped
X** off.  This is why we have to tell shell_mung() where to start globbing.
V  The
X** assumption is made that unglobbable arguments (such as strings) will appe
Var
X** as parameters before globbable arguments (such as filespecs), an assumpti
Von
X** that holds for most GNU utilities, probably because it's the only rationa
Vl
X** way to code utilities that accept multiple filespecs on the command line.
X**  As an example, consider the following command line, where "fgrep" is a D
VCL
X** command to run the GNU "fgrep" program:
X**
X**      $ fgrep -n xyzzy *.c *.h
X**
X** "xyzzy", "*.c", and "*.h" are the parameters.  For fgrep, the string to b
Ve
X** searched for is always the first parameter ("xyzzy" in this case); the fi
Vles
X** to be searched always begin as a second parameter.  The "-n" is an option
V,
X** which could be placed anywhere.  The following commands mean the same thi
Vng
X** as the previous one:
X**
X**      $ fgrep xyzzy -n *.c *.h
X**      $ fgrep xyzzy *.c -n *.h
X**      $ fgrep xyzzy *.c *.h -n
X**
X** (It is, however, usually considered better form to type the options first
V.
X** Some programs actually require that certain options appear before certain
X** parameters.)  To indicate that we expect input filespecs to begin as the
X** second parameter, we call shell_mung() with 2 as its third argument:
X**
X**      shell_mung(&argc,&argv,2,...);
X**
X** This changes `60argc' and `60argv' so that if the user types this:
X**
X**      $ fgrep -n xyzzy *.c
X**
X** It's as if the user had typed this (for example):
X**
X**      $ fgrep -n xyzzy dev:`5Bdir`5Dbar.c dev:`5Bdir`5Dbaz.c dev:`5Bdir`5D
Vfoo.c
X**
X** If all of the parameters are to be considered globbable filespecs, the th
Vird
X** argument to shell_mung() should be 1 (indicating, of course, that globbin
Vg
X** can start with the first parameter).  If no parameters are to be consider
Ved
X** globbable, shell_mung()'s third argument should be 0.  If the user uses a
X** negative number as the third argument, it is treated as 0.
X**  The fourth argument is a list of options which are followed by values, w
Vith
X** indications as to which values are to be globbed, and which option/value
X** combinations are to be considered as replacements for parameters (more on
X** this later).  The list is passed as a character string.
X**  As an example, the "make" program has a "-f" option that expects a files
Vpec
X** as its value:
X**
X**      $ make `5B-f makefile`5D `5Btarget`5D `5Bmacros`5D...
X**
X** To indicate that we have a "-f" option followed by a globbable value, we
V put
X** 'f' in shell_mung()'s fourth argument:
X**
X**      shell_mung(&argc,&argv,0,"f");
X**
X** When an option's value is globbed, only the first matching filespec is us
Ved
X** to replace that value.  If, for example, "makefile.vms" and "makefile.xen
Vix"
X** are the only two files in your directory, and the user types one of these
V:
X**
X**      $ make -fmakefile.*
X**      $ make -f makefile.*
X**
X** It's as if the user had typed one of these (respectively):
X**
X**      $ make -fdev:`5Bdir`5Dmakefile.vms
X**      $ make -f dev:`5Bdir`5Dmakefile.vms
X**
X**  Options with unglobbable values must also be listed, with indications th
Vat
X** they are unglobbable.  The "from" program is an example of this:
X**
X**      $ from `5B-s sender`5D `5Buser`5D
X**
X** The "-s" option is followed by a username, not an input filespec.  Thus w
Ve
X** put a '-' after the 's' in shell_mung()'s fourth argument:
X**
X**      shell_mung(&argc,&argv,0,"s-");
X**
X**  There are times when an option/value combination can replace a parameter
V.
X** Using fgrep as an example again, its first parameter---the string to be
X** searched for---can be replaced by the "-e" and "-f" options and their
X** values.  The "-e" option is used when the string to be searched for start
Vs
X** with a '-' character and could be confused with an option, and the "-f"
X** option is used when the string or strings to be searched for is in a file
V.
X** We indicate such options by appending a '+' character to them in the stri
Vng
X** that is shell_mungs()'s fourth argument:
X**
X**      shell_mung(&argc,&argv,2,"e+-f+");
X**
X** (Note that the "-e" option also has a '-' character following it, since w
Ve
X** don't want its value to be globbed.  When both '+' and '-' are used, the
V '+'
X** should always be first.)  It should be noted that such option/value pairs
X** should be typed early in the command line, in positions where the paramet
Vers
X** they're replacing would have been.  For example, you would do this:
X**
X**      $ fgrep -f stringfile inputfile
X**
X** But this would be an invitation to disaster:
X**
X**      $ fgrep inputfile -f stringfile
X**
X**  Programs that use the getopt() library function to process options will
X** help you decide which options to include in shell_mung()'s fourth argumen
Vt.
X** The third argument to getopt() is a list of options, and options that hav
Ve
X** values are followed by a ':' character.  Here's an example from the sourc
Ve
X** to the GNU "grep" program:
X**
X**      while ((c = getopt(argc,argv,"0123456789A:B:CVbce:f:hilnsvwx")) != E
VOF)
X**
X** This tells us that the "-A", "-B", "-e", and "-f" options have values.  O
Vf
X** these, "-A", "-B", and "-e" have unglobbable values; and "-e" and "-f" ca
Vn
X** replace a parameter.  Thus, our call to shell_mung() for the GNU grep
X** program looks like this:
X**
X**      shell_mung(&argc,&argv,2,"A-B-e+-f+");
X**
X**  The IO redirection capabilities provided are as follows:
X**
X**      <infile         Input comes from "infile".
X**      >outfile        Output goes to "outfile".
X**      >&outfile       Output and errors go to "outfile".
X**      >>outfile       Output appended to "outfile".
X**      >>&outfile      Output and errors appended to "outfile".
X**
X** They can be used anywhere on the command line, except between an option a
Vnd
X** its value.  Here are some examples:
X**
X**      $ fgrep xyzzy *.txt >&lines_with_xyzzy.lis
X**      $ from -s flintstone >>accumulated_flintstone_missives.dat
X**      $ my_mailer -d <mail_commands.com
X**
X** Some notes:  (1) The filespecs must be next to the redirection characters
V;
X** they can't be separate arguments.  (2) For input redirection, the "infile
V"
X** is globbed to the first matching filespec, just like an option's value.
V  (3)
X** The "<<" redirection characters are not implemented.  Unlike shell script
Vs,
X** VMS DCL command procedures define standard input as records that don't st
Vart
X** with a '$' character, or aren't the record defined by the DECK command.
X** Thus, "<<" redirection is irrelevant.  (4) The "!" redirection character
V as
X** used in ">!", ">&!", ">>!", and ">>&!" is also not implemented.  VMS uses
X** file versions, which makes it irrelevant.  (5) If a globbable argument tu
Vrns
X** out to be unglobbable, the new vector will simply point to the original
X** argument.  (6) Pipes (as in the "`7C" and "`7C&" redirection characters)
V are not
X** implemented.
X**--------------------------------------------------------------------------
V---
X** Calling Sequence
X** `7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E
X** delta-arg-count = shell_mung(argc_p,argv_p,parameter_number,option_string
V);
X**--------------------------------------------------------------------------
V---
X** Formal Arguments     Description
X** `7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E     `7E`7E`7E`7E`7E`7E`7
VE`7E`7E`7E`7E
X** argc_p               Pointer to argument count (main()'s `60argc').
X** argv_p               Pointer to argument vector (main()'s `60argv').
X** parameter_number     Position among parameters where filespecs are expect
Ved.
X** option_string        List of options that may be followed by filespecs.
X**--------------------------------------------------------------------------
V---
X** Implicit Inputs:     None
X**--------------------------------------------------------------------------
V---
X** Implicit Outputs:    None
X**--------------------------------------------------------------------------
V---
X** Return Value
X** `7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E
X**  Returns the number of new arguments that have been added to the argument
X** vector.  In other words, the difference between the new value of `60argc_
Vp'
X** and its old value.
X**--------------------------------------------------------------------------
V---
X** Side Effects
X** `7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E`7E
X**  Function may cause the program to exit if it can't open files for error,
X** input, and output redirection.  Uses global variable `60vaxc$errno' for e
Vxit
X** status.
X**--------------------------------------------------------------------------
V---
X*/
Xint
Xshell_mung(argc_p,argv_p,parameter_number,option_string)
X int *  argc_p;
X char ***  argv_p;
X int  parameter_number;
X char *  option_string;
X`7B
X  /* --- LOCAL VARIABLES --- */
X
X  register char *  arg_p;               /* General-purpose argument pointer.
X                                        */
X  int  filespec_count;                  /* Number of filespecs in `60filespe
Vc_v',
X                                        ** returned from shell_glob().
X                                        */
X  char **  filespec_v;                  /* Vector of filespecs returned from
X                                        ** shell_glob().
X                                        */
X  char  from_err_too = FALSE;           /* Flag set to indicate that error t
Vext
X                                        ** will be redirected to a file alon
Vg
X                                        ** with the output text.
X                                        */
X  register int  i_new;                  /* Index to new pointers in `60new_a
Vrgv'.
X                                        */
X  register int  i_old;                  /* Index to old pointers in `60argv_
Vp'.
X                                        */
X  char **  new_argv;                    /* New argument vector, which `60arg
Vv_p'
X                                        ** will end up being replaced with.
X                                        */
X  int  new_argv_count;                  /* Count of pointers in `60new_argv'
V.
X                                        */
X  int  output_fd;                       /* File descriptor for file being
X                                        ** created as redirected output, for
X                                        ** use with creat() and dup2().
X                                        */
X  int  parameter_count = 0;             /* Counts parameters---arguments tha
Vt
X                                        ** don't have '<' or '>' or '-' in
X                                        ** front of them.  When and if the
X                                        ** count reaches `60parameter_number
V',
X                                        ** we start attempting to parse the
X                                        ** parameters as filespecs.
X                                        */
X  register char *  place_p;             /* Location of a character, as retur
Vned
X                                        ** from strchr() or strrchr().
X                                        */
X
X  /* --- INITIALIZE THINGS --- */
X
X  /* Allocate the new argument vector.
X  */
X  new_argv_count = *argc_p;
X  new_argv = xmalloc(new_argv_count * sizeof (char *));
X
X  /* Replace main()'s `60argv`5B0`5D' with a GNU-like truncated version.
X  */
X  new_argv`5B0`5D = truncate_argv_0((*argv_p)`5B0`5D);
X
X  /* --- TRAVERSE THE ARGUMENT VECTOR --- */
X
X  for (i_new = i_old = 1; i_old < *argc_p; ++i_old)
X   switch (*(arg_p = (*argv_p)`5Bi_old`5D))
X  `7B
X    /* If it begins with '<', we're redirecting input.
X    */
X    case '<':
X    filespec_v = shell_glob(++arg_p,NULL);
X    if (freopen(*filespec_v,"r",stdin) == NULL)
X    `7B
X      perror(*filespec_v);
X      sys$exit(vaxc$errno `7C STS$M_INHIB_MSG);
X    `7D
X    free(*filespec_v);
X    free(filespec_v);
X    --new_argv_count;
X    break;
X
X    /* If it begins with '>', we're redirecting output.  This comes in four
X    ** varieties, as one can append output to an existing file and/or send
X    ** error text out along with the output.  If we're told to append it (by
X    ** two '>' characters), we try to access the filespec and append to it.
X    ** If we can't access it, we proceed as if we were told to create one.
X    ** We create an output file (which is also what we're told to do when we
X    ** only get one '>' character) with "standard" VMS attributes.  If we're
X    ** told to redirect error text as well (by the '&' character), we set
X    ** `60stderr' to refer to the same file.
X    */
X    case '>':
X    if (*++arg_p == '>')
X    `7B
X      if (*++arg_p == '&')
X      `7B
X        from_err_too = TRUE;
X        ++arg_p;
X      `7D
X      if (access(arg_p,2) == 0)
X      `7B
X        if (freopen(arg_p,"a",stdout) != NULL)
X        `7B
X          if (from_err_too == TRUE)
X           stderr = stdout;
X          --new_argv_count;
X          break;
X        `7D
X        perror(arg_p);
X        sys$exit(vaxc$errno `7C STS$M_INHIB_MSG);
X      `7D
X    `7D
X    /* We get to this point if we didn't want to append output text to an
X    ** existing file, or if an attempt to establish append access to an
X    ** existing file has failed.
X    */
X    if ((from_err_too == FALSE) && (*arg_p == '&'))
X    `7B
X      from_err_too = TRUE;
X      ++arg_p;
X    `7D
X    if (
X      ((output_fd = creat(arg_p,0,"rat=cr","rfm=var","mrs=512")) != 1)
X      && (dup2(output_fd,fileno(stdout)) != -1)
X      && ((from_err_too == FALSE) `7C`7C (dup2(output_fd,fileno(stderr)) !=
V -1))
X    )
X    `7B
X      --new_argv_count;
X      break;
X    `7D
X    perror(arg_p);
X    sys$exit(vaxc$errno `7C STS$M_INHIB_MSG);
X
X    /* If it begins with '-' or '+', it's an option.  We check it against
X    ** `60option_string' to see if it's an option followed by an argument.
X    */
X    case '-':
X    case '+':
X    if (
X      (option_string == NULL)
X      `7C`7C (((char *) place_p = strchr(option_string,(*(arg_p + 1)))) == 0
V)
X    )
X    `7B
X      /* Option is not in `60option_string'.  We copy it into `60new_argv'.
X      */
X      new_argv`5Bi_new++`5D = arg_p;
X    `7D
X    else
X    `7B
X      /* Option is in `60option_string'.  First we check to see if its exist
Vence
X      ** is to be thought of as introducing a parameter.  This is indicated
V by
X      ** a '+' character following the option in `60option_string'.
X      */
X      if (*++place_p == '+')
X       ++parameter_count;
X      else
X       --place_p;
X
X      /* Next we check to see if the string following it is to be considered
V an
X      ** input filespec.  If a '-' character follows the option in `60option
V_
X      ** string' (or a '+' character following that option), that indicates
+-+-+-+-+-+-+-+-  END  OF PART 5 +-+-+-+-+-+-+-+-
