home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD2.bin / bbs / gnu / gawk-2.15.5-src.lha / gawk-2.15.5 / vms / vms_args.c < prev    next >
C/C++ Source or Header  |  1994-01-04  |  15KB  |  413 lines

  1. /*
  2.  * vms_args.c -- command line parsing, to emulate shell i/o redirection.
  3.  *        [ Escape sequence parsing now suppressed. ]
  4.  */
  5.  
  6. /*
  7.  * Copyright (C) 1991-1993 the Free Software Foundation, Inc.
  8.  *
  9.  * This file is part of GAWK, the GNU implementation of the
  10.  * AWK Progamming Language.
  11.  *
  12.  * GAWK is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2 of the License, or
  15.  * (at your option) any later version.
  16.  *
  17.  * GAWK is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with GAWK; see the file COPYING.  If not, write to
  24.  * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25.  */
  26.  
  27. /*
  28.  * [.vms]vms_arg_fixup - emulate shell's command line processing: handle
  29.  *        stdio redirection, backslash escape sequences, and file wildcard
  30.  *        expansion.    Should be called immediately upon image startup.
  31.  *
  32.  *                              Pat Rankin, Nov'89
  33.  *                            rankin@eql.Caltech.EDU
  34.  *
  35.  *    <ifile        - open 'ifile' (readonly) as 'stdin'
  36.  *    >nfile        - create 'nfile' as 'stdout' (stream-lf format)
  37.  *    >>ofile     - append to 'ofile' for 'stdout'; create it if necessary
  38.  *    >&efile     - point 'stderr' (SYS$ERROR) at 'efile', but don't open
  39.  *    >$vfile     - create 'vfile' as 'stdout', using rms attributes
  40.  *              appropriate for a standard text file (variable length
  41.  *              records with implied carriage control)
  42.  *    2>&1        - special case: direct error messages into output file
  43.  *    1>&2        - special case: direct output data to error destination
  44.  *    <<sentinal  - error; reading stdin until 'sentinal' not supported
  45.  *    <-, >-        - error: stdin/stdout closure not implemented
  46.  *    | anything  - error; pipes not implemented
  47.  *    & <end-of-line> - error; background execution not implemented
  48.  *
  49.  *    any\Xany    - convert 'X' as appropriate; \000 will not work as
  50.  *              intended since subsequent processing will misinterpret
  51.  *
  52.  *    any*any     - perform wildcard directory lookup to find file(s)
  53.  *    any%any     -     "       "    ('%' is vms wildcard for '?' [ie, /./])
  54.  *    any?any     - treat like 'any%any' unless no files match
  55.  *    *, %, ?     - if no file(s) match, leave original value in arg list
  56.  *
  57.  *
  58.  * Notes:  a redirection operator  can have optional white space between it
  59.  *    and its filename; the  operator itself *must* be preceded by  white
  60.  *    space  so that it starts  a  separate  argument.  '<' is  ambiguous
  61.  *    since "<dir>file" is a valid VMS file specification; leading '<' is
  62.  *    assumed  to be    stdin--use "\<dir>file" to override.  '>$' is local
  63.  *    kludge to force  stdout to be created with text file RMS attributes
  64.  *    instead of  stream  format;  file  sharing is disabled    for  stdout
  65.  *    regardless.  Multiple  instances of  stdin  or stdout or stderr are
  66.  *    treated as fatal errors  rather than using the first or last.  If a
  67.  *    wildcard file specification is detected, it is expanded into a list
  68.  *    of  filenames  which match; if there  are no  matches, the original
  69.  *    file-spec is left in the argument list rather than having it expand
  70.  *    into thin  air.   No  attempt is made to identify  and    make $(var)
  71.  *    environment substitutions--must draw the line somewhere!
  72.  *
  73.  *   Oct'91, gawk 2.13.3
  74.  *    Open '<' with full sharing allowed, so that we can  read batch logs
  75.  *    and other open files.  Create record-format output ('>$') with read
  76.  *    sharing permited,  so that others can read our output file to check
  77.  *    progess.  For stream  output ('>' or  '>>'), sharing is  disallowed
  78.  *    (for performance reasons).
  79.  */
  80.  
  81. #include "awk.h"    /* really "../awk.h" */
  82. #include "vms.h"
  83. #include <lnmdef.h>
  84.  
  85.        void   v_add_arg(int, const char *);
  86. static char  *skipblanks(const char *);
  87. static void   vms_expand_wildcards(const char *);
  88. static u_long vms_define(const char *, const char *);
  89. static char  *t_strstr(const char *, const char *);
  90. #define strstr t_strstr        /* strstr() missing from vaxcrtl for V4.x */
  91.  
  92. static    int    v_argc,  v_argz = 0;
  93. static    char  **v_argv;
  94.  
  95. /* vms_arg_fixup() - scan argv[] for i/o redirection and wildcards and also */
  96. /*            rebuild it with those removed or expanded, respectively */
  97. void
  98. vms_arg_fixup( int *pargc, char ***pargv )
  99. {
  100.     const char *f_in, *f_out, *f_err,
  101.     *out_mode, *rms_rfm, *rms_shr, *rms_mrs;
  102.     char **argv = *pargv;
  103.     int i, argc = *pargc;
  104.     int err_to_out_redirect = 0, out_to_err_redirect = 0;
  105.  
  106. #ifdef CHECK_DECSHELL        /* don't define this if linking with DECC$SHR */
  107.     if (shell$is_shell())
  108.     return;            /* don't do anything if we're running DEC/Shell */
  109. #endif
  110. #ifndef NO_DCL_CMD
  111.     for (i = 1; i < argc ; i++)     /* check for dash or other non-VMS args */
  112.     if (strchr("->\\|", *argv[i]))    break;        /* found => (i < argc) */
  113.     if (i >= argc && (v_argc = vms_gawk()) > 0) {   /* vms_gawk => dcl_parse */
  114.     /* if we successfully parsed the command, replace original argv[] */
  115.     argc = v_argc,    argv = v_argv;
  116.     v_argz = v_argc = 0,  v_argv = NULL;
  117.     }
  118. #endif
  119.     v_add_arg(v_argc = 0, argv[0]);    /* store arg #0 (image name) */
  120.  
  121.     f_in = f_out = f_err = NULL;    /* stdio setup (no filenames yet) */
  122.     out_mode = "w";            /* default access for stdout */
  123.     rms_rfm = "rfm=stmlf";        /* stream_LF format */
  124.     rms_shr = "shr=nil";        /* no sharing (for '>' output file) */
  125.     rms_mrs = "mrs=0";            /* no maximum record size */
  126.  
  127.     for (i = 1; i < argc; i++) {
  128.     char *p, *fn;
  129.     int  is_arg;
  130.  
  131.     is_arg = 0;        /* current arg does not begin with dash */
  132.     p = argv[i];        /* current arg */
  133.     switch (*p) {
  134.       case '<':        /* stdin */
  135.           /*[should try to determine whether this is really a directory
  136.          spec using <>; for now, force user to quote them with '\<']*/
  137.         if ( f_in ) {
  138.             fatal("multiple specification of '<' for stdin");
  139.         } else if (*++p == '<') {   /* '<<' is not supported */
  140.             fatal("'<<' not available for stdin");
  141.         } else {
  142.             p = skipblanks(p);
  143.             fn = (*p ? p : argv[++i]);    /* use next arg if necessary */
  144.             if (i >= argc || *fn == '-')
  145.             fatal("invalid i/o redirection, null filespec after '<'");
  146.             else
  147.             f_in = fn;        /* save filename for stdin */
  148.         }
  149.         break;
  150.       case '>':   {        /* stdout or stderr */
  151.           /*[vms-specific kludge '>$' added to force stdout to be created
  152.          as record-oriented text file instead of in stream-lf format]*/
  153.         int is_out = 1;            /* assume stdout */
  154.         if (*++p == '>')    /* '>>' => append */
  155.             out_mode = "a",  p++;
  156.         else if (*p == '&')    /* '>&' => stderr */
  157.             is_out = 0,  p++;
  158.         else if (*p == '$')    /* '>$' => kludge for record format */
  159.             rms_rfm = "rfm=var",  rms_shr = "shr=get,upi",
  160.             rms_mrs = "mrs=32767",  p++;
  161.         else            /* '>'    => create */
  162.             {}        /* use default values initialized prior to loop */
  163.         p = skipblanks(p);
  164.         fn = (*p ? p : argv[++i]);    /* use next arg if necessary */
  165.         if (i >= argc || *fn == '-') {
  166.             fatal("invalid i/o redirection, null filespec after '>'");
  167.         } else if (is_out) {
  168.             if (out_to_err_redirect)
  169.             fatal("conflicting specifications for stdout");
  170.             else if (f_out)
  171.             fatal("multiple specification of '>' for stdout");
  172.             else
  173.             f_out = fn;        /* save filename for stdout */
  174.         } else {
  175.             if (err_to_out_redirect)
  176.             fatal("conflicting specifications for stderr");
  177.             else if (f_err)
  178.             fatal("multiple specification of '>&' for stderr");
  179.             else
  180.             f_err = fn;        /* save filename for stderr */
  181.         }
  182.         }    break;
  183.       case '2':        /* check for ``2>&1'' special case'' */
  184.         if (strcmp(p, "2>&1") != 0)
  185.             goto ordinary_arg;
  186.         else if (f_err || out_to_err_redirect)
  187.             fatal("conflicting specifications for stderr");
  188.         else {
  189.             err_to_out_redirect = 1;
  190.             f_err = "SYS$OUTPUT:";
  191.         }  break;
  192.       case '1':        /* check for ``1>&2'' special case'' */
  193.         if (strcmp(p, "1>&2") != 0)
  194.             goto ordinary_arg;
  195.         else if (f_out || err_to_out_redirect)
  196.             fatal("conflicting specifications for stdout");
  197.         else {
  198.             out_to_err_redirect = 1;
  199.             f_out =