X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Flexer%2Fq2c.c;h=78c626d4b5624783cc4b4af0a345289958f84495;hb=41a3a550334da96a9b4e5e089ad1768acf288092;hp=70a4d780db1187014d41cfa4f40a21daf7680e8d;hpb=244ade48f9c233532cc535d3233fdef53bf9266b;p=pspp diff --git a/src/language/lexer/q2c.c b/src/language/lexer/q2c.c index 70a4d780db..78c626d4b5 100644 --- a/src/language/lexer/q2c.c +++ b/src/language/lexer/q2c.c @@ -1,6 +1,5 @@ /* q2c - parser generator for PSPP procedures. Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. - Written by Ben Pfaff . This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -17,22 +16,36 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include - #include #include #include #include #include -#include +#include +#include #include #include -#include -#include -#include -#include "exit.h" - +/* GNU C allows the programmer to declare that certain functions take + printf-like arguments, never return, etc. Conditionalize these + declarations on whether gcc is in use. */ +#if __GNUC__ > 1 +#define ATTRIBUTE(X) __attribute__ (X) +#else +#define ATTRIBUTE(X) +#endif + +/* Marks a function argument as possibly not used. */ +#define UNUSED ATTRIBUTE ((unused)) + +/* Marks a function that will never return. */ +#define NO_RETURN ATTRIBUTE ((noreturn)) + +/* Mark a function as taking a printf- or scanf-like format + string as its FMT'th argument and that the FIRST'th argument + is the first one to be checked against the format string. */ +#define PRINTF_FORMAT(FMT, FIRST) ATTRIBUTE ((format (__printf__, FMT, FIRST))) + /* Max length of an input line. */ #define MAX_LINE_LEN 1024 @@ -40,22 +53,22 @@ #define MAX_TOK_LEN 1024 /* argv[0]. */ -char *program_name; +static char *program_name; /* Have the input and output files been opened yet? */ -bool is_open; +static bool is_open; /* Input, output files. */ -FILE *in, *out; +static FILE *in, *out; /* Input, output file names. */ -char *ifn, *ofn; +static char *ifn, *ofn; /* Input, output file line number. */ -int ln, oln = 1; +static int ln, oln = 1; /* Input line buffer, current position. */ -char *buf, *cp; +static char *buf, *cp; /* Token types. */ enum @@ -65,14 +78,14 @@ enum }; /* Current token: either one of the above, or a single character. */ -int token; +static int token; /* Token string value. */ -char *tokstr; +static char *tokstr; /* Utility functions. */ -char nullstr[] = ""; +static char nullstr[] = ""; /* Close all open files and delete the output file, on failure. */ static void @@ -459,7 +472,8 @@ enum { VAL_NONE, /* No value. */ VAL_INT, /* Integer value. */ - VAL_DBL /* Floating point value. */ + VAL_DBL, /* Floating point value. */ + VAL_STRING /* String value. */ }; /* For those specifiers with values, the syntax of those values. */ @@ -629,8 +643,10 @@ parse_setting (setting *s, specifier *spec) s->value = VAL_INT; else if (match_id ("D")) s->value = VAL_DBL; + else if (match_id ("S")) + s->value = VAL_STRING; else - error ("`n' or `d' expected."); + error ("`n', `d', or `s' expected."); skip_token (':'); @@ -939,8 +955,11 @@ dump_specifier_vars (const specifier *spec, const subcommand *sbc) { const char *typename; - assert (s->value == VAL_INT || s->value == VAL_DBL); - typename = s->value == VAL_INT ? "long" : "double"; + assert (s->value == VAL_INT || s->value == VAL_DBL + || s->value == VAL_STRING); + typename = (s->value == VAL_INT ? "long" + : s->value == VAL_DBL ? "double" + : "char *"); dump (0, "%s %s%s;", typename, sbc->prefix, st_lower (s->valname)); } @@ -990,6 +1009,8 @@ dump_declarations (void) { indent = 0; + dump (0, "struct dataset;"); + /* Write out enums for all the identifiers in the symbol table. */ { int f, k; @@ -1121,12 +1142,12 @@ dump_declarations (void) case SBC_VARLIST: dump (0, "size_t %sn_%s;", st_lower (sbc->prefix), st_lower (sbc->name)); - dump (0, "struct variable **%sv_%s;", st_lower (sbc->prefix), + dump (0, "const struct variable **%sv_%s;", st_lower (sbc->prefix), st_lower (sbc->name)); break; case SBC_VAR: - dump (0, "struct variable *%sv_%s;", st_lower (sbc->prefix), + dump (0, "const struct variable *%sv_%s;", st_lower (sbc->prefix), st_lower (sbc->name)); break; @@ -1177,7 +1198,7 @@ dump_declarations (void) dump (0, "/* Prototype for custom subcommands of %s. */", cmdname); } - dump (0, "static int %scustom_%s (struct dataset *, struct cmd_%s *, void *);", + dump (0, "static int %scustom_%s (struct lexer *, struct dataset *, struct cmd_%s *, void *);", st_lower (prefix), st_lower (sbc->name), make_identifier (cmdname)); } @@ -1189,7 +1210,7 @@ dump_declarations (void) /* Prototypes for parsing and freeing functions. */ { dump (0, "/* Command parsing functions. */"); - dump (0, "static int parse_%s (struct dataset *, struct cmd_%s *, void *);", + dump (0, "static int parse_%s (struct lexer *, struct dataset *, struct cmd_%s *, void *);", make_identifier (cmdname), make_identifier (cmdname)); dump (0, "static void free_%s (struct cmd_%s *);", make_identifier (cmdname), make_identifier (cmdname)); @@ -1223,8 +1244,11 @@ dump_specifier_init (const specifier *spec, const subcommand *sbc) { const char *init; - assert (s->value == VAL_INT || s->value == VAL_DBL); - init = s->value == VAL_INT ? "NOT_LONG" : "SYSMIS"; + assert (s->value == VAL_INT || s->value == VAL_DBL + || s->value == VAL_STRING); + init = (s->value == VAL_INT ? "NOT_LONG" + : s->value == VAL_DBL ? "SYSMIS" + : "NULL"); dump (0, "p->%s%s = %s;", sbc->prefix, st_lower (s->valname), init); } @@ -1250,13 +1274,13 @@ dump_vars_init (int persistent) switch (sbc->type) { case SBC_INT_LIST: - break; - case SBC_DBL_LIST: dump (1, "{"); dump (0, "int i;"); dump (1, "for (i = 0; i < MAXLISTS; ++i)"); - dump (0, "subc_list_double_create(&p->dl_%s[i]) ;", + dump (0, "subc_list_%s_create(&p->%cl_%s[i]) ;", + sbc->type == SBC_INT_LIST ? "int" : "double", + sbc->type == SBC_INT_LIST ? 'i' : 'd', st_lower (sbc->name) ); dump (-2, "}"); @@ -1322,7 +1346,7 @@ dump_vars_init (int persistent) break; default: - NOT_REACHED (); + abort (); } } } @@ -1342,17 +1366,17 @@ make_match (const char *t) t++; if (is_keyword (t)) - sprintf (s, "lex_match (T_%s)", t); + sprintf (s, "lex_match (lexer, T_%s)", t); else if (!strcmp (t, "ON") || !strcmp (t, "YES")) - strcpy (s, "(lex_match_id (\"ON\") || lex_match_id (\"YES\") " - "|| lex_match_id (\"TRUE\"))"); + strcpy (s, "(lex_match_id (lexer, \"ON\") || lex_match_id (lexer, \"YES\") " + "|| lex_match_id (lexer, \"TRUE\"))"); else if (!strcmp (t, "OFF") || !strcmp (t, "NO")) - strcpy (s, "(lex_match_id (\"OFF\") || lex_match_id (\"NO\") " - "|| lex_match_id (\"FALSE\"))"); + strcpy (s, "(lex_match_id (lexer, \"OFF\") || lex_match_id (lexer, \"NO\") " + "|| lex_match_id (lexer, \"FALSE\"))"); else if (isdigit ((unsigned char) t[0])) - sprintf (s, "lex_match_int (%s)", t); + sprintf (s, "lex_match_int (lexer, %s)", t); else - sprintf (s, "lex_match_id (\"%s\")", t); + sprintf (s, "lex_match_id (lexer, \"%s\")", t); return s; } @@ -1416,12 +1440,12 @@ dump_specifier_parse (const specifier *spec, const subcommand *sbc) { if (s->optvalue) { - dump (1, "if (lex_match ('('))"); + dump (1, "if (lex_match (lexer, '('))"); dump (1, "{"); } else { - dump (1, "if (!lex_match ('('))"); + dump (1, "if (!lex_match (lexer, '('))"); dump (1, "{"); dump (0, "msg (SE, _(\"`(' expected after %s " "specifier of %s subcommand.\"));", @@ -1434,28 +1458,44 @@ dump_specifier_parse (const specifier *spec, const subcommand *sbc) if (s->value == VAL_INT) { - dump (1, "if (!lex_is_integer ())"); + dump (1, "if (!lex_is_integer (lexer))"); dump (1, "{"); dump (0, "msg (SE, _(\"%s specifier of %s subcommand " "requires an integer argument.\"));", s->specname, sbc->name); dump (0, "goto lossage;"); dump (-1, "}"); - dump (-1, "p->%s%s = lex_integer ();", + dump (-1, "p->%s%s = lex_integer (lexer);", sbc->prefix, st_lower (s->valname)); } - else + else if (s->value == VAL_DBL) { - dump (1, "if (!lex_is_number ())"); + dump (1, "if (!lex_is_number (lexer))"); dump (1, "{"); dump (0, "msg (SE, _(\"Number expected after %s " "specifier of %s subcommand.\"));", s->specname, sbc->name); dump (0, "goto lossage;"); dump (-1, "}"); - dump (-1, "p->%s%s = tokval;", sbc->prefix, + dump (-1, "p->%s%s = lex_tokval (lexer);", sbc->prefix, st_lower (s->valname)); } + else if (s->value == VAL_STRING) + { + dump (1, "if (lex_token (lexer) != T_ID " + "&& lex_token (lexer) != T_STRING)"); + dump (1, "{"); + dump (0, "msg (SE, _(\"%s specifier of %s subcommand " + "requires a string argument.\"));", + s->specname, sbc->name); + dump (0, "goto lossage;"); + dump (-1, "}"); + dump (-1, "free (p->%s%s);", sbc->prefix, st_lower (s->valname)); + dump (0, "p->%s%s = xstrdup (ds_cstr (lex_tokstr (lexer)));", + sbc->prefix, st_lower (s->valname)); + } + else + abort (); if (s->restriction) { @@ -1480,11 +1520,11 @@ dump_specifier_parse (const specifier *spec, const subcommand *sbc) outdent (); } - dump (0, "lex_get ();"); + dump (0, "lex_get (lexer);"); if (s->valtype == VT_PAREN) { - dump (1, "if (!lex_match (')'))"); + dump (1, "if (!lex_match (lexer, ')'))"); dump (1, "{"); dump (0, "msg (SE, _(\"`)' expected after argument for " "%s specifier of %s.\"));", @@ -1520,7 +1560,7 @@ dump_subcommand (const subcommand *sbc) { int count; - dump (1, "while (token != '/' && token != '.')"); + dump (1, "while (lex_token (lexer) != '/' && lex_token (lexer) != '.')"); dump (1, "{"); { @@ -1571,20 +1611,20 @@ dump_subcommand (const subcommand *sbc) { dump (1, "else"); dump (1, "{"); - dump (0, "lex_error (NULL);"); + dump (0, "lex_error (lexer, NULL);"); dump (0, "goto lossage;"); dump (-1, "}"); outdent (); } } - dump (0, "lex_match (',');"); + dump (0, "lex_match (lexer, ',');"); dump (-1, "}"); outdent (); } else if (sbc->type == SBC_VARLIST) { - dump (1, "if (!parse_variables (dataset_dict (ds), &p->%sv_%s, &p->%sn_%s, " + dump (1, "if (!parse_variables_const (lexer, dataset_dict (ds), &p->%sv_%s, &p->%sn_%s, " "PV_APPEND%s%s))", st_lower (sbc->prefix), st_lower (sbc->name), st_lower (sbc->prefix), st_lower (sbc->name), @@ -1595,7 +1635,7 @@ dump_subcommand (const subcommand *sbc) } else if (sbc->type == SBC_VAR) { - dump (0, "p->%sv_%s = parse_variable (dataset_dict (ds));", + dump (0, "p->%sv_%s = parse_variable (lexer, dataset_dict (ds));", st_lower (sbc->prefix), st_lower (sbc->name)); dump (1, "if (!p->%sv_%s)", st_lower (sbc->prefix), st_lower (sbc->name)); @@ -1609,12 +1649,12 @@ dump_subcommand (const subcommand *sbc) dump (1, "{"); dump (0, "int x;"); } - dump (1, "if (!lex_force_string ())"); + dump (1, "if (!lex_force_string (lexer))"); dump (0, "return false;"); outdent (); if (sbc->restriction) { - dump (0, "x = ds_length (&tokstr);"); + dump (0, "x = ds_length (lex_tokstr (lexer));"); dump (1, "if (!(%s))", sbc->restriction); dump (1, "{"); dump (0, "msg (SE, _(\"String for %s must be %s.\"));", @@ -1624,28 +1664,28 @@ dump_subcommand (const subcommand *sbc) outdent (); } dump (0, "free(p->s_%s);", st_lower(sbc->name) ); - dump (0, "p->s_%s = ds_xstrdup (&tokstr);", + dump (0, "p->s_%s = ds_xstrdup (lex_tokstr (lexer));", st_lower (sbc->name)); - dump (0, "lex_get ();"); + dump (0, "lex_get (lexer);"); if (sbc->restriction) dump (-1, "}"); } else if (sbc->type == SBC_DBL) { - dump (1, "if (!lex_force_num ())"); + dump (1, "if (!lex_force_num (lexer))"); dump (0, "goto lossage;"); - dump (-1, "p->n_%s[p->sbc_%s - 1] = lex_number ();", + dump (-1, "p->n_%s[p->sbc_%s - 1] = lex_number (lexer);", st_lower (sbc->name), st_lower (sbc->name) ); - dump (0, "lex_get();"); + dump (0, "lex_get(lexer);"); } else if (sbc->type == SBC_INT) { dump(1, "{"); dump(0, "int x;"); - dump (1, "if (!lex_force_int ())"); + dump (1, "if (!lex_force_int (lexer))"); dump (0, "goto lossage;"); - dump (-1, "x = lex_integer ();"); - dump (0, "lex_get();"); + dump (-1, "x = lex_integer (lexer);"); + dump (0, "lex_get(lexer);"); if (sbc->restriction) { char buf[1024]; @@ -1664,13 +1704,13 @@ dump_subcommand (const subcommand *sbc) } else if (sbc->type == SBC_PINT) { - dump (0, "lex_match ('(');"); - dump (1, "if (!lex_force_int ())"); + dump (0, "lex_match (lexer, '(');"); + dump (1, "if (!lex_force_int (lexer))"); dump (0, "goto lossage;"); - dump (-1, "p->n_%s = lex_integer ();", st_lower (sbc->name)); - dump (0, "lex_match (')');"); + dump (-1, "p->n_%s = lex_integer (lexer);", st_lower (sbc->name)); + dump (0, "lex_match (lexer, ')');"); } - else if (sbc->type == SBC_DBL_LIST) + else if (sbc->type == SBC_DBL_LIST || sbc->type == SBC_INT_LIST) { dump (0, "if ( p->sbc_%s > MAXLISTS)",st_lower(sbc->name)); dump (1, "{"); @@ -1678,25 +1718,26 @@ dump_subcommand (const subcommand *sbc) dump (0, "goto lossage;"); dump (-1,"}"); - dump (1, "while (token != '/' && token != '.')"); + dump (1, "while (lex_token (lexer) != '/' && lex_token (lexer) != '.')"); dump (1, "{"); - dump (0, "lex_match(',');"); - dump (0, "if (!lex_force_num ())"); + dump (0, "lex_match (lexer, ',');"); + dump (0, "if (!lex_force_num (lexer))"); dump (1, "{"); dump (0, "goto lossage;"); dump (-1,"}"); - dump (0, "subc_list_double_push(&p->dl_%s[p->sbc_%s-1],lex_number ());", - st_lower (sbc->name),st_lower (sbc->name) - ); + dump (0, "subc_list_%s_push (&p->%cl_%s[p->sbc_%s-1], lex_number (lexer));", + sbc->type == SBC_INT_LIST ? "int" : "double", + sbc->type == SBC_INT_LIST ? 'i' : 'd', + st_lower (sbc->name), st_lower (sbc->name)); - dump (0, "lex_get();"); + dump (0, "lex_get (lexer);"); dump (-1,"}"); } else if (sbc->type == SBC_CUSTOM) { - dump (1, "switch (%scustom_%s (ds, p, aux))", + dump (1, "switch (%scustom_%s (lexer, ds, p, aux))", st_lower (prefix), st_lower (sbc->name)); dump (0, "{"); dump (1, "case 0:"); @@ -1706,7 +1747,7 @@ dump_subcommand (const subcommand *sbc) dump (0, "break;"); dump (-1, "case 2:"); indent (); - dump (0, "lex_error (NULL);"); + dump (0, "lex_error (lexer, NULL);"); dump (0, "goto lossage;"); dump (-1, "default:"); indent (); @@ -1725,7 +1766,7 @@ dump_parser (int persistent) indent = 0; dump (0, "static int"); - dump (0, "parse_%s (struct dataset *ds%s, struct cmd_%s *p, void *aux UNUSED)", + dump (0, "parse_%s (struct lexer *lexer, struct dataset *ds%s, struct cmd_%s *p, void *aux UNUSED)", make_identifier (cmdname), (def && ( def->type == SBC_VARLIST && def->type == SBC_CUSTOM))?"":" UNUSED", make_identifier (cmdname)); @@ -1740,19 +1781,19 @@ dump_parser (int persistent) if (def && (def->type == SBC_VARLIST)) { if (def->type == SBC_VARLIST) - dump (1, "if (token == T_ID " - "&& dict_lookup_var (dataset_dict (ds), tokid) != NULL " - "&& lex_look_ahead () != '=')"); + dump (1, "if (lex_token (lexer) == T_ID " + "&& dict_lookup_var (dataset_dict (ds), lex_tokid (lexer)) != NULL " + "&& lex_look_ahead (lexer) != '=')"); else { - dump (0, "if ((token == T_ID " - "&& dict_lookup_var (dataset_dict (ds), tokid) " + dump (0, "if ((lex_token (lexer) == T_ID " + "&& dict_lookup_var (dataset_dict (ds), lex_tokid (lexer)) " "&& lex_look_ahead () != '=')"); dump (1, " || token == T_ALL)"); } dump (1, "{"); dump (0, "p->sbc_%s++;", st_lower (def->name)); - dump (1, "if (!parse_variables (dataset_dict (ds), &p->%sv_%s, &p->%sn_%s, " + dump (1, "if (!parse_variables_const (lexer, dataset_dict (ds), &p->%sv_%s, &p->%sn_%s, " "PV_APPEND))", st_lower (def->prefix), st_lower (def->name), st_lower (def->prefix), st_lower (def->name)); @@ -1763,7 +1804,7 @@ dump_parser (int persistent) } else if (def && def->type == SBC_CUSTOM) { - dump (1, "switch (%scustom_%s (ds, p, aux))", + dump (1, "switch (%scustom_%s (lexer, ds, p, aux))", st_lower (prefix), st_lower (def->name)); dump (0, "{"); dump (1, "case 0:"); @@ -1791,7 +1832,7 @@ dump_parser (int persistent) f = 1; dump (1, "{"); - dump (0, "lex_match ('=');"); + dump (0, "lex_match (lexer, '=');"); dump (0, "p->sbc_%s++;", st_lower (sbc->name)); if (sbc->arity != ARITY_MANY) { @@ -1811,15 +1852,15 @@ dump_parser (int persistent) /* Now deal with the /ALGORITHM subcommand implicit to all commands */ - dump(1,"else if ( get_syntax() != COMPATIBLE && lex_match_id(\"ALGORITHM\"))"); + dump(1,"else if ( get_syntax() != COMPATIBLE && lex_match_id(lexer, \"ALGORITHM\"))"); dump(1,"{"); - dump (0, "lex_match ('=');"); + dump (0, "lex_match (lexer, '=');"); - dump(1,"if (lex_match_id(\"COMPATIBLE\"))"); + dump(1,"if (lex_match_id(lexer, \"COMPATIBLE\"))"); dump(0,"set_cmd_algorithm(COMPATIBLE);"); outdent(); - dump(1,"else if (lex_match_id(\"ENHANCED\"))"); + dump(1,"else if (lex_match_id(lexer, \"ENHANCED\"))"); dump(0,"set_cmd_algorithm(ENHANCED);"); dump (-1, "}"); @@ -1827,14 +1868,14 @@ dump_parser (int persistent) - dump (1, "if (!lex_match ('/'))"); + dump (1, "if (!lex_match (lexer, '/'))"); dump (0, "break;"); dump (-2, "}"); outdent (); dump (0, nullstr); - dump (1, "if (token != '.')"); + dump (1, "if (lex_token (lexer) != '.')"); dump (1, "{"); - dump (0, "lex_error (_(\"expecting end of command\"));"); + dump (0, "lex_error (lexer, _(\"expecting end of command\"));"); dump (0, "goto lossage;"); dump (-1, "}"); dump (0, nullstr); @@ -1876,18 +1917,10 @@ dump_parser (int persistent) static void dump_header (void) { - time_t curtime; - struct tm *loctime; - char *timep; - indent = 0; - curtime = time (NULL); - loctime = localtime (&curtime); - timep = asctime (loctime); - timep[strlen (timep) - 1] = 0; dump (0, "/* %s\t\t-*- mode: c; buffer-read-only: t -*-", ofn); dump (0, nullstr); - dump (0, " Generated by q2c from %s on %s.", ifn, timep); + dump (0, " Generated by q2c from %s.", ifn); dump (0, " Do not modify!"); dump (0, " */"); } @@ -1905,13 +1938,9 @@ dump_free (int persistent) if ( ! persistent ) { for (sbc = subcommands; sbc; sbc = sbc->next) - { - if (sbc->type == SBC_STRING) - used = 1; - if (sbc->type == SBC_DBL_LIST) - used = 1; - } - + used = (sbc->type == SBC_STRING + || sbc->type == SBC_DBL_LIST + || sbc->type == SBC_INT_LIST); } dump (0, "static void"); @@ -1933,13 +1962,28 @@ dump_free (int persistent) dump (0, "free (p->s_%s);", st_lower (sbc->name)); break; case SBC_DBL_LIST: + case SBC_INT_LIST: dump (0, "{"); dump (1, "int i;"); dump (2, "for(i = 0; i < MAXLISTS ; ++i)"); - dump (1, "subc_list_double_destroy(&p->dl_%s[i]);", st_lower (sbc->name)); + dump (1, "subc_list_%s_destroy(&p->%cl_%s[i]);", + sbc->type == SBC_INT_LIST ? "int" : "double", + sbc->type == SBC_INT_LIST ? 'i' : 'd', + st_lower (sbc->name)); dump (0, "}"); outdent(); break; + case SBC_PLAIN: + { + specifier *spec; + setting *s; + + for (spec = sbc->spec; spec; spec = spec->next) + for (s = spec->s; s; s = s->next) + if (s->value == VAL_STRING) + dump (0, "free (p->%s%s);", + sbc->prefix, st_lower (s->valname)); + } default: break; } @@ -2037,6 +2081,7 @@ main (int argc, char *argv[]) dump (0, "#include "); dump (0, "#include "); dump (0, "#include "); + dump (0, "#include "); dump (0, "#include "); dump (0, "#include "); dump (0, "#include ");