home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / dirs / gnuawk_406.lzh / GnuAwk / src.lzh / src / awk1.c < prev    next >
C/C++ Source or Header  |  1990-09-27  |  14KB  |  597 lines

  1. /*
  2.  * awk1 -- Expression tree constructors and main program for gawk. 
  3.  *
  4.  * $Log:    awk1.c,v $
  5.  * Revision 1.39  89/03/31  13:16:33  david
  6.  * GNU public license, MSDOS support, -V opt.
  7.  * 
  8.  * Revision 1.38  89/03/30  10:19:13  david
  9.  * moved awk_opts outside main() because cc doesn't like initialized autos
  10.  * delete flush_io() since close_io() comes next
  11.  * 
  12.  * Revision 1.37  89/03/29  21:54:53  david
  13.  * to get this to work with gcc, awk_opts must be a character array rather
  14.  * than a pointer (it is not readonly)
  15.  * 
  16.  * Revision 1.36  89/03/29  14:17:23  david
  17.  * delinting and code movement
  18.  * 
  19.  * Revision 1.35  89/03/26  13:32:15  david
  20.  * moved nextfile to awk7.c
  21.  * 
  22.  * Revision 1.34  89/03/24  15:57:21  david
  23.  * hashnode changes to NODE
  24.  * 
  25.  * Revision 1.33  89/03/21  10:58:26  david
  26.  * cleanup and movement of code to awk.y
  27.  * 
  28.  * Revision 1.32  89/03/15  22:00:35  david
  29.  * old case stuff removed
  30.  * new case stuff added
  31.  * add new escape sequences
  32.  * 
  33.  * Revision 1.31  89/03/15  21:31:10  david
  34.  * purge obstack stuff
  35.  * 
  36.  * Revision 1.30  88/12/15  12:56:18  david
  37.  * changes from Jay to compile under gcc and fixing a bug in treatment of
  38.  * input files
  39.  * 
  40.  * Revision 1.29  88/12/08  15:57:41  david
  41.  * *** empty log message ***
  42.  * 
  43.  * Revision 1.28  88/12/07  20:00:15  david
  44.  * changes for incorporating source filename into error messages
  45.  * 
  46.  * Revision 1.27  88/12/01  15:05:26  david
  47.  * changes to allow source line number printing in error messages
  48.  * 
  49.  * Revision 1.26  88/11/28  20:12:30  david
  50.  * unbuffer stdout if compiled with DEBUG
  51.  * 
  52.  * Revision 1.25  88/11/23  21:39:57  david
  53.  * Arnold: set strict if invoked as "awk"
  54.  * 
  55.  * Revision 1.24  88/11/22  13:47:40  david
  56.  * Arnold: changes for case-insensitive matching
  57.  * 
  58.  * Revision 1.23  88/11/15  10:18:57  david
  59.  * Arnold: cleanup; allow multiple -f options; if invoked as awk disable
  60.  * -v option for compatability
  61.  * 
  62.  * Revision 1.22  88/11/14  21:54:27  david
  63.  * Arnold: cleanup
  64.  * 
  65.  * Revision 1.21  88/11/03  15:22:22  david
  66.  * revised flags
  67.  * 
  68.  * Revision 1.20  88/11/01  11:47:24  david
  69.  * mostly cleanup and code movement
  70.  * 
  71.  * Revision 1.19  88/10/19  21:56:00  david
  72.  * replace malloc with emalloc
  73.  * 
  74.  * Revision 1.18  88/10/17  20:57:19  david
  75.  * Arnold: purge FAST
  76.  * 
  77.  * Revision 1.17  88/10/14  22:11:24  david
  78.  * pathc from Hack to get gcc to work
  79.  * 
  80.  * Revision 1.16  88/10/13  21:55:08  david
  81.  * purge FAST; clean up error messages
  82.  * 
  83.  * Revision 1.15  88/10/06  21:55:20  david
  84.  * be more careful about I/O errors on exit
  85.  * Arnold's fixes for command line processing
  86.  * 
  87.  * Revision 1.14  88/10/06  15:52:24  david
  88.  * changes from Arnold: use getopt; ifdef -v option; change semantics of = args.
  89.  * 
  90.  * Revision 1.13  88/09/26  10:16:35  david
  91.  * cleanup from Arnold
  92.  * 
  93.  * Revision 1.12  88/09/19  20:38:29  david
  94.  * added -v option
  95.  * set FILENAME to "-" if stdin
  96.  * 
  97.  * Revision 1.11  88/08/09  14:49:23  david
  98.  * reorganized handling of command-line arguments and files
  99.  * 
  100.  * Revision 1.10  88/06/13  18:08:25  david
  101.  * delete \a and -R options
  102.  * separate exit value from flag indicating that exit has been called
  103.  * [from Arnold]
  104.  * 
  105.  * Revision 1.9  88/06/05  22:19:41  david
  106.  * func_level goes away; param_counter is used to count order of local vars.
  107.  * 
  108.  * Revision 1.8  88/05/31  09:21:56  david
  109.  * Arnold's portability changes (vprintf)
  110.  * fixed handling of function parameter use inside function
  111.  * 
  112.  * Revision 1.7  88/05/30  09:51:17  david
  113.  * exit after yyparse() if any errors were encountered
  114.  * mk_re_parse() parses C escapes in regexps.
  115.  * do panic() properly with varargs
  116.  * clean up and simplify pop_var()
  117.  * 
  118.  * Revision 1.6  88/05/26  22:46:19  david
  119.  * minor changes: break out separate case for making regular expressions
  120.  *   from parser vs. from strings
  121.  * 
  122.  * Revision 1.5  88/05/13  22:02:31  david
  123.  * moved BEGIN and END block merging into parse-phase (sorry Arnold)
  124.  * if there is only a BEGIN block and nothing else, don't read any files
  125.  * cleaned up func_install a bit
  126.  * 
  127.  * Revision 1.4  88/05/04  12:18:28  david
  128.  * make_for_loop() now returns a NODE *
  129.  * pop_var() now returns the value of the node being popped, to be used
  130.  * in func_call() if the variable is an array (call by reference)
  131.  * 
  132.  * Revision 1.3  88/04/15  13:12:19  david
  133.  * small fix to arg reading code
  134.  * 
  135.  * Revision 1.2  88/04/14  14:40:25  david
  136.  * Arnold's changes to read program from a file
  137.  * 
  138.  * Revision 1.1  88/04/08  15:14:52  david
  139.  * Initial revision
  140.  *  Revision 1.6  88/04/08  14:48:30  david changes from
  141.  * Arnold Robbins 
  142.  *
  143.  * Revision 1.5  88/03/28  14:13:33  david *** empty log message *** 
  144.  *
  145.  * Revision 1.4  88/03/23  22:17:33  david mostly delinting -- a couple of bug
  146.  * fixes 
  147.  *
  148.  * Revision 1.3  88/03/18  21:00:09  david Baseline -- hoefully all the
  149.  * functionality of the new awk added. Just debugging and tuning to do. 
  150.  *
  151.  * Revision 1.2  87/11/19  14:40:17  david added support for user-defined
  152.  * functions 
  153.  *
  154.  * Revision 1.1  87/10/27  15:23:26  david Initial revision 
  155.  *
  156.  */
  157.  
  158. /* 
  159.  * Copyright (C) 1986, 1988, 1989 the Free Software Foundation, Inc.
  160.  * 
  161.  * This file is part of GAWK, the GNU implementation of the
  162.  * AWK Progamming Language.
  163.  * 
  164.  * GAWK is free software; you can redistribute it and/or modify
  165.  * it under the terms of the GNU General Public License as published by
  166.  * the Free Software Foundation; either version 1, or (at your option)
  167.  * any later version.
  168.  * 
  169.  * GAWK is distributed in the hope that it will be useful,
  170.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  171.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  172.  * GNU General Public License for more details.
  173.  * 
  174.  * You should have received a copy of the GNU General Public License
  175.  * along with GAWK; see the file COPYING.  If not, write to
  176.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  177.  */
  178.  
  179. #include "awk.h"
  180.  
  181. extern int yyparse();
  182. extern void do_input();
  183. extern void init_vars();
  184. extern void set_fs();
  185. extern int close_io();
  186. extern void init_args();
  187. extern void init_fields();
  188. extern int getopt();
  189. extern int re_set_syntax();
  190.  
  191. static void usage();
  192.  
  193. /*
  194.  * The parse tree and field nodes are stored here.  Parse_end is a dummy item
  195.  * used to free up unneeded fields without freeing the program being run 
  196.  */
  197. int errcount = 0;    /* error counter, used by yyerror() */
  198. int param_counter;
  199.  
  200. /* The global null string */
  201. NODE *Nnull_string;
  202.  
  203. /* The name the program was invoked under, for error messages */
  204. char *myname;
  205.  
  206. /* A block of AWK code to be run before running the program */
  207. NODE *begin_block = 0;
  208.  
  209. /* A block of AWK code to be run after the last input file */
  210. NODE *end_block = 0;
  211.  
  212. int exiting = 0;        /* Was an "exit" statement executed? */
  213. int exit_val = 0;        /* optional exit value */
  214.  
  215. #ifdef DEBUG
  216. /* non-zero means in debugging is enabled.  Probably not very useful */
  217. int debugging = 0;
  218. #endif
  219.  
  220. int tempsource = 0;        /* source is in a temp file */
  221. char **sourcefile = NULL;    /* source file name(s) */
  222. int numfiles = -1;        /* how many source files */
  223.  
  224. int strict = 0;            /* turn off gnu extensions */
  225.  
  226. NODE *expression_value;
  227.  
  228. /*
  229.  * for strict to work, legal options must be first
  230.  */
  231. #define EXTENSIONS    5    /* where to clear */
  232. #ifdef DEBUG
  233. char awk_opts[] = "F:f:vVdD";
  234. #else
  235. char awk_opts[] = "F:f:vV";
  236. #endif
  237.  
  238. /*** CHANGE [238,241] IN x:awk1.c TO [238,243] IN awk1.c ***/
  239. #ifdef AMIGA
  240.     #define TEMPLATE "T:gawk.XXXXXX"
  241. #elif defined MSDOS
  242.     #define TEMPLATE "%s/gaXXXXXX"
  243. #else
  244.     #define TEMPLATE "/tmp/gawk.XXXXX"
  245. #endif
  246. /*** CHANGE [238,241] IN x:awk1.c TO [238,243] IN awk1.c ***/
  247.  
  248. main(argc, argv)
  249. int argc;
  250. char **argv;
  251. {
  252. #ifdef DEBUG
  253.     /* Print out the parse tree.   For debugging */
  254.     register int dotree = 0;
  255.     extern int yydebug;
  256. #endif
  257.     extern char *version_string;
  258.     FILE *fp;
  259.     static char template[255];
  260. #ifdef MSDOS
  261.     char *ptr;
  262. #endif
  263.     int c;
  264.     extern int opterr, optind;
  265.     extern char *optarg;
  266.     char *cp;
  267.      extern char *rindex();
  268.      extern char *mktemp();
  269.  
  270.     myname = argv[0];
  271.     if (argc < 2)
  272.         usage();
  273.  
  274.     /* Tell the regex routines how they should work. . . */
  275.     (void) re_set_syntax(RE_SYNTAX_AWK);
  276.  
  277.     /* initialize the null string */
  278.     Nnull_string = make_string("", 0);
  279.     Nnull_string->numbr = 0.0;
  280.     Nnull_string->type = Node_val;
  281.     Nnull_string->flags = (PERM|STR|NUM);
  282.  
  283.     /* Set up the special variables */
  284.  
  285.     /*
  286.      * Note that this must be done BEFORE arg parsing else -F
  287.      * breaks horribly 
  288.      */
  289.     init_vars();
  290.  
  291.     /* worst case */
  292.     emalloc(sourcefile, char **, argc * sizeof(char *), "main");
  293.  
  294.  
  295. #ifdef STRICT    /* strict Unix awk compatibility */
  296.     strict = 1;
  297. #else
  298.     /* if invoked as 'awk', also behave strictly */
  299.     if ((cp = rindex(myname, '/')) != NULL)
  300.         cp++;
  301.     else
  302.         cp = myname;
  303.     if (STREQ(cp, "awk"))
  304.         strict = 1;
  305. #endif
  306.  
  307.     if (strict)
  308.         awk_opts[EXTENSIONS] = '\0';
  309.  
  310.     while ((c = getopt (argc, argv, awk_opts)) != EOF) {
  311.         switch (c) {
  312. #ifdef DEBUG
  313.         case 'd':
  314.             debugging++;
  315.             dotree++;
  316.             break;
  317.  
  318.         case 'D':
  319.             debugging++;
  320.             yydebug = 2;
  321.             break;
  322. #endif
  323.  
  324.         case 'F':
  325.             set_fs(optarg);
  326.             break;
  327.  
  328.         case 'f':
  329.             /*
  330.              * a la MKS awk, allow multiple -f options.
  331.              * this makes function libraries real easy.
  332.              * most of the magic is in the scanner.
  333.              */
  334.             sourcefile[++numfiles] = optarg;
  335.             break;
  336.  
  337.         case 'v':
  338.             fprintf(stderr, "%s", version_string);
  339.             break;
  340.  
  341.         case 'V':
  342.             copyleft();
  343.             break;
  344.  
  345.         case '?':
  346.         default:
  347.             /* getopt will print a message for us */
  348.             /* S5R4 awk ignores bad options and keeps going */
  349.             break;
  350.         }
  351.     }
  352. #ifdef DEBUG
  353.     setbuf(stdout, (char *) NULL);    /* make debugging easier */
  354. #endif
  355.     /* No -f option, use next arg */
  356.     /* write to temp file and save sourcefile name */
  357.     if (numfiles == -1) {
  358.         int i;
  359.  
  360.         if (optind > argc - 1)    /* no args left */
  361.             usage();
  362.         numfiles++;
  363. #ifdef MSDOS
  364.         if ((ptr = getenv ("TMP")) == NULL)
  365.             ptr = ".";
  366.         sprintf (template, TEMPLATE, ptr);
  367. #else
  368.         strcpy (template, TEMPLATE);
  369. #endif
  370.         sourcefile[0] = mktemp (template);
  371.         i = strlen (argv[optind]);
  372.         if ((fp = fopen (sourcefile[0], "w")) == NULL)
  373.             fatal("could not save source prog in temp file (%s)",
  374.             sys_errlist[errno]);
  375.         if (fwrite (argv[optind], 1, i, fp) == 0)
  376.             fatal(
  377.             "could not write source program to temp file (%s)",
  378.             sys_errlist[errno]);
  379.         if (argv[optind][i-1] != '\n')
  380.             putc ('\n', fp);
  381.         (void) fclose (fp);
  382.         tempsource++;
  383.         optind++;
  384.     }
  385.     init_args(optind, argc, myname, argv);
  386.  
  387.     /* Read in the program */
  388.     if (yyparse() || errcount)
  389.         exit(1);
  390.  
  391. #ifdef DEBUG
  392.     if (dotree)
  393.         print_parse_tree(expression_value);
  394. #endif
  395.     /* Set up the field variables */
  396.     init_fields();
  397.  
  398.     if (begin_block)
  399.         (void) interpret(begin_block);
  400.     if (!exiting && (expression_value || end_block))
  401.         do_input();
  402.     if (end_block)
  403.         (void) interpret(end_block);
  404.     if (close_io() != 0 && exit_val == 0)
  405.         exit_val = 1;
  406.     exit(exit_val);
  407. }
  408.  
  409. static void
  410. usage()
  411. {
  412. #ifdef STRICT
  413.     char *opt1 = "[ -Ffs ] -f progfile [ -- ]";
  414.     char *opt2 = "[ -Ffs ] [ -- ] 'program'";
  415. #else
  416.     char *opt1 = "[ -v ] [ -Ffs ] -f progfile [ -- ]";
  417.     char *opt2 = "[ -v ] [ -Ffs ] [ -- ] 'program'";
  418. #endif
  419.  
  420.     fprintf(stderr, "usage: %s %s file ...\n       %s %s file ...\n",
  421.         myname, opt1, myname, opt2);
  422.     exit(11);
  423. }
  424.  
  425. /* Generate compiled regular expressions */
  426. struct re_pattern_buffer *
  427. make_regexp(s, ignorecase)
  428. NODE *s;
  429. int ignorecase;
  430. {
  431.     struct re_pattern_buffer *rp;
  432.     char *err;
  433.  
  434.     emalloc(rp, struct re_pattern_buffer *, sizeof(*rp), "make_regexp");
  435.     bzero((char *) rp, sizeof(*rp));
  436.     emalloc(rp->buffer, char *, 8, "make_regexp");
  437.     rp->allocated = 8;
  438.     emalloc(rp->fastmap, char *, 256, "make_regexp");
  439.  
  440.     if (! strict && ignorecase)
  441.         rp->translate = casetable;
  442.     else
  443.         rp->translate = NULL;
  444.     if ((err = re_compile_pattern(s->stptr, s->stlen, rp)) != NULL)
  445.         fatal("%s: /%s/", err, s->stptr);
  446.     free_temp(s);
  447.     return rp;
  448. }
  449.  
  450. struct re_pattern_buffer *
  451. mk_re_parse(s, ignorecase)
  452. char *s;
  453. int ignorecase;
  454. {
  455.     register char *src, *dest;
  456.     register int c;
  457.  
  458.     for (dest = src = s; *src != '\0'; src++) {
  459.         if (*src == '\\') {
  460.             c = *++src;
  461.             switch (c) {
  462.             case 'a':
  463.                 if (strict)
  464.                     goto def;
  465.                 else
  466.                     *dest++ = BELL;
  467.                 break;
  468.             case 'b':
  469.                 *dest++ = '\b';
  470.                 break;
  471.             case 'f':
  472.                 *dest++ = '\f';
  473.                 break;
  474.             case 'n':
  475.                 *dest++ = '\n';
  476.                 break;
  477.             case 'r':
  478.                 *dest++ = '\r';
  479.                 break;
  480.             case 't':
  481.                 *dest++ = '\t';
  482.                 break;
  483.             case 'v':
  484.                 if (strict)
  485.                     goto def;
  486.                 else
  487.                     *dest++ = '\v';
  488.                 break;
  489.             case 'x':
  490.                 if (strict)
  491.                     goto def;
  492.                 else {
  493.                     register int i = 0;
  494.  
  495.                     while ((c = *++src)) {
  496.                         if (! isxdigit(c))
  497.                             break;
  498.                         if (isdigit(c))
  499.                             i += c - '0';
  500.                         else if (isupper(c))
  501.                             i += c - 'A' + 10;
  502.                         else
  503.                             i += c - 'a' + 10;
  504.                     }
  505.                     *dest++ = i;
  506.                 }
  507.                 break;
  508.             case '0':
  509.             case '1':
  510.             case '2':
  511.             case '3':
  512.             case '4':
  513.             case '5':
  514.             case '6':
  515.             case '7':
  516.                 {
  517.                 register int i = c - '0';
  518.                 register int count = 0;
  519.     
  520.                 while (++count < 3) {
  521.                     if ((c = *++src) >= '0' && c <= '7') {
  522.                         i *= 8;
  523.                         i += c - '0';
  524.                     } else
  525.                         break;
  526.                 }
  527.                 *dest++ = i;
  528.                 }
  529.                 break;
  530.             default:
  531.             def:
  532.                 *dest++ = '\\';
  533.                 *dest++ = c;
  534.                 break;
  535.             }
  536.         } else if (*src == '/')
  537.             break;
  538.         else
  539.             *dest++ = *src;
  540.     }
  541.     return make_regexp(tmp_string(s, dest-s), ignorecase);
  542. }
  543.  
  544. copyleft ()
  545. {
  546.     extern char *version_string;
  547.     char *cp;
  548.     static char blurb[] =
  549. ".\nCopyright (C) 1989, Free Software Foundation.\n\
  550. GNU Awk comes with ABSOLUTELY NO WARRANTY.  This is free software, and\n\
  551. you are welcome to distribute it under the terms of the GNU General\n\
  552. Public License, which covers both the warranty information and the\n\
  553. terms for redistribution.\n\n\
  554. You should have received a copy of the GNU General Public License along\n\
  555. with this program; if not, write to the Free Software Foundation, Inc.,\n\
  556. 675 Mass Ave, Cambridge, MA 02139, USA.\n";
  557.  
  558.     for (cp = version_string; *cp && *cp != '\n'; cp++)
  559.         putc (*cp, stderr);
  560.     fputs(blurb, stderr);
  561.     fflush(stderr);
  562. }
  563.  
  564. /*** APPEND AFTER 558 IN x:awk1.c ***/
  565.  
  566. #ifdef AMIGA
  567.  
  568. #include <time.h>
  569.  
  570. char *mktemp(s)
  571. char *s;
  572. {
  573.     long timeVal;
  574.     char timeAry[4];
  575.     char tBuf[7];
  576.   struct tm *ut;
  577.     
  578.     timeVal = time(NULL);
  579.     ut = localtime(&timeVal);
  580.     timeAry[0] = (unsigned char)ut->tm_hour;
  581.     timeAry[1] = (unsigned char)ut->tm_min;
  582.     timeAry[2] = (unsigned char)ut->tm_sec;
  583.     timeAry[3] = (unsigned char)0;
  584.  
  585.     stptime(tBuf, 1, timeAry);
  586.     
  587.     strmfe(s, s, tBuf);
  588.     
  589.     return(s);
  590.     
  591.     /* bugs: depends on s having a six character extension on input */
  592. }
  593.  
  594. #endif
  595. /*** APPEND AFTER 558 IN x:awk1.c ***/
  596.  
  597.