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

  1. /* $Id: main.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 <string.h>
  13. #include "common.h"
  14. #include "header.h"
  15.  
  16. static void print_opts(void);
  17. void process_input(void);
  18. void mkfirst(void);
  19. void mkstats(void);
  20. void mkrdcts(void);
  21. void ptstats(void);
  22. void process_tables(void);
  23.  
  24. /*********************************************************************/
  25. /* Jikes PG is a parser generator capable of generating LALR(k) and  */
  26. /* SLR(1) tables.  It is organized as a main routine: MAIN, which    */
  27. /* invokes five other major subroutines which are:                   */
  28. /*                                                                   */
  29. /*    1) PROCESS_INPUT     - inputs and structures the grammar.      */
  30. /*    2) MKFIRST           - builds basic maps such as FIRST,        */
  31. /*                           FOLLOW, CLOSURE, CLITEMS, ITEM_TABLE,   */
  32. /*                           ADEQUATE_ITEMS.                         */
  33. /*    3) MKSTATS           - constructs the LR(0) automaton.         */
  34. /*    4) MKRDCTS           - constructs reduction map.               */
  35. /*    5) One of the following three procedures:                      */
  36. /*       a) CMPRSPA        - Space Table generation                  */
  37. /*       b) CMPRTIM        - Time Table generation                   */
  38. /*       c) BASETAB        - Write out Base Table                    */
  39. /*                                                                   */
  40. /*   The following files are used:                                   */
  41. /*                                                                   */
  42. /*    1) SYSGRM           - Input file containing grammar            */
  43. /*    2) SYSLIS           - Output file used for listings, statistics*/
  44. /*                          and diagnostics.                         */
  45. /*    3) SYSACT           - Output file used for semantic actions.   */
  46. /*    4) SYSTAB           - Output file used for Parsing tables.     */
  47. /*                                                                   */
  48. /*********************************************************************/
  49.  
  50. /****************************************************************************/
  51. /****************************************************************************/
  52. /*                          MAIN PROGRAM  MAIN:                             */
  53. /****************************************************************************/
  54. /****************************************************************************/
  55. int main(int argc, char *argv[])
  56. {
  57.     int i,
  58.         op_start,
  59.         j = 0;
  60.  
  61.     char *dot,
  62.          *slash,
  63.          tmpbuf[20];
  64.  
  65. /*********************************************************************/
  66. /* If only "jikespg" or "jikespg ?*" is typed, we display the help   */
  67. /* screen.                                                           */
  68. /*                                                                   */
  69. /* NOTE that because of some bug (feature?) in AIX, when two or more */
  70. /* consecutive "?" is passed as argument to a program, the behaviour */
  71. /* of the system becomes unpredictable. 1/4/94                       */
  72. /* You may test this by invoking the "echo" program with "???".      */
  73. /*********************************************************************/
  74.     if (argc == 1 || argv[1][0] == '?')
  75.     {
  76.         print_opts();
  77.         return 4;
  78.     }
  79.  
  80. /**********************************************************************/
  81. /*     If options are passed to the program, copy them into "parm".   */
  82. /**********************************************************************/
  83. #if defined(C370) || defined(CW)
  84.     if (argc > 1)
  85.     {
  86.         char *p;
  87.  
  88.         for (i = 1; i < argc; i++)
  89.         {
  90.             /* Search for '(' which would indicate that options are listed. */
  91.             if ((p = strchr(argv[i], '(')) != NULL)
  92.                 break; /* if found then exit from loop */
  93.         }
  94.         op_start = i;
  95.         if (i != argc)     /* if there are options */
  96.         {
  97.             if (*(p+1) != '\0') /* first option is concatenated to '(' ? */
  98.                 strcpy(parm, p+1); /* Copy from next char till end */
  99.             else if (i != argc - 1)
  100.                 strcpy(parm, argv[++i]); /* Next argument is first option */
  101.  
  102.             while (i < argc - 1) /* Process remaining options */
  103.             {
  104.                strcat(parm, BLANK);
  105.                strcat(parm, argv[++i]);
  106.             }
  107.  
  108.             if (p != argv[op_start]) /* is '('  concatenated to some string?*/
  109.             {
  110.                 op_start++;
  111.                 *p = '\0';
  112.             }
  113.         }
  114.     }
  115. #else
  116.     if (argc > 2)
  117.     {
  118.         parm[0] = '\0';
  119.         while (j < argc - 2)
  120.         {
  121.             if (*(argv[++j]) == '-')
  122.                 strcat(parm, argv[j]+1);
  123.             else
  124.             {
  125.                 strcat(parm, argv[j]);
  126.                 printf("***WARNING: Option \"%s\" is missing preceding '-'.\n",
  127.                        argv[j]);
  128.             }
  129.             strcat(parm, BLANK);
  130.         }
  131.     }
  132. #endif
  133.  
  134.  
  135. /****************************************************************************/
  136. /*               Create file names for output files                         */
  137. /****************************************************************************/
  138. #if defined(C370) || defined(CW)
  139.     strupr(argv[1]);
  140. #if defined(MVS)
  141.     if (argv[1][0] == '\'')
  142.     {
  143.        int n;
  144.  
  145.        strcpy(grm_file, argv[1]);
  146.        dot = strchr(grm_file, '.');
  147.        j = 1+(int)(dot-grm_file);
  148.        n = strlen(grm_file) - 1;
  149.        for (i = j; i < n; i++)
  150.            file_prefix[i-j] = grm_file[i];
  151.        i = i - j;
  152.        file_prefix[i] = '\0';
  153.        sprintf(lis_file, "%s.LISTING", file_prefix);
  154.        sprintf(tab_file, "%s.TABLE",   file_prefix);
  155.        file_prefix[i] = '.';
  156.        file_prefix[i+1] = '\0';
  157.     }
  158.     else
  159.     {
  160.        sprintf(grm_file, "%s.GRAMMAR", argv[1]);
  161.        sprintf(lis_file, "%s.LISTING", argv[1]);
  162.        sprintf(tab_file, "%s.TABLE",   argv[1]);
  163.        strcpy(file_prefix, argv[1]);
  164.     }
  165. #else
  166.     switch(op_start - 1)
  167.     {
  168.         case 1:
  169.             sprintf(grm_file, "%s.GRAMMAR.*", argv[1]);
  170.             sprintf(lis_file, "%s.LISTING.A", argv[1]);
  171.             sprintf(tab_file, "%s.TABLE.A", argv[1]);
  172.             break;
  173.         case 2:
  174.             sprintf(grm_file, "%s.%s.*", argv[1], strupr(argv[2]));
  175.             sprintf(lis_file, "%s.LISTING.A", argv[1]);
  176.             sprintf(tab_file, "%s.TABLE.A", argv[1]);
  177.             break;
  178.         case 3:
  179.             strupr(argv[2]);
  180.             strupr(argv[3]);
  181.             sprintf(grm_file, "%s.%s.%s", argv[1], argv[2], argv[3]);
  182.             sprintf(lis_file, "%s.LISTING.%s", argv[1], argv[3]);
  183.             sprintf(tab_file, "%s.TABLE.%s", argv[1], argv[3]);
  184.             break;
  185.         default:
  186.             break;
  187.     }
  188. #endif
  189.  
  190.     i = strlen(argv[1]);
  191.     for (i = MIN(i, 5) - 1; i >= 0; i--)
  192.         file_prefix[i] = argv[1][i];
  193.     file_prefix[i] = '\0';
  194.     strupr(file_prefix);
  195. #else
  196.     strcpy(grm_file, argv[argc - 1]);
  197.  
  198. #if defined(DOS) || defined(OS2)
  199.     slash = strrchr(grm_file, '\\');
  200. #else
  201.     slash = strrchr(grm_file, '/');
  202. #endif
  203.     if (slash != NULL)
  204.          strcpy(tmpbuf, slash + 1);
  205.     else strcpy(tmpbuf, grm_file);
  206.  
  207.     dot = strrchr(tmpbuf, '.');
  208.  
  209.     if (dot == NULL) /* if filename has no extension, copy it. */
  210.     {
  211.         strcpy(lis_file, tmpbuf);
  212.         strcpy(tab_file, tmpbuf);
  213.         for (i = 0; i < 5; i++)
  214.             file_prefix[i] = tmpbuf[i];
  215.         file_prefix[i] = '\0';
  216.     }
  217.     else   /* if file name contains an extension copy up to the dot */
  218.     {
  219.         for (i = 0; i < 5 && tmpbuf + i != dot; i++)
  220.             file_prefix[i] = tmpbuf[i];
  221.         file_prefix[i] = '\0';
  222.         memcpy(lis_file, tmpbuf, dot - tmpbuf);
  223.         memcpy(tab_file, tmpbuf, dot - tmpbuf);
  224.         lis_file[dot - tmpbuf] = '\0';
  225.         tab_file[dot - tmpbuf] = '\0';
  226.     }
  227.  
  228.     strcat(lis_file, ".l");  /* add .l extension for listing file */
  229.     strcat(tab_file, ".t");  /* add .t extension for table file */
  230. #endif
  231.  
  232.     process_input();
  233.  
  234. /****************************************************************************/
  235. /* If the user only wanted to edit his grammar, we quit the program.        */
  236. /****************************************************************************/
  237.     if (edit_bit)
  238.     {
  239.         if (first_bit || follow_bit || xref_bit)
  240.             mkfirst();
  241.         PR_HEADING;
  242.         sprintf(msg_line, "\nNumber of Terminals: %d",
  243.                           num_terminals - 1); /*-1 for %empty */
  244.         PRNT(msg_line);
  245.  
  246.         sprintf(msg_line, "Number of Nonterminals: %d",
  247.                           num_non_terminals - 1); /* -1 for %ACC */
  248.         PRNT(msg_line);
  249.  
  250.         sprintf(msg_line, "Number of Productions: %d", num_rules + 1);
  251.         PRNT(msg_line);
  252.  
  253.         if (single_productions_bit)
  254.         {
  255.             sprintf(msg_line, "Number of Single Productions: %d",
  256.                               num_single_productions);
  257.             PRNT(msg_line);
  258.         }
  259.  
  260.         sprintf(msg_line, "Number of Items: %d", num_items);
  261.         PRNT(msg_line);
  262.  
  263.         fclose(syslis);      /* close listing file */
  264.         return 0;
  265.     }
  266.  
  267.     mkfirst(); /* Construct basic maps */
  268.  
  269.     mkstats(); /* Build State Automaton */
  270.  
  271.     mkrdcts(); /* Build Reduce map, and detect conflicts if any */
  272.  
  273. /****************************************************************************/
  274. /*                  Print more relevant statistics.                         */
  275. /****************************************************************************/
  276.     PR_HEADING;
  277.     sprintf(msg_line, "\nNumber of Terminals: %d", num_terminals - 1);
  278.     PRNT(msg_line);
  279.  
  280.     sprintf(msg_line, "Number of Nonterminals: %d", num_non_terminals - 1);
  281.     PRNT(msg_line);
  282.  
  283.     sprintf(msg_line, "Number of Productions: %d", num_rules + 1);
  284.     PRNT(msg_line);
  285.  
  286.     if (single_productions_bit)
  287.     {
  288.         sprintf(msg_line,
  289.                 "Number of Single Productions: %d",
  290.                 num_single_productions);
  291.         PRNT(msg_line);
  292.     }
  293.  
  294.     sprintf(msg_line, "Number of Items: %d", num_items);
  295.     PRNT(msg_line);
  296.     if (scopes_bit)
  297.     {
  298.         sprintf(msg_line, "Number of Scopes: %d", num_scopes);
  299.         PRNT(msg_line);
  300.     }
  301.  
  302.     sprintf(msg_line, "Number of States: %d", num_states);
  303.     PRNT(msg_line);
  304.  
  305.     if (max_la_state > num_states)
  306.     {
  307.         sprintf(msg_line,
  308.                 "Number of look-ahead states: %d",
  309.                 max_la_state - num_states);
  310.         PRNT(msg_line);
  311.     }
  312.  
  313.     sprintf(msg_line, "Number of Shift actions: %d", num_shifts);
  314.     PRNT(msg_line);
  315.  
  316.     sprintf(msg_line, "Number of Goto actions: %d", num_gotos);
  317.     PRNT(msg_line);
  318.  
  319.     if (read_reduce_bit)
  320.     {
  321.         sprintf(msg_line,
  322.                 "Number of Shift/Reduce actions: %d", num_shift_reduces);
  323.         PRNT(msg_line);
  324.  
  325.         sprintf(msg_line,
  326.                 "Number of Goto/Reduce actions: %d", num_goto_reduces);
  327.         PRNT(msg_line);
  328.     }
  329.  
  330.     sprintf(msg_line, "Number of Reduce actions: %d", num_reductions);
  331.     PRNT(msg_line);
  332.  
  333.     sprintf(msg_line,
  334.            "Number of Shift-Reduce conflicts: %d", num_sr_conflicts);
  335.     PRNT(msg_line);
  336.  
  337.     sprintf(msg_line,
  338.             "Number of Reduce-Reduce conflicts: %d", num_rr_conflicts);
  339.     PRNT(msg_line);
  340.  
  341.     /**********************************************************/
  342.     /* If the removal of single productions is requested, do  */
  343.     /* so now.                                                */
  344.     /* If STATE_BIT is on, we print the states.               */
  345.     /**********************************************************/
  346.     if (states_bit)
  347.     {
  348.         ptstats();
  349.         if (table_opt != 0)
  350.         {
  351.             PR_HEADING;
  352.         }
  353.     }
  354.  
  355.     /**********************************************************/
  356.     /* If the tables are requested, we process them.          */
  357.     /**********************************************************/
  358.     if (table_opt != 0)
  359.     {
  360.         if (goto_default_bit && nt_check_bit)
  361.         {
  362.             PRNTERR("The options GOTO_DEFAULT and NT_CHECK are "
  363.                     "incompatible.  Tables not generated");
  364.         }
  365.         else
  366.         {
  367.             struct node *head;
  368.             int state_no;
  369.  
  370.             num_entries = max_la_state + num_shifts + num_shift_reduces
  371.                                        + num_gotos  + num_goto_reduces
  372.                                        + num_reductions;
  373.  
  374.             /***********************************************************/
  375.             /* We release space used by RHS_SYM, the ADEQUATE_ITEM     */
  376.             /* map, ITEM_TABLE (if we don't have to dump error maps),  */
  377.             /* IN_STAT, FIRST, NULL_NT and FOLLOW (if it's no longer   */
  378.             /* needed).                                                */
  379.             /***********************************************************/
  380.             ffree(rhs_sym);
  381.             if (adequate_item != NULL)
  382.             {
  383.                 struct node *q;
  384.                 int rule_no;
  385.  
  386.                 for ALL_RULES(rule_no)
  387.                 {
  388.                     q = adequate_item[rule_no];
  389.                     if (q != NULL)
  390.                         free_nodes(q, q);
  391.                 }
  392.                 ffree(adequate_item);
  393.             }
  394.  
  395.             if (! error_maps_bit)
  396.                 ffree(item_table);
  397.  
  398.             for ALL_STATES(state_no)
  399.             {
  400.                 head = in_stat[state_no];
  401.                 if (head != NULL)
  402.                 {
  403.                     head = head -> next;
  404.                     free_nodes(head, in_stat[state_no]);
  405.                 }
  406.             }
  407.             ffree(in_stat);
  408.             ffree(first);
  409.             null_nt += (num_terminals + 1);
  410.             ffree(null_nt);
  411.             if (follow != NULL)
  412.             {
  413.                 if ((! error_maps_bit) || c_bit || cpp_bit || java_bit)
  414.                 {
  415.                     follow += ((num_terminals + 1) * term_set_size);
  416.                     ffree(follow);
  417.                 }
  418.             }
  419.  
  420.             process_tables();
  421.         }
  422.     }
  423.  
  424.     fclose(syslis);      /* close listing file */
  425.     return 0;
  426. }
  427.  
  428.  
  429.  
  430. /****************************************************************************/
  431. /*                              PRINT_OPTS:                                 */
  432. /****************************************************************************/
  433. static void print_opts(void)
  434. {
  435. #if defined(C370) || defined(CW)
  436. #if defined(VM)
  437.     printf("\n%s\n\n"
  438.     "Usage: jikespg [filename [filetype [filemode]]] ([options]\n\n"
  439.     "Options                   Options                   Options\n"
  440.     "=======                   =======                   =======\n"
  441.     "action                    "
  442.     "actfile-name=string       "
  443.     "actfile-mode=string\n"
  444.     "actfile-type=string       "
  445.     "blockb=string             "
  446.     "blocke=string\n"
  447.     "byte                      "
  448.     "conflicts                 "
  449.     "default[=<0|1|2|3|4|5>]\n"
  450.     "edit                      "
  451.     "error-maps                "
  452.     "escape=character\n"
  453.     "first                     "
  454.     "follow                    "
  455.     "generate-parser[=string]\n"
  456.     "goto-default              "
  457.     "hactfile-name=string      "
  458.     "hactfile-mode=string\n"
  459.     "hactfile-type=string      "
  460.     "half-word                 "
  461.     "hblockb=string\n"
  462.     "hblocke=string            "
  463.     "lalr[=integer]            "
  464.     "list\n"
  465.     "names=<OPTIMIZED|MAX|MIN> "
  466.     "nt-check                  "
  467.     "ormark=character\n"
  468.     "output-size=integer       "
  469.     "read-reduce               "
  470.     "record-format=< F | V >\n"
  471.     "scopes                    "
  472.     "shift-default             "
  473.     "single-productions\n"
  474.     "slr                       "
  475.     "states                    "
  476.     "table[=<space|time>]\n"
  477.     "trace[=<conflicts|full>]  "
  478.     "verbose                   "
  479.     "warnings\n"
  480.     "xref\n\n"
  481.  
  482.     "The following options are valid only if GENERATE-PARSER "
  483.     "and TABLE are activated:\n\n"
  484.  
  485.     "debug                     "
  486.     "deferred                  "
  487.     "file-prefix=string\n"
  488.     "max-distance=integer      "
  489.     "min-distance=integer      "
  490.     "prefix=string\n"
  491.     "stack-size=integer        "
  492.     "suffix=string\n\n"
  493.  
  494.     "Options must be separated by a space.  "
  495.     "Any non-ambiguous initial prefix of a\n"
  496.     "valid option may be used as an abbreviation "
  497.     "for that option.  When an option is\n"
  498.     "composed of two separate words, an "
  499.     "abbreviation may be formed by concatenating\n"
  500.     "the first character of each word.  Options "
  501.     "that are switches may benegated by\n"
  502.     "prefixing them with the string \"no\". "
  503.     "Default filetype is \"grammar\"; filemode is \"*\"\n",
  504.  
  505.     HEADER_INFO);
  506. #else
  507.     printf("\n%s\n\n"
  508.     "Usage: jikespg [filename] [([options]]\n\n"
  509.     "Options                   Options                   Options\n"
  510.     "=======                   =======                   =======\n"
  511.     "action                    "
  512.     "actfile-name=string       "
  513.     "blockb=string\n"
  514.     "blocke=string             "
  515.     "byte                      "
  516.     "conflicts\n"
  517.     "default[=<0|1|2|3|4|5>]   "
  518.     "edit                      "
  519.     "error-maps\n"
  520.     "escape=character          "
  521.     "first                     "
  522.     "follow\n"
  523.     "generate-parser[=string]  "
  524.     "goto-default              "
  525.     "hactfile-name=string\n"
  526.     "half-word                 "
  527.     "hblockb=string            "
  528.     "hblocke=string\n"
  529.     "lalr[=integer]            "
  530.     "list                      "
  531.     "names=<OPTIMIZED|MAX|MIN>\n"
  532.     "nt-check                  "
  533.     "ormark=character          "
  534.     "output-size=integer\n"
  535.     "read-reduce               "
  536.     "record-format=< F | V >   "
  537.     "scopes\n"
  538.     "shift-default             "
  539.     "single-productions        "
  540.     "slr\n"
  541.     "states                    "
  542.     "table[=<space|time>]      "
  543.     "trace[=<conflicts|full>]\n"
  544.     "verbose                   "
  545.     "warnings                  "
  546.     "xref\n\n"
  547.  
  548.     "The following options are valid only if GENERATE-PARSER "
  549.     "and TABLE are activated:\n\n"
  550.  
  551.     "debug                     "
  552.     "deferred                  "
  553.     "file-prefix=string\n"
  554.     "max-distance=integer      "
  555.     "min-distance=integer      "
  556.     "prefix=string\n"
  557.     "stack-size=integer        "
  558.     "suffix=string\n\n"
  559.  
  560.     "Options must be separated by a space.  "
  561.     "Any non-ambiguous initial prefix of a\n"
  562.     "valid option may be used as an abbreviation "
  563.     "for that option.  When an option is\n"
  564.     "composed of two separate words, an "
  565.     "abbreviation may be formed by concatenating\n"
  566.     "the first character of each word.  Options "
  567.     "that are switches may benegated by\n"
  568.     "prefixing them with the string \"no\". "
  569.     "Default filetype is \"grammar\"; filemode is \"*\"\n",
  570.  
  571.     HEADER_INFO);
  572. #endif
  573. #else
  574.    printf("\n%s"
  575.     "\n(C) Copyright IBM Corp. 1983, 1999.\n"
  576.     "Licensed Materials - Program Property of IBM - All Rights Reserved.\n\n"
  577.     "Usage: jikespg [options] [filename[.extension]]\n\n"
  578.     "Options                   Options                   Options\n"
  579.     "=======                   =======                   =======\n"
  580.  
  581.     "-action                   "
  582.     "-actfile-name=string      "
  583.     "-blockb=string\n"
  584.     "-blocke=string            "
  585.     "-byte                     "
  586.     "-conflicts\n"
  587.     "-default[=<0|1|2|3|4|5>]  "
  588.     "-edit                     "
  589.     "-error-maps\n"
  590.     "-escape=character         "
  591.     "-first                    "
  592.     "-follow\n"
  593.     "-generate-parser[=string] "
  594.     "-goto-default             "
  595.     "-half-word\n"
  596.     "-hactfile-name=string     "
  597.     "-hblockb=string           "
  598.     "-hblocke=string\n"
  599.     "-lalr[=integer]           "
  600.     "-list                     "
  601.     "-names=<OPTIMIZED|MAX|MIN>\n"
  602.     "-nt-check                 "
  603.     "-ormark=character         "
  604.     "-output-size=integer\n"
  605.     "-read-reduce              "
  606.     "-scopes                   "
  607.     "-shift-default\n"
  608.     "-single-productions       "
  609.     "-slr                      "
  610.     "-states\n"
  611.     "-table[=<space|time>]     "
  612.     "-trace[=<conflicts|full>] "
  613.     "-verbose\n"
  614.     "-warnings                 "
  615.     "-xref\n\n"
  616.  
  617.     "The following options are valid only if "
  618.     "GENERATE-PARSER and TABLE are activated:\n"
  619.  
  620.     "-debug                    "
  621.     "-deferred                 "
  622.     "-file-prefix=string\n"
  623.     "-max-distance=integer     "
  624.     "-min-distance=integer     "
  625.     "-prefix=string\n"
  626.     "-stack-size=integer       "
  627.     "-suffix=string\n\n"
  628.  
  629.     "Options must be separated by a space.  "
  630.     "Any non-ambiguous initial prefix of a\n"
  631.     "valid option may be used as an abbreviation "
  632.     "for that option.  When an option is\n"
  633.     "composed of two separate words, an "
  634.     "abbreviation may be formed by concatenating\n"
  635.     "the first character of each word.  "
  636.     "Options that are switches may benegated by\n"
  637.     "prefixing them with the string \"no\".  "
  638.     "Default input file extension is \".g\"\n",
  639.  
  640.     HEADER_INFO);
  641.  
  642.     printf("\nVersion %s (27 Jan 98) by Philippe Charles, IBM Research."
  643.            "\nAddress comments and questions to charles@watson.ibm.com.\n", VERSION);
  644. #endif
  645.  
  646.    return;
  647. }
  648.