home *** CD-ROM | disk | FTP | other *** search
- /* $Id: main.c,v 1.2 1999/11/04 14:02:22 shields Exp $ */
- /*
- This software is subject to the terms of the IBM Jikes Compiler
- License Agreement available at the following URL:
- http://www.ibm.com/research/jikes.
- Copyright (C) 1983, 1999, International Business Machines Corporation
- and others. All Rights Reserved.
- You must accept the terms of that agreement to use this software.
- */
- static char hostfile[] = __FILE__;
-
- #include <string.h>
- #include "common.h"
- #include "header.h"
-
- static void print_opts(void);
- void process_input(void);
- void mkfirst(void);
- void mkstats(void);
- void mkrdcts(void);
- void ptstats(void);
- void process_tables(void);
-
- /*********************************************************************/
- /* Jikes PG is a parser generator capable of generating LALR(k) and */
- /* SLR(1) tables. It is organized as a main routine: MAIN, which */
- /* invokes five other major subroutines which are: */
- /* */
- /* 1) PROCESS_INPUT - inputs and structures the grammar. */
- /* 2) MKFIRST - builds basic maps such as FIRST, */
- /* FOLLOW, CLOSURE, CLITEMS, ITEM_TABLE, */
- /* ADEQUATE_ITEMS. */
- /* 3) MKSTATS - constructs the LR(0) automaton. */
- /* 4) MKRDCTS - constructs reduction map. */
- /* 5) One of the following three procedures: */
- /* a) CMPRSPA - Space Table generation */
- /* b) CMPRTIM - Time Table generation */
- /* c) BASETAB - Write out Base Table */
- /* */
- /* The following files are used: */
- /* */
- /* 1) SYSGRM - Input file containing grammar */
- /* 2) SYSLIS - Output file used for listings, statistics*/
- /* and diagnostics. */
- /* 3) SYSACT - Output file used for semantic actions. */
- /* 4) SYSTAB - Output file used for Parsing tables. */
- /* */
- /*********************************************************************/
-
- /****************************************************************************/
- /****************************************************************************/
- /* MAIN PROGRAM MAIN: */
- /****************************************************************************/
- /****************************************************************************/
- int main(int argc, char *argv[])
- {
- int i,
- op_start,
- j = 0;
-
- char *dot,
- *slash,
- tmpbuf[20];
-
- /*********************************************************************/
- /* If only "jikespg" or "jikespg ?*" is typed, we display the help */
- /* screen. */
- /* */
- /* NOTE that because of some bug (feature?) in AIX, when two or more */
- /* consecutive "?" is passed as argument to a program, the behaviour */
- /* of the system becomes unpredictable. 1/4/94 */
- /* You may test this by invoking the "echo" program with "???". */
- /*********************************************************************/
- if (argc == 1 || argv[1][0] == '?')
- {
- print_opts();
- return 4;
- }
-
- /**********************************************************************/
- /* If options are passed to the program, copy them into "parm". */
- /**********************************************************************/
- #if defined(C370) || defined(CW)
- if (argc > 1)
- {
- char *p;
-
- for (i = 1; i < argc; i++)
- {
- /* Search for '(' which would indicate that options are listed. */
- if ((p = strchr(argv[i], '(')) != NULL)
- break; /* if found then exit from loop */
- }
- op_start = i;
- if (i != argc) /* if there are options */
- {
- if (*(p+1) != '\0') /* first option is concatenated to '(' ? */
- strcpy(parm, p+1); /* Copy from next char till end */
- else if (i != argc - 1)
- strcpy(parm, argv[++i]); /* Next argument is first option */
-
- while (i < argc - 1) /* Process remaining options */
- {
- strcat(parm, BLANK);
- strcat(parm, argv[++i]);
- }
-
- if (p != argv[op_start]) /* is '(' concatenated to some string?*/
- {
- op_start++;
- *p = '\0';
- }
- }
- }
- #else
- if (argc > 2)
- {
- parm[0] = '\0';
- while (j < argc - 2)
- {
- if (*(argv[++j]) == '-')
- strcat(parm, argv[j]+1);
- else
- {
- strcat(parm, argv[j]);
- printf("***WARNING: Option \"%s\" is missing preceding '-'.\n",
- argv[j]);
- }
- strcat(parm, BLANK);
- }
- }
- #endif
-
-
- /****************************************************************************/
- /* Create file names for output files */
- /****************************************************************************/
- #if defined(C370) || defined(CW)
- strupr(argv[1]);
- #if defined(MVS)
- if (argv[1][0] == '\'')
- {
- int n;
-
- strcpy(grm_file, argv[1]);
- dot = strchr(grm_file, '.');
- j = 1+(int)(dot-grm_file);
- n = strlen(grm_file) - 1;
- for (i = j; i < n; i++)
- file_prefix[i-j] = grm_file[i];
- i = i - j;
- file_prefix[i] = '\0';
- sprintf(lis_file, "%s.LISTING", file_prefix);
- sprintf(tab_file, "%s.TABLE", file_prefix);
- file_prefix[i] = '.';
- file_prefix[i+1] = '\0';
- }
- else
- {
- sprintf(grm_file, "%s.GRAMMAR", argv[1]);
- sprintf(lis_file, "%s.LISTING", argv[1]);
- sprintf(tab_file, "%s.TABLE", argv[1]);
- strcpy(file_prefix, argv[1]);
- }
- #else
- switch(op_start - 1)
- {
- case 1:
- sprintf(grm_file, "%s.GRAMMAR.*", argv[1]);
- sprintf(lis_file, "%s.LISTING.A", argv[1]);
- sprintf(tab_file, "%s.TABLE.A", argv[1]);
- break;
- case 2:
- sprintf(grm_file, "%s.%s.*", argv[1], strupr(argv[2]));
- sprintf(lis_file, "%s.LISTING.A", argv[1]);
- sprintf(tab_file, "%s.TABLE.A", argv[1]);
- break;
- case 3:
- strupr(argv[2]);
- strupr(argv[3]);
- sprintf(grm_file, "%s.%s.%s", argv[1], argv[2], argv[3]);
- sprintf(lis_file, "%s.LISTING.%s", argv[1], argv[3]);
- sprintf(tab_file, "%s.TABLE.%s", argv[1], argv[3]);
- break;
- default:
- break;
- }
- #endif
-
- i = strlen(argv[1]);
- for (i = MIN(i, 5) - 1; i >= 0; i--)
- file_prefix[i] = argv[1][i];
- file_prefix[i] = '\0';
- strupr(file_prefix);
- #else
- strcpy(grm_file, argv[argc - 1]);
-
- #if defined(DOS) || defined(OS2)
- slash = strrchr(grm_file, '\\');
- #else
- slash = strrchr(grm_file, '/');
- #endif
- if (slash != NULL)
- strcpy(tmpbuf, slash + 1);
- else strcpy(tmpbuf, grm_file);
-
- dot = strrchr(tmpbuf, '.');
-
- if (dot == NULL) /* if filename has no extension, copy it. */
- {
- strcpy(lis_file, tmpbuf);
- strcpy(tab_file, tmpbuf);
- for (i = 0; i < 5; i++)
- file_prefix[i] = tmpbuf[i];
- file_prefix[i] = '\0';
- }
- else /* if file name contains an extension copy up to the dot */
- {
- for (i = 0; i < 5 && tmpbuf + i != dot; i++)
- file_prefix[i] = tmpbuf[i];
- file_prefix[i] = '\0';
- memcpy(lis_file, tmpbuf, dot - tmpbuf);
- memcpy(tab_file, tmpbuf, dot - tmpbuf);
- lis_file[dot - tmpbuf] = '\0';
- tab_file[dot - tmpbuf] = '\0';
- }
-
- strcat(lis_file, ".l"); /* add .l extension for listing file */
- strcat(tab_file, ".t"); /* add .t extension for table file */
- #endif
-
- process_input();
-
- /****************************************************************************/
- /* If the user only wanted to edit his grammar, we quit the program. */
- /****************************************************************************/
- if (edit_bit)
- {
- if (first_bit || follow_bit || xref_bit)
- mkfirst();
- PR_HEADING;
- sprintf(msg_line, "\nNumber of Terminals: %d",
- num_terminals - 1); /*-1 for %empty */
- PRNT(msg_line);
-
- sprintf(msg_line, "Number of Nonterminals: %d",
- num_non_terminals - 1); /* -1 for %ACC */
- PRNT(msg_line);
-
- sprintf(msg_line, "Number of Productions: %d", num_rules + 1);
- PRNT(msg_line);
-
- if (single_productions_bit)
- {
- sprintf(msg_line, "Number of Single Productions: %d",
- num_single_productions);
- PRNT(msg_line);
- }
-
- sprintf(msg_line, "Number of Items: %d", num_items);
- PRNT(msg_line);
-
- fclose(syslis); /* close listing file */
- return 0;
- }
-
- mkfirst(); /* Construct basic maps */
-
- mkstats(); /* Build State Automaton */
-
- mkrdcts(); /* Build Reduce map, and detect conflicts if any */
-
- /****************************************************************************/
- /* Print more relevant statistics. */
- /****************************************************************************/
- PR_HEADING;
- sprintf(msg_line, "\nNumber of Terminals: %d", num_terminals - 1);
- PRNT(msg_line);
-
- sprintf(msg_line, "Number of Nonterminals: %d", num_non_terminals - 1);
- PRNT(msg_line);
-
- sprintf(msg_line, "Number of Productions: %d", num_rules + 1);
- PRNT(msg_line);
-
- if (single_productions_bit)
- {
- sprintf(msg_line,
- "Number of Single Productions: %d",
- num_single_productions);
- PRNT(msg_line);
- }
-
- sprintf(msg_line, "Number of Items: %d", num_items);
- PRNT(msg_line);
- if (scopes_bit)
- {
- sprintf(msg_line, "Number of Scopes: %d", num_scopes);
- PRNT(msg_line);
- }
-
- sprintf(msg_line, "Number of States: %d", num_states);
- PRNT(msg_line);
-
- if (max_la_state > num_states)
- {
- sprintf(msg_line,
- "Number of look-ahead states: %d",
- max_la_state - num_states);
- PRNT(msg_line);
- }
-
- sprintf(msg_line, "Number of Shift actions: %d", num_shifts);
- PRNT(msg_line);
-
- sprintf(msg_line, "Number of Goto actions: %d", num_gotos);
- PRNT(msg_line);
-
- if (read_reduce_bit)
- {
- sprintf(msg_line,
- "Number of Shift/Reduce actions: %d", num_shift_reduces);
- PRNT(msg_line);
-
- sprintf(msg_line,
- "Number of Goto/Reduce actions: %d", num_goto_reduces);
- PRNT(msg_line);
- }
-
- sprintf(msg_line, "Number of Reduce actions: %d", num_reductions);
- PRNT(msg_line);
-
- sprintf(msg_line,
- "Number of Shift-Reduce conflicts: %d", num_sr_conflicts);
- PRNT(msg_line);
-
- sprintf(msg_line,
- "Number of Reduce-Reduce conflicts: %d", num_rr_conflicts);
- PRNT(msg_line);
-
- /**********************************************************/
- /* If the removal of single productions is requested, do */
- /* so now. */
- /* If STATE_BIT is on, we print the states. */
- /**********************************************************/
- if (states_bit)
- {
- ptstats();
- if (table_opt != 0)
- {
- PR_HEADING;
- }
- }
-
- /**********************************************************/
- /* If the tables are requested, we process them. */
- /**********************************************************/
- if (table_opt != 0)
- {
- if (goto_default_bit && nt_check_bit)
- {
- PRNTERR("The options GOTO_DEFAULT and NT_CHECK are "
- "incompatible. Tables not generated");
- }
- else
- {
- struct node *head;
- int state_no;
-
- num_entries = max_la_state + num_shifts + num_shift_reduces
- + num_gotos + num_goto_reduces
- + num_reductions;
-
- /***********************************************************/
- /* We release space used by RHS_SYM, the ADEQUATE_ITEM */
- /* map, ITEM_TABLE (if we don't have to dump error maps), */
- /* IN_STAT, FIRST, NULL_NT and FOLLOW (if it's no longer */
- /* needed). */
- /***********************************************************/
- ffree(rhs_sym);
- if (adequate_item != NULL)
- {
- struct node *q;
- int rule_no;
-
- for ALL_RULES(rule_no)
- {
- q = adequate_item[rule_no];
- if (q != NULL)
- free_nodes(q, q);
- }
- ffree(adequate_item);
- }
-
- if (! error_maps_bit)
- ffree(item_table);
-
- for ALL_STATES(state_no)
- {
- head = in_stat[state_no];
- if (head != NULL)
- {
- head = head -> next;
- free_nodes(head, in_stat[state_no]);
- }
- }
- ffree(in_stat);
- ffree(first);
- null_nt += (num_terminals + 1);
- ffree(null_nt);
- if (follow != NULL)
- {
- if ((! error_maps_bit) || c_bit || cpp_bit || java_bit)
- {
- follow += ((num_terminals + 1) * term_set_size);
- ffree(follow);
- }
- }
-
- process_tables();
- }
- }
-
- fclose(syslis); /* close listing file */
- return 0;
- }
-
-
-
- /****************************************************************************/
- /* PRINT_OPTS: */
- /****************************************************************************/
- static void print_opts(void)
- {
- #if defined(C370) || defined(CW)
- #if defined(VM)
- printf("\n%s\n\n"
- "Usage: jikespg [filename [filetype [filemode]]] ([options]\n\n"
- "Options Options Options\n"
- "======= ======= =======\n"
- "action "
- "actfile-name=string "
- "actfile-mode=string\n"
- "actfile-type=string "
- "blockb=string "
- "blocke=string\n"
- "byte "
- "conflicts "
- "default[=<0|1|2|3|4|5>]\n"
- "edit "
- "error-maps "
- "escape=character\n"
- "first "
- "follow "
- "generate-parser[=string]\n"
- "goto-default "
- "hactfile-name=string "
- "hactfile-mode=string\n"
- "hactfile-type=string "
- "half-word "
- "hblockb=string\n"
- "hblocke=string "
- "lalr[=integer] "
- "list\n"
- "names=<OPTIMIZED|MAX|MIN> "
- "nt-check "
- "ormark=character\n"
- "output-size=integer "
- "read-reduce "
- "record-format=< F | V >\n"
- "scopes "
- "shift-default "
- "single-productions\n"
- "slr "
- "states "
- "table[=<space|time>]\n"
- "trace[=<conflicts|full>] "
- "verbose "
- "warnings\n"
- "xref\n\n"
-
- "The following options are valid only if GENERATE-PARSER "
- "and TABLE are activated:\n\n"
-
- "debug "
- "deferred "
- "file-prefix=string\n"
- "max-distance=integer "
- "min-distance=integer "
- "prefix=string\n"
- "stack-size=integer "
- "suffix=string\n\n"
-
- "Options must be separated by a space. "
- "Any non-ambiguous initial prefix of a\n"
- "valid option may be used as an abbreviation "
- "for that option. When an option is\n"
- "composed of two separate words, an "
- "abbreviation may be formed by concatenating\n"
- "the first character of each word. Options "
- "that are switches may benegated by\n"
- "prefixing them with the string \"no\". "
- "Default filetype is \"grammar\"; filemode is \"*\"\n",
-
- HEADER_INFO);
- #else
- printf("\n%s\n\n"
- "Usage: jikespg [filename] [([options]]\n\n"
- "Options Options Options\n"
- "======= ======= =======\n"
- "action "
- "actfile-name=string "
- "blockb=string\n"
- "blocke=string "
- "byte "
- "conflicts\n"
- "default[=<0|1|2|3|4|5>] "
- "edit "
- "error-maps\n"
- "escape=character "
- "first "
- "follow\n"
- "generate-parser[=string] "
- "goto-default "
- "hactfile-name=string\n"
- "half-word "
- "hblockb=string "
- "hblocke=string\n"
- "lalr[=integer] "
- "list "
- "names=<OPTIMIZED|MAX|MIN>\n"
- "nt-check "
- "ormark=character "
- "output-size=integer\n"
- "read-reduce "
- "record-format=< F | V > "
- "scopes\n"
- "shift-default "
- "single-productions "
- "slr\n"
- "states "
- "table[=<space|time>] "
- "trace[=<conflicts|full>]\n"
- "verbose "
- "warnings "
- "xref\n\n"
-
- "The following options are valid only if GENERATE-PARSER "
- "and TABLE are activated:\n\n"
-
- "debug "
- "deferred "
- "file-prefix=string\n"
- "max-distance=integer "
- "min-distance=integer "
- "prefix=string\n"
- "stack-size=integer "
- "suffix=string\n\n"
-
- "Options must be separated by a space. "
- "Any non-ambiguous initial prefix of a\n"
- "valid option may be used as an abbreviation "
- "for that option. When an option is\n"
- "composed of two separate words, an "
- "abbreviation may be formed by concatenating\n"
- "the first character of each word. Options "
- "that are switches may benegated by\n"
- "prefixing them with the string \"no\". "
- "Default filetype is \"grammar\"; filemode is \"*\"\n",
-
- HEADER_INFO);
- #endif
- #else
- printf("\n%s"
- "\n(C) Copyright IBM Corp. 1983, 1999.\n"
- "Licensed Materials - Program Property of IBM - All Rights Reserved.\n\n"
- "Usage: jikespg [options] [filename[.extension]]\n\n"
- "Options Options Options\n"
- "======= ======= =======\n"
-
- "-action "
- "-actfile-name=string "
- "-blockb=string\n"
- "-blocke=string "
- "-byte "
- "-conflicts\n"
- "-default[=<0|1|2|3|4|5>] "
- "-edit "
- "-error-maps\n"
- "-escape=character "
- "-first "
- "-follow\n"
- "-generate-parser[=string] "
- "-goto-default "
- "-half-word\n"
- "-hactfile-name=string "
- "-hblockb=string "
- "-hblocke=string\n"
- "-lalr[=integer] "
- "-list "
- "-names=<OPTIMIZED|MAX|MIN>\n"
- "-nt-check "
- "-ormark=character "
- "-output-size=integer\n"
- "-read-reduce "
- "-scopes "
- "-shift-default\n"
- "-single-productions "
- "-slr "
- "-states\n"
- "-table[=<space|time>] "
- "-trace[=<conflicts|full>] "
- "-verbose\n"
- "-warnings "
- "-xref\n\n"
-
- "The following options are valid only if "
- "GENERATE-PARSER and TABLE are activated:\n"
-
- "-debug "
- "-deferred "
- "-file-prefix=string\n"
- "-max-distance=integer "
- "-min-distance=integer "
- "-prefix=string\n"
- "-stack-size=integer "
- "-suffix=string\n\n"
-
- "Options must be separated by a space. "
- "Any non-ambiguous initial prefix of a\n"
- "valid option may be used as an abbreviation "
- "for that option. When an option is\n"
- "composed of two separate words, an "
- "abbreviation may be formed by concatenating\n"
- "the first character of each word. "
- "Options that are switches may benegated by\n"
- "prefixing them with the string \"no\". "
- "Default input file extension is \".g\"\n",
-
- HEADER_INFO);
-
- printf("\nVersion %s (27 Jan 98) by Philippe Charles, IBM Research."
- "\nAddress comments and questions to charles@watson.ibm.com.\n", VERSION);
- #endif
-
- return;
- }
-