home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Utilities / Programming / EnterAct 3.7.3 / hAWK project / AWK Source / AWK_MAIN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-18  |  22.0 KB  |  848 lines  |  [TEXT/TOPC]

  1. /* AWK_MAIN.C -- Expression tree constructors and main program for g/hawk. 
  2.  */
  3.  
  4. /* Copyright © 1986, 1988, 1989 1991 the Free Software Foundation, Inc.
  5.  *         This file is part of GAWK, the GNU implementation of the
  6.  * AWK Progamming Language, modified for the Macintosh (also called hAWK).
  7.  *         GAWK is free software; you can redistribute or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; either version 1, or any later version.
  10.  *         GAWK is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  * GNU General Public License for more details.
  14.  *         You should have received a copy of the GNU General Public License
  15.  * along with GAWK; see the file "COPYING hAWK". If not, write to
  16.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  * Modified for THINK C 4 on the Macintosh by Ken Earle (Dynabyte) Aug 1991.
  18.  * Entirely revised to compile under CodeWarrior 6.1 sometime before Aug 95.
  19.  */
  20.  
  21. #include "AWK.H"
  22. #include "AppCodeComm.h"
  23. #include "PATCHLEV.H" /* just defines PATCHLEVEL == 10 */
  24. #include <signal.h>
  25.  
  26. extern short yyparse(void);
  27. extern void do_input(void);
  28. extern short close_io(void);
  29. extern void init_fields(void);
  30. extern short getopt(short argc, char **argv, char *opts);
  31. extern short re_set_syntax(short syntax);
  32. extern NODE *node(NODE *left, NODETYPE op, NODE *right);
  33.  
  34. short AWKmain(short argc, char **argv);
  35. static void usage(void);
  36. static void set_fs(char *str);
  37. static void init_vars(void);
  38. static void init_args(short argc0, short argc, char *argv0, char **argv);
  39. static void MakeOutAsInName(void);
  40. static NODE *spc_var(char *name, NODE *value);
  41. static void pre_assign(char *v);
  42. static void copyleft(void);
  43. SIGTYPE catchsig(int sig);
  44.  
  45. /* These nodes store all the special variables AWK uses */
  46. NODE *FS_node, *NF_node, *RS_node, *NR_node;
  47. NODE *FILENAME_node, *OFS_node, *ORS_node, *OFMT_node;
  48. NODE *FNR_node, *RLENGTH_node, *RSTART_node, *SUBSEP_node;
  49. NODE *ENVIRON_node, *IGNORECASE_node;
  50. NODE *ARGC_node, *ARGV_node; /* used primarily to hold the "leftover"
  51. file names to be used for input during program execution. See nextfile(). */
  52. NODE *RUNERR_node; /* Holds name of file to use for user error messages */
  53. NODE *STDPATH_node; /* Holds path to use as prefix for files to be written to
  54. same folder as stdout - typ looks like "Disk:folder1:...:folderN: */
  55. NODE /* *DAY_node, *DATE_node, */ *TIME_node; /* day, date, time (work in progress) */
  56. /*
  57.  * The parse tree and field nodes are stored here. Parse_end is a dummy
  58.  item used to free up unneeded fields without freeing the program being
  59.  run . NOTE can't find "Parse_end" anywhere. */
  60. short errcount = 0;    /* error counter, used by yyerror() */
  61.  
  62. /* The global null string */
  63. NODE *Nnull_string;
  64.  
  65. /* The name the program was invoked under, for error messages */
  66. char *myname;
  67.  
  68. /* A block of AWK code to be run before running the program */
  69. NODE *begin_block = 0;
  70.  
  71. /* A block of AWK code to be run after the last input file */
  72. NODE *end_block = 0;
  73.  
  74. NODE *expression_value; /* The block of AWK code that IS the program */
  75.  
  76. short exiting = 0;        /* Was an "exit" statement executed? */
  77. short exit_val = 0;        /* optional exit value */
  78.  
  79. #ifdef DEBUG
  80. /* non-zero means in debugging is enabled.  Probably not very useful */
  81. /* NOTE DEBUG is not yet supported in the Mac version. */
  82. short debugging = 0;
  83. extern short yydebug;
  84. #endif
  85.  
  86. short tempsource = 0;        /* source is in a temp file */
  87. char **sourcefile = NULL;    /* source file name(s) -see sourcefileNote */
  88. short numfiles = -1;        /* how many source files */
  89.  
  90. #define STRICT            /* keep it simple at first  */
  91. short strict = 0;            /* set to 1 below */
  92. /* NOTE ignoring the case while comparing strings and matching regular
  93. expressions is now allowed even if strict is nonzero, since it seems
  94. like a useful thing */
  95. short output_is_tty = 0;        /* control flushing of output */
  96.  
  97. char *stdOutAsInFileName = NULL; /* Holds stdout when used as input */
  98.  
  99. /*
  100.  * for strict to work, legal options must be first
  101.  *
  102.  * Unfortunately, -a and -e are orthogonal to -c.
  103.  */
  104. #define EXTENSIONS    8    /* where to clear */
  105. #ifdef DEBUG
  106. char awk_opts[14] /*= "F:f:v:caeCVdD"*/;
  107. /* colon means preceding option takes an argument */
  108. #else
  109. char awk_opts[12] /*= "F:f:v:caeCV"*/;
  110. #endif
  111.  
  112. /* Init functions, mainly since code resources are unhappy about
  113. initializing globals to an address. */
  114. void InitCommonsInAwkH(void); /* at bottom here */
  115. extern void InitAwkTabVars(void);
  116. extern void InitGetOpt(void);
  117. extern void InitEval(void);
  118. extern void InitField(void);
  119. extern void InitIO(void);
  120. extern void InitNode(void);
  121. extern void InitRegex(void);
  122. extern void InitRandom(void);
  123.  
  124. /* Revision: redirect stdout/err to text files, at end close them and
  125. free up all allocated memory. This function is largely unchanged for the
  126. Mac version, since hAWK_Interface.c creates a command line based on
  127. user mouse-waves. */
  128. short AWKmain(short argc, char **argv)
  129. {
  130. //extern short OKStopAlert(Ptr cstringPtr);
  131.  
  132. #ifdef DEBUG
  133.     /* Print out the parse tree.   For debugging */
  134.     register short dotree = 0;
  135. #endif
  136.     extern char *version_string; /* see VERSION.c */
  137.     FILE *fp, *textstdout, textstderr;
  138.     short c;
  139.     extern short opterr, optind;
  140.     extern char *optarg;
  141.      extern char *strrchr(); /* <string.h> */
  142.      extern char *tmpnam();    /* <stdio.h> */
  143.     short i;
  144.     short nostalgia;
  145. #ifdef somtime_in_the_future
  146.     short regex_mode = RE_SYNTAX_POSIX_EGREP;
  147. #else
  148.     short regex_mode = RE_SYNTAX_AWK;
  149. #endif
  150.     
  151.     extern Boolean gConcurrent;
  152.  
  153.     /* initialize variables */
  154.     
  155.     //OKStopAlert("DBG about to do main inits");
  156.     
  157.     InitCommonsInAwkH();
  158.     InitAwkTabVars();
  159.     InitGetOpt();
  160.     InitEval();
  161.     InitField();
  162.     InitIO();
  163.     InitNode();
  164.     InitRegex();
  165.     if (!hAWKstackDepth)
  166.         InitRandom();
  167.  
  168.     if (!hAWKstackDepth)
  169.         {
  170.         if (strncmp(version_string, "@(#)", 4) == 0)
  171.             version_string += 4;
  172.  
  173.         (void) signal(SIGFPE, catchsig); /* <signal.h> div by zero etc */
  174.  
  175.         /* redirect stderr to text file. stdout is reopened in
  176.         init_args - postponed because reopening it now would
  177.         zero it out, and user may want to take input from
  178.         stdout (ie the results of the last Drag_on Module run. */
  179.         if (!freopen(gacc.stdErrFileName, "w", stderr))
  180.             /* fatal error */
  181.             exit(1);
  182.         }
  183.     
  184.     /* Pick out "AWK" or somesuch from first argument */
  185.     myname = strrchr(argv[0], '/');
  186.     if (myname == NULL)
  187.         myname = argv[0]; /* typical case, since not using '/' */
  188.     else
  189.         myname++;
  190.     if (argc < 2)
  191.         usage();
  192.  
  193.     /* initialize the null string */
  194.     Nnull_string = make_string("", 0);
  195.     Nnull_string->numbr = 0.0;
  196.     Nnull_string->type = Node_val;
  197.     Nnull_string->flags = (PERM|STR|NUM|NUMERIC);
  198.  
  199.     /* Set up the special variables */
  200.  
  201.     /*
  202.      * Note that this must be done BEFORE arg parsing else -F
  203.      * breaks horribly 
  204.      */
  205.     init_vars();
  206.     
  207.     //OKStopAlert("DBG just did init vars");
  208.  
  209.     /* worst case */
  210.     emalloc(sourcefile, char **, argc * sizeof(char *), "main");
  211.                 
  212. #ifdef STRICT    /* strict new awk compatibility */
  213.     strict = 1;
  214.     awk_opts[EXTENSIONS] = '\0';
  215. #endif
  216.  
  217. #ifndef STRICT
  218.     /* undocumented feature, inspired by nostalgia, and a T-shirt */
  219.     nostalgia = 0;
  220.     for (i = 1; i < argc && argv[i][0] == '-'; i++) {
  221.         if (argv[i][1] == '-')        /* -- */
  222.             break;
  223.         else if (argv[i][1] == 'c') {    /* compatibility mode */
  224.             nostalgia = 0;
  225.             break;
  226.         } else if (STREQ(&argv[i][1], "nostalgia"))
  227.             nostalgia = 1;
  228.             /* keep looping, in case -c after -nostalgia */
  229.     }
  230.     if (nostalgia) {
  231.         fprintf (stderr, "awk: bailing out near line 1\n");
  232.         abort();
  233.     }
  234. #endif
  235.     
  236.     //OKStopAlert("DBG about to call getopt a lot");
  237.     /* AWK options: see AWKOptionsNote */
  238.     while ((c = getopt (argc, argv, awk_opts)) != EOF) {
  239.         switch (c) {
  240.         /* Note '--' is detected by getopt() */
  241. #ifdef DEBUG
  242.         case 'd':
  243.             debugging++;
  244.             dotree++;
  245.             break;
  246.  
  247.         case 'D':
  248.             debugging++;
  249.             yydebug = 2;
  250.             break;
  251. #endif
  252.  
  253. #ifndef STRICT
  254.         case 'c':
  255.             strict = 1;
  256.             break;
  257. #endif
  258.  
  259.         case 'F':
  260.             set_fs(optarg);
  261.             break;
  262.  
  263.         case 'f':
  264.             /*
  265.              * a la MKS awk, allow multiple -f options.
  266.              * this makes function libraries real easy.
  267.              * most of the magic is in the scanner.
  268.              NOTE each source file to be preceded by '-f' */
  269.              
  270.              /* REVISION RecordSourceFile() */
  271.             sourcefile[++numfiles] = optarg;
  272.             break;
  273.  
  274.         case 'v':
  275.             pre_assign(optarg);
  276.             break;
  277.  
  278.         case 'V':
  279.             fprintf(stderr, "%s, patchlevel %d\n",
  280.                     version_string, PATCHLEVEL);
  281.             break;
  282.  
  283.         case 'C':
  284.             copyleft();
  285.             break;
  286.  
  287.         case 'a':    /* use old fashioned awk regexps */
  288.             regex_mode = RE_SYNTAX_AWK;
  289.             break;
  290.  
  291.         case 'e':    /* use egrep style regexps, per Posix */
  292.             regex_mode = RE_SYNTAX_POSIX_EGREP;
  293.             break;
  294.  
  295.         case '?':
  296.         default:
  297.             /* getopt will print a message for us */
  298.             /* S5R4 awk ignores bad options and keeps going */
  299.             break;
  300.         }
  301.     }
  302.  
  303.     /* Tell the regex routines how they should work. . . */
  304.     (void) re_set_syntax(regex_mode);
  305.  
  306. #ifdef DEBUG
  307.     setbuf(stdout, (char *) NULL);    /* make debugging easier */
  308. #endif
  309. //    if (isatty(fileno(stdout)))
  310. //        output_is_tty = 1;
  311.     /* No -f option, use next arg */
  312.     /* write to temp file and save sourcefile name */
  313.     if (numfiles == -1) {
  314.         short i;
  315.  
  316.         if (optind > argc - 1)    /* no args left */
  317.             usage();
  318.         numfiles++;
  319.         i = strlen (argv[optind]);
  320.         if (i == 0) {    /* sanity check */
  321.             fprintf(stderr, "%s: empty program text\n", myname);
  322.             usage();
  323.             /* NOTREACHED */
  324.         }
  325.         sourcefile[0] = tmpnam((char *) NULL);
  326.         if ((fp = fopen (sourcefile[0], "w")) == NULL)
  327.             fatal("could not save source prog in temp file (%s)",
  328.             strerror(errno));
  329.         if (fwrite (argv[optind], 1, i, fp) == 0)
  330.             fatal(
  331.             "could not write source program to temp file (%s)",
  332.             strerror(errno));
  333.         if (argv[optind][i-1] != '\n')
  334.             putc ('\n', fp);
  335.         (void) fclose (fp);
  336.         tempsource++;
  337.         optind++;
  338.     }
  339.     
  340.     //OKStopAlert("DBG about build list of input files");
  341.     /* This builds list of input files to ARGVnode */
  342.     init_args(optind, argc, myname, argv);
  343.     
  344.     errcount = 0;
  345.     if (!gConcurrent)
  346.         CheckForInterrupt();
  347.     
  348.     //OKStopAlert("DBG about to read in the program");
  349.     /* Read in the program */
  350.     if (yyparse() || errcount)
  351.         exit(1);
  352.     if (!gConcurrent)
  353.         CheckForInterrupt();
  354. #ifdef DEBUG
  355.     if (dotree)
  356.         print_parse_tree(expression_value);
  357. #endif
  358.     
  359.     //OKStopAlert("DBG about to set up the field variables");
  360.     /* Set up the field variables */
  361.     init_fields();
  362.     
  363.     if (begin_block)
  364.         (void) interpret(begin_block);
  365.     if (gConcurrent)
  366.         {
  367.         if (CheckInWithCallingApp())  /* CodeResource_Helper.c */
  368.             JumpOnHAWKError(999);
  369.         }
  370.     else
  371.         CheckForInterrupt();
  372.     if (!exiting && (expression_value || end_block))
  373.         do_input();
  374.     if (!gConcurrent)
  375.         CheckForInterrupt();
  376.     if (end_block)
  377.         (void) interpret(end_block);
  378.     if (close_io() != 0 && exit_val == 0)
  379.         exit_val = 1;
  380.     
  381.     //OKStopAlert("DBG about to exit the main call");
  382.     /* REACHED */
  383.     return exit_val;
  384. }
  385.  
  386. static void
  387. usage()
  388. {
  389.     char *opt1 = " -f progfile [--]";
  390.     char *opt2 = " [--] 'program'";
  391. #ifdef STRICT
  392.     char *regops = " [-ae] [-F fs] [-v var=val]";
  393. #else
  394.     char *regops = " [-aecCV] [-F fs] [-v var=val]";
  395. #endif
  396.  
  397.     fprintf(stderr, "usage: %s%s%s file ...\n       %s%s%s file ...\n",
  398.         myname, regops, opt1, myname, regops, opt2);
  399.     exit(11);
  400. }
  401.  
  402. /* Generate compiled regular expressions */
  403. struct re_pattern_buffer *
  404. make_regexp(NODE *s, short ignorecase)
  405. {
  406.     struct re_pattern_buffer *rp;
  407.     char *err;
  408.  
  409.     emalloc(rp, struct re_pattern_buffer *, sizeof(*rp), "make_regexp");
  410.     memset((char *) rp, 0, sizeof(*rp));
  411.     emalloc(rp->buffer, char *, 16, "make_regexp");
  412.     rp->allocated = 16;
  413.     emalloc(rp->fastmap, char *, 256, "make_regexp");
  414.  
  415.     if (/*! strict && */ ignorecase)
  416.         rp->translate = casetable;
  417.     else
  418.         rp->translate = NULL;
  419.     if ((err = re_compile_pattern(s->stptr, s->stlen, rp)) != NULL)
  420.         fatal("%s: /%s/", err, s->stptr);
  421.     free_temp(s);
  422.     return rp;
  423. }
  424.  
  425. struct re_pattern_buffer *
  426. mk_re_parse(char *s, short ignorecase)
  427. {
  428.     char *src;
  429.     register char *dest;
  430.     register short c;
  431.     short in_brack = 0;
  432.  
  433.     for (dest = src = s; *src != '\0';) {
  434.         if (*src == '\\') {
  435.             c = *++src;
  436.             switch (c) {
  437.             case '/':
  438.             case 'a':
  439.             /*case 'b':*/
  440.             case 'f':
  441.             case 'n':
  442.             case 'r':
  443.             case 't':
  444.             case 'v':
  445.             case 'x':
  446.             case '0':
  447.                 c = parse_escape(&src);
  448.                 if (c < 0)
  449.                     cant_happen();
  450.                 *dest++ = (char)c;
  451.                 break;
  452.             case '1':
  453.             case '2':
  454.             case '3':
  455.             case '4':
  456.             case '5':
  457.             case '6':
  458.             case '7':
  459.                 if (*(src+1) >= '0' && *(src+1) <= '7')
  460.                     {
  461.                     c = parse_escape(&src);
  462.                     if (c < 0)
  463.                         cant_happen();
  464.                     *dest++ = (char)c;
  465.                     }
  466.                 else
  467.                     {
  468.                     *dest++ = '\\';
  469.                     *dest++ = (char)c;
  470.                     src++;
  471.                     }
  472.                 break;
  473.             default:
  474.                 *dest++ = '\\';
  475.                 *dest++ = (char)c;
  476.                 src++;
  477.                 break;
  478.             }
  479.         } else if (*src == '/' && ! in_brack)
  480.             break;
  481.         else {
  482.             if (*src == '[')
  483.                 in_brack = 1;
  484.             else if (*src == ']')
  485.                 in_brack = 0;
  486.  
  487.             *dest++ = *src++;
  488.         }
  489.     }
  490.     return make_regexp(tmp_string(s, (short)(dest-s)), ignorecase);
  491. }
  492.  
  493. /* This replaced by "About" button in main dialog. */
  494. static void
  495. copyleft ()
  496. {
  497.     extern char *version_string;
  498.     char *cp;
  499.     static char blurb[] =
  500. "Copyright (C) 1989, Free Software Foundation.\n\
  501. GNU Awk comes with ABSOLUTELY NO WARRANTY.  This is free software, and\n\
  502. you are welcome to distribute it under the terms of the GNU General\n\
  503. Public License, which covers both the warranty information and the\n\
  504. terms for redistribution.\n\n\
  505. You should have received a copy of the GNU General Public License along\n\
  506. with this program; if not, write to the Free Software Foundation, Inc.,\n\
  507. 675 Mass Ave, Cambridge, MA 02139, USA.\n";
  508.  
  509.     fprintf (stderr, "%s, patchlevel %d\n", version_string, PATCHLEVEL);
  510.     fputs(blurb, stderr);
  511.     fflush(stderr);
  512. }
  513.  
  514. static void
  515. set_fs(char *str)
  516. {
  517.     register NODE **tmp;
  518.  
  519.     tmp = get_lhs(FS_node, 0);
  520.     /*
  521.      * Only if in full compatibility mode check for the stupid special
  522.      * case so -F\t works as documented in awk even though the shell
  523.      * hands us -Ft.  Bleah!
  524.      */
  525.     if (strict && str[0] == 't' && str[1] == '\0')
  526.         str[0] = '\t';
  527.     *tmp = make_string(str, 1);
  528.     do_deref();
  529. }
  530.  
  531. static void
  532. init_args(short argc0, short argc, char *argv0, char **argv)
  533.     {
  534.     short i, j;
  535.     NODE **aptr;
  536.     Boolean    stdOutReset = FALSE;
  537.  
  538.     ARGV_node = spc_var("ARGV", Nnull_string);
  539.     aptr = assoc_lookup(ARGV_node, tmp_number(0.0));
  540.     *aptr = make_string(argv0, strlen(argv0));
  541.     for (i = argc0, j = 1; i < argc; i++)
  542.         {
  543.         /* Allow stdout from last run to be used as input for this
  544.         run; since stdout is overwritten, first save its contents under
  545.         a new name. This quietly changes the name of stdout stored in
  546.         ARGV[] which would throw off redirection, but normally one does
  547.         not both take input from stdout and redirect output to one of the
  548.         input files. */
  549.         if (!strcmp(argv[i], gacc.stdOutFileName))
  550.             {
  551.             if (stdOutAsInFileName == NULL)
  552.                 MakeOutAsInName();
  553.             fclose(stdout);/* ignore error if not open */
  554.             remove(stdOutAsInFileName); /* ignore error if doesn't exist */
  555.             rename(gacc.stdOutFileName, stdOutAsInFileName);/* fails if stdout not there... */
  556.             stdOutReset = TRUE;
  557.             aptr = assoc_lookup(ARGV_node, tmp_number((AWKNUM) j));
  558.             *aptr = make_string(stdOutAsInFileName, strlen(stdOutAsInFileName));
  559.             }
  560.         else
  561.             {
  562.             aptr = assoc_lookup(ARGV_node, tmp_number((AWKNUM) j));
  563.             *aptr = make_string(argv[i], strlen(argv[i]));
  564.             }
  565.         j++;
  566.         }
  567.     ARGC_node = spc_var("ARGC", make_number((AWKNUM) j));
  568.     
  569.     /* stdout is finally safe to (re)open */
  570.     if (!hAWKstackDepth || stdOutReset)
  571.         {
  572.         if (!freopen(gacc.stdOutFileName, "w", stdout))
  573.             /* fatal error */
  574.             exit(1);
  575.         }
  576.     }
  577.  
  578. /* Set global stdOutAsInFileName to temp file name to use for
  579. stdout file which will be used for current input. 
  580. Typ stdOutAsInFileName = "Disk:...:THINK C folder:$tempOutAsInput" */
  581. static void MakeOutAsInName()
  582.     {
  583.     char     *var;
  584.     short     i;
  585.     
  586.     var = gacc.stdOutFileName;
  587.     i = strlen(gacc.stdOutFileName);
  588.     while (*(var + i - 1) != ':' && i > 0)
  589.         --i;
  590.     /* note the trailing colon is kept */
  591.     emalloc(stdOutAsInFileName, char *, i+16, "init_args");
  592.     BlockMove(gacc.stdOutFileName, stdOutAsInFileName, i);
  593.     BlockMove("$tempOutAsInput", stdOutAsInFileName+i, 16);
  594.     }
  595.  
  596. /*
  597.  * Set all the special variables to their initial values.
  598.  ENVIRION not done for the Mac version.
  599.  */
  600. static void
  601. init_vars()
  602. {
  603. #ifndef MACVERSION
  604.     extern char **environ;
  605. #endif
  606.     char         *var, *val, temp[3];
  607.     NODE         **aptr;
  608.     time_t        now;
  609.     struct tm    *date;
  610.     char        s[50];
  611.     short         i;
  612.  
  613.     FS_node = spc_var("FS", make_string(" ", 1));
  614.     NF_node = spc_var("NF", make_number(-1.0));
  615.     RS_node = spc_var("RS", make_string("\n", 1));
  616.     NR_node = spc_var("NR", make_number(0.0));
  617.     FNR_node = spc_var("FNR", make_number(0.0));
  618.     FILENAME_node = spc_var("FILENAME", make_string("-", 1));
  619.     OFS_node = spc_var("OFS", make_string(" ", 1));
  620.     ORS_node = spc_var("ORS", make_string("\n", 1));
  621.     OFMT_node = spc_var("OFMT", make_string("%.6g", 4));
  622.     RLENGTH_node = spc_var("RLENGTH", make_number(0.0));
  623.     RSTART_node = spc_var("RSTART", make_number(0.0));
  624.     SUBSEP_node = spc_var("SUBSEP", make_string("\034", 1));
  625.     IGNORECASE_node = spc_var("IGNORECASE", make_number(0.0));
  626.  
  627.     ENVIRON_node = spc_var("ENVIRON", Nnull_string);
  628. #ifdef MACVERSION
  629.     /* the stdErrFileName is $tempStdErr, whereas the RUNERR file name is
  630.     $tempRunErr. */
  631.     var = gacc.stdErrFileName;
  632.     i = strlen(gacc.stdErrFileName);
  633.     if (i >= 6)
  634.         {
  635.         temp[0] = var[i-6];
  636.         var[i-6] = 'R';
  637.         temp[1] = var[i-5];
  638.         var[i-5] = 'u';
  639.         temp[2] = var[i-4];
  640.         var[i-4] = 'n';
  641.         RUNERR_node = spc_var("RUNERR", make_string(gacc.stdErrFileName, i));
  642.         var[i-6] = temp[0];
  643.         var[i-5] = temp[1];
  644.         var[i-4] = temp[2];
  645.         }
  646.     /* STDPATH holds path name to be used as prefix for any file that is to be 
  647.     written to the same folder as stdout. */
  648.     while (*(var + i - 1) != ':' && i > 0)
  649.         --i;
  650.     /* note the trailing colon is kept */
  651.     STDPATH_node = spc_var("STDPATH", make_string(gacc.stdErrFileName, i));
  652.     
  653.     /* Date/time */
  654.     now = time(NULL);
  655.     date = localtime(&now);
  656.     i = strftime(s,50, "%A, %B %d, %Y %I:%M %p", date);
  657.     TIME_node = spc_var("TIME", make_string(s, i));
  658.     /* work in progress ****************
  659.     i = strftime(s,50, "%A", date);
  660.     DAY_node = spc_var("DAY", make_string(s, i));
  661.     i = strftime(s,50, "%B %d, %Y", date);
  662.     DATE_node = spc_var("DATE", make_string(s, i));
  663.     i = strftime(s,50, "%I:%M:%S %p", date);
  664.     TIME_node = spc_var("TIME", make_string(s, i));
  665.     *********/
  666.     
  667.     return;
  668.     
  669. #else
  670.     for (i = 0; environ[i]; i++) {
  671.         static char nullstr[] = "";
  672.  
  673.         var = environ[i];
  674.         val = strchr(var, '=');
  675.         if (val)
  676.             *val++ = '\0';
  677.         else
  678.             val = nullstr;
  679.         aptr = assoc_lookup(ENVIRON_node, tmp_string(var, strlen (var)));
  680.         *aptr = make_string(val, strlen (val));
  681.  
  682.         /* restore '=' so that system() gets a valid environment */
  683.         if (val != nullstr)
  684.             *--val = '=';
  685.     }
  686. #endif
  687. }
  688.  
  689. /* Create a special variable */
  690. static NODE *
  691. spc_var(char *name, NODE *value)
  692. {
  693.     register NODE *r;
  694.  
  695.     if ((r = lookup(variables, name)) == NULL)
  696.         r = install(variables, name, node(value, Node_var, (NODE *) NULL));
  697.     return r;
  698. }
  699.  
  700. static void
  701. pre_assign(char *v)
  702. {
  703.     char *cp;
  704.  
  705.     cp = strchr(v, '=');
  706.     if (cp != NULL) {
  707.         *cp++ = '\0';
  708.         variable(v)->var_value = make_string(cp, strlen(cp));
  709.     } else {
  710.         fprintf (stderr,
  711.             "%s: '%s' argument to -v not in 'var=value' form\n",
  712.                 myname, v);
  713.         usage();
  714.     }
  715. }
  716.  
  717.  
  718. SIGTYPE catchsig(int sig)
  719. {
  720. extern void msg(char *va_alist, ...);
  721.  
  722.     if (sig == SIGFPE) {
  723.         fatal("floating point exception");
  724.     } else if (sig == SIGSEGV) {
  725.         msg("fatal error: segmentation fault");
  726.         /* fatal won't abort() if not compiled for debugging */
  727.         abort();
  728.     } else
  729.         cant_happen();
  730.     /* NOTREACHED */
  731. }
  732.  
  733. void InitCommonsInAwkH()
  734.     {
  735.     extern char *version_string; /* see VERSION.c */
  736.     version_string = "@(#)Gnu Awk (gawk) 2.11.1";
  737.     
  738.     if (!hAWKstackDepth)
  739.         {
  740. #ifdef DEBUG
  741.     strcpy(awk_opts, "F:f:v:caeCVdD");
  742. /* colon means preceding option takes an argument */
  743. #else
  744.     strcpy(awk_opts, "F:f:v:caeCV");
  745. #endif
  746.         }
  747.     exiting = 0;        /* Was an "exit" statement executed? */
  748.     exit_val = 0;        /* optional exit value */
  749.     tempsource = 0;        /* source is in a temp file */
  750.     sourcefile = NULL;    /* source file name(s) -see sourcefileNote */
  751.     numfiles = -1;        /* how many source files */
  752.     output_is_tty = 0;        /* control flushing of output */
  753.     /* gawk builtin variables */
  754.     FS_node = NF_node = RS_node = NR_node = NULL;
  755.     FILENAME_node = OFS_node = ORS_node = OFMT_node = NULL;
  756.     FNR_node = RLENGTH_node = RSTART_node = SUBSEP_node = NULL;
  757.     IGNORECASE_node = NULL;
  758.     
  759.     stack_ptr = NULL;
  760.     Nnull_string = NULL;
  761.     deref = NULL;
  762.     fields_arr = NULL;
  763.     sourceline = 0;
  764.     source = NULL;
  765.     expression_value = NULL;
  766.     _t = NULL;    /* used as temporary in tree_eval */
  767.     myname = NULL;
  768.     node0_valid = 1;
  769.     }
  770.  
  771. void SaveCommonsInAwkH(void);
  772. void RestoreCommonsInAwkH(void);
  773. void SaveCommonsInAwkH()
  774.     {
  775.     hs->exiting = exiting;
  776.     hs->exit_val = exit_val;
  777.     hs->tempsource = tempsource;
  778.     hs->sourcefile = sourcefile;
  779.     hs->numfiles = numfiles;
  780.     hs->output_is_tty = output_is_tty;
  781.     hs->FS_node = FS_node;
  782.     hs->NF_node = NF_node;
  783.     hs->RS_node = RS_node;
  784.     hs->NR_node = NR_node;
  785.     hs->FILENAME_node = FILENAME_node;
  786.     hs->OFS_node = OFS_node;
  787.     hs->ORS_node = ORS_node;
  788.     hs->OFMT_node = OFMT_node;
  789.     hs->FNR_node = FNR_node;
  790.     hs->RLENGTH_node = RLENGTH_node;
  791.     hs->RSTART_node = RSTART_node;
  792.     hs->SUBSEP_node = SUBSEP_node;
  793.     hs->IGNORECASE_node = IGNORECASE_node;
  794.     hs->ARGC_node = ARGC_node;
  795.     hs->ARGV_node = ARGV_node;
  796.     hs->RUNERR_node = RUNERR_node;
  797.     hs->STDPATH_node = STDPATH_node;
  798.     hs->TIME_node = TIME_node;
  799.     hs->stack_ptr = stack_ptr;
  800.     hs->deref = deref;
  801.     hs->fields_arr = fields_arr;
  802.     hs->sourceline = sourceline;
  803.     hs->source = source;
  804.     hs->expression_value = expression_value;
  805.     hs->_t = _t;
  806.     hs->myname = myname;
  807.     hs->node0_valid = node0_valid;
  808.     
  809.     }
  810.  
  811. void RestoreCommonsInAwkH()
  812.     {
  813.     exiting = hs->exiting;
  814.     exit_val = hs->exit_val;
  815.     tempsource = hs->tempsource;
  816.     sourcefile = hs->sourcefile;
  817.     numfiles = hs->numfiles;
  818.     output_is_tty = hs->output_is_tty;
  819.     FS_node = hs->FS_node;
  820.     NF_node = hs->NF_node;
  821.     RS_node = hs->RS_node;
  822.     NR_node = hs->NR_node;
  823.     FILENAME_node = hs->FILENAME_node;
  824.     OFS_node = hs->OFS_node;
  825.     ORS_node = hs->ORS_node;
  826.     OFMT_node = hs->OFMT_node;
  827.     FNR_node = hs->FNR_node;
  828.     RLENGTH_node = hs->RLENGTH_node;
  829.     RSTART_node = hs->RSTART_node;
  830.     SUBSEP_node = hs->SUBSEP_node;
  831.     IGNORECASE_node = hs->IGNORECASE_node;
  832.     ARGC_node = hs->ARGC_node;
  833.     ARGV_node = hs->ARGV_node;
  834.     RUNERR_node = hs->RUNERR_node;
  835.     STDPATH_node = hs->STDPATH_node;
  836.     TIME_node = hs->TIME_node;
  837.     stack_ptr = hs->stack_ptr;
  838.     deref = hs->deref;
  839.     fields_arr = hs->fields_arr;
  840.     sourceline = hs->sourceline;
  841.     source = hs->source;
  842.     expression_value = hs->expression_value;
  843.     _t = hs->_t;
  844.     myname = hs->myname;
  845.     node0_valid = hs->node0_valid;
  846.     
  847.     }
  848.