home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / jikepg12.zip / jikespg / src / lpgparse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-11-04  |  123.9 KB  |  3,478 lines

  1. /* $Id: lpgparse.c,v 1.2 1999/11/04 14:02:22 shields Exp $ */
  2. /*
  3.  This software is subject to the terms of the IBM Jikes Compiler
  4.  License Agreement available at the following URL:
  5.  http://www.ibm.com/research/jikes.
  6.  Copyright (C) 1983, 1999, International Business Machines Corporation
  7.  and others.  All Rights Reserved.
  8.  You must accept the terms of that agreement to use this software.
  9. */
  10. static char hostfile[] = __FILE__;
  11.  
  12. #include <time.h>
  13. #include <string.h>
  14. #include <ctype.h>
  15. #include "common.h"
  16. #undef scope_state
  17. #undef SCOPE_UBOUND
  18. #undef SCOPE_SIZE
  19. #include "header.h"
  20. #include "lpgsym.h"
  21. #include "lpgdef.h"
  22. #include "lpgdcl.h"
  23. #include "lpgparse.h"
  24.  
  25. #define SPACE_CODE  1
  26. #define DIGIT_CODE  2
  27. #define ALPHA_CODE  3
  28. #define IsSpace(c)  (code[c] == SPACE_CODE)
  29. #define IsDigit(c)  (code[c] == DIGIT_CODE)
  30. #define IsAlpha(c)  (code[c] == ALPHA_CODE)
  31.  
  32. static char code[256] = {0};
  33.  
  34. static int output_size = 80,
  35.            line_no = 0;
  36.  
  37. /****************************************************************************/
  38. /*                             PROCESS_INPUT:                               */
  39. /****************************************************************************/
  40. /* This procedures opens all relevant files and processes the input grammar.*/
  41. /****************************************************************************/
  42. void process_input(void)
  43. {
  44.     time_t ltime;
  45.     unsigned c;
  46.  
  47. /****************************************************************************/
  48. /* Open input grammar file. If the file cannot be opened and that file name */
  49. /* did not have an extension, then the extension ".g" is added to the file  */
  50. /* name and we try again. If no file can be found an error message is       */
  51. /* issued and the program halts.                                            */
  52. /****************************************************************************/
  53.     if ((sysgrm = fopen(grm_file, "r")) == (FILE *) NULL)
  54.     {
  55.         register int i;
  56.  
  57.         for (i = strlen(grm_file); i > 0 &&
  58.                                    grm_file[i] != '.' &&
  59.                                    grm_file[i] != '/' && /* Unix */
  60.                                    grm_file[i] != '\\';  /* Dos  */
  61.                                    i--);
  62.  
  63.         if (grm_file[i] != '.')
  64.         {
  65.             strcat(grm_file, ".g");
  66.             if ((sysgrm = fopen(grm_file, "r")) == (FILE *) NULL)
  67.             {
  68.                 fprintf(stderr,
  69.                         "***ERROR: Input file %s containing grammar "
  70.                         "is empty, undefined, or invalid\n",grm_file);
  71.                 exit(12);
  72.             }
  73.         }
  74.         else
  75.         {
  76.             fprintf(stderr,
  77.                     "***ERROR: Input file %s containing grammar "
  78.                     "is empty, undefined, or invalid\n",grm_file);
  79.             exit(12);
  80.         }
  81.     }
  82. #if !defined(C370) && !defined(CW)
  83.     else
  84.     {
  85.         if (strrchr(grm_file, '.') == NULL)
  86.         {
  87.             sprintf(msg_line,
  88.                     "A file named \"%s\" with no extension "
  89.                     "is being opened", grm_file);
  90.             PRNTWNG(msg_line);
  91.         }
  92.     }
  93. #endif
  94.  
  95. /****************************************************************************/
  96. /*               Assign timeptr to the local time.                          */
  97. /****************************************************************************/
  98.     time(<ime);
  99.     timeptr = ctime(<ime);
  100.  
  101. /****************************************************************************/
  102. /*                Open listing file for output.                             */
  103. /****************************************************************************/
  104. #if defined(C370) && !defined(CW)
  105.     syslis = fopen(lis_file, "w, lrecl=85, recfm=VBA");
  106. #else
  107.     syslis = fopen(lis_file, "w");
  108. #endif
  109.     if (syslis  == (FILE *) NULL)
  110.     {
  111.         fprintf(stderr,
  112.                 "***ERROR: Listing file \"%s\" cannot be openned.\n",
  113.                 lis_file);
  114.         exit(12);
  115.     }
  116.  
  117. /****************************************************************************/
  118. /* Complete the initialization of the code array used to replace the        */
  119. /* builtin functions isalpha, isdigit and isspace.                          */
  120. /****************************************************************************/
  121.     for (c = 'a'; c <= 'z'; c++)
  122.     {
  123.         if (isalpha(c))
  124.             code[c] = ALPHA_CODE;
  125.     }
  126.     for (c = 'A'; c <= 'Z'; c++)
  127.     {
  128.         if (isalpha(c))
  129.             code[c] = ALPHA_CODE;
  130.     }
  131.     for (c = '0'; c <= '9'; c++)
  132.     {
  133.         if (isdigit(c))
  134.             code[c] = DIGIT_CODE;
  135.     }
  136.     code[' ']  = SPACE_CODE;
  137.     code['\n'] = SPACE_CODE;
  138.     code['\t'] = SPACE_CODE;
  139.     code['\r'] = SPACE_CODE;
  140.     code['\v'] = SPACE_CODE;
  141.     code['\f'] = SPACE_CODE;
  142.  
  143.  
  144. /****************************************************************************/
  145. /*          Print heading on terminal and in listing file                   */
  146. /****************************************************************************/
  147.     printf("\n %s %35.24s\n", HEADER_INFO, timeptr);
  148.     PR_HEADING;
  149.  
  150.     init_process();
  151.  
  152.     process_grammar();
  153.  
  154.     exit_process();
  155.  
  156.     return;
  157. }
  158.  
  159.  
  160. /********************************************************************/
  161. /*                          READ_INPUT:                             */
  162. /********************************************************************/
  163. /*         READ_INPUT fills the buffer from p1 to the end.          */
  164. /********************************************************************/
  165. static void read_input(void)
  166. {
  167.     long num_read;
  168.  
  169.     num_read = input_buffer + IOBUFFER_SIZE - bufend;
  170.     if ((num_read = fread(bufend, 1, num_read, sysgrm)) == 0)
  171.     {
  172.         if (ferror(sysgrm) != 0)
  173.         {
  174.            fprintf(stderr,
  175.                    "*** Error reading input file \"%s\".\n", grm_file);
  176.            exit(12);
  177.         }
  178.     }
  179.     bufend += num_read;
  180.     *bufend = '\0';
  181.  
  182.     return;
  183. }
  184.  
  185.  
  186. /*****************************************************************************/
  187. /*                              INIT_PROCESS:                                */
  188. /*****************************************************************************/
  189. /* This routine is invoked to allocate space for the global structures       */
  190. /* needed to process the input grammar.                                      */
  191. /*****************************************************************************/
  192. static void init_process(void)
  193. {
  194.     /******************************************************************/
  195.     /* Set up a a pool of temporary space.                            */
  196.     /******************************************************************/
  197.     reset_temporary_space();
  198.  
  199.     terminal = (struct terminal_type *)
  200.                calloc(STACK_SIZE, sizeof(struct terminal_type));
  201.     if (terminal == (struct terminal_type *) NULL)
  202.         nospace(__FILE__, __LINE__);
  203.  
  204.     hash_table = (struct hash_type **)
  205.                  calloc(HT_SIZE, sizeof(struct hash_type *));
  206.     if (hash_table == (struct hash_type **) NULL)
  207.         nospace(__FILE__, __LINE__);
  208.  
  209.     /***********************************************************************/
  210.     /* Allocate space for input buffer and read in initial data in input   */
  211.     /* file. Next, invoke PROCESS_OPTION_LINES to process all lines in     */
  212.     /* input file that are options line.                                   */
  213.     /***********************************************************************/
  214.     input_buffer = (char *)
  215.             calloc(IOBUFFER_SIZE + 1 + MAX_LINE_SIZE, sizeof(char));
  216.     if (input_buffer == (char *) NULL)
  217.         nospace(__FILE__, __LINE__);
  218.  
  219.     bufend = &input_buffer[0];
  220.     read_input();
  221.  
  222.     p2 = &input_buffer[0];
  223.     linestart = p2 - 1;
  224.     p1 = p2;
  225.     line_no++;
  226.  
  227.     if (*p2 == '\0')
  228.     {
  229.         fprintf(stderr,
  230.                 "Input file \"%s\" containing grammar is "
  231.                 "empty, undefined, or invalid\n",
  232.                 grm_file);
  233.         exit(12);
  234.     }
  235.  
  236.     process_options_lines();
  237.  
  238.     eolt_image = OMEGA;
  239.  
  240.     blockb_len = strlen(blockb);
  241.     blocke_len = strlen(blocke);
  242.  
  243.     hblockb_len = strlen(hblockb);
  244.     hblocke_len = strlen(hblocke);
  245.  
  246.     /*****************************************************/
  247.     /* Keywords, Reserved symbols, and predefined macros */
  248.     /*****************************************************/
  249.     kdefine[0]            = escape;  /*Set empty first space to the default */
  250.     kterminals[0]         = escape;  /* escape symbol.                      */
  251.     kalias[0]             = escape;
  252.     kstart[0]             = escape;
  253.     krules[0]             = escape;
  254.     knames[0]             = escape;
  255.     kend[0]               = escape;
  256.     krule_number[0]       = escape;
  257.     krule_text[0]         = escape;
  258.     krule_size[0]         = escape;
  259.     knum_rules[0]         = escape;
  260.     knum_terminals[0]     = escape;
  261.     knum_non_terminals[0] = escape;
  262.     knum_symbols[0]       = escape;
  263.     kinput_file[0]        = escape;
  264.     kcurrent_line[0]      = escape;
  265.     knext_line[0]         = escape;
  266.     kstart_nt[0]          = escape;
  267.     keolt[0]              = escape;
  268.  
  269.     return;
  270. }
  271.  
  272.  
  273. /*****************************************************************************/
  274. /*                              EXIT_PROCESS:                                */
  275. /*****************************************************************************/
  276. /* This routine is invoked to free all space used to process the input that  */
  277. /* is no longer needed. Note that for the string_table, only the unused      */
  278. /* space is released.                                                        */
  279. /*****************************************************************************/
  280. static void exit_process(void)
  281. {
  282.     if (string_offset > 0)
  283.     {
  284.         string_table = (char *)
  285.             (string_table == (char *) NULL
  286.              ? malloc((string_offset) * sizeof(char))
  287.              : realloc(string_table, (string_offset) * sizeof(char)));
  288.  
  289.         if (string_table == (char *) NULL)
  290.             nospace(__FILE__, __LINE__);
  291.     }
  292.     ffree(terminal);
  293.     ffree(hash_table);
  294.     ffree(input_buffer);
  295.     ffree(rulehdr); /* allocated in action LPGACT when grammar is not empty */
  296.  
  297.     return;
  298. }
  299.  
  300.  
  301. /*****************************************************************************/
  302. /*                                 VERIFY:                                   */
  303. /*****************************************************************************/
  304. /* VERIFY takes as argument a character string and checks whether or not each*/
  305. /* character is a digit. If all are digits, then 1 is returned; if not, then */
  306. /* 0 is returned.                                                            */
  307. /*****************************************************************************/
  308. static BOOLEAN verify(char *item)
  309. {
  310.     while (IsDigit(*item))
  311.         item++;
  312.     return (*item == '\0');
  313. }
  314.  
  315.  
  316. /*****************************************************************************/
  317. /*                              TRANSLATE:                                   */
  318. /*****************************************************************************/
  319. /* TRANSLATE takes as arguments a character array, which it folds to upper   */
  320. /* to uppercase and returns.                                                 */
  321. /*****************************************************************************/
  322. static char *translate(char *str, int len)
  323. {
  324.     register int i;
  325.  
  326.     for (i = 0; i < len; i++)
  327.         str[i] = TOUPPER(str[i]);
  328.  
  329.     return(str);
  330. } /* end translate */
  331.  
  332.  
  333. /**********************************************************************/
  334. /*                             STRXEQ:                                */
  335. /**********************************************************************/
  336. /* Compare two character strings s1 and s2 to check whether or not s2 */
  337. /* is a substring of s1.  The string s2 is assumed to be in lowercase */
  338. /* and NULL terminated. However, s1 does not have to (indeed, may not)*/
  339. /* be NULL terminated.                                                */
  340. /*                                                                    */
  341. /* The test below may look awkward. For example, why not use:         */
  342. /*                  if (tolower(s1[i]) != s2[i])  ?                   */
  343. /* because tolower(ch) is sometimes implemented as (ch-'A'+'a') which */
  344. /* does not work when "ch" is already a lower case character.         */
  345. /*                                                                    */
  346. /**********************************************************************/
  347. static BOOLEAN strxeq(char *s1, char *s2)
  348. {
  349.     for (; *s2 != '\0'; s1++, s2++)
  350.     {
  351.         if (*s1 != *s2  && *s1 != toupper(*s2))
  352.             return FALSE;
  353.     }
  354.  
  355.     return TRUE;
  356. }
  357.  
  358.  
  359. /*****************************************************************************/
  360. /*                              OPTIONS:                                     */
  361. /*****************************************************************************/
  362. /*   OPTION handles the decoding of options passed by the user and resets    */
  363. /* them appropriately. "options" may be called twice: when a parameter line  */
  364. /* is passed to the main program and when the user codes an %OPTIONS line in */
  365. /* his grammar.                                                              */
  366. /*    Basically, there are two kinds of options: switches which indicate a   */
  367. /* certain setting just by their appearance, and valued options which are    */
  368. /* followed by an equal sign and the value to be assigned to them.           */
  369. /*****************************************************************************/
  370. static void options(void)
  371. {
  372.     char *c,
  373.          token[MAX_PARM_SIZE+1],
  374.          temp [MAX_PARM_SIZE+1],
  375.          delim;
  376.  
  377.     register int i,
  378.                  j,
  379.                  len;
  380.  
  381.     BOOLEAN flag;
  382.  
  383. /*******************************************************************/
  384. /* If we scan the comment sign, we stop processing the rest of the */
  385. /* parameter string.                                               */
  386. /*******************************************************************/
  387.     for (c = parm; *c != '\0'; c++)
  388.     {
  389.         if (*c == '-' && *(c+1) == '-')
  390.             break;
  391.     }
  392.     *c = '\0';
  393.  
  394.     i = 0;
  395.  
  396.     while ((parm[i] != '\0') &&    /* Clean front of string */
  397.            ((parm[i] == ',') ||
  398.             (parm[i] == '/') ||
  399.             (parm[i] == ' ')))
  400.          i++;
  401.  
  402.     while (parm[i] != '\0')     /* Repeat until parm line is exhausted */
  403.     {
  404.         strcpy(parm, parm + i);       /* Remove garbage in front */
  405.  
  406.         i = 0;
  407.  
  408.         while ((parm[i] != '\0')&&    /* Search for delimiter */
  409.                ((parm[i] != ',') &&
  410.                 (parm[i] != '/') &&
  411.                 (parm[i] != '=') &&
  412.                 (parm[i] != ' ')))
  413.             i++;
  414.  
  415.         for (j = 0; j < i; j++)   /* Fold actual parameter */
  416.         {
  417.             token[j] = TOUPPER(parm[j]);
  418.             temp[j] = parm[j];
  419.         }
  420.         token[i] = '\0';
  421.         temp[i] = '\0';
  422.  
  423.         /***********************************/
  424.         /* find first non-blank after parm */
  425.         /***********************************/
  426.         while (parm[i] != '\0' && parm[i] == ' ')
  427.             i++;
  428.  
  429.         if (parm[i] != '\0')  /* not end of parameter line */
  430.             delim = parm[i];
  431.         else
  432.             delim = ' ';
  433.  
  434.         len = strlen(token);
  435.         if (len > MAX_PARM_SIZE)
  436.             token[MAX_PARM_SIZE] = '\0';
  437.  
  438. /*****************************************************************************/
  439. /*  We check whether we have a switch or a value parameter.                  */
  440. /* Each category is checked separately.  A match is made whenever            */
  441. /* a minimum unambiguous prefix of the token in question matches an          */
  442. /* option...                                                                 */
  443. /*                                                                           */
  444. /* At this stage, TEMP contains the value of the switch as specified         */
  445. /* and TOKEN contains the upper-case folded value of TEMP.                   */
  446. /*****************************************************************************/
  447.         if (delim != '=')  /* if switch parameter then process */
  448.         {
  449.             if ((len > 2) &&
  450.                 (memcmp(token, "NO", 2) == 0)) /* option has "NO" */
  451.             {                                  /* prefix?         */
  452.                 flag = FALSE;
  453.                 len = len-2;
  454.                 strcpy(token, token + 2);  /* get rid of "NO" prefix */
  455.             }
  456.             else
  457.                 flag = TRUE;
  458.  
  459.             if (memcmp(oaction, token, len) == 0)
  460.                 action_bit = flag;
  461.             else if (memcmp(obyte, token, len) == 0)
  462.                 byte_bit = flag;
  463.             else if (memcmp(oconflicts, token, len) == 0)
  464.                 conflicts_bit = flag;
  465.             else if (len >=4 && memcmp(odefault, token, len) == 0)
  466.             {
  467.                 if (flag)
  468.                     default_opt = 5;
  469.                 else
  470.                     default_opt = 0;
  471.             }
  472.             else if (len >= 3 && memcmp(odebug, token, len) == 0)
  473.                 debug_bit = flag;
  474.             else if (len >= 4 && memcmp(odeferred, token, len) == 0)
  475.                 deferred_bit = flag;
  476.             else if (len >= 2 && memcmp(oedit, token, len) == 0)
  477.                 edit_bit = flag;
  478.             else if ((len >= 2) &&
  479.                       ((memcmp(oerrormaps,token, len) == 0) ||
  480.                        (strcmp("EM", token) == 0) ||
  481.                        (memcmp(oerrormaps2, token, len) == 0) ||
  482.                        (memcmp(oerrormaps3, token, len) == 0)))
  483.                 error_maps_bit = flag;
  484.             else if ((len >= 2) && (memcmp(ofirst, token, len) == 0))
  485.                 first_bit = flag;
  486.             else if ((len >= 2) && (memcmp(ofollow, token, len) == 0))
  487.                 follow_bit = flag;
  488.             else if (len >= 2 &&
  489.                      ((strcmp(token, "GP") == 0) ||
  490.                       (memcmp(ogenprsr, token, len) == 0) ||
  491.                       (memcmp(ogenprsr2, token, len) == 0) ||
  492.                       (memcmp(ogenprsr3, token, len) == 0)))
  493.             {
  494.                 c_bit = flag;
  495.                 cpp_bit = FALSE;
  496.                 java_bit = FALSE;
  497.             }
  498.             else if (len >= 2 &&
  499.                      ((strcmp(token, "GD") == 0) ||
  500.                       (memcmp(ogotodefault, token, len) == 0) ||
  501.                       (memcmp(ogotodefault2, token, len) == 0) ||
  502.                       (memcmp(ogotodefault3, token, len) == 0)))
  503.                 goto_default_bit = flag;
  504.             else if  ((strcmp(token, "HW") == 0) ||
  505.                       (memcmp(ohalfword, token, len) == 0) ||
  506.                       (memcmp(ohalfword2, token, len) == 0) ||
  507.                       (memcmp(ohalfword3, token, len) == 0))
  508.                 byte_bit = NOT(flag);
  509.             else if (len >= 2 && memcmp(olalr, token, len) == 0)
  510.             {
  511.                 slr_bit = NOT(flag);
  512.                 lalr_level = 1;
  513.             }
  514.             else if (len >= 2 && memcmp(olist, token, len) == 0)
  515.                 list_bit = flag;
  516.             else if  ((strcmp(token, "NC") == 0) ||
  517.                       (memcmp(ontcheck, token, len) == 0) ||
  518.                       (memcmp(ontcheck2, token, len) == 0) ||
  519.                       (memcmp(ontcheck3, token, len) == 0))
  520.                 nt_check_bit = flag;
  521.             else if ((strcmp(token, "RR") == 0) ||
  522.                      (memcmp(oreadreduce, token, len) == 0) ||
  523.                      (memcmp(oreadreduce2, token, len) == 0) ||
  524.                      (memcmp(oreadreduce3, token, len) == 0))
  525.                 read_reduce_bit = flag;
  526.             else if (len >=2 && memcmp(oscopes, token, len) == 0)
  527.                 scopes_bit = flag;
  528.             else if ((len >= 2) &&
  529.                      ((strcmp(token, "SD") == 0) ||
  530.                       (memcmp(oshiftdefault, token, len) == 0)  ||
  531.                       (memcmp(oshiftdefault2, token, len) == 0) ||
  532.                       (memcmp(oshiftdefault3, token, len) == 0)))
  533.                 shift_default_bit = flag;
  534.             else if ((len >= 2) &&
  535.                      ((strcmp(token, "SP") == 0) ||
  536.                       (memcmp(osingleproductions, token, len) == 0) ||
  537.                       (memcmp(osingleproductions2, token, len) == 0) ||
  538.                       (memcmp(osingleproductions3, token, len) == 0)))
  539.                 single_productions_bit = flag;
  540.             else if (len >= 2 && memcmp(oslr, token, len) == 0)
  541.             {
  542.                 slr_bit = flag;
  543.                 lalr_level = 1;
  544.             }
  545.             else if (len >= 2 && memcmp(ostates, token, len) == 0)
  546.                 states_bit = flag;
  547.             else if (len >= 2 && memcmp(otable, token, len) == 0)
  548.             {
  549.                 if (flag)
  550.                     table_opt = OPTIMIZE_SPACE;
  551.                 else
  552.                     table_opt = 0;
  553.             }
  554.             else if (len >= 2 && memcmp(otrace, token, len) == 0)
  555.             {
  556.                 if (flag)
  557.                     trace_opt = TRACE_CONFLICTS;
  558.                 else
  559.                     trace_opt = NOTRACE;
  560.             }
  561.             else if (memcmp(overbose, token, len) == 0)
  562.                 verbose_bit = flag;
  563.             else if (memcmp(owarnings, token, len) == 0)
  564.                 warnings_bit = flag;
  565.             else if (memcmp(oxref, token, len) == 0)
  566.                 xref_bit = flag;
  567.             else if ((strcmp(token, "D") == 0) ||
  568.                      (strcmp(token, "DE") == 0))
  569.             {
  570.                 sprintf(msg_line,
  571.                         "\"%s\" is an ambiguous option: "
  572.                         "DEBUG, DEFAULT, DEFERRED ?", temp);
  573.                 PRNTERR(msg_line);
  574.             }
  575.             else if (strcmp(token, "DEF") == 0)
  576.             {
  577.                 PRNTERR("\"DEF\" is an ambiguous option: "
  578.                         "DEFAULT, DEFERRED ?");
  579.             }
  580.             else if (strcmp(token, "E") == 0)
  581.             {
  582.                 PRNTERR("\"E\" is an ambiguous option: "
  583.                         "EDIT, ERROR-MAPS ?");
  584.             }
  585.             else if (strcmp(token, "F") == 0)
  586.             {
  587.                 PRNTERR("\"F\" is an ambiguous option: FOLLOW, FIRST ?");
  588.             }
  589.             else if (strcmp(token, "G") == 0)
  590.             {
  591.                 PRNTERR("\"G\" is an ambiguous option: "
  592.                         "GENERATE-PARSER, GOTO-DEFAULT ?");
  593.             }
  594.             else if (strcmp(token, "L") == 0)
  595.             {
  596.                 PRNTERR("\"L\" is an ambiguous option: LALR, LIST ?");
  597.             }
  598.             else if (strcmp(token, "S") == 0)
  599.             {
  600.                 PRNTERR("\"S\" is an ambiguous option:\n "
  601.                         "SCOPES, SEARCH, STATES, SLR, "
  602.                         "SHIFT-DEFAULT, SINGLE-PRODUCTIONS  ?");
  603.             }
  604.             else if (strcmp(token, "T") == 0)
  605.             {
  606.                 PRNTERR("\"T\" is an ambiguous option:  TABLE, TRACE ?");
  607.             }
  608.             else
  609.             {
  610.                 sprintf(msg_line, "\"%s\" is an invalid option", temp);
  611.                 PRNTERR(msg_line);
  612.             }
  613.         }
  614.  
  615.         /****************************************/
  616.         /* We now process the valued-parameter. */
  617.         /****************************************/
  618.         else /* value parameter. pick value after "=" and process */
  619.         {
  620.             i++;
  621.             if (IsSpace(parm[i]) || parm[i] == '\0')/* no value specified */
  622.             {
  623.                 sprintf(msg_line,
  624.                         "Null string or blank is invalid for parameter %s",
  625.                         token);
  626.                 PRNTERR(msg_line);
  627.                 continue;
  628.             }
  629.  
  630.             j = i;
  631.             while ((parm[i] != '\0')&&   /* find next delimeter */
  632.                    ((parm[i] !=  ',') &&
  633.                     (parm[i] !=  '/') &&
  634.                     (parm[i] !=  ' ')))
  635.                 i++;
  636.  
  637.             memcpy(temp, parm+j, i - j);  /* copy into TEMP */
  638.             temp[i - j] = '\0';
  639.  
  640. #if (defined(C370) || defined(CW)) && (!defined(MVS))
  641.             if ((strcmp(token, "AN") == 0) ||
  642.                  ((len >= 9) &&
  643.                   ((memcmp(token, oactfile_name, len) == 0) ||
  644.                    (memcmp(token, oactfile_name2, len) == 0) ||
  645.                    (memcmp(token, oactfile_name3, len) == 0))))
  646.             {
  647.                 memcpy(an, temp, 8);
  648.                 pn[MIN(strlen(temp), 8)] = '\0';
  649.                 strupr(an);
  650.             }
  651.             else if ((strcmp(token, "AT") == 0) ||
  652.                       ((len >= 9) &&
  653.                        ((memcmp(token, oactfile_type, len) == 0) ||
  654.                         (memcmp(token, oactfile_type2, len) == 0) ||
  655.                         (memcmp(token, oactfile_type3, len) == 0))))
  656.             {
  657.                 memcpy(at, temp, 8);
  658.                 at[MIN(strlen(temp), 8)] = '\0';
  659.                 strupr(at);
  660.             }
  661.             else if ((strcmp(token, "AM") == 0) ||
  662.                      ((len >= 9) &&
  663.                       ((memcmp(token, oactfile_mode, len) == 0) ||
  664.                        (memcmp(token, oactfile_mode2, len) == 0) ||
  665.                        (memcmp(token, oactfile_mode3, len) == 0))))
  666.             {
  667.                 memcpy(am, temp, 2);
  668.                 am[MIN(strlen(temp), 2)] = '\0';
  669.                 strupr(am);
  670.             }
  671. #else
  672.             if ((strcmp(token, "AN") == 0) ||
  673.                 (memcmp(token, oactfile_name, len) == 0) ||
  674.                 (memcmp(token, oactfile_name2, len) == 0) ||
  675.                 (memcmp(token, oactfile_name3, len) == 0))
  676.                strcpy(act_file, temp);
  677. #endif
  678.             else if (strcmp(token, oblockb) == 0)
  679.                 strcpy(blockb, temp);
  680.             else if (strcmp(token, oblocke) == 0)
  681.                 strcpy(blocke, temp);
  682.             else if (memcmp(odefault, token, len) == 0)
  683.             {
  684.                 if (verify(temp))
  685.                     default_opt = MIN(atoi(temp), 5);
  686.                 else
  687.                 {
  688.                     sprintf(msg_line,
  689.                             "\"%s\" is an invalid value for %s",
  690.                             temp, token);
  691.                     PRNTERR(msg_line);
  692.                 }
  693.             }
  694.             else if (len >= 2 && memcmp(token, oescape, len) == 0)
  695.                 escape = temp[0];
  696.             else if (((strcmp(token, "FP") == 0) ||
  697.                       (memcmp(token, ofile_prefix, len) == 0) ||
  698.                       (memcmp(token, ofile_prefix2, len) == 0) ||
  699.                       (memcmp(token, ofile_prefix3, len) == 0)))
  700.             {
  701.                 memcpy(file_prefix, temp, 5);
  702.                 file_prefix[MIN(5, strlen(temp))] = '\0';
  703.             }
  704.             else if ((strcmp(token, "GP") == 0) ||
  705.                      (memcmp(ogenprsr, token, len) == 0) ||
  706.                      (memcmp(ogenprsr2, token, len) == 0) ||
  707.                      (memcmp(ogenprsr3, token, len) == 0))
  708.             {
  709.                 BOOLEAN invalid_language = TRUE;
  710.  
  711.                 if (temp[0] == 'c' || temp[0] == 'C')
  712.                 {
  713.                     if (temp[1] == '\0')
  714.                     {
  715.                         c_bit = TRUE;
  716.                         cpp_bit = FALSE;
  717.                         java_bit = FALSE;
  718.                         invalid_language = FALSE;
  719.                     }
  720.                     else if (((temp[1] == '+' && temp[2] == '+') ||
  721.                               ((temp[1] == 'p' || temp[1] == 'P') &&
  722.                                (temp[2] == 'p' || temp[2] == 'P')))
  723.                              && temp[3] == '\0')
  724.                     {
  725.                         c_bit = FALSE;
  726.                         cpp_bit = TRUE;
  727.                         java_bit = FALSE;
  728.                         invalid_language = FALSE;
  729.                     }
  730.                 }
  731.                 else if ((len == 1 && (*temp == 'j' || *temp == 'J')) ||
  732.                          (len == 2 && strxeq(temp, "ja")) ||
  733.                          (len == 3 && strxeq(temp, "jav")) ||
  734.                          (len == 4 && strxeq(temp, "java")))
  735.                 {
  736.                     c_bit = FALSE;
  737.                     cpp_bit = FALSE;
  738.                     java_bit = TRUE;
  739.                     invalid_language = FALSE;
  740.                 }
  741.  
  742.                 if (invalid_language)
  743.                 {
  744.                     sprintf(msg_line,
  745.                             "\"%s\" is an invalid value for %s",
  746.                             temp, token);
  747.                     PRNTERR(msg_line);
  748.                 }
  749.             }
  750. #if (defined(C370) || defined(CW)) && (!defined(MVS))
  751.             else if ((strcmp(token, "HN") == 0) ||
  752.                  ((len >= 9) &&
  753.                   ((memcmp(token, ohactfile_name,  len) == 0) ||
  754.                    (memcmp(token, ohactfile_name2, len) == 0) ||
  755.                    (memcmp(token, ohactfile_name3, len) == 0))))
  756.             {
  757.                 memcpy(han, temp, 8);
  758.                 pn[MIN(strlen(temp), 8)] = '\0';
  759.                 strupr(han);
  760.             }
  761.             else if ((strcmp(token, "HT") == 0) ||
  762.                       ((len >= 9) &&
  763.                        ((memcmp(token, ohactfile_type,  len) == 0) ||
  764.                         (memcmp(token, ohactfile_type2, len) == 0) ||
  765.                         (memcmp(token, ohactfile_type3, len) == 0))))
  766.             {
  767.                 memcpy(hat, temp, 8);
  768.                 hat[MIN(strlen(temp), 8)] = '\0';
  769.                 strupr(hat);
  770.             }
  771.             else if ((strcmp(token, "HM") == 0) ||
  772.                      ((len >= 9) &&
  773.                       ((memcmp(token, ohactfile_mode,  len) == 0) ||
  774.                        (memcmp(token, ohactfile_mode2, len) == 0) ||
  775.                        (memcmp(token, ohactfile_mode3, len) == 0))))
  776.             {
  777.                 memcpy(ham, temp, 2);
  778.                 ham[MIN(strlen(temp), 2)] = '\0';
  779.                 strupr(ham);
  780.             }
  781. #else
  782.             else if ((strcmp(token, "HN") == 0) ||
  783.                  ((len >= 2) &&
  784.                   ((memcmp(token, ohactfile_name,  len) == 0) ||
  785.                    (memcmp(token, ohactfile_name2, len) == 0) ||
  786.                    (memcmp(token, ohactfile_name3, len) == 0))))
  787.                strcpy(hact_file, temp);
  788. #endif
  789.             else if (len >= 2 && strcmp(token, ohblockb) == 0)
  790.                 strcpy(hblockb, temp);
  791.             else if (len >= 2 && strcmp(token, ohblocke) == 0)
  792.                 strcpy(hblocke, temp);
  793.             else if (memcmp (olalr, token, len) == 0)
  794.             {
  795.                 len = strlen(temp);
  796.                 if (len > MAX_PARM_SIZE)
  797.                     temp[MAX_PARM_SIZE - 1] = '\0';
  798.                 if ((! verify(temp)) &&
  799.                     (memcmp(translate(temp, len), omax, len) != 0))
  800.                 {
  801.                     sprintf(msg_line,
  802.                             "\"%s\" is an invalid value for %s",
  803.                             temp, token);
  804.                     PRNTERR(msg_line);
  805.                 }
  806.                 else
  807.                 {
  808.                     slr_bit = FALSE;
  809.                     if (memcmp(omax, translate(temp, len), len) == 0)
  810.                         lalr_level = MAXIMUM_LA_LEVEL;
  811.                     else
  812.                     {
  813.                         lalr_level =  atoi(temp);
  814.                         if (lalr_level > MAXIMUM_LA_LEVEL)
  815.                         {
  816.                             sprintf(msg_line,
  817.                                     "\"%s\" exceeds maximum value "
  818.                                     "of %d allowed for %s",
  819.                                     temp, MAXIMUM_LA_LEVEL, token);
  820.                             PRNTWNG(msg_line);
  821.                             lalr_level = MAXIMUM_LA_LEVEL;
  822.                         }
  823.                     }
  824.                 }
  825.             }
  826.             else if ((len >= 2) &&
  827.                      ((memcmp(token, omaximum_distance,len) == 0) ||
  828.                       (memcmp(token, omaximum_distance2, len) == 0) ||
  829.                       (memcmp(token, omaximum_distance3, len) == 0)))
  830.             {
  831.                 if (verify(temp))
  832.                     maximum_distance =  atoi(temp);
  833.                 else
  834.                 {
  835.                     sprintf(msg_line,
  836.                             "\"%s\" is an invalid value for %s",
  837.                             temp, token);
  838.                     PRNTERR(msg_line);
  839.                 }
  840.             }
  841.             else if ((len >= 2) &&
  842.                      ((memcmp(token, ominimum_distance,len) == 0) ||
  843.                       (memcmp(token, ominimum_distance2, len) == 0) ||
  844.                       (memcmp(token, ominimum_distance3, len) == 0)))
  845.             {
  846.                 if (verify(temp))
  847.                     minimum_distance =  atoi(temp);
  848.                 else
  849.                 {
  850.                     sprintf(msg_line,
  851.                             "\"%s\" is an invalid value for %s",
  852.                             temp, token);
  853.                     PRNTERR(msg_line);
  854.                 }
  855.             }
  856.             else if ((memcmp(onames, token, len) == 0))
  857.             {
  858.                 len = strlen(temp);
  859.                 if (len >= 2 && memcmp(omax, translate(temp, len), len) == 0)
  860.                     names_opt = MAXIMUM_NAMES;
  861.                 else if (len >= 2 &&
  862.                          memcmp(omin, translate(temp, len), len) == 0)
  863.                     names_opt = MINIMUM_NAMES;
  864.                 else if (memcmp(translate(temp, len), ooptimized, len) == 0)
  865.                     names_opt = OPTIMIZE_PHRASES;
  866.                 else if ((temp[0] == 'm' || temp[0] == 'M') &&
  867.                                             temp[1] != '\0')
  868.                 {
  869.                     sprintf(msg_line,
  870.                             "\"M\" is an ambiguous value for %s: "
  871.                             "MAXIMUM, MINIMUM?", token);
  872.                     PRNTERR(msg_line);
  873.                 }
  874.                 else
  875.                 {
  876.                     sprintf(msg_line,
  877.                             "\"%s\" is an invalid value for %s",
  878.                             temp, token);
  879.                     PRNTERR(msg_line);
  880.                 }
  881.             }
  882.             else if (len >= 2 && memcmp(token, oormark, len) == 0)
  883.                 ormark = temp[0];
  884.             else if ((len >= 2) &&
  885.                      ((strcmp(token, "OS") == 0) ||
  886.                       (memcmp(token, ooutputsize, len) == 0) ||
  887.                       (memcmp(token, ooutputsize2, len) == 0) ||
  888.                       (memcmp(token, ooutputsize3, len) == 0)))
  889.             {
  890.                 if (verify(temp))
  891.                 {
  892.                     int tmpval;
  893.                     tmpval =  atoi(temp);
  894.                     if (tmpval > MAX_LINE_SIZE)
  895.                     {
  896.                         sprintf(msg_line, "OUTPUT_SIZE cannot exceed %d",
  897.                                 MAX_LINE_SIZE);
  898.                         PRNTERR(msg_line);
  899.                     }
  900.                     else
  901.                         output_size =  tmpval;
  902.                 }
  903.                 else
  904.                 {
  905.                     sprintf(msg_line,
  906.                             "\"%s\" is an invalid value for %s",
  907.                             temp, token);
  908.                     PRNTERR(msg_line);
  909.                 }
  910.             }
  911.             else if (memcmp(token, oprefix, len) == 0)
  912.                 strcpy(prefix,temp);
  913. #if defined(C370) || defined(CW)
  914.             else if ((strcmp(token, "RF") == 0) ||
  915.                      (strcmp(token, "RECFM") == 0) ||
  916.                      (memcmp(token, orecordformat, len) == 0) ||
  917.                      (memcmp(token, orecordformat2, len) == 0) ||
  918.                      (memcmp(token, orecordformat3, len) == 0))
  919.             {
  920.                 len = strlen(temp);
  921.                 if (len > MAX_PARM_SIZE)
  922.                     temp[MAX_PARM_SIZE-1] = '\0';
  923.  
  924.                 if (memcmp(ofixed, translate(temp, len), len) == 0)
  925.                     record_format = 'F';
  926.                 else if (memcmp(translate(temp, len), ovariable,len) == 0)
  927.                     record_format = 'V';
  928.                 else
  929.                 {
  930.                     sprintf(msg_line,
  931.                             "\"%s\" is an invalid value for %s",
  932.                             temp, token);
  933.                     PRNTERR(msg_line);
  934.                 }
  935.             }
  936. #endif
  937.             else if (strcmp(token, "SS") == 0 ||
  938.                      ((memcmp(token, ostack_size,len) == 0) ||
  939.                       (memcmp(token, ostack_size2, len) == 0) ||
  940.                       (memcmp(token, ostack_size3, len) == 0)))
  941.             {
  942.                 if (verify(temp))
  943.                     stack_size =  atoi(temp);
  944.                 else
  945.                 {
  946.                     sprintf(msg_line,
  947.                             "\"%s\" is an invalid value for %s",
  948.                             temp, token);
  949.                     PRNTERR(msg_line);
  950.                 }
  951.             }
  952.             else if (len >= 2 && memcmp(token, osuffix, len) == 0)
  953.                 strcpy(suffix,temp);
  954.             else if (len >= 2 && memcmp(token,otable, len) == 0)
  955.             {
  956.                 len = strlen(temp);
  957.                 if (len > MAX_PARM_SIZE)
  958.                     temp[MAX_PARM_SIZE - 1] = '\0';
  959.  
  960.                 if (memcmp(ospace, translate(temp, len), len) == 0)
  961.                     table_opt = OPTIMIZE_SPACE;
  962.                 else if (memcmp(translate(temp, len), otime, len) == 0)
  963.                     table_opt = OPTIMIZE_TIME;
  964.                 else
  965.                 {
  966.                     sprintf(msg_line,
  967.                             "\"%s\" is an invalid value for %s",
  968.                             temp, token);
  969.                     PRNTERR(msg_line);
  970.                 }
  971.             }
  972.             else if (len >= 2 && memcmp(token, otrace, len) == 0)
  973.             {
  974.                 len = strlen(temp);
  975.                 if (len > MAX_PARM_SIZE)
  976.                     temp[MAX_PARM_SIZE-1] = '\0';
  977.  
  978.                 if (memcmp(oconflicts,  translate(temp, len), len) == 0)
  979.                     trace_opt = TRACE_CONFLICTS;
  980.                 else if (memcmp(translate(temp, len), ofull, len) == 0)
  981.                     trace_opt = TRACE_FULL;
  982.                 else
  983.                 {
  984.                     sprintf(msg_line,
  985.                             "\"%s\" is an invalid value for %s",
  986.                             temp, token);
  987.                     PRNTERR(msg_line);
  988.                 }
  989.             }
  990. #if (defined(C370) || defined(CW)) && (!defined(MVS))
  991.             else if (memcmp(token, oactfile_name2, len) == 0 ||
  992.                      memcmp(token, oactfile_name3, len) == 0)
  993.             {
  994.                 sprintf(msg_line,
  995.                         "Option \"%s\" is ambiguous: "
  996.                         "ACTFILE-NAME, ACTFILE-TYPE, ACTFILE-MODE?",
  997.                         token);
  998.                 PRNTERR(msg_line);
  999.             }
  1000. #endif
  1001.             else if (strcmp(token, "BLOCK") == 0)
  1002.             {
  1003.                 PRNTERR("Option \"BLOCK\" is ambiguous: BLOCKB, BLOCKE ?");
  1004.             }
  1005.             else if (strcmp("E",token) == 0)
  1006.             {
  1007.                 PRNTERR("Option \"E\" is ambiguous: "
  1008.                         "ERROR-PROC, ERROR-MAPS ?");
  1009.             }
  1010.             else if (strcmp(token, "H") == 0)
  1011.             {
  1012.                 PRNTERR("Option \"H\" is ambiguous: HBLOCKB, HBLOCKE ?");
  1013.             }
  1014. #if (defined(C370) || defined(CW)) && (!defined(MVS))
  1015.             else if (memcmp(token, ohactfile_name2, len) == 0 ||
  1016.                      memcmp(token, ohactfile_name3, len) == 0)
  1017.             {
  1018.                 sprintf(msg_line,
  1019.                         "Option \"%s\" is ambiguous: "
  1020.                         "HACTFILE-NAME, HACTFILE-TYPE, HACTFILE-MODE?",
  1021.                         token);
  1022.                 PRNTERR(msg_line);
  1023.             }
  1024. #endif
  1025.             else if (strcmp(token, "HBLOCK") == 0)
  1026.             {
  1027.                 PRNTERR("Option \"HBLOCK\" is ambiguous: HBLOCKB, HBLOCKE ?");
  1028.             }
  1029.             else if (strcmp("M",token) == 0 || strcmp("MD",token) == 0)
  1030.             {
  1031.                 sprintf(msg_line,
  1032.                         "Option \"%s\" is ambiguous: "
  1033.                         "MAX-DISTANCE, MIN-DISTANCE?", token);
  1034.                 PRNTERR(msg_line);
  1035.             }
  1036.             else if (strcmp("O",token) == 0)
  1037.             {
  1038.                 PRNTERR("Option \"O\" is ambiguous: OUTPUT-SIZE, ORMARK ?");
  1039.             }
  1040.             else if (strcmp("T", token) == 0)
  1041.             {
  1042.                 PRNTERR("Option \"T\" is ambiguous: TABLE, TRACE?");
  1043.             }
  1044.             else
  1045.             {
  1046.                 sprintf(msg_line, "\"%s\" is an invalid option", token);
  1047.                 PRNTERR(msg_line);
  1048.             }
  1049.         }
  1050.  
  1051.         while ((parm[i] != '\0')&&          /* clean after paramter */
  1052.                 ((parm[i] == ',') ||
  1053.                  (parm[i] == '/') ||
  1054.                  (parm[i] == ' ')))
  1055.             i++;
  1056.     }
  1057.  
  1058.     return;
  1059. }
  1060.  
  1061.  
  1062. /****************************************************************************/
  1063. /*                       PROCESS_OPTIONS_LINES:                             */
  1064. /****************************************************************************/
  1065. /*    In this function, we read the first line(s) of the input text to see  */
  1066. /* if they are (it is an) "options" line(s).  If so, the options are        */
  1067. /* processed.  Then, we process user-supplied options if there are any.  In */
  1068. /* any case, the options in effect are printed.                             */
  1069. /****************************************************************************/
  1070. static void process_options_lines(void)
  1071. {
  1072.     char old_parm[MAX_LINE_SIZE + 1],
  1073.          output_line[PRINT_LINE_SIZE + 1],
  1074.          opt_string[60][OUTPUT_PARM_SIZE + 1],
  1075.          *line_end,
  1076.          temp[SYMBOL_SIZE + 1];
  1077.  
  1078.     static char ooptions[9] = " OPTIONS";
  1079.  
  1080.     int top = 0,
  1081.         i;
  1082.  
  1083.     strcpy(old_parm, parm); /* Save new options passed to program */
  1084.     ooptions[0] = escape;   /* "ooptions" always uses default escape symbol */
  1085.  
  1086.     while (p1 != '\0') /* Until end-of-file is reached, process */
  1087.     {                 /* all comment and %options lines.       */
  1088.         while(IsSpace(*p2))    /* skip all space symbols */
  1089.         {
  1090.             if (*p2 == '\n')
  1091.             {
  1092.                 line_no++;
  1093.                 linestart = p2;
  1094.                 p1 = p2 + 1;
  1095.             }
  1096.             p2++;
  1097.         }
  1098.         line_end = strchr(p2, '\n'); /* find end-of-line */
  1099.  
  1100.         /*********************************************************************/
  1101.         /* First, check if line is a comment line. If so, skip it.  Next,    */
  1102.         /* check if line is an options line. If so, process it. Otherwise,   */
  1103.         /* break out of the loop.                                            */
  1104.         /* Note that no length check is necessary before checking for "--"   */
  1105.         /* or "%options" since the buffer is always extended by              */
  1106.         /* MAX_LINE_SIZE elements past its required length. (see read_input) */
  1107.         /*********************************************************************/
  1108.         if (*p2 == '-' && *(p2 + 1) == '-')
  1109.             /* skip comment line */ ;
  1110.         else if (memcmp(ooptions, translate(p2, 8), 8) == 0)
  1111.         {
  1112.             *line_end = '\0';
  1113.             PRNT(p2);    /* Print options line */
  1114.             strcpy(parm, p2 + strlen(ooptions));
  1115.             options();   /* Process hard-coded options */
  1116.         }
  1117.         else
  1118.         {
  1119.             p2 = p1; /* make p2 point to first character */
  1120.             break;
  1121.         }
  1122.  
  1123.         /*********************************************************************/
  1124.         /* If the line was a comment or an option line, check the following  */
  1125.         /* line.  If we are at the end of the buffer, read in more data...   */
  1126.         /*********************************************************************/
  1127.         p1 = line_end + 1;
  1128.         if (bufend == input_buffer + IOBUFFER_SIZE)
  1129.         {
  1130.             i = bufend - p1;
  1131.             if (i < MAX_LINE_SIZE)
  1132.             {
  1133.                 strcpy(input_buffer, p1);
  1134.                 bufend = &input_buffer[i];
  1135.                 read_input();
  1136.                 p1 = &input_buffer[0];
  1137.             }
  1138.         }
  1139.         line_no++;
  1140.         linestart = p1 - 1;
  1141.         p2 = p1;
  1142.     }
  1143.  
  1144.     fprintf(syslis, "\n");
  1145.     strcpy(parm, old_parm);
  1146.     options();  /* Process new options passed directly to  program */
  1147.  
  1148.     if (! error_maps_bit)  /* Deferred parsing without error maps is useless*/
  1149.         deferred_bit = FALSE;
  1150.  
  1151. #if (defined(C370) || defined(CW)) && (!defined(MVS))
  1152.         strupr(file_prefix);
  1153.         if (pn[0] == '\0')
  1154.         {
  1155.             strcpy(pn,file_prefix);
  1156.             strcat(pn, "PRS");
  1157.         }
  1158.         if (sn[0] == '\0')
  1159.         {
  1160.             strcpy(sn,file_prefix);
  1161.             strcat(sn, "SYM");
  1162.         }
  1163.         if (an[0] == '\0')
  1164.         {
  1165.             strcpy(an,file_prefix);
  1166.             strcat(an, "ACT");
  1167.         }
  1168.         if (han[0] == '\0')
  1169.         {
  1170.             strcpy(han,file_prefix);
  1171.             strcat(han, "HDR");
  1172.         }
  1173.         sprintf(act_file, "%s.%s.%s", an, at, am);
  1174.         sprintf(hact_file, "%s.%s.%s", han, hat, ham);
  1175.         sprintf(sym_file, "%s.%s.%s", sn, st, sm);
  1176.         sprintf(def_file, "%sDEF.%s.%s", file_prefix, (java_bit ? "JAVA" : "H"), sm);
  1177.         sprintf(prs_file, "%s.%s.%s", pn, pt, pm);
  1178.         sprintf(dcl_file, "%sDCL.%s.%s", file_prefix, (java_bit ? "JAVA" : "H"), sm);
  1179. #else
  1180. #if defined(MVS)
  1181.         if (act_file[0] == '\0')
  1182.             sprintf(act_file, "%sACT.JAVA", file_prefix, (java_bit ? "JAVA" : "H"));
  1183.         if (hact_file[0] == '\0')
  1184.             sprintf(hact_file, "%sHDR.%s", file_prefix, (java_bit ? "JAVA" : "H"));
  1185.         sprintf(sym_file, "%sSYM.%s", file_prefix, (java_bit ? "JAVA" : "H"));
  1186.         sprintf(def_file, "%sDEF.%s", file_prefix, (java_bit ? "JAVA" : "H"));
  1187.         sprintf(prs_file, "%sPRS.%s", file_prefix, (java_bit ? "JAVA" : "H"));
  1188.         sprintf(dcl_file, "%sDCL.%S", file_prefix, (java_bit ? "JAVA" : "H"));
  1189. #else
  1190.         if (act_file[0] == '\0')
  1191.             sprintf(act_file, "%sact.%s", file_prefix, (java_bit ? "java" : "h"));
  1192.         if (hact_file[0] == '\0')
  1193.             sprintf(hact_file, "%shdr.%s", file_prefix, (java_bit ? "java" : "h"));
  1194.         sprintf(sym_file, "%ssym.%s", file_prefix, (java_bit ? "java" : "h"));
  1195.         sprintf(def_file, "%sdef.%s", file_prefix, (java_bit ? "java" : "h"));
  1196.         sprintf(prs_file, "%sprs.%s", file_prefix, (java_bit ? "java" : "h"));
  1197.         sprintf(dcl_file, "%sdcl.%s", file_prefix, (java_bit ? "java" : "h"));
  1198. #endif
  1199. #endif
  1200.  
  1201.     if (verbose_bit)   /* turn everything on */
  1202.     {
  1203.         first_bit = TRUE;
  1204.         follow_bit = TRUE;
  1205.         list_bit = TRUE;
  1206.         states_bit = TRUE;
  1207.         xref_bit = TRUE;
  1208.         warnings_bit = TRUE;
  1209.     }
  1210.  
  1211.  
  1212. /*****************************************************************************/
  1213. /*                          PRINT OPTIONS:                                   */
  1214. /*****************************************************************************/
  1215. /* Here we print all options set by the user.  As of now, only about 48      */
  1216. /* different options and related aliases are allowed.  In case that number   */
  1217. /* goes up, the bound of the array, opt_string, should be changed.           */
  1218. /* BLOCKB, BLOCKE, HBLOCKB and HBLOCKE can generate the longest strings      */
  1219. /* since their value can be up to MAX_PARM_SIZE characters long.             */
  1220. /*****************************************************************************/
  1221.     if (action_bit)
  1222.         strcpy(opt_string[++top], "ACTION");
  1223.     else
  1224.         strcpy(opt_string[++top], "NOACTION");
  1225.  
  1226. #if (defined(C370) || defined(CW)) && (!defined(MVS))
  1227.     sprintf(opt_string[++top], "ACTFILE-NAME=%s",an);
  1228.     sprintf(opt_string[++top], "ACTFILE-TYPE=%s",at);
  1229.     sprintf(opt_string[++top], "ACTFILE-MODE=%s",am);
  1230. #else
  1231.     sprintf(opt_string[++top], "ACTFILE-NAME=%s",act_file);
  1232. #endif
  1233.  
  1234.     sprintf(opt_string[++top], "BLOCKB=%s",blockb);
  1235.  
  1236.     sprintf(opt_string[++top], "BLOCKE=%s", blocke);
  1237.  
  1238.     if (byte_bit)
  1239.         strcpy(opt_string[++top], "BYTE");
  1240.  
  1241.     if (conflicts_bit)
  1242.         strcpy(opt_string[++top], "CONFLICTS");
  1243.     else
  1244.         strcpy(opt_string[++top], "NOCONFLICTS");
  1245.  
  1246.     if (default_opt == 0)
  1247.         strcpy(opt_string[++top], "NODEFAULT");
  1248.     else
  1249.         sprintf(opt_string[++top], "DEFAULT=%d",default_opt);
  1250.  
  1251.     if (debug_bit)
  1252.         strcpy(opt_string[++top], "DEBUG");
  1253.     else
  1254.         strcpy(opt_string[++top], "NODEBUG");
  1255.  
  1256.     if (deferred_bit)
  1257.         strcpy(opt_string[++top], "DEFERRED");
  1258.     else
  1259.         strcpy(opt_string[++top], "NODEFERRED");
  1260.  
  1261.     if (edit_bit)
  1262.         strcpy(opt_string[++top], "EDIT");
  1263.     else
  1264.         strcpy(opt_string[++top], "NOEDIT");
  1265.  
  1266.     if (error_maps_bit)
  1267.         strcpy(opt_string[++top], "ERROR-MAPS");
  1268.     else
  1269.         strcpy(opt_string[++top], "NOERROR-MAPS");
  1270.  
  1271.     sprintf(opt_string[++top], "ESCAPE=%c", escape);
  1272.  
  1273.     sprintf(opt_string[++top], "FILE-PREFIX=%s", file_prefix);
  1274.     if (first_bit)
  1275.         strcpy(opt_string[++top], "FIRST");
  1276.     else
  1277.         strcpy(opt_string[++top], "NOFIRST");
  1278.  
  1279.     if (follow_bit)
  1280.         strcpy(opt_string[++top], "FOLLOW");
  1281.     else
  1282.         strcpy(opt_string[++top], "NOFOLLOW");
  1283.  
  1284.     if (c_bit)
  1285.         sprintf(opt_string[++top], "GENERATE-PARSER=C");
  1286.     else if (cpp_bit)
  1287.         sprintf(opt_string[++top], "GENERATE-PARSER=C++");
  1288.     else if (java_bit)
  1289.         sprintf(opt_string[++top], "GENERATE-PARSER=JAVA");
  1290.     else
  1291.         strcpy(opt_string[++top], "NOGENERATE-PARSER");
  1292.  
  1293.     if (goto_default_bit)
  1294.         strcpy(opt_string[++top], "GOTO-DEFAULT");
  1295.     else
  1296.         strcpy(opt_string[++top], "NOGOTO-DEFAULT");
  1297.  
  1298. #if defined(C370) || defined(CW)
  1299.     sprintf(opt_string[++top], "HACTFILE-NAME=%s", han);
  1300.     sprintf(opt_string[++top], "HACTFILE-TYPE=%s", hat);
  1301.     sprintf(opt_string[++top], "HACTFILE-MODE=%s", ham);
  1302. #else
  1303.     sprintf(opt_string[++top], "HACTFILE-NAME=%s", hact_file);
  1304. #endif
  1305.  
  1306.     if (! byte_bit)
  1307.         strcpy(opt_string[++top], "HALF-WORD");
  1308.  
  1309.     sprintf(opt_string[++top], "HBLOCKB=%s", hblockb);
  1310.  
  1311.     sprintf(opt_string[++top], "HBLOCKE=%s", hblocke);
  1312.  
  1313.     if (! slr_bit)
  1314.         sprintf(opt_string[++top], "LALR=%d", lalr_level);
  1315.  
  1316.     if (list_bit)
  1317.         strcpy(opt_string[++top], "LIST");
  1318.     else
  1319.         strcpy(opt_string[++top], "NOLIST");
  1320.  
  1321.     sprintf(opt_string[++top], "MAX-DISTANCE=%d",maximum_distance);
  1322.     sprintf(opt_string[++top], "MIN-DISTANCE=%d",minimum_distance);
  1323.     if (names_opt == MAXIMUM_NAMES)
  1324.         strcpy(opt_string[++top], "NAMES=MAXIMUM");
  1325.     else if (names_opt == MINIMUM_NAMES)
  1326.         strcpy(opt_string[++top], "NAMES=MINIMUM");
  1327.     else
  1328.         strcpy(opt_string[++top], "NAMES=OPTIMIZED");
  1329.  
  1330.     if (nt_check_bit)
  1331.         strcpy(opt_string[++top], "NT-CHECK");
  1332.     else
  1333.         strcpy(opt_string[++top], "NONT-CHECK");
  1334.  
  1335.     sprintf(opt_string[++top], "ORMARK=%c", ormark);
  1336.     sprintf(opt_string[++top], "OUTPUT-SIZE=%d", output_size);
  1337.     sprintf(opt_string[++top], "PREFIX=%s",prefix);
  1338.  
  1339.     if (read_reduce_bit)
  1340.         strcpy(opt_string[++top], "READ-REDUCE");
  1341.     else
  1342.         strcpy(opt_string[++top], "NOREAD-REDUCE");
  1343.  
  1344. #if defined(C370) || defined(CW)
  1345.     if (record_format == 'F')
  1346.         strcpy(opt_string[++top], "RECORD-FORMAT=F");
  1347.     else
  1348.         strcpy(opt_string[++top], "RECORD-FORMAT=V");
  1349. #endif
  1350.  
  1351.     if (scopes_bit)
  1352.         strcpy(opt_string[++top], "SCOPES");
  1353.     else
  1354.         strcpy(opt_string[++top], "NOSCOPES");
  1355.  
  1356.     if (shift_default_bit)
  1357.         strcpy(opt_string[++top], "SHIFT-DEFAULT");
  1358.     else
  1359.         strcpy(opt_string[++top], "NOSHIFT-DEFAULT");
  1360.  
  1361.     if (single_productions_bit)
  1362.         strcpy(opt_string[++top], "SINGLE-PRODUCTIONS");
  1363.     else
  1364.         strcpy(opt_string[++top], "NOSINGLE-PRODUCTIONS");
  1365.  
  1366.     if (slr_bit)
  1367.         strcpy(opt_string[++top], "SLR");
  1368.  
  1369.     sprintf(opt_string[++top], "STACK-SIZE=%d",stack_size);
  1370.     if (states_bit)
  1371.         strcpy(opt_string[++top], "STATES");
  1372.     else
  1373.         strcpy(opt_string[++top], "NOSTATES");
  1374.  
  1375.     sprintf(opt_string[++top], "SUFFIX=%s",suffix);
  1376.  
  1377.     if (table_opt == 0)
  1378.         strcpy(opt_string[++top], "NOTABLE");
  1379.     else if (table_opt == OPTIMIZE_SPACE)
  1380.         strcpy(opt_string[++top], "TABLE=SPACE");
  1381.     else
  1382.         strcpy(opt_string[++top], "TABLE=TIME");
  1383.  
  1384.     if (trace_opt == NOTRACE)
  1385.         strcpy(opt_string[++top], "NOTRACE");
  1386.     else if (trace_opt == TRACE_CONFLICTS)
  1387.         strcpy(opt_string[++top], "TRACE=CONFLICTS");
  1388.     else
  1389.         strcpy(opt_string[++top], "TRACE=FULL");
  1390.  
  1391.     if (verbose_bit)
  1392.         strcpy(opt_string[++top], "VERBOSE");
  1393.     else
  1394.         strcpy(opt_string[++top], "NOVERBOSE");
  1395.  
  1396.     if (warnings_bit)
  1397.         strcpy(opt_string[++top], "WARNINGS");
  1398.     else
  1399.         strcpy(opt_string[++top], "NOWARNINGS");
  1400.  
  1401.     if (xref_bit)
  1402.         strcpy(opt_string[++top], "XREF");
  1403.     else
  1404.         strcpy(opt_string[++top], "NOXREF");
  1405.  
  1406.     PRNT("Options in effect:");
  1407.     strcpy(output_line, "    ");
  1408.     for (i = 1; i <= top; i++)
  1409.     {
  1410.         if (strlen(output_line) + strlen(opt_string[i]) > PRINT_LINE_SIZE-1)
  1411.         {
  1412.             PRNT(output_line);
  1413.             strcpy(output_line, "    ");
  1414.         }
  1415.         strcat(output_line, opt_string[i]);
  1416.         if (strlen(output_line) + 2 < PRINT_LINE_SIZE-1)
  1417.             strcat(output_line, "  ");
  1418.     }
  1419.     PRNT(output_line);
  1420.  
  1421.     PRNT("");
  1422.     if (warnings_bit)
  1423.     {
  1424.         if (table_opt == OPTIMIZE_SPACE)
  1425.         {
  1426.             if (default_opt < 4)
  1427.             {
  1428.                 PRNTWNG("DEFAULT_OPTion requested must be >= 4");
  1429.             }
  1430.         }
  1431.         else if (shift_default_bit)
  1432.         {
  1433.             PRNTWNG("SHIFT-DEFAULT option is only valid for Space tables")
  1434.         }
  1435.     }
  1436.  
  1437. /*********************************************************************/
  1438. /* Check if there are any conflicts in the options.                  */
  1439. /*********************************************************************/
  1440.     temp[0] = '\0';
  1441.  
  1442.     if (minimum_distance <= 1)
  1443.     {
  1444.         PRNT("MIN_DISTANCE must be > 1");
  1445.         exit(12);
  1446.     }
  1447.     if (maximum_distance <= minimum_distance + 1)
  1448.     {
  1449.         PRNT("MAX_DISTANCE must be > MIN_DISTANCE + 1");
  1450.         exit(12);
  1451.     }
  1452.     if (strcmp(blockb, blocke) == 0)
  1453.         strcpy(temp, "BLOCKB and BLOCKE");
  1454.     else if (strlen(blockb) == 1 && blockb[0] == escape)
  1455.         strcpy(temp, "BLOCKB and ESCAPE");
  1456.     else if (strlen(blockb) == 1 && blockb[0] == ormark)
  1457.         strcpy(temp, "BLOCKB and ORMARK");
  1458.     else if (strlen(blocke) == 1 && blocke[0] == escape)
  1459.         strcpy(temp, "ESCAPE and BLOCKE");
  1460.     else if (strlen(blocke) == 1 && blocke[0] == ormark)
  1461.         strcpy(temp, "ORMARK and BLOCKE");
  1462.     else if (strcmp(hblockb, hblocke) == 0)
  1463.         strcpy(temp, "HBLOCKB and HBLOCKE");
  1464.     else if (strlen(hblockb) == 1 && hblockb[0] == escape)
  1465.         strcpy(temp, "HBLOCKB and ESCAPE");
  1466.     else if (strlen(hblockb) == 1 && hblockb[0] == ormark)
  1467.         strcpy(temp, "HBLOCKB and ORMARK");
  1468.     else if (strlen(hblocke) == 1 && hblocke[0] == escape)
  1469.         strcpy(temp, "ESCAPE and HBLOCKE");
  1470.     else if (strlen(hblocke) == 1 && hblocke[0] == ormark)
  1471.         strcpy(temp, "ORMARK and HBLOCKE");
  1472.     else if (ormark == escape)
  1473.         strcpy(temp, "ORMARK and ESCAPE");
  1474.  
  1475.     if (temp[0] != '\0')
  1476.     {
  1477.         sprintf(msg_line,
  1478.                 "The options %s cannot have the same value", temp);
  1479.         PRNTERR(msg_line);
  1480.         sprintf(msg_line,
  1481.                 "Input process aborted at line %d ...", line_no);
  1482.         PRNT(msg_line);
  1483.         exit(12);
  1484.     }
  1485.  
  1486.     if (strlen(hblockb) <= strlen(blockb) &&
  1487.         memcmp(hblockb, blockb, strlen(hblockb)) == 0)
  1488.     {
  1489.         sprintf(msg_line,
  1490.                 "Hblockb value, %s, cannot be a suffix of blockb: %s",
  1491.                 hblockb, blockb);
  1492.         PRNTERR(msg_line);
  1493.         sprintf(msg_line,
  1494.                 "Input process aborted at line %d ...", line_no);
  1495.         PRNT(msg_line);
  1496.         exit(12);
  1497.     }
  1498.  
  1499.     return;
  1500. } /* end process_options_lines */
  1501.  
  1502.  
  1503. /*****************************************************************************/
  1504. /*                                 HASH:                                     */
  1505. /*****************************************************************************/
  1506. /*    HASH takes as argument a symbol and hashes it into a location in       */
  1507. /* HASH_TABLE.                                                               */
  1508. /*****************************************************************************/
  1509. static int hash(char *symb)
  1510. {
  1511.     register unsigned short k;
  1512.     register unsigned long hash_value = 0;
  1513.  
  1514.     for (; *symb != '\0'; symb++)
  1515.     {
  1516.         k = *symb;
  1517.         symb++;
  1518.         hash_value += ((k << 7) + *symb);
  1519.         if (*symb == '\0')
  1520.             break;
  1521.     }
  1522.  
  1523.     return hash_value % HT_SIZE;
  1524. }
  1525.  
  1526.  
  1527. /*****************************************************************************/
  1528. /*                           INSERT_STRING:                                  */
  1529. /*****************************************************************************/
  1530. /*   INSERT_STRING takes as an argument a pointer to a ht_elemt structure and*/
  1531. /* a character string.  It inserts the string into the string table and sets */
  1532. /* the value of node to the index into the string table.                     */
  1533. /*****************************************************************************/
  1534. static void insert_string(struct hash_type *q, char *string)
  1535. {
  1536.     if (string_offset + strlen(string) >= string_size)
  1537.     {
  1538.         string_size += STRING_BUFFER_SIZE;
  1539.         INT_CHECK(string_size);
  1540.         string_table = (char *)
  1541.             (string_table == (char *) NULL
  1542.              ? malloc(string_size * sizeof(char))
  1543.              : realloc(string_table, string_size * sizeof(char)));
  1544.         if (string_table == (char *) NULL)
  1545.             nospace(__FILE__, __LINE__);
  1546.     }
  1547.  
  1548.     q -> st_ptr = string_offset;
  1549.     while(string_table[string_offset++] = *string++); /* Copy until NULL */
  1550.                                                       /* is copied.      */
  1551.     return;
  1552. }
  1553.  
  1554.  
  1555. /*****************************************************************************/
  1556. /*                             ASSIGN_SYMBOL_NO:                             */
  1557. /*****************************************************************************/
  1558. /* PROCESS_SYMBOL takes as an argument a pointer to the most recent token    */
  1559. /* which would be either a symbol or a macro name and then processes it. If  */
  1560. /* the token is a a macro name then a check is made to see if it is a pre-   */
  1561. /* defined macro. If it is then an error message is printed and the program  */
  1562. /* is halted. If not, or if the token is a symbol then it is hashed into the */
  1563. /* hash_table and its string is copied into the string table.  A struct is   */
  1564. /* created for the token. The ST_PTR field contains the index into the string*/
  1565. /* table and the NUMBER field is set to zero. Later on if the token is a     */
  1566. /* symbol, the value of the NUMBER field is changed to the appropriate symbol*/
  1567. /* number. However, if the token is a macro name, its value will remain zero.*/
  1568. /* The NAME_INDEX field is set to OMEGA and will be assigned a value later.  */
  1569. /*****************************************************************************/
  1570. /*   ASSIGN_SYMBOL_NO takes as arguments a pointer to a node and an image    */
  1571. /* number and assigns a symbol number to the symbol pointed to by the node.  */
  1572. /*****************************************************************************/
  1573. static void assign_symbol_no(char *string_ptr, int image)
  1574. {
  1575.     register int i;
  1576.     register struct hash_type *p;
  1577.  
  1578.     i = hash(string_ptr);
  1579.     for (p = hash_table[i]; p != NULL; p = p -> link)
  1580.     {
  1581.         if (EQUAL_STRING(string_ptr, p)) /* Are they the same */
  1582.             return;
  1583.     }
  1584.  
  1585.     p = (struct hash_type *) talloc(sizeof(struct hash_type));
  1586.     if (p == (struct hash_type *) NULL)
  1587.         nospace(__FILE__, __LINE__);
  1588.  
  1589.     if (image == OMEGA)
  1590.     {
  1591.         num_symbols++;
  1592.         p -> number = num_symbols;
  1593.     }
  1594.     else
  1595.         p -> number = -image;
  1596.     p -> name_index = OMEGA;
  1597.     insert_string(p, string_ptr);
  1598.     p -> link = hash_table[i];
  1599.     hash_table[i] = p;
  1600.  
  1601.     return;
  1602. }
  1603.  
  1604.  
  1605. /*****************************************************************************/
  1606. /*                              ALIAS_MAP:                                   */
  1607. /*****************************************************************************/
  1608. /* ALIAS_MAP takes as input a symbol and an image. It searcheds the hash     */
  1609. /* table for stringptr and if it finds it, it turns it into an alias of the  */
  1610. /* symbol whose number is IMAGE. Otherwise, it invokes PROCESS_SYMBOL and    */
  1611. /* ASSIGN SYMBOL_NO to enter stringptr into the table and then we alias it.  */
  1612. /*****************************************************************************/
  1613. static void alias_map(char *stringptr, int image)
  1614. {
  1615.     register struct hash_type *q;
  1616.  
  1617.     for (q = hash_table[hash(stringptr)]; q != NULL; q = q -> link)
  1618.     {
  1619.         if (EQUAL_STRING(stringptr, q))
  1620.         {
  1621.             q -> number = -image;      /* Mark alias of image */
  1622.             return;
  1623.         }
  1624.     }
  1625.  
  1626.     assign_symbol_no(stringptr, image);
  1627.  
  1628.     return;
  1629. }
  1630.  
  1631.  
  1632. /*****************************************************************************/
  1633. /*                              SYMBOL_IMAGE:                                */
  1634. /*****************************************************************************/
  1635. /*    SYMBOL_IMAGE takes as argument a symbol.  It searches for that symbol  */
  1636. /* in the HASH_TABLE, and if found, it returns its image; otherwise, it      */
  1637. /* returns OMEGA.                                                            */
  1638. /*****************************************************************************/
  1639. static int symbol_image(char *item)
  1640. {
  1641.     register struct hash_type *q;
  1642.  
  1643.     for (q = hash_table[hash(item)]; q != NULL; q = q -> link)
  1644.     {
  1645.         if (EQUAL_STRING(item, q))
  1646.             return ABS(q -> number);
  1647.     }
  1648.  
  1649.     return(OMEGA);
  1650. }
  1651.  
  1652.  
  1653. /*****************************************************************************/
  1654. /*                                NAME_MAP:                                  */
  1655. /*****************************************************************************/
  1656. /* NAME_MAP takes as input a symbol and inserts it into the HASH_TABLE if it */
  1657. /* is not yet in the table. If it was already in the table then it is        */
  1658. /* assigned a NAME_INDEX number if it did not yet have one.  The name index  */
  1659. /* assigned is returned.                                                     */
  1660. /*****************************************************************************/
  1661. static int name_map(char *symb)
  1662. {
  1663.     register int i;
  1664.     register struct hash_type *p;
  1665.  
  1666.     i = hash(symb);
  1667.     for (p = hash_table[i]; p != NULL; p = p -> link)
  1668.     {
  1669.         if (EQUAL_STRING(symb, p))
  1670.         {
  1671.             if (p -> name_index != OMEGA)
  1672.                 return(p -> name_index);
  1673.             else
  1674.             {
  1675.                 num_names++;
  1676.                 p -> name_index = num_names;
  1677.                 return(num_names);
  1678.             }
  1679.         }
  1680.     }
  1681.  
  1682.     p = (struct hash_type *) talloc(sizeof(struct hash_type));
  1683.     if (p == (struct hash_type *) NULL)
  1684.         nospace(__FILE__, __LINE__);
  1685.     p -> number = 0;
  1686.     insert_string(p, symb);
  1687.     p -> link = hash_table[i];
  1688.     hash_table[i] = p;
  1689.  
  1690.     num_names++;
  1691.     p -> name_index = num_names;
  1692.  
  1693.     return num_names;
  1694. }
  1695.  
  1696.  
  1697. /*****************************************************************************/
  1698. /*                            PROCESS_GRAMMAR:                               */
  1699. /*****************************************************************************/
  1700. /*    PROCESS_GRAMMAR is invoked to process the source input. It uses an     */
  1701. /* LALR(1) parser table generated by LPG to recognize the grammar which it   */
  1702. /* places in the rulehdr structure.                                          */
  1703. /*****************************************************************************/
  1704. #include "lpgact.i"
  1705. #include "lpgact.h"
  1706. #include "lpgprs.h"
  1707. static void process_grammar(void)
  1708. {
  1709.     short state_stack[STACK_SIZE];
  1710.     register int act;
  1711.  
  1712.     scanner();  /* Get first token */
  1713.     act = START_STATE;
  1714.  
  1715. process_terminal:
  1716. /******************************************************************/
  1717. /* Note that this driver assumes that the tables are LPG SPACE    */
  1718. /* tables with no GOTO-DEFAULTS.                                  */
  1719. /******************************************************************/
  1720.     state_stack[++stack_top] = act;
  1721.     act = t_action(act, ct, ?);
  1722.  
  1723.     if (act <= NUM_RULES)             /* Reduce */
  1724.         stack_top--;
  1725.     else if ((act > ERROR_ACTION) || /* Shift_reduce */
  1726.              (act < ACCEPT_ACTION))  /* Shift */
  1727.     {
  1728.         token_action();
  1729.         scanner();
  1730.         if (act < ACCEPT_ACTION)
  1731.             goto process_terminal;
  1732.         act -= ERROR_ACTION;
  1733.     }
  1734.     else if (act == ACCEPT_ACTION)
  1735.     {
  1736.         accept_action();
  1737.         return;
  1738.     }
  1739.     else error_action();
  1740.  
  1741. process_non_terminal:
  1742.     do
  1743.     {
  1744.         register int lhs_sym = lhs[act]; /* to bypass IBMC12 bug */
  1745.  
  1746.         stack_top -= (rhs[act] - 1);
  1747.         rule_action[act]();
  1748.         act = nt_action(state_stack[stack_top], lhs_sym);
  1749.     }   while(act <= NUM_RULES);
  1750.  
  1751.     goto process_terminal;
  1752. }
  1753.  
  1754.  
  1755. /*****************************************************************************/
  1756. /*                                SCANNER:                                   */
  1757. /*****************************************************************************/
  1758. /* SCANNER scans the input stream and returns the next input token.          */
  1759. /*****************************************************************************/
  1760. static void scanner(void)
  1761. {
  1762.     register int i;
  1763.     register char *p3;
  1764.  
  1765.     char  tok_string[SYMBOL_SIZE + 1];
  1766.  
  1767. scan_token:
  1768.     /*****************************************************************/
  1769.     /* Skip "blank" spaces.                                          */
  1770.     /*****************************************************************/
  1771.     p1 = p2;
  1772.     while(IsSpace(*p1))
  1773.     {
  1774.         if (*(p1++) == '\n')
  1775.         {
  1776.             if (bufend == input_buffer + IOBUFFER_SIZE)
  1777.             {
  1778.                 i = bufend - p1;
  1779.                 if (i < MAX_LINE_SIZE)
  1780.                 {
  1781.                     strcpy(input_buffer, p1);
  1782.                     bufend = &input_buffer[i];
  1783.                     read_input();
  1784.                     p1 = &input_buffer[0];
  1785.                 }
  1786.             }
  1787.             line_no++;
  1788.             linestart = p1 - 1;
  1789.         }
  1790.     }
  1791.  
  1792.     if (strncmp(p1, hblockb, hblockb_len) == 0) /* check block opener */
  1793.     {
  1794.         p1 = p1 + hblockb_len;
  1795.         ct_length = 0;
  1796.         ct_ptr = p1;
  1797.         if (*p1 == '\n')
  1798.         {
  1799.             ct_ptr++;
  1800.             ct_length--;
  1801.             ct_start_line = line_no + 1;
  1802.             ct_start_col = 1;
  1803.         }
  1804.         else
  1805.         {
  1806.             ct_start_line = line_no;
  1807.             ct_start_col = p1 - linestart;
  1808.         }
  1809.  
  1810.         while(strncmp(p1, hblocke, hblocke_len) != 0)
  1811.         {
  1812.             if (*p1 == '\0')
  1813.             {
  1814.                 sprintf(msg_line,
  1815.                         "End of file encountered while "
  1816.                         "scanning header action block in rule %d",
  1817.                         num_rules);
  1818.                 PRNTERR(msg_line);
  1819.                 exit(12);
  1820.             }
  1821.             if (*(p1++) == '\n')
  1822.             {
  1823.                 if (bufend == input_buffer + IOBUFFER_SIZE)
  1824.                 {
  1825.                     i = bufend - p1;
  1826.                     if (i < MAX_LINE_SIZE)
  1827.                     {
  1828.                         strcpy(input_buffer, p1);
  1829.                         bufend = &input_buffer[i];
  1830.                         read_input();
  1831.                         p1 = &input_buffer[0];
  1832.                     }
  1833.                 }
  1834.                 line_no++;
  1835.                 linestart = p1 - 1;
  1836.             }
  1837.             ct_length++;
  1838.         }
  1839.         ct = HBLOCK_TK;
  1840.         ct_end_line = line_no;
  1841.         ct_end_col = p1 - linestart - 1;
  1842.         p2 = p1 + hblocke_len;
  1843.  
  1844.         return;
  1845.     }
  1846.     else if (strncmp(p1, blockb, blockb_len) == 0) /* check block  */
  1847.     {
  1848.         p1 = p1 + blockb_len;
  1849.         ct_length = 0;
  1850.         ct_ptr = p1;
  1851.         if (*p1 == '\n')
  1852.         {
  1853.             ct_ptr++;
  1854.             ct_length--;
  1855.             ct_start_line = line_no + 1;
  1856.             ct_start_col = 1;
  1857.         }
  1858.         else
  1859.         {
  1860.             ct_start_line = line_no;
  1861.             ct_start_col = p1 - linestart;
  1862.         }
  1863.  
  1864.         while(strncmp(p1, blocke, blocke_len) != 0)
  1865.         {
  1866.             if (*p1 == '\0')
  1867.             {
  1868.                 sprintf(msg_line,
  1869.                         "End of file encountered while "
  1870.                         "scanning action block in rule %d", num_rules);
  1871.                 PRNTERR(msg_line);
  1872.                 exit(12);
  1873.             }
  1874.             if (*(p1++) == '\n')
  1875.             {
  1876.                 if (bufend == input_buffer + IOBUFFER_SIZE)
  1877.                 {
  1878.                     i = bufend - p1;
  1879.                     if (i < MAX_LINE_SIZE)
  1880.                     {
  1881.                         strcpy(input_buffer, p1);
  1882.                         bufend = &input_buffer[i];
  1883.                         read_input();
  1884.                         p1 = &input_buffer[0];
  1885.                     }
  1886.                 }
  1887.                 line_no++;
  1888.                 linestart = p1 - 1;
  1889.             }
  1890.             ct_length++;
  1891.         }
  1892.         ct = BLOCK_TK;
  1893.         ct_end_line = line_no;
  1894.         ct_end_col = p1 - linestart - 1;
  1895.         p2 = p1 + blocke_len;
  1896.  
  1897.         return;
  1898.     }
  1899.  
  1900. /*********************************************************************/
  1901. /* Scan the next token.                                              */
  1902. /*********************************************************************/
  1903.     ct_ptr = p1;
  1904.     ct_start_line = line_no;
  1905.     ct_start_col = p1 - linestart;
  1906.  
  1907.     p2 = p1 + 1;
  1908.     switch(*p1)
  1909.     {
  1910.         case '<':
  1911.             if (IsAlpha(*p2))
  1912.             {
  1913.                 p2++;
  1914.                 while(*p2 != '\n')
  1915.                 {
  1916.                     if (*(p2++) == '>')
  1917.                     {
  1918.                         ct = SYMBOL_TK;
  1919.                         ct_length = p2 - p1;
  1920.                         goto check_symbol_length;
  1921.                     }
  1922.                 }
  1923.                 i = min(SYMBOL_SIZE, p2 - p1);
  1924.                 memcpy(tok_string, p1, i);
  1925.                 tok_string[i] = '\0';
  1926.                 sprintf(msg_line,
  1927.                         "Symbol \"%s\""
  1928.                         " has been referenced in line %d "
  1929.                         " without the closing \">\"",
  1930.                         tok_string, ct_start_line);
  1931.                 PRNTERR(msg_line);
  1932.                 exit(12);
  1933.             }
  1934.             break;
  1935.  
  1936.         case '\'':
  1937.             ct_ptr = p2;
  1938.             ct = SYMBOL_TK;
  1939.             while(*p2 != '\n')
  1940.             {
  1941.                 if (*p2 == '\'')
  1942.                 {
  1943.                     p2++;
  1944.                     if (*p2 != '\'')
  1945.                     {
  1946.                         ct_length = p2 - p1 - 2;
  1947.                         goto remove_quotes;
  1948.                     }
  1949.                 }
  1950.                 p2++;
  1951.             }
  1952.             ct_length = p2 - p1 - 1;
  1953.             if (warnings_bit)
  1954.             {
  1955.                 memcpy(tok_string, p1, ct_length);
  1956.                 tok_string[ct_length] = '\0';
  1957.                 sprintf(msg_line,
  1958.                         "Symbol \"%s\" referenced in line %d"
  1959.                         " requires a closing quote",
  1960.                         tok_string, ct_start_line);
  1961.                 PRNTWNG(msg_line);
  1962.             }
  1963.  
  1964. remove_quotes:
  1965.             if (ct_length == 0)  /* Empty symbol? disregard it */
  1966.                 goto scan_token;
  1967.  
  1968.             i = 0;
  1969.             p1 = ct_ptr;
  1970.             do
  1971.             {
  1972.                 *(p1++) = ct_ptr[i++];
  1973.                 if (ct_ptr[i] == '\'')
  1974.                     i++;                       /* skip next quote */
  1975.             }   while(i < ct_length);
  1976.             ct_length = p1 - ct_ptr;
  1977.  
  1978.             goto check_symbol_length;
  1979.  
  1980.         case '-':                      /* scan possible comment  */
  1981.             if (*p2 == '-')
  1982.             {
  1983.                 p2++;
  1984.                 while(*p2 != '\n')
  1985.                     p2++;
  1986.                 goto scan_token;
  1987.             }
  1988.             else if (*p2 == '>' && IsSpace(*(p2+1)))
  1989.             {
  1990.                 ct = ARROW_TK;
  1991.                 ct_length = 2;
  1992.                 p2++;
  1993.                 return;
  1994.             }
  1995.             break;
  1996.  
  1997.         case ':':
  1998.             if (*p2 == ':' && *(p2+1) == '=' && IsSpace(*(p2+2)))
  1999.             {
  2000.                 ct = EQUIVALENCE_TK;
  2001.                 ct_length = 3;
  2002.                 p2 = p1 + 3;
  2003.                 return;
  2004.             }
  2005.             break;
  2006.  
  2007.         case '\0': case CTL_Z:                 /* END-OF-FILE? */
  2008.             ct = EOF_TK;
  2009.             ct_length = 0;
  2010.             p2 = p1;
  2011.  
  2012.             return;
  2013.  
  2014.         default:
  2015.             if (*p1 == ormark && IsSpace(*p2))
  2016.             {
  2017.                 ct = OR_TK;
  2018.                 ct_length = 1;
  2019.                 return;
  2020.             }
  2021.             else if (*p1 == escape)       /* escape character? */
  2022.             {
  2023.                 p3 = p2 + 1;
  2024.                 switch(*p2)
  2025.                 {
  2026.                     case 't': case 'T':
  2027.                         if (strxeq(p3, "erminals") && IsSpace(*(p1+10)))
  2028.                         {
  2029.                             ct = TERMINALS_KEY_TK;
  2030.                             ct_length = 10;
  2031.                             p2 = p1 + 10;
  2032.                             return;
  2033.                         }
  2034.                         break;
  2035.  
  2036.                     case 'd': case 'D':
  2037.                         if (strxeq(p3, "efine") && IsSpace(*(p1+7)))
  2038.                         {
  2039.                             ct = DEFINE_KEY_TK;
  2040.                             ct_length = 7;
  2041.                             p2 = p1 + 7;
  2042.                             return;
  2043.                         }
  2044.                         break;
  2045.  
  2046.                     case 'e': case 'E':
  2047.                         if (strxeq(p3, "mpty") && IsSpace(*(p1+6)))
  2048.                         {
  2049.                             ct = EMPTY_SYMBOL_TK;
  2050.                             ct_length = 6;
  2051.                             p2 = p1 + 6;
  2052.                             return;
  2053.                         }
  2054.                         if (strxeq(p3, "rror") && IsSpace(*(p1+6)))
  2055.                         {
  2056.                             ct = ERROR_SYMBOL_TK;
  2057.                             ct_length = 6;
  2058.                             p2 = p1 + 6;
  2059.                             return;
  2060.                         }
  2061.                         if (strxeq(p3, "ol") && IsSpace(*(p1+4)))
  2062.                         {
  2063.                             ct = EOL_SYMBOL_TK;
  2064.                             ct_length = 4;
  2065.                             p2 = p1 + 4;
  2066.                             return;
  2067.                         }
  2068.                         if (strxeq(p3, "of") && IsSpace(*(p1+4)))
  2069.                         {
  2070.                             ct = EOF_SYMBOL_TK;
  2071.                             ct_length = 4;
  2072.                             p2 = p1 + 4;
  2073.                             return;
  2074.                         }
  2075.                         if (strxeq(p3, "nd") && IsSpace(*(p1+4)))
  2076.                         {
  2077.                             ct = END_KEY_TK;
  2078.                             ct_length = 4;
  2079.                             p2 = p1 + 4;
  2080.                             return;
  2081.                         }
  2082.                         break;
  2083.  
  2084.                     case 'r': case 'R':
  2085.                         if (strxeq(p3, "ules") && IsSpace(*(p1+6)))
  2086.                         {
  2087.                             ct = RULES_KEY_TK;
  2088.                             ct_length = 6;
  2089.                             p2 = p1 + 6;
  2090.                             return;
  2091.                         }
  2092.                         break;
  2093.  
  2094.                     case 'a': case 'A':
  2095.                         if (strxeq(p3, "lias") && IsSpace(*(p1+6)))
  2096.                         {
  2097.                             ct = ALIAS_KEY_TK;
  2098.                             ct_length = 6;
  2099.                             p2 = p1 + 6;
  2100.                             return;
  2101.                         }
  2102.                         break;
  2103.  
  2104.                     case 's': case 'S':
  2105.                         if (strxeq(p3, "tart") && IsSpace(*(p1+6)))
  2106.                         {
  2107.                             ct = START_KEY_TK;
  2108.                             ct_length = 6;
  2109.                             p2 = p1 + 6;
  2110.                             return;
  2111.                         }
  2112.                         break;
  2113.  
  2114.                     case 'n': case 'N':
  2115.                         if (strxeq(p3, "ames") && IsSpace(*(p1+6)))
  2116.                         {
  2117.                             ct = NAMES_KEY_TK;
  2118.                             ct_length = 6;
  2119.                             p2 = p1 + 6;
  2120.                             return;
  2121.                         }
  2122.                         break;
  2123.  
  2124.                     default:
  2125.                         break;
  2126.                 }
  2127.  
  2128.                 ct = MACRO_NAME_TK;
  2129.                 while(! IsSpace(*p2))
  2130.                     p2++;
  2131.                 ct_length = p2 - p1;
  2132.                 goto check_symbol_length;
  2133.             }
  2134.     }
  2135.  
  2136.     ct = SYMBOL_TK;
  2137.     while(! IsSpace(*p2))
  2138.         p2++;
  2139.     ct_length = p2 - p1;
  2140.  
  2141. check_symbol_length:
  2142.     if (ct_length > SYMBOL_SIZE)
  2143.     {
  2144.         ct_length = SYMBOL_SIZE;
  2145.         memcpy(tok_string, p1, ct_length);
  2146.         tok_string[ct_length] = '\0';
  2147.         if (warnings_bit)
  2148.         {
  2149.             if (symbol_image(tok_string) == OMEGA)
  2150.             {
  2151.                 sprintf(msg_line,
  2152.                         "Length of Symbol \"%s\""
  2153.                         " in line %d exceeds maximum of ",
  2154.                         tok_string,  line_no);
  2155.                 PRNTWNG(msg_line);
  2156.             }
  2157.         }
  2158.     }
  2159.  
  2160.     return;
  2161.  
  2162. }
  2163.  
  2164.  
  2165. /****************************************************************************/
  2166. /*                             TOKEN_ACTION:                                */
  2167. /****************************************************************************/
  2168. /*    This function, TOKEN_ACTION, pushes the current token onto the        */
  2169. /* parse stack called TERMINAL. Note that in case of a BLOCK_, the name of  */
  2170. /* the token is not copied since blocks are processed separately on a       */
  2171. /* second pass.                                                             */
  2172. /****************************************************************************/
  2173. static void token_action(void)
  2174. {
  2175.     register int top = stack_top + 1;
  2176.  
  2177.     terminal[top].kind         = ct;
  2178.     terminal[top].start_line   = ct_start_line;
  2179.     terminal[top].start_column = ct_start_col;
  2180.     terminal[top].end_line     = ct_end_line;
  2181.     terminal[top].end_column   = ct_end_col;
  2182.     terminal[top].length       = ct_length;
  2183.  
  2184.     if (ct != BLOCK_TK)
  2185.     {
  2186.         memcpy(terminal[top].name, ct_ptr, ct_length);
  2187.         terminal[top].name[ct_length] = '\0';
  2188.     }
  2189.     else terminal[top].name[0] = '\0';
  2190.  
  2191.     return;
  2192. }
  2193.  
  2194. /****************************************************************************/
  2195. /*                              ERROR_ACTION:                               */
  2196. /****************************************************************************/
  2197. /*  Error messages to be printed if an error is encountered during parsing. */
  2198. /****************************************************************************/
  2199. static void error_action(void)
  2200. {
  2201.     char tok_string[SYMBOL_SIZE + 1];
  2202.  
  2203.     ct_ptr[ct_length] = '\0';
  2204.  
  2205.     if (ct == EOF_TK)
  2206.         sprintf(msg_line, "End-of file reached prematurely");
  2207.     else if (ct == MACRO_NAME_TK)
  2208.     {
  2209.         sprintf(msg_line,
  2210.                 "Misplaced macro name \"%s\" found "
  2211.                 "in line %d, column %d",
  2212.                 ct_ptr, line_no, ct_start_col);
  2213.     }
  2214.     else if (ct == SYMBOL_TK)
  2215.     {
  2216.         restore_symbol(tok_string, ct_ptr);
  2217.         sprintf(msg_line,
  2218.                 "Misplaced symbol \"%s\" found "
  2219.                 "in line %d, column %d",
  2220.                 tok_string, line_no, ct_start_col);
  2221.     }
  2222.     else
  2223.     {
  2224.         sprintf(msg_line,
  2225.                 "Misplaced keyword \"%s\" found "
  2226.                 "in line %d, column %d",
  2227.                 ct_ptr, line_no, ct_start_col);
  2228.     }
  2229.  
  2230.     PRNTERR(msg_line);
  2231.  
  2232.     exit(12);
  2233. }
  2234.  
  2235.  
  2236. /****************************************************************************/
  2237. /*                            ACCEPT_ACTION:                                */
  2238. /****************************************************************************/
  2239. /*          Actions to be taken if grammar is successfully parsed.          */
  2240. /****************************************************************************/
  2241. static void accept_action(void)
  2242. {
  2243.     if (rulehdr == NULL)
  2244.     {
  2245.         printf("Informative: Empty grammar read in. "
  2246.                "Processing stopped.\n");
  2247.         fprintf(syslis, "***Informative: Empty grammar read in. "
  2248.                         "Processing stopped.\n");
  2249.         fclose(sysgrm);
  2250.         fclose(syslis);
  2251.         exit(12);
  2252.     }
  2253.  
  2254.     num_non_terminals = num_symbols - num_terminals;
  2255.  
  2256.     if (error_maps_bit)
  2257.         make_names_map();
  2258.  
  2259.     if (list_bit)
  2260.         process_aliases();
  2261.  
  2262.     make_rules_map();      /* Construct rule table      */
  2263.  
  2264.     fclose(sysgrm);        /* Close grammar input file. */
  2265.  
  2266.     if (action_bit)
  2267.         process_actions();
  2268.     else if (list_bit)
  2269.         display_input();
  2270.  
  2271.     return;
  2272. }
  2273.  
  2274.  
  2275. /*****************************************************************************/
  2276. /*                             BUILD_SYMNO:                                  */
  2277. /*****************************************************************************/
  2278. /* BUILD_SYMNO constructs the SYMNO table which is a mapping from each       */
  2279. /* symbol number into that symbol.                                           */
  2280. /*****************************************************************************/
  2281. static void build_symno(void)
  2282. {
  2283.     register int i,
  2284.                  symbol;
  2285.  
  2286.     register struct hash_type *p;
  2287.  
  2288.     symno_size = num_symbols + 1;
  2289.     symno = (struct symno_type *)
  2290.             calloc(symno_size, sizeof(struct symno_type));
  2291.     if (symno == (struct symno_type *) NULL)
  2292.         nospace(__FILE__, __LINE__);
  2293.  
  2294.     /***********************************************************************/
  2295.     /* Go thru entire hash table. For each non_empty bucket, go through    */
  2296.     /* linked list in that bucket.                                         */
  2297.     /***********************************************************************/
  2298.     for (i = 0; i < HT_SIZE; ++i)
  2299.     {
  2300.         for (p = hash_table[i]; p != NULL; p = p -> link)
  2301.         {
  2302.             symbol = p -> number;
  2303.             if (symbol >= 0) /* Not an alias */
  2304.             {
  2305.                 symno[symbol].name_index = OMEGA;
  2306.                 symno[symbol].ptr = p -> st_ptr;
  2307.             }
  2308.         }
  2309.     }
  2310.  
  2311.     return;
  2312. }
  2313.  
  2314.  
  2315. /****************************************************************************/
  2316. /*                              PROCESS_ACTIONS:                            */
  2317. /****************************************************************************/
  2318. /*     Process all semantic actions and generate action file.               */
  2319. /****************************************************************************/
  2320. static void process_actions(void)
  2321. {
  2322.     register int i,
  2323.                  j,
  2324.                  k,
  2325.                  len;
  2326.     register char *p;
  2327.  
  2328.     char  line[MAX_LINE_SIZE + 1];
  2329.  
  2330. #if defined(C370) && !defined(CW)
  2331.     sprintf(msg_line, "w, recfm=%cB, lrecl=%d",
  2332.                       record_format, output_size);
  2333.     if (record_format != 'F')
  2334.         output_size -= 4;
  2335.     sysact  = fopen(act_file,  msg_line);
  2336.     syshact = fopen(hact_file, msg_line);
  2337. #else
  2338.     sysact  = fopen(act_file,  "w");
  2339.     syshact = fopen(hact_file, "w");
  2340. #endif
  2341.  
  2342.     if (sysact == (FILE *) NULL)
  2343.     {
  2344.         fprintf(stderr,
  2345.                 "***ERROR: Action file \"%s\" cannot be opened.\n",
  2346.                 act_file);
  2347.         exit(12);
  2348.     }
  2349.  
  2350.     if (syshact == (FILE *) NULL)
  2351.     {
  2352.         fprintf(stderr,
  2353.                 "***ERROR: Header Action file "
  2354.                 "\"%s\" cannot be opened.\n", hact_file);
  2355.         exit(12);
  2356.     }
  2357.  
  2358.     if ((sysgrm = fopen(grm_file, "r")) == (FILE *) NULL)
  2359.     {
  2360.         fprintf(stderr,
  2361.                 "***ERROR: Input file %s containing grammar "
  2362.                 "is empty, undefined, or invalid\n",grm_file);
  2363.         exit(12);
  2364.     }
  2365.  
  2366.     macro_table = Allocate_short_array(HT_SIZE);
  2367.     for (i = 0; i < HT_SIZE; i++)
  2368.         macro_table[i] = NIL;
  2369.  
  2370.     bufend = &input_buffer[0];
  2371.     read_input();
  2372.  
  2373.     p2 = &input_buffer[0];
  2374.     linestart = p2 - 1;
  2375.     p1 = p2;
  2376.     line_no = 1;
  2377.  
  2378. /***********************************************************************/
  2379. /* Read in all the macro definitions and insert them into macro_table. */
  2380. /***********************************************************************/
  2381.     for (i = 0; i < num_defs; i++)
  2382.     {
  2383.         defelmt[i].macro = (char *)
  2384.                            calloc(defelmt[i].length + 2, sizeof(char));
  2385.         if (defelmt[i].macro == (char *) NULL)
  2386.             nospace(__FILE__, __LINE__);
  2387.  
  2388.         for (; line_no < defelmt[i].start_line; line_no++)
  2389.         {
  2390.             while (*p1 != '\n')
  2391.                 p1++;
  2392.             p1++;
  2393.             if (bufend == input_buffer + IOBUFFER_SIZE)
  2394.             {
  2395.                 k = bufend - p1;
  2396.                 if (k < MAX_LINE_SIZE)
  2397.                 {
  2398.                     strcpy(input_buffer, p1);
  2399.                     bufend = &input_buffer[k];
  2400.                     read_input();
  2401.                     p1 = &input_buffer[0];
  2402.                 }
  2403.             }
  2404.             linestart = p1 - 1;
  2405.         }
  2406.  
  2407.         p1 = linestart + defelmt[i].start_column;
  2408.  
  2409.         for (j = 0; j < defelmt[i].length; j++)
  2410.         {
  2411.             defelmt[i].macro[j] = *p1;
  2412.             if (*(p1++) == '\n')
  2413.             {
  2414.                 if (bufend == input_buffer + IOBUFFER_SIZE)
  2415.                 {
  2416.                     k = bufend - p1;
  2417.                     if (k < MAX_LINE_SIZE)
  2418.                     {
  2419.                         strcpy(input_buffer, p1);
  2420.                         bufend = &input_buffer[k];
  2421.                         read_input();
  2422.                         p1 = &input_buffer[0];
  2423.                     }
  2424.                 }
  2425.                 line_no++;
  2426.                 linestart = p1 - 1;
  2427.             }
  2428.         }
  2429.         defelmt[i].macro[defelmt[i].length] = '\n';
  2430.         defelmt[i].macro[defelmt[i].length + 1] = '\0';
  2431.  
  2432.         for (p = defelmt[i].name; *p != '\0'; p++)
  2433.         {
  2434.             *p = (isupper(*p) ? tolower(*p) : *p);
  2435.         }
  2436.  
  2437.         mapmacro(i);
  2438.     }
  2439.  
  2440. /****************************************************************************/
  2441. /* If LISTING was requested, invoke listing procedure.                      */
  2442. /****************************************************************************/
  2443.     if (list_bit)
  2444.         display_input();
  2445.  
  2446. /****************************************************************************/
  2447. /* Read in all the action blocks and process them.                          */
  2448. /****************************************************************************/
  2449.     for (i = 0; i < num_acts; i++)
  2450.     {
  2451.         for (; line_no < actelmt[i].start_line; line_no++)
  2452.         {
  2453.             while (*p1 != '\n')
  2454.                 p1++;
  2455.             p1++;
  2456.             if (bufend == input_buffer + IOBUFFER_SIZE)
  2457.             {
  2458.                 k = bufend - p1;
  2459.                 if (k < MAX_LINE_SIZE)
  2460.                 {
  2461.                     strcpy(input_buffer, p1);
  2462.                     bufend = &input_buffer[k];
  2463.                     read_input();
  2464.                     p1 = &input_buffer[0];
  2465.                 }
  2466.             }
  2467.             linestart = p1 - 1;
  2468.         }
  2469.  
  2470.         if (actelmt[i].start_line == actelmt[i].end_line)
  2471.         {
  2472.             len = actelmt[i].end_column -
  2473.                   actelmt[i].start_column + 1;
  2474.             memcpy(line, linestart + actelmt[i].start_column, len);
  2475.             line[len] = '\0';
  2476.  
  2477.             while (*p1 != '\n')
  2478.                 p1++;
  2479.         }
  2480.         else
  2481.         {
  2482.             p = line;
  2483.             p1 = linestart + actelmt[i].start_column;
  2484.             while (*p1 != '\n')
  2485.                 *(p++) = *(p1++);
  2486.             *p = '\0';
  2487.         }
  2488.  
  2489.         if (actelmt[i].header_block)
  2490.              process_action_line(syshact, line, line_no,
  2491.                                  actelmt[i].rule_number);
  2492.         else process_action_line(sysact, line, line_no,
  2493.                                  actelmt[i].rule_number);
  2494.  
  2495.         if (line_no != actelmt[i].end_line)
  2496.         {
  2497.             while (line_no < actelmt[i].end_line)
  2498.             {
  2499.                 p1++;
  2500.                 if (bufend == input_buffer + IOBUFFER_SIZE)
  2501.                 {
  2502.                     k = bufend - p1;
  2503.                     if (k < MAX_LINE_SIZE)
  2504.                     {
  2505.                         strcpy(input_buffer, p1);
  2506.                         bufend = &input_buffer[k];
  2507.                         read_input();
  2508.                         p1 = &input_buffer[0];
  2509.                     }
  2510.                 }
  2511.                 line_no++;
  2512.                 linestart = p1 - 1;
  2513.  
  2514.                 if (line_no < actelmt[i].end_line)
  2515.                 {
  2516.                     p = line;
  2517.                     while (*p1 != '\n')
  2518.                         *(p++) = *(p1++);
  2519.                     *p = '\0';
  2520.  
  2521.                     if (actelmt[i].header_block)
  2522.                          process_action_line(syshact, line, line_no,
  2523.                                              actelmt[i].rule_number);
  2524.                     else process_action_line(sysact, line, line_no,
  2525.                                              actelmt[i].rule_number);
  2526.                 }
  2527.             }
  2528.  
  2529.             if (actelmt[i].end_column != 0)
  2530.             {
  2531.                 len = actelmt[i].end_column;
  2532.                 memcpy(line, p1, len);
  2533.                 line[len] = '\0';
  2534.  
  2535.                 if (actelmt[i].header_block)
  2536.                      process_action_line(syshact, line, line_no,
  2537.                                          actelmt[i].rule_number);
  2538.                 else process_action_line(sysact, line, line_no,
  2539.                                          actelmt[i].rule_number);
  2540.             }
  2541.         }
  2542.     }
  2543.  
  2544.     for (i = 0; i < num_defs; i++)
  2545.     {
  2546.         ffree(defelmt[i].macro);
  2547.     }
  2548.  
  2549.     ffree(defelmt);
  2550.     ffree(actelmt);
  2551.     fclose(sysgrm);  /* Close grammar file and reopen it. */
  2552.     fclose(sysact);
  2553.     fclose(syshact);
  2554.  
  2555.     return;
  2556. }
  2557.  
  2558.  
  2559.  
  2560. /************************************************************************/
  2561. /*                          MAKE_NAMES_MAP:                             */
  2562. /************************************************************************/
  2563. /*  Construct the NAME map, and update the elements of SYMNO with their */
  2564. /* names.                                                               */
  2565. /************************************************************************/
  2566. static void make_names_map(void)
  2567. {
  2568.     register int i,
  2569.                  symbol;
  2570.  
  2571.     register struct hash_type *p;
  2572.  
  2573.     symno[accept_image].name_index = name_map("");
  2574.  
  2575.     if (error_image == DEFAULT_SYMBOL)
  2576.         symno[DEFAULT_SYMBOL].name_index = symno[accept_image].name_index;
  2577.  
  2578.     for ALL_TERMINALS(symbol)
  2579.     {
  2580.         if (symno[symbol].name_index == OMEGA)
  2581.             symno[symbol].name_index = name_map(RETRIEVE_STRING(symbol));
  2582.     }
  2583.  
  2584.     for ALL_NON_TERMINALS(symbol)
  2585.     {
  2586.         if (symno[symbol].name_index == OMEGA)
  2587.         {
  2588.             if (names_opt == MAXIMUM_NAMES)
  2589.                 symno[symbol].name_index = name_map(RETRIEVE_STRING(symbol));
  2590.             else if (names_opt == OPTIMIZE_PHRASES)
  2591.                 symno[symbol].name_index = - name_map(RETRIEVE_STRING(symbol));
  2592.             else
  2593.                 symno[symbol].name_index = symno[error_image].name_index;
  2594.         }
  2595.     }
  2596.  
  2597.     /************************/
  2598.     /* Allocate NAME table. */
  2599.     /************************/
  2600.     name = (int *) calloc(num_names + 1, sizeof(int));
  2601.     if (name == (int *) NULL)
  2602.         nospace(__FILE__, __LINE__);
  2603.  
  2604.     for (i = 0; i < HT_SIZE; i++)
  2605.     {
  2606.         for (p = hash_table[i]; p != NULL; p = p -> link)
  2607.         {
  2608.             if (p -> name_index != OMEGA)
  2609.                 name[p -> name_index] = p -> st_ptr;
  2610.         }
  2611.     }
  2612.  
  2613.     return;
  2614. }
  2615.  
  2616.  
  2617.  
  2618. /*****************************************************************************/
  2619. /*                             MAKE_RULES_MAP:                               */
  2620. /*****************************************************************************/
  2621. /*   Construct the rule table.  At this stage, NUM_ITEMS is equal to the sum */
  2622. /* of the right-hand side lists of symbols.  It is used in the declaration of*/
  2623. /* RULE_TAB.  After RULE_TAB is allocated, we increase NUM_ITEMS to its      */
  2624. /* correct value.  Recall that the first rule is numbered 0; therefore we    */
  2625. /* increase the number of items by 1 to reflect this numbering.              */
  2626. /*****************************************************************************/
  2627. static void make_rules_map(void)
  2628. {
  2629.     register struct node *ptr, *q;
  2630.  
  2631.     char temp[SYMBOL_SIZE + 1];
  2632.  
  2633.     register int i = 0,
  2634.                  rhs_ct = 0;
  2635.  
  2636.     rules = (struct ruletab_type *)
  2637.             calloc(num_rules + 2, sizeof(struct ruletab_type));
  2638.     if (rules == (struct ruletab_type *) NULL)
  2639.         nospace(__FILE__, __LINE__);
  2640.  
  2641.     rhs_sym = Allocate_short_array(num_items + 1);
  2642.  
  2643.     num_items += (num_rules + 1);
  2644.     SHORT_CHECK(num_items);
  2645.  
  2646. /*****************************************************************************/
  2647. /* Put starting rules from start symbol linked list in rule and rhs table    */
  2648. /*****************************************************************************/
  2649.     if (start_symbol_root != NULL)
  2650.     {
  2651.         /* Turn circular list into linear */
  2652.         q = start_symbol_root;
  2653.         start_symbol_root = q -> next;
  2654.         q -> next = NULL;
  2655.  
  2656.         for (ptr = start_symbol_root; ptr != NULL; ptr = ptr -> next)
  2657.         {
  2658.             rules[i].lhs = accept_image;
  2659.             rules[i].sp = 0;
  2660.             rules[i++].rhs = rhs_ct;
  2661.             if (ptr -> value != empty)
  2662.                 rhs_sym[rhs_ct++] = ptr -> value;
  2663.         }
  2664.  
  2665.         free_nodes(start_symbol_root, q);
  2666.     }
  2667.  
  2668. /*****************************************************************************/
  2669. /*   In this loop, the grammar is placed in the rule table structure and the */
  2670. /* right-hand sides are placed in the RHS table.  A check is made to prevent */
  2671. /* terminals from being used as left hand sides.                             */
  2672. /*****************************************************************************/
  2673.     for (i = i; i <= num_rules; i++)
  2674.     {
  2675.         rules[i].rhs = rhs_ct;
  2676.         ptr = rulehdr[i].rhs_root;
  2677.         if (ptr != NULL) /* not am empty right-hand side? */
  2678.         {
  2679.             do
  2680.             {
  2681.                 ptr = ptr -> next;
  2682.                 rhs_sym[rhs_ct++] = ptr -> value;
  2683.             }  while (ptr != rulehdr[i].rhs_root);
  2684.             ptr = ptr -> next;                /* point to 1st element */
  2685.             rules[i].sp = (rulehdr[i].sp && ptr == rulehdr[i].rhs_root);
  2686.             if (rules[i].sp)
  2687.                 num_single_productions++;
  2688.             free_nodes(ptr, rulehdr[i].rhs_root);
  2689.         }
  2690.         else
  2691.             rules[i].sp = FALSE;
  2692.  
  2693.         if (rulehdr[i].lhs == OMEGA)
  2694.         {
  2695.             if (list_bit) /* Proper LHS will be updated after printing */
  2696.                 rules[i].lhs = OMEGA;
  2697.             else rules[i].lhs = rules[i - 1].lhs;
  2698.         }
  2699.         else if (rulehdr[i].lhs IS_A_TERMINAL)
  2700.         {
  2701.             restore_symbol(temp, RETRIEVE_STRING(rulehdr[i].lhs));
  2702.             sprintf(msg_line,
  2703.                     "In rule %d: terminal \"%s\" used as left hand side",
  2704.                     i, temp);
  2705.             PRNTERR(msg_line);
  2706.             PRNTERR("Processing terminated due to input errors.");
  2707.             exit(12);
  2708.         }
  2709.         else rules[i].lhs = rulehdr[i].lhs;
  2710.     }
  2711.  
  2712.     rules[num_rules + 1].rhs = rhs_ct; /* Fence !! */
  2713.  
  2714.     return;
  2715. }
  2716.  
  2717.  
  2718. /****************************************************************************/
  2719. /*                             ALLOC_LINE:                                  */
  2720. /****************************************************************************/
  2721. /*  This function allocates a line_elemt structure and returns a pointer    */
  2722. /* to it.                                                                   */
  2723. /****************************************************************************/
  2724. static struct line_elemt *alloc_line(void)
  2725. {
  2726.     register struct line_elemt *p;
  2727.  
  2728.     p = line_pool_root;
  2729.     if (p != NULL)
  2730.         line_pool_root = p -> link;
  2731.     else
  2732.     {
  2733.         p = (struct line_elemt *) talloc(sizeof(struct line_elemt));
  2734.         if (p == (struct line_elemt *) NULL)
  2735.             nospace(__FILE__, __LINE__);
  2736.     }
  2737.  
  2738.     return(p);
  2739. }
  2740.  
  2741.  
  2742. /****************************************************************************/
  2743. /*                              FREE_LINE:                                  */
  2744. /****************************************************************************/
  2745. /*  This function frees a line_elemt structure which is returned to a free  */
  2746. /* pool.                                                                    */
  2747. /****************************************************************************/
  2748. static void free_line(struct line_elemt *p)
  2749. {
  2750.     p -> link = line_pool_root;
  2751.     line_pool_root = p;
  2752.  
  2753.     return;
  2754. }
  2755.  
  2756.  
  2757. /*****************************************************************************/
  2758. /*                            PROCESS_ACTION_LINE:                           */
  2759. /*****************************************************************************/
  2760. /* PROCESS_ACTION_LINE takes as arguments a line of text from an action      */
  2761. /* block and the rule number with which thwe block is associated.            */
  2762. /* It first scans the text for predefined macro names and then for           */
  2763. /* user defined macro names. If one is found, the macro definition is sub-   */
  2764. /* stituted for the name. The modified action text is then printed out in    */
  2765. /* the action file.                                                          */
  2766. /*****************************************************************************/
  2767. static void process_action_line(FILE *sysout, char *text,
  2768.                                 int line_no, int rule_no)
  2769. {
  2770.     register int j,
  2771.                  k,
  2772.                  text_len;
  2773.  
  2774.     char temp1[MAX_LINE_SIZE + 1];
  2775.     char temp2[MAX_LINE_SIZE + 1];
  2776.     char suffix[MAX_LINE_SIZE + 1];
  2777.     char symbol[SYMBOL_SIZE + 1];
  2778.  
  2779.     struct line_elemt *q;
  2780.     struct line_elemt *root = NULL;
  2781.     struct line_elemt *input_line_root = NULL;
  2782.  
  2783. next_line:
  2784.    text_len = strlen(text);
  2785.    k = 0; /* k is the cursor */
  2786.    while (k < text_len)
  2787.    {
  2788.        if (text[k] == escape) /* all macro names begin with the ESCAPE */
  2789.        {                      /* character                             */
  2790.            if (k + 12 <= text_len) /* 12 is length of %rule_number and */
  2791.                                    /* %num_symbols.                    */
  2792.            {
  2793.                if (strxeq(text + k, krule_number))
  2794.                {
  2795.                    strcpy(temp1, text + k + 12);
  2796.                    if (k + 12 != text_len)
  2797.                        sprintf(text + k, "%d%s", rule_no, temp1);
  2798.                    else
  2799.                        sprintf(text + k, "%d", rule_no);
  2800.                    goto proceed;
  2801.                }
  2802.  
  2803.                if (strxeq(text + k, knum_symbols))
  2804.                {
  2805.                    strcpy(temp1, text + k + 12);
  2806.                    if (k + 12 != text_len)
  2807.                        sprintf(text + k, "%d%s", num_symbols, temp1);
  2808.                    else
  2809.                        sprintf(text + k, "%d", num_symbols);
  2810.                    goto proceed;
  2811.                }
  2812.            }
  2813.  
  2814.            if (k + 11 <= text_len) /* 11 is the length of %input_file    */
  2815.            {
  2816.                if (strxeq(text + k, kinput_file))
  2817.                {
  2818.                    strcpy(temp1, text + k + 11);
  2819.                    if (k + 11 != text_len)
  2820.                        sprintf(text + k, "%s%s", grm_file, temp1);
  2821.                    else
  2822.                        sprintf(text + k, "%s", grm_file);
  2823.                    goto proceed;
  2824.                }
  2825.            }
  2826.  
  2827.            if (k + 10 <= text_len) /* 10 is the length of %rule_size and */
  2828.                                 /* %rule_text, %num_rules and %next_line */
  2829.            {
  2830.                if (strxeq(text + k, krule_text))
  2831.                {
  2832.                    register int max_len;
  2833.  
  2834.                    if (k + 10 != text_len)
  2835.                    {
  2836.                        strcpy(temp1, text + k + 10);
  2837.  
  2838.                        /* Remove trailing blanks */
  2839.                        for (j = strlen(temp1) - 1;
  2840.                             j >= 0 && temp1[j] == ' '; j--);
  2841.  
  2842.                        if (j != 0)  /* if not a string of blanks */
  2843.                            temp1[++j] = '\0';
  2844.                        else
  2845.                            temp1[0] = '\0';
  2846.                    }
  2847.                    else
  2848.                    {
  2849.                        temp1[0] = '\0';
  2850.                        j = 0;
  2851.                    }
  2852.                    max_len = output_size - k - j;
  2853.  
  2854.                    restore_symbol(temp2,
  2855.                                   RETRIEVE_STRING(rules[rule_no].lhs));
  2856.                    if (rules[rule_no].sp) /* if a single production */
  2857.                        strcat(temp2, " ->");
  2858.                    else
  2859.                        strcat(temp2, " ::=");
  2860.  
  2861.                    if (strlen(temp2) > max_len)
  2862.                        strcpy(temp2, " ... ");
  2863.                    else /* Copy right-hand-side symbols to temp2 */
  2864.                    {
  2865.                        for ENTIRE_RHS(j, rule_no)
  2866.                        {
  2867.                            restore_symbol(symbol, RETRIEVE_STRING(rhs_sym[j]));
  2868.                            if (strlen(temp2) + strlen(symbol) + 1 < max_len)
  2869.                            {
  2870.                                strcat(temp2, BLANK);
  2871.                                strcat(temp2, symbol);
  2872.                            }
  2873.                            else
  2874.                            {
  2875.                                 if (strlen(temp2) + 3 < max_len)
  2876.                                     strcat(temp2, "...");
  2877.                                 break;
  2878.                            }
  2879.                        }
  2880.                    }
  2881.                    text[k] = '\0';
  2882.                    strcat(text, temp2);
  2883.                    strcat(text, temp1);
  2884.                    k = k - 1 + strlen(temp2); /* Adjust cursor */
  2885.                    goto proceed;
  2886.                }
  2887.  
  2888.                if (strxeq(text + k, krule_size))
  2889.                {
  2890.                    strcpy(temp1, text + k + 10);
  2891.                    if (k + 10 != text_len)
  2892.                        sprintf(text + k, "%d%s", RHS_SIZE(rule_no), temp1);
  2893.                    else
  2894.                        sprintf(text + k, "%d", RHS_SIZE(rule_no));
  2895.                    goto proceed;
  2896.                }
  2897.  
  2898.                if (strxeq(text + k, knext_line))
  2899.                {
  2900.                    strcpy(temp1, text + k + 10);
  2901.                    if (k + 10 != text_len)
  2902.                        sprintf(text + k, "%d%s", line_no + 1, temp1);
  2903.                    else
  2904.                        sprintf(text + k, "%d", line_no + 1);
  2905.                    goto proceed;
  2906.                }
  2907.  
  2908.                if (strxeq(text + k, knum_rules))
  2909.                {
  2910.                    strcpy(temp1, text + k + 10);
  2911.                    if (k + 10 != text_len)
  2912.                        sprintf(text + k, "%d%s", num_rules, temp1);
  2913.                    else
  2914.                        sprintf(text + k, "%d", num_rules);
  2915.                    goto proceed;
  2916.                }
  2917.            }
  2918.  
  2919.            if (k + 13 <= text_len) /* 13 is length of %current_line  */
  2920.            {
  2921.                if (strxeq(text + k, kcurrent_line))
  2922.                {
  2923.                    strcpy(temp1, text + k + 13);
  2924.                    if (k + 13 != text_len)
  2925.                        sprintf(text + k, "%d%s", line_no, temp1);
  2926.                    else
  2927.                        sprintf(text + k, "%d", line_no);
  2928.                    goto proceed;
  2929.                }
  2930.            }
  2931.  
  2932.            if (k + 14 <= text_len) /* 14 is length of %num_terminals */
  2933.            {
  2934.                if (strxeq(text + k, knum_terminals))
  2935.                {
  2936.                    strcpy(temp1, text + k + 14);
  2937.                    if (k + 14 != text_len)
  2938.                        sprintf(text + k, "%d%s", num_terminals, temp1);
  2939.                    else
  2940.                        sprintf(text + k, "%d", num_terminals);
  2941.                    goto proceed;
  2942.                }
  2943.            }
  2944.  
  2945.            if (k + 18 <= text_len) /* 18 is length of %num_non_terminals */
  2946.            {
  2947.                if (strxeq(text + k, knum_non_terminals))
  2948.                {
  2949.                    strcpy(temp1, text + k + 18);
  2950.                    if (k + 18 != text_len)
  2951.                        sprintf(text + k, "%d%s", num_non_terminals, temp1);
  2952.                    else
  2953.                        sprintf(text + k, "%d", num_non_terminals);
  2954.                    goto proceed;
  2955.                }
  2956.            }
  2957.  
  2958. /*****************************************************************************/
  2959. /* Macro in question is not one of the predefined macros. Try user-defined   */
  2960. /* macro list.                                                               */
  2961. /*****************************************************************************/
  2962.            /* find next delimeter */
  2963.            for (j = k + 1; j < text_len && !IsSpace(text[j]); ++j)
  2964.                ;
  2965.  
  2966.            memcpy(symbol, text + k, j - k); /* copy macro name into symbol */
  2967.            symbol[j - k] = '\0';
  2968.  
  2969.            if (j < text_len) /* Is there any text after macro ? */
  2970.                strcpy(suffix, text + j); /* Copy rest of text into "suffix". */
  2971.            else
  2972.                suffix[0] = '\0';
  2973.            text[k] = '\0';  /* prefix before macro */
  2974.  
  2975.            root = find_macro(symbol); /* "root" points to a circular  */
  2976.                                       /* linked list of line_elemt(s) */
  2977.                                       /* containing macro definition. */
  2978.  
  2979.            if (root != NULL)  /* if macro name was found */
  2980.            {
  2981.                struct line_elemt *tail;
  2982.  
  2983.                q = root;
  2984.                root = root -> link;
  2985.                if (suffix[0] != '\0')
  2986.                {
  2987.                    /**********************************************/
  2988.                    /* If there is room to add the suffix to the  */
  2989.                    /* last macro line then do it. Or else        */
  2990.                    /* allocate a new line_elemt, copy the suffix */
  2991.                    /* into it and add it to the list of lines to */
  2992.                    /* be processed.                              */
  2993.                    /**********************************************/
  2994.                    if (strlen(q -> line) + strlen(suffix) < output_size)
  2995.                    {
  2996.                        strcat(q -> line, suffix);
  2997.                        tail = q;
  2998.                    }
  2999.                    else
  3000.                    {
  3001.                        tail = alloc_line();
  3002.                        strcpy(tail -> line, suffix);
  3003.                        q -> link = tail;
  3004.                    }
  3005.                }
  3006.                else
  3007.                    tail = q;
  3008.                tail -> link = NULL; /* make circular list linear */
  3009.  
  3010.                /****************************************************/
  3011.                /* If there is space for the first macro line to be */
  3012.                /* added to the prefix then do it.                  */
  3013.                /****************************************************/
  3014.                if (strlen(text) + strlen(root -> line) < output_size)
  3015.                {
  3016.                    strcat(text, root -> line);
  3017.                    q = root;
  3018.                    root = root -> link;
  3019.                    free_line(q);
  3020.                }
  3021.  
  3022.                /*********************************************/
  3023.                /* if there are more macro lines to process, */
  3024.                /* add list to list headed by INPUT_LINE_ROOT*/
  3025.                /*********************************************/
  3026.                if (root != NULL)
  3027.                {
  3028.                    tail -> link = input_line_root;
  3029.                    input_line_root = root;
  3030.                }
  3031.                k--;
  3032.            }
  3033.            else /* If macro name is not found then rebuild line.*/
  3034.            {
  3035.                strcat(text, symbol);
  3036.                if (suffix[0] != '\0')
  3037.                    strcat(text, suffix);
  3038.                k = j;
  3039.            }
  3040.  
  3041. proceed:
  3042.            text_len = strlen(text);
  3043.        }
  3044.        ++k;
  3045.    }
  3046.  
  3047. /*****************************************************************************/
  3048. /* If text is greater than output size, print error message and truncate     */
  3049. /* line.                                                                     */
  3050. /*****************************************************************************/
  3051.    if (strlen(text) > output_size)
  3052.    {
  3053.        for (j = strlen(text) - 1; j >= output_size; j--)
  3054.        {
  3055.            if (text[j] != ' ')
  3056.            {
  3057.                sprintf(msg_line,
  3058.                        "Size of output line \"%s\""
  3059.                        " is greater than OUTPUT_SIZE", text);
  3060.                PRNTERR(msg_line);
  3061.                break;
  3062.            }
  3063.        }
  3064.        text[output_size] = '\0';
  3065.    }
  3066.  
  3067.    fprintf(sysout, "%s\n", text);
  3068.  
  3069.    /* If there is another macro line copy it to TEXT and then process it. */
  3070.    if (input_line_root != NULL)
  3071.    {
  3072.        strcpy(text, input_line_root -> line);
  3073.        q = input_line_root;
  3074.        input_line_root = input_line_root -> link;
  3075.  
  3076.        free_line(q);
  3077.  
  3078.        goto next_line;
  3079.    }
  3080.    return;
  3081. }
  3082.  
  3083.  
  3084. /****************************************************************************/
  3085. /*                                MAPMACRO:                                 */
  3086. /****************************************************************************/
  3087. /* This procedure takes as argument a macro definition.  If the name of the */
  3088. /* macro is one of the predefined names, it issues an error.  Otherwise, it */
  3089. /* inserts the macro definition into the table headed by MACRO_TABLE.       */
  3090. /****************************************************************************/
  3091. static void mapmacro(int def_index)
  3092. {
  3093.     register int i,
  3094.                  j;
  3095.  
  3096.     if (strcmp(defelmt[def_index].name, krule_text)         == 0 ||
  3097.         strcmp(defelmt[def_index].name, krule_number)       == 0 ||
  3098.         strcmp(defelmt[def_index].name, knum_rules)         == 0 ||
  3099.         strcmp(defelmt[def_index].name, krule_size)         == 0 ||
  3100.         strcmp(defelmt[def_index].name, knum_terminals)     == 0 ||
  3101.         strcmp(defelmt[def_index].name, knum_non_terminals) == 0 ||
  3102.         strcmp(defelmt[def_index].name, knum_symbols)       == 0 ||
  3103.         strcmp(defelmt[def_index].name, kinput_file)        == 0 ||
  3104.         strcmp(defelmt[def_index].name, kcurrent_line)      == 0 ||
  3105.         strcmp(defelmt[def_index].name, knext_line)         == 0)
  3106.     {
  3107.         sprintf(msg_line, "predefined macro \"%s\""
  3108.                           " cannot be redefined. Line %d",
  3109.                           defelmt[def_index].name,
  3110.                           defelmt[def_index].start_line);
  3111.         PRNTWNG(msg_line);
  3112.         return;
  3113.     }
  3114.  
  3115.     i = hash(defelmt[def_index].name);
  3116.     for (j = macro_table[i]; j != NIL; j = defelmt[j].next)
  3117.     {
  3118.         if (strcmp(defelmt[j].name, defelmt[def_index].name) == 0)
  3119.         {
  3120.             if (warnings_bit)
  3121.             {
  3122.                 sprintf(msg_line, "Redefinition of macro \"%s\""
  3123.                                   " in line %d",
  3124.                                   defelmt[def_index].name,
  3125.                                   defelmt[def_index].start_line);
  3126.                 PRNTWNG(msg_line);
  3127.                 break;
  3128.             }
  3129.         }
  3130.     }
  3131.  
  3132.     defelmt[def_index].next = macro_table[i];
  3133.     macro_table[i] = def_index;
  3134.  
  3135.     return;
  3136. }
  3137.  
  3138.  
  3139. /*****************************************************************************/
  3140. /*                                FIND_MACRO:                                */
  3141. /*****************************************************************************/
  3142. /* FIND_MACRO takes as argument a pointer to a macro name. It searches for   */
  3143. /* the macro name in the hash table based on MACRO_TABLE. If the macro name  */
  3144. /* is found then the macro definition associated with it is returned.        */
  3145. /* If the name is not found, then a message is printed, a new definition is  */
  3146. /* entered so as to avoid more messages and NULL is returned.                */
  3147. /*****************************************************************************/
  3148. static struct line_elemt *find_macro(char *name)
  3149. {
  3150.     register int i,
  3151.                  j;
  3152.     register char *ptr,
  3153.                   *s;
  3154.  
  3155.     register struct line_elemt *q,
  3156.                                *root = NULL;
  3157.     char macro_name[MAX_LINE_SIZE + 1];
  3158.  
  3159.     s = macro_name;
  3160.     for (ptr = name; *ptr != '\0'; ptr++)
  3161.     {
  3162.         *(s++) = (isupper(*ptr) ? tolower(*ptr) : *ptr);
  3163.     }
  3164.     *s = '\0';
  3165.  
  3166.     i = hash(macro_name);
  3167.     for (j = macro_table[i]; j != NIL; j = defelmt[j].next)
  3168.     {
  3169.         if (strcmp(macro_name, defelmt[j].name) == 0)
  3170.         {
  3171.             ptr = defelmt[j].macro;
  3172.  
  3173.             if (ptr) /* undefined macro? */
  3174.             {
  3175.                 while(*ptr != '\0')
  3176.                 {
  3177.                     q = alloc_line();
  3178.                     s = q -> line;
  3179.                     while(*ptr != '\n')
  3180.                         *(s++) = *(ptr++);
  3181.                     *s = '\0';
  3182.                     ptr++; /* skip newline marker */
  3183.  
  3184.                     if (root == NULL)
  3185.                         q -> link = q; /* make circular */
  3186.                     else
  3187.                     {
  3188.                         q -> link = root -> link;
  3189.                         root -> link = q;
  3190.                     }
  3191.                     root = q;
  3192.                 }
  3193.             }
  3194.  
  3195.             return root;
  3196.         }
  3197.     }
  3198.  
  3199.     /**********************************************************/
  3200.     /* Make phony definition for macro so as to avoid future  */
  3201.     /* errors.                                                */
  3202.     /**********************************************************/
  3203.     if (num_defs >= (int)defelmt_size)
  3204.     {
  3205.         defelmt_size += DEFELMT_INCREMENT;
  3206.         defelmt = (struct defelmt_type *)
  3207.             (defelmt == (struct defelmt_type *) NULL
  3208.              ? malloc(defelmt_size * sizeof(struct defelmt_type))
  3209.              : realloc(defelmt, defelmt_size*sizeof(struct defelmt_type)));
  3210.         if (defelmt == (struct defelmt_type *) NULL)
  3211.             nospace(__FILE__, __LINE__);
  3212.     }
  3213.  
  3214.     strcpy(defelmt[num_defs].name, macro_name);
  3215.     defelmt[num_defs].length = 0;
  3216.     defelmt[num_defs].macro = NULL;
  3217.  
  3218.     defelmt[num_defs].next = macro_table[i];
  3219.     macro_table[i] = num_defs;
  3220.     num_defs++;
  3221.  
  3222.     return NULL;
  3223. }
  3224.  
  3225.  
  3226.  
  3227. /*************************************************************************/
  3228. /*                            PROCESS_ALIASES:                           */
  3229. /*************************************************************************/
  3230. /* Aliases are placed in a separate linked list.  NOTE!! After execution */
  3231. /* of this loop the hash_table is destroyed because the LINK field of    */
  3232. /* alias symbols is used to construct a list of the alias symbols.       */
  3233. /*************************************************************************/
  3234. static void process_aliases(void)
  3235. {
  3236.     register int i;
  3237.     register struct hash_type *p,
  3238.                               *tail;
  3239.  
  3240.     for (i = 0; i < HT_SIZE; i++)
  3241.     {
  3242.         tail = hash_table[i];
  3243.         for (p = tail; p != NULL; p = tail)
  3244.         {
  3245.             tail = p -> link;
  3246.  
  3247.             if (p -> number < 0)
  3248.             {
  3249.                 p -> link = alias_root;
  3250.                 alias_root = p;
  3251.             }
  3252.         }
  3253.     }
  3254.  
  3255.     return;
  3256. }
  3257.  
  3258.  
  3259. /*****************************************************************************/
  3260. /*                             DISPLAY_INPUT:                                */
  3261. /*****************************************************************************/
  3262. /*   If a listing is requested, this prints all the macros(if any), followed */
  3263. /* by the aliases(if any), followed by the terminal symbols, followed by the */
  3264. /* rules.                                                                    */
  3265. /*   This grammar information is printed on lines no longer than             */
  3266. /* PRINT_LINE_SIZE characters long.  If all the symbols in a rule cannot fit */
  3267. /* on one line, it is continued on a subsequent line beginning at the        */
  3268. /* position after the equivalence symbol (::= or ->) or the middle of the    */
  3269. /* print_line, whichever is smaller.  If a symbol cannot fit on a line       */
  3270. /* beginning at the proper offset, it is laid out on successive lines,       */
  3271. /* beginning at the proper offset.                                           */
  3272. /*****************************************************************************/
  3273. static void display_input(void)
  3274. {
  3275.     register int j,
  3276.                  len,
  3277.                  offset,
  3278.                  symb,
  3279.                  rule_no;
  3280.     char line[PRINT_LINE_SIZE + 1],
  3281.          temp[SYMBOL_SIZE + 1];
  3282.  
  3283.     /******************************************/
  3284.     /* Print the Macro definitions, if any.   */
  3285.     /******************************************/
  3286.     if (num_defs > 0)
  3287.     {
  3288.         PR_HEADING;
  3289.         fprintf(syslis, "\nDefined Symbols:\n\n");
  3290.         output_line_no += 3;
  3291.         for (j = 0; j < num_defs; j++)
  3292.         {
  3293.             char *ptr;
  3294.  
  3295.             fill_in(line, (PRINT_LINE_SIZE - (strlen(blockb)+1)), '-');
  3296.             fprintf(syslis, "\n\n%s\n%s%s\n",
  3297.                             defelmt[j].name, blockb, line);
  3298.  
  3299.             output_line_no += 4;
  3300.  
  3301.             for (ptr = defelmt[j].macro; *ptr != '\0'; ptr++)
  3302.             {
  3303.                 for (; *ptr != '\n'; ptr++)
  3304.                 {
  3305.                     putc(*ptr, syslis);
  3306.                 }
  3307.                 putc(*ptr, syslis);
  3308.                 ENDPAGE_CHECK;
  3309.             }
  3310.  
  3311.             fill_in(line, (PRINT_LINE_SIZE - (strlen(blocke) + 1)), '-');
  3312.             fprintf(syslis, "%s%s\n", blocke, line);
  3313.             ENDPAGE_CHECK;
  3314.         }
  3315.     }
  3316.  
  3317.  
  3318.     /**********************************/
  3319.     /*   Print the Aliases, if any.   */
  3320.     /**********************************/
  3321.     if (alias_root != NULL)
  3322.     {
  3323.         struct hash_type *p;
  3324.  
  3325.         PR_HEADING;
  3326.         if (alias_root -> link == NULL)
  3327.         {
  3328.             fprintf(syslis, "\nAlias:\n\n");
  3329.             output_line_no += 3;
  3330.         }
  3331.         else
  3332.         {
  3333.             fprintf(syslis, "\nAliases:\n\n");
  3334.             output_line_no += 3;
  3335.         }
  3336.  
  3337.         for (p = alias_root; p != NULL; p = p -> link)
  3338.         {
  3339.             restore_symbol(temp, EXTRACT_STRING(p -> st_ptr));
  3340.  
  3341.             len = PRINT_LINE_SIZE - 5;
  3342.             print_large_token(line, temp, "", len);
  3343.             strcat(line, " ::= ");
  3344.             symb = -(p -> number);
  3345.             restore_symbol(temp, RETRIEVE_STRING(symb));
  3346.  
  3347.             if (strlen(line) + strlen(temp) > PRINT_LINE_SIZE)
  3348.             {
  3349.                 fprintf(syslis, "%s\n", line);
  3350.                 ENDPAGE_CHECK;
  3351.                 len = PRINT_LINE_SIZE - 4;
  3352.                 print_large_token(line, temp, "    ", len);
  3353.             }
  3354.             else
  3355.                 strcat(line, temp);
  3356.             fprintf(syslis, "%s\n", line);
  3357.             ENDPAGE_CHECK;
  3358.         }
  3359.     }
  3360.  
  3361.  /***************************************************************************/
  3362.  /*   Print the terminals.                                                  */
  3363.  /*   The first symbol (#1) represents the empty string.  The last terminal */
  3364.  /* declared by the user is followed by EOFT which may be followed by the   */
  3365.  /* ERROR symbol.  See LPG GRAMMAR for more details.                        */
  3366.  /***************************************************************************/
  3367.     PR_HEADING;
  3368.     fprintf(syslis, "\nTerminals:\n\n");
  3369.     output_line_no += 3;
  3370.     strcpy(line, "        ");  /* 8 spaces */
  3371.     len = PRINT_LINE_SIZE - 4;
  3372.  
  3373.     for (symb = 2; symb <= num_terminals; symb++)
  3374.     {
  3375.         restore_symbol(temp, RETRIEVE_STRING(symb));
  3376.  
  3377.         if (strlen(line) + strlen(temp) > PRINT_LINE_SIZE)
  3378.         {
  3379.             fprintf(syslis, "\n%s", line);
  3380.             ENDPAGE_CHECK;
  3381.             print_large_token(line, temp, "    ", len);
  3382.         }
  3383.         else
  3384.             strcat(line, temp);
  3385.         strcat(line, BLANK);
  3386.     }
  3387.     fprintf(syslis, "\n%s", line);
  3388.     ENDPAGE_CHECK;
  3389.  
  3390.     /**************************/
  3391.     /*    Print the Rules     */
  3392.     /**************************/
  3393.     PR_HEADING;
  3394.     fprintf(syslis, "\nRules:\n\n");
  3395.     output_line_no += 3;
  3396.     for (rule_no = 0; rule_no <= num_rules; rule_no++)
  3397.     {
  3398.         register int i;
  3399.  
  3400.         symb = rules[rule_no].lhs;
  3401.         sprintf(line, "%-4d  ", rule_no);
  3402.         if (symb != OMEGA)
  3403.         {
  3404.             restore_symbol(temp, RETRIEVE_STRING(symb));
  3405.             if (strlen(temp) > PRINT_LINE_SIZE - 12)
  3406.             {
  3407.                 strncat(line, temp, PRINT_LINE_SIZE - 12);
  3408.                 fprintf(syslis, "\n%s", line);
  3409.                 ENDPAGE_CHECK;
  3410.                 strcpy(temp, temp + (PRINT_LINE_SIZE - 12));
  3411.                 i = PRINT_LINE_SIZE - 12;
  3412.                 print_large_token(line, temp, "       ", i);
  3413.             }
  3414.             else
  3415.                 strcat(line, temp);
  3416.  
  3417.             if (rules[rule_no].sp)
  3418.                 strcat(line, " -> ");
  3419.             else
  3420.                 strcat(line, " ::= ");
  3421.  
  3422.             i = (PRINT_LINE_SIZE / 2) + 1;
  3423.             offset = MIN(strlen(line) - 1, i);
  3424.             len = PRINT_LINE_SIZE - offset - 1;
  3425.         }
  3426.         else
  3427.         {
  3428.             symb = rules[rule_no - 1].lhs;
  3429.             rules[rule_no].lhs = symb; /* update rules map */
  3430.             if (rules[rule_no].sp)
  3431.             {
  3432.                 restore_symbol(temp, RETRIEVE_STRING(symb));
  3433.                 if (strlen(temp) > PRINT_LINE_SIZE - 12)
  3434.                 {
  3435.                     strncat(line, temp, PRINT_LINE_SIZE - 12);
  3436.                     fprintf(syslis, "\n%s", line);
  3437.                     ENDPAGE_CHECK;
  3438.                     strcpy(temp, temp + (PRINT_LINE_SIZE - 12));
  3439.                     i = PRINT_LINE_SIZE - 12;
  3440.                     print_large_token(line, temp, "       ", i);
  3441.                 }
  3442.                 else
  3443.                     strcat(line, temp);
  3444.                 strcat(line, "  -> ");
  3445.             }
  3446.             else
  3447.             {
  3448.                 for (i = 1; i <= offset - 7; i++)
  3449.                     strcat(line, BLANK);
  3450.                 strcat(line, "| ");
  3451.             }
  3452.         }
  3453.  
  3454.         for ENTIRE_RHS(i, rule_no)
  3455.         {
  3456.             restore_symbol(temp, RETRIEVE_STRING(rhs_sym[i]));
  3457.             if (strlen(temp) + strlen(line) > PRINT_LINE_SIZE - 1)
  3458.             {
  3459.                 char tempbuffer1[SYMBOL_SIZE + 1];
  3460.  
  3461.                 fprintf(syslis, "\n%s", line);
  3462.                 ENDPAGE_CHECK;
  3463.                 strcpy(tempbuffer1, BLANK);
  3464.                 for (j = 1; j < offset + 1; j++)
  3465.                      strcat(tempbuffer1, BLANK);
  3466.                 print_large_token(line, temp, tempbuffer1, len);
  3467.             }
  3468.             else
  3469.                 strcat(line, temp);
  3470.             strcat(line, BLANK);
  3471.         }
  3472.         fprintf(syslis, "\n%s", line);
  3473.         ENDPAGE_CHECK;
  3474.     }
  3475.  
  3476.     return;
  3477. }
  3478.