X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fq2c.c;h=c1b7e8d77cc3c9b82a0ab770903a1137f1fed903;hb=92fb12eb06716d14c05b781f5d9dcde956d77c30;hp=e8f09d8d5daa38f195166f44355de5f0a84ce7ea;hpb=0a2cdacebb16d9a13c1b382c5ffa29e32cf858ea;p=pspp diff --git a/src/q2c.c b/src/q2c.c index e8f09d8d5d..c1b7e8d77c 100644 --- a/src/q2c.c +++ b/src/q2c.c @@ -14,8 +14,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ #include #include @@ -53,7 +53,7 @@ #define MAX_TOK_LEN 1024 /* argv[0]. */ -char *pgmname; +char *program_name; /* Have the input and output files been opened yet? */ int is_open; @@ -97,7 +97,7 @@ finish_up (void) fclose (in); fclose (out); if (remove (ofn) == -1) - fprintf (stderr, "%s: %s: remove: %s\n", pgmname, ofn, strerror (errno)); + fprintf (stderr, "%s: %s: remove: %s\n", program_name, ofn, strerror (errno)); } void hcf (void) NO_RETURN; @@ -120,7 +120,7 @@ fail (const char *format, ...) va_list args; va_start (args, format); - fprintf (stderr, "%s: ", pgmname); + fprintf (stderr, "%s: ", program_name); vfprintf (stderr, format, args); fprintf (stderr, "\n"); va_end (args); @@ -284,7 +284,7 @@ add_symbol (const char *name, int unique, int value) symbol *iter, *sym; int x; - sym = xmalloc (sizeof (symbol)); + sym = xmalloc (sizeof *sym); sym->name = xstrdup (name); sym->unique = unique; sym->value = value; @@ -342,14 +342,11 @@ find_symbol (int x) #if DEBUGGING /* Writes a printable representation of the current token to stdout. */ -void +static void dump_token (void) { switch (token) { - case T_TSTRING: - printf ("TR_STRING\t\"%s\"\n", tokstr); - break; case T_STRING: printf ("STRING\t\"%s\"\n", tokstr); break; @@ -535,6 +532,13 @@ typedef enum } subcommand_type; +typedef enum + { + ARITY_ONCE_EXACTLY, /* must occur exactly once */ + ARITY_ONCE_ONLY, /* zero or once */ + ARITY_MANY /* 0, 1, ... , inf */ + }subcommand_arity; + /* A single subcommand. */ typedef struct subcommand subcommand; struct subcommand @@ -542,7 +546,7 @@ struct subcommand subcommand *next; /* Next in the chain. */ char *name; /* Subcommand name. */ subcommand_type type; /* One of SBC_*. */ - int once; /* 1=Subcommand may appear only once. */ + subcommand_arity arity; /* How many times should the subcommand occur*/ int narray; /* Index of next array element. */ const char *prefix; /* Prefix for variable and constant names. */ specifier *spec; /* Array of specifiers. */ @@ -553,16 +557,6 @@ struct subcommand int translatable; /* Error message is translatable */ }; -typedef struct aux_subcommand aux_subcommand; -struct aux_subcommand - { - aux_subcommand *next; /* Next in the chain. */ - char *name; /* Subcommand name. */ - char *value; /* Subcommand value */ - }; - -static aux_subcommand *aux_subcommands ; - /* Name of the command; i.e., DESCRIPTIVES. */ char *cmdname; @@ -705,13 +699,22 @@ parse_specifier (specifier *spec, subcommand *sbc) } skip_token (':'); + if ( sbc->type == SBC_ARRAY && token == T_ID ) + { + spec->varname = xstrdup (st_lower (tokstr)); + spec->index = sbc->narray; + sbc->narray++; + } + + + /* Parse all the settings. */ { setting **s = &spec->s; for (;;) { - *s = xmalloc (sizeof (setting)); + *s = xmalloc (sizeof **s); parse_setting (*s, spec); if (token == ',' || token == ';' || token == '.') break; @@ -736,7 +739,7 @@ parse_specifiers (subcommand *sbc) for (;;) { - *spec = xmalloc (sizeof (specifier)); + *spec = xmalloc (sizeof **spec); parse_specifier (*spec, sbc); if (token == ';' || token == '.') break; @@ -750,6 +753,8 @@ parse_specifiers (subcommand *sbc) static void parse_subcommand (subcommand *sbc) { + sbc->arity = ARITY_MANY; + if (match_token ('*')) { if (def) @@ -757,7 +762,11 @@ parse_subcommand (subcommand *sbc) def = sbc; } - sbc->once = match_token ('+'); + if ( match_token('+')) + sbc->arity = ARITY_ONCE_ONLY ; + else if (match_token('^')) + sbc->arity = ARITY_ONCE_EXACTLY ; + force_id (); sbc->name = xstrdup (tokstr); @@ -779,6 +788,7 @@ parse_subcommand (subcommand *sbc) sbc->type = SBC_ARRAY; parse_specifiers (sbc); + } else { @@ -873,7 +883,7 @@ parse_subcommands (void) for (;;) { - *sbc = xmalloc (sizeof (subcommand)); + *sbc = xmalloc (sizeof **sbc); (*sbc)->next = NULL; parse_subcommand (*sbc); @@ -1062,7 +1072,6 @@ dump_declarations (void) specifier *spec; for (spec = sbc->spec; spec; spec = spec->next) - if (!spec->s) dump (0, "%s%s%s = %d,", st_upper (prefix), st_upper (sbc->prefix), st_upper (spec->varname), spec->index); @@ -1108,8 +1117,12 @@ dump_declarations (void) spec->varname); else if (f == 0) { - dump (0, "int a_%s[%d];", - st_lower (sbc->name), sbc->narray); + dump (0, "int a_%s[%s%scount];", + st_lower (sbc->name), + st_upper (prefix), + st_upper (sbc->prefix) + ); + f = 1; } } @@ -1120,7 +1133,7 @@ dump_declarations (void) break; case SBC_VARLIST: - dump (0, "int %sn_%s;", st_lower (sbc->prefix), + dump (0, "size_t %sn_%s;", st_lower (sbc->prefix), st_lower (sbc->name)); dump (0, "struct variable **%sv_%s;", st_lower (sbc->prefix), st_lower (sbc->name)); @@ -1137,11 +1150,11 @@ dump_declarations (void) case SBC_INT: case SBC_PINT: - dump (0, "long n_%s;", st_lower (sbc->name)); + dump (0, "long n_%s[MAXLISTS];", st_lower (sbc->name)); break; case SBC_DBL: - dump (0, "double n_%s;", st_lower (sbc->name)); + dump (0, "double n_%s[MAXLISTS];", st_lower (sbc->name)); break; case SBC_DBL_LIST: @@ -1254,16 +1267,23 @@ dump_vars_init (int persistent) break; case SBC_DBL_LIST: - dump (0, "int i;"); - dump (0, "for (i = 0; i < MAXLISTS; ++i)"); dump (1, "{"); + dump (0, "int i;"); + dump (1, "for (i = 0; i < MAXLISTS; ++i)"); dump (0, "subc_list_double_create(&p->dl_%s[i]) ;", st_lower (sbc->name) ); - dump (-1, "}"); + dump (-2, "}"); break; case SBC_DBL: + dump (1, "{"); + dump (0, "int i;"); + dump (1, "for (i = 0; i < MAXLISTS; ++i)"); + dump (0, "p->n_%s[i] = SYSMIS;", st_lower (sbc->name)); + dump (-2, "}"); + break; + case SBC_CUSTOM: /* nothing */ break; @@ -1308,7 +1328,11 @@ dump_vars_init (int persistent) case SBC_INT: case SBC_PINT: - dump (0, "p->n_%s = NOT_LONG;", st_lower (sbc->name)); + dump (1, "{"); + dump (0, "int i;"); + dump (1, "for (i = 0; i < MAXLISTS; ++i)"); + dump (0, "p->n_%s[i] = NOT_LONG;", st_lower (sbc->name)); + dump (-2, "}"); break; default: @@ -1379,6 +1403,7 @@ dump_specifier_parse (const specifier *spec, const subcommand *sbc) dump (1, "%sif (%s)", first ? "" : "else ", make_match (s->specname)); + /* Handle values. */ if (s->value == VAL_NONE) dump (0, "p->%s%s = %s%s;", sbc->prefix, spec->varname, @@ -1389,9 +1414,18 @@ dump_specifier_parse (const specifier *spec, const subcommand *sbc) dump (1, "{"); if (spec->varname) - dump (0, "p->%s%s = %s%s;", sbc->prefix, spec->varname, - st_upper (prefix), find_symbol (s->con)->name); - + { + dump (0, "p->%s%s = %s%s;", sbc->prefix, spec->varname, + st_upper (prefix), find_symbol (s->con)->name); + + if ( sbc->type == SBC_ARRAY ) + dump (0, "p->a_%s[%s%s%s] = 1;", + st_lower (sbc->name), + st_upper (prefix), st_upper (sbc->prefix), + st_upper (spec->varname)); + } + + if (s->valtype == VT_PAREN) { if (s->optvalue) @@ -1414,7 +1448,7 @@ dump_specifier_parse (const specifier *spec, const subcommand *sbc) if (s->value == VAL_INT) { - dump (1, "if (!lex_integer_p ())"); + dump (1, "if (!lex_is_integer ())"); dump (1, "{"); dump (0, "msg (SE, _(\"%s specifier of %s subcommand " "requires an integer argument.\"));", @@ -1426,7 +1460,7 @@ dump_specifier_parse (const specifier *spec, const subcommand *sbc) } else { - dump (1, "if (token != T_NUM)"); + dump (1, "if (!lex_is_number ())"); dump (1, "{"); dump (0, "msg (SE, _(\"Number expected after %s " "specifier of %s subcommand.\"));", @@ -1577,7 +1611,7 @@ dump_subcommand (const subcommand *sbc) { dump (0, "p->%sv_%s = parse_variable ();", st_lower (sbc->prefix), st_lower (sbc->name)); - dump (1, "if (p->%sv_%s)", + dump (1, "if (!p->%sv_%s)", st_lower (sbc->prefix), st_lower (sbc->name)); dump (0, "goto lossage;"); outdent (); @@ -1614,7 +1648,8 @@ dump_subcommand (const subcommand *sbc) { dump (1, "if (!lex_force_num ())"); dump (0, "goto lossage;"); - dump (-1, "p->n_%s = lex_double ();", st_lower (sbc->name)); + dump (-1, "p->n_%s[p->sbc_%s - 1] = lex_number ();", + st_lower (sbc->name), st_lower (sbc->name) ); dump (0, "lex_get();"); } else if (sbc->type == SBC_INT) @@ -1638,7 +1673,7 @@ dump_subcommand (const subcommand *sbc) dump (0, "goto lossage;"); dump (-1, "}"); } - dump (-1, "p->n_%s = x;", st_lower (sbc->name)); + dump (0, "p->n_%s[p->sbc_%s - 1] = x;", st_lower (sbc->name), st_lower(sbc->name) ); dump (-1,"}"); } else if (sbc->type == SBC_PINT) @@ -1665,7 +1700,7 @@ dump_subcommand (const subcommand *sbc) dump (0, "goto lossage;"); dump (-1,"}"); - dump (0, "subc_list_double_push(&p->dl_%s[p->sbc_%s-1],lex_double ());", + dump (0, "subc_list_double_push(&p->dl_%s[p->sbc_%s-1],lex_number ());", st_lower (sbc->name),st_lower (sbc->name) ); @@ -1770,7 +1805,7 @@ dump_parser (int persistent) dump (0, "lex_match ('=');"); dump (0, "p->sbc_%s++;", st_lower (sbc->name)); - if (sbc->once) + if (sbc->arity != ARITY_MANY) { dump (1, "if (p->sbc_%s > 1)", st_lower (sbc->name)); dump (1, "{"); @@ -1785,6 +1820,8 @@ dump_parser (int persistent) outdent (); } } + + /* Now deal with the /ALGORITHM subcommand implicit to all commands */ dump(1,"else if ( get_syntax() != COMPATIBLE && lex_match_id(\"ALGORITHM\"))"); dump(1,"{"); @@ -1800,6 +1837,7 @@ dump_parser (int persistent) dump (-1, "}"); outdent (); + dump (1, "if (!lex_match ('/'))"); dump (0, "break;"); @@ -1812,154 +1850,36 @@ dump_parser (int persistent) dump (0, "goto lossage;"); dump (-1, "}"); dump (0, nullstr); - dump (-1, "return 1;"); - dump (0, nullstr); - dump (-1, "lossage:"); - indent (); - dump (0, "free_%s (p);", make_identifier (cmdname)); - dump (0, "return 0;"); - dump (-1, "}"); - dump (0, nullstr); -} - - -/* Write out the code to parse aux subcommand SBC. */ -static void -dump_aux_subcommand (const subcommand *sbc) -{ - if (sbc->type == SBC_PLAIN ) - { - specifier *spec; - - for (spec = sbc->spec; spec; spec = spec->next) - { - char buf[80]; - sprintf(buf,"p->%s%s",st_lower(sbc->prefix),spec->varname); - dump (0, "msg(MM,\"%s is %%s\",",sbc->name); - dump (0, "(%s < 1000)?\"not set\":settings[%s - 1000]", buf, buf); - - dump (0, ");"); - } - } - else if (sbc->type == SBC_STRING) - { - dump (0, "msg(MM,\"%s is \\\"%%s\\\"\",p->s_%s);", sbc->name,st_lower(sbc->name) ); - } - else if (sbc->type == SBC_INT) - { - dump (0, "msg(MM,\"%s is %%ld\",p->n_%s);", sbc->name,st_lower(sbc->name) ); - } - else if (sbc->type == SBC_CUSTOM) - { - dump (0, "aux_%scustom_%s(p);",st_lower(prefix),make_identifier(sbc->name)); - } - else - assert(0); -} - - - -/* Write out auxilliary parser. */ -static void -dump_aux_parser (void) -{ - int f=0; - subcommand *sbc; - aux_subcommand *asbc; + outdent (); - /* Write out English strings for all the identifiers in the symbol table. */ { - int f, k; - symbol *sym; - char *buf = NULL; - - /* Note the squirmings necessary to make sure that the last string - is not followed by a comma (is it necessary to do that ?? ) */ - for (sym = symtab, f = k = 0; sym; sym = sym->next) - if (!sym->unique && !is_keyword (sym->name)) - { - if (!f) - { - dump (0, "/* Strings for subcommand specifiers. */"); - dump (1, "static const char *settings[]="); - dump (1, "{"); - f = 1; - } - - if (buf == NULL) - buf = xmalloc (1024); - else - dump (0, buf); + /* Check that mandatory subcommands have been specified */ + subcommand *sbc; - sprintf (buf, "\"%s\",",sym->name); - } - if (buf) - { - buf[strlen (buf) - 1] = 0; - dump (0, buf); - free (buf); - } - if (f) + for (sbc = subcommands; sbc; sbc = sbc->next) { - dump (-1, "};"); - dump (-1, nullstr); + + if ( sbc->arity == ARITY_ONCE_EXACTLY ) + { + dump (0, "if ( 0 == p->sbc_%s)", st_lower (sbc->name)); + dump (1, "{"); + dump (0, "msg (SE, _(\"%s subcommand must be given.\"));", + sbc->name); + dump (0, "goto lossage;"); + dump (-1, "}"); + dump (0, nullstr); + } } } - - indent = 0; - - dump (0, "static int"); - dump (0, "aux_parse_%s (struct cmd_%s *p)", make_identifier (cmdname), - make_identifier (cmdname)); - dump (1, "{"); - - dump (1, "for (;;)"); - dump (1, "{"); - - - for (sbc = subcommands; sbc; sbc = sbc->next) - { - dump (1, "%sif (%s)", f ? "else " : "", make_match (sbc->name)); - f = 1; - dump (1, "{"); - - dump_aux_subcommand (sbc); - - dump (-1, "}"); - outdent (); - } - - for (asbc = aux_subcommands ; asbc ; asbc = asbc->next) - { - dump (1, "%sif (%s)", f ? "else " : "", make_match (asbc->name)); - f = 1; - dump (1, "{"); - dump(0,"aux_%s();",make_identifier(asbc->value)); - dump (-1, "}"); - outdent (); - } - - dump (1, "if (!lex_match ('/'))"); - dump (0, "break;"); - dump (-2, "}"); - outdent (); - dump (0, nullstr); - dump (1, "if (token != '.')"); - dump (1, "{"); - dump (0, "lex_error (_(\"expecting end of command\"));"); - dump (0, "goto lossage;"); - dump (-1, "}"); - dump (0, nullstr); dump (-1, "return 1;"); dump (0, nullstr); dump (-1, "lossage:"); indent (); dump (0, "free_%s (p);", make_identifier (cmdname)); dump (0, "return 0;"); - dump (-1, "} /* aux_parse_%s (struct cmd_%s *p) */", - make_identifier (cmdname), make_identifier (cmdname)); + dump (-1, "}"); dump (0, nullstr); } @@ -1982,11 +1902,6 @@ dump_header (void) dump (0, " Generated by q2c from %s on %s.", ifn, timep); dump (0, " Do not modify!"); dump (0, " */"); - - dump (0, nullstr); - dump (0, "#include \"settings.h\""); - dump (0, "#include \"subclist.h\""); - dump (0, nullstr); } /* Write out commands to free variable state. */ @@ -2023,11 +1938,17 @@ dump_free (int persistent) { switch (sbc->type) { + case SBC_VARLIST: + dump (0, "free (p->v_variables);"); + break; case SBC_STRING: dump (0, "free (p->s_%s);", st_lower (sbc->name)); break; case SBC_DBL_LIST: - dump (0, "subc_list_double_destroy(p->dl_%s);", st_lower (sbc->name)); + dump (0, "int i;"); + dump (1, "for(i = 0; i < MAXLISTS ; ++i)"); + dump (0, "subc_list_double_destroy(&p->dl_%s[i]);", st_lower (sbc->name)); + outdent(); break; default: break; @@ -2068,12 +1989,10 @@ recognize_directive (void) return directive; } -static void aux_parse (void); - int main (int argc, char *argv[]) { - pgmname = argv[0]; + program_name = argv[0]; if (argc != 3) fail ("Syntax: q2c input.q output.c"); @@ -2105,7 +2024,7 @@ main (int argc, char *argv[]) continue; } - dump (0, "#line %d \"%s\"", oln - 1, ofn); + dump (0, "#line %d \"%s\"", oln + 1, ofn); if (!strcmp (directive, "specification")) { /* Skip leading slash-star line. */ @@ -2125,9 +2044,14 @@ main (int argc, char *argv[]) dump (0, "#include \"alloc.h\""); dump (0, "#include \"error.h\""); dump (0, "#include \"lexer.h\""); + dump (0, "#include \"settings.h\""); dump (0, "#include \"str.h\""); + dump (0, "#include \"subclist.h\""); dump (0, "#include \"var.h\""); + dump (0, nullstr); + dump (0, "#include \"gettext.h\""); + dump (0, "#define _(msgid) gettext (msgid)"); dump (0, nullstr); } else if (!strcmp (directive, "declarations")) @@ -2142,11 +2066,6 @@ main (int argc, char *argv[]) dump_parser (1); dump_free (1); } - else if (!strcmp (directive, "aux_functions")) - { - aux_parse(); - dump_aux_parser (); - } else error ("unknown directive `%s'", directive); indent = 0; @@ -2157,34 +2076,3 @@ main (int argc, char *argv[]) return EXIT_SUCCESS; } - -/* Parse an entire auxilliary specification. */ -static void -aux_parse (void) -{ - aux_subcommand *sbc; - aux_subcommand *prevsbc = 0 ; - get_line(); - lex_get(); - - for (;;) - { - sbc = xmalloc(sizeof(aux_subcommand)); - sbc->next = prevsbc; - sbc->name = xstrdup (tokstr); - lex_get(); - skip_token('='); - sbc->value = xstrdup (tokstr); - lex_get(); - if (token == '.') - break; - skip_token(';'); - prevsbc = sbc; - - } - /* Skip trailing star-slash line. */ - get_line (); - aux_subcommands = sbc; -} - -