X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Flanguage%2Flexer%2Fq2c.c;h=20bdd564969adf24c05caf83d82e5104cf1f3f9c;hb=45e451f87ff06ec753ed9e860f2b1dd953ce5eed;hp=90357ebf958dbdc9cc2a74753f43b6b42f4df086;hpb=48386ee68a5283653435d05a9ea4e449710fd370;p=pspp
diff --git a/src/language/lexer/q2c.c b/src/language/lexer/q2c.c
index 90357ebf95..20bdd56496 100644
--- a/src/language/lexer/q2c.c
+++ b/src/language/lexer/q2c.c
@@ -1,20 +1,18 @@
-/* q2c - parser generator for PSPP procedures.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 1997-9, 2000, 2008, 2010, 2011 Free Software Foundation, Inc.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
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., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
+ along with this program. If not, see . */
#include
#include
@@ -85,8 +83,6 @@ static char *tokstr;
/* Utility functions. */
-static char nullstr[] = "";
-
/* Close all open files and delete the output file, on failure. */
static void
finish_up (void)
@@ -110,8 +106,8 @@ hcf (void)
exit (EXIT_FAILURE);
}
-int fail (const char *, ...) PRINTF_FORMAT (1, 2);
-int error (const char *, ...) PRINTF_FORMAT (1, 2);
+int fail (const char *, ...) PRINTF_FORMAT (1, 2) NO_RETURN;
+int error (const char *, ...) PRINTF_FORMAT (1, 2) NO_RETURN;
/* Output an error message and terminate unsuccessfully. */
int
@@ -152,14 +148,14 @@ static void *
xmalloc (size_t size)
{
void *vp;
-
+
if (size == 0)
return NULL;
-
+
vp = malloc (size);
if (!vp)
fail ("xmalloc(%lu): %s", (unsigned long) size, VME);
-
+
return vp;
}
@@ -173,11 +169,11 @@ xstrdup (const char *s)
assert (s != NULL);
size = strlen (s) + 1;
-
+
t = malloc (size);
if (!t)
fail ("xstrdup(%lu): %s", (unsigned long) strlen (s), VME);
-
+
memcpy (t, s, size);
return t;
}
@@ -192,22 +188,22 @@ get_buffer (void)
if (++cb >= 8)
cb = 0;
-
+
return b[cb];
}
-
+
/* Copies a string to a static buffer, converting it to lowercase in
the process, and returns a pointer to the static buffer. */
static char *
st_lower (const char *s)
{
char *p, *cp;
-
+
p = cp = get_buffer ();
while (*s)
*cp++ = tolower ((unsigned char) (*s++));
*cp++ = '\0';
-
+
return p;
}
@@ -222,18 +218,18 @@ st_upper (const char *s)
while (*s)
*cp++ = toupper ((unsigned char) (*s++));
*cp++ = '\0';
-
+
return p;
}
/* Returns the address of the first non-whitespace character in S, or
the address of the null terminator if none. */
static char *
-skip_ws (const char *s)
+skip_ws (char *s)
{
while (isspace ((unsigned char) *s))
s++;
- return (char *) s;
+ return s;
}
/* Read one line from the input file into buf. Lines having special
@@ -339,7 +335,7 @@ find_symbol (int x)
return iter;
}
-#if DUMP_TOKENS
+#if DUMP_TOKENS
/* Writes a printable representation of the current token to
stdout. */
static void
@@ -359,6 +355,45 @@ dump_token (void)
}
#endif /* DUMP_TOKENS */
+
+const char hyphen_proxy = '_';
+
+static void
+id_cpy (char **cp)
+{
+ char *dest = tokstr;
+ char *src = *cp;
+
+ while (*src == '_' || *src == '-' || isalnum ((unsigned char) *src))
+ {
+ *dest++ = *src == '-' ? hyphen_proxy :toupper ((unsigned char) (*src));
+ src++;
+ }
+
+ *cp = src;
+ *dest++ = '\0';
+}
+
+static char *
+unmunge (const char *s)
+{
+ char *dest = xmalloc (strlen (s) + 1);
+ char *d = dest;
+
+ while (*s)
+ {
+ if (*s == hyphen_proxy)
+ *d = '-';
+ else
+ *d = *s;
+ s++;
+ d++;
+ }
+ *d = '\0';
+
+ return dest;
+}
+
/* Reads a token from the input file. */
static int
lex_get (void)
@@ -369,11 +404,11 @@ lex_get (void)
cp = skip_ws (cp);
if (*cp != '\0')
break;
-
+
if (!get_line ())
fail ("%s: Unexpected end of file.", ifn);
}
-
+
if (*cp == '"')
{
char *dest = tokstr;
@@ -400,17 +435,16 @@ lex_get (void)
{
char *dest = tokstr;
token = T_ID;
- while (*cp == '_' || isalnum ((unsigned char) *cp))
- *dest++ = toupper ((unsigned char) (*cp++));
- *dest++ = '\0';
+
+ id_cpy (&cp);
}
else
token = *cp++;
-
+
#if DUMP_TOKENS
dump_token ();
#endif
-
+
return token;
}
@@ -472,7 +506,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. */
@@ -511,7 +546,7 @@ struct specifier
setting *def; /* Default setting. */
setting *omit_kw; /* Setting for which the keyword can be omitted. */
-
+
int index; /* Next array index. */
};
@@ -550,11 +585,7 @@ struct subcommand
int narray; /* Index of next array element. */
const char *prefix; /* Prefix for variable and constant names. */
specifier *spec; /* Array of specifiers. */
-
- /* SBC_STRING and SBC_INT only. */
- char *restriction; /* Expression restricting string length. */
- char *message; /* Error message. */
- int translatable; /* Error message is translatable */
+ char *pv_options; /* PV_* options for SBC_VARLIST. */
};
/* Name of the command; i.e., DESCRIPTIVES. */
@@ -601,7 +632,7 @@ static void
parse_setting (setting *s, specifier *spec)
{
s->parent = spec;
-
+
if (match_token ('*'))
{
if (spec->omit_kw)
@@ -609,7 +640,7 @@ parse_setting (setting *s, specifier *spec)
else
spec->omit_kw = s;
}
-
+
if (match_token ('!'))
{
if (spec->def)
@@ -617,7 +648,7 @@ parse_setting (setting *s, specifier *spec)
else
spec->def = s;
}
-
+
force_id ();
s->specname = xstrdup (tokstr);
s->con = add_symbol (s->specname, 0, 0);
@@ -637,20 +668,22 @@ parse_setting (setting *s, specifier *spec)
s->valtype = VT_PLAIN;
s->optvalue = match_token ('*');
-
+
if (match_id ("N"))
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 (':');
-
+
force_id ();
s->valname = xstrdup (tokstr);
lex_get ();
-
+
if (token == ',')
{
lex_get ();
@@ -660,7 +693,7 @@ parse_setting (setting *s, specifier *spec)
}
else
s->restriction = NULL;
-
+
if (s->valtype == VT_PAREN)
skip_token (')');
}
@@ -682,7 +715,7 @@ parse_specifier (specifier *spec, subcommand *sbc)
spec->varname = xstrdup (st_lower (tokstr));
lex_get ();
}
-
+
/* Handle array elements. */
if (token != ':')
{
@@ -698,20 +731,20 @@ parse_specifier (specifier *spec, subcommand *sbc)
return;
}
skip_token (':');
-
- if ( sbc->type == SBC_ARRAY && token == T_ID )
+
+ 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 **s);
@@ -736,7 +769,7 @@ parse_specifiers (subcommand *sbc)
*spec = NULL;
return;
}
-
+
for (;;)
{
*spec = xmalloc (sizeof **spec);
@@ -770,21 +803,20 @@ parse_subcommand (subcommand *sbc)
force_id ();
sbc->name = xstrdup (tokstr);
lex_get ();
-
+
sbc->narray = 0;
sbc->type = SBC_PLAIN;
sbc->spec = NULL;
- sbc->translatable = 0;
if (match_token ('['))
{
force_id ();
sbc->prefix = xstrdup (st_lower (tokstr));
lex_get ();
-
+
skip_token (']');
skip_token ('=');
-
+
sbc->type = SBC_ARRAY;
parse_specifiers (sbc);
@@ -796,12 +828,12 @@ parse_subcommand (subcommand *sbc)
force_id ();
sbc->prefix = xstrdup (st_lower (tokstr));
lex_get ();
-
+
skip_token (')');
}
else
sbc->prefix = "";
-
+
skip_token ('=');
if (match_id ("VAR"))
@@ -811,39 +843,18 @@ parse_subcommand (subcommand *sbc)
if (match_token ('('))
{
force_string ();
- sbc->message = xstrdup (tokstr);
+ sbc->pv_options = xstrdup (tokstr);
lex_get();
-
+
skip_token (')');
}
- else sbc->message = NULL;
+ else
+ sbc->pv_options = NULL;
sbc->type = SBC_VARLIST;
}
else if (match_id ("INTEGER"))
- {
sbc->type = match_id ("LIST") ? SBC_INT_LIST : SBC_INT;
- if ( token == T_STRING)
- {
- sbc->restriction = xstrdup (tokstr);
- lex_get ();
- if ( match_id("N_") )
- {
- skip_token('(');
- force_string ();
- lex_get();
- skip_token(')');
- sbc->translatable = 1;
- }
- else {
- force_string ();
- lex_get ();
- }
- sbc->message = xstrdup (tokstr);
- }
- else
- sbc->restriction = NULL;
- }
else if (match_id ("PINT"))
sbc->type = SBC_PINT;
else if (match_id ("DOUBLE"))
@@ -854,19 +865,7 @@ parse_subcommand (subcommand *sbc)
sbc->type = SBC_DBL;
}
else if (match_id ("STRING"))
- {
- sbc->type = SBC_STRING;
- if (token == T_STRING)
- {
- sbc->restriction = xstrdup (tokstr);
- lex_get ();
- force_string ();
- sbc->message = xstrdup (tokstr);
- lex_get ();
- }
- else
- sbc->restriction = NULL;
- }
+ sbc->type = SBC_STRING;
else if (match_id ("CUSTOM"))
sbc->type = SBC_CUSTOM;
else
@@ -879,7 +878,7 @@ void
parse_subcommands (void)
{
subcommand **sbc = &subcommands;
-
+
for (;;)
{
*sbc = xmalloc (sizeof **sbc);
@@ -922,7 +921,7 @@ dump (int indention, const char *format, ...)
if (indention < 0)
indent += BASE_INDENT * indention;
-
+
oln++;
va_start (args, format);
for (i = 0; i < indent; i++)
@@ -935,6 +934,19 @@ dump (int indention, const char *format, ...)
indent += BASE_INDENT * indention;
}
+/* Writes a blank line to the output file and adjusts 'indent' by BASE_INDENT
+ * INDENTION characters.
+
+ (This is only useful because GCC complains about using "" as a format
+ string, for whatever reason.) */
+static void
+dump_blank_line (int indention)
+{
+ oln++;
+ indent += BASE_INDENT * indention;
+ putc ('\n', out);
+}
+
/* Write the structure members for specifier SPEC to the output file.
SBC is the including subcommand. */
static void
@@ -942,7 +954,7 @@ dump_specifier_vars (const specifier *spec, const subcommand *sbc)
{
if (spec->varname)
dump (0, "long %s%s;", sbc->prefix, spec->varname);
-
+
{
setting *s;
@@ -952,8 +964,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));
}
@@ -993,7 +1008,7 @@ make_identifier (const char *name)
else
*cp++ = '_';
*cp = '\0';
-
+
return p;
}
@@ -1003,6 +1018,8 @@ dump_declarations (void)
{
indent = 0;
+ dump (0, "struct dataset;");
+
/* Write out enums for all the identifiers in the symbol table. */
{
int f, k;
@@ -1025,8 +1042,8 @@ dump_declarations (void)
if (buf == NULL)
buf = xmalloc (1024);
else
- dump (0, buf);
-
+ dump (0, "%s", buf);
+
if (k)
sprintf (buf, "%s%s,", st_upper (prefix), sym->name);
else
@@ -1038,13 +1055,13 @@ dump_declarations (void)
if (buf)
{
buf[strlen (buf) - 1] = 0;
- dump (0, buf);
+ dump (0, "%s", buf);
free (buf);
}
if (f)
{
dump (-1, "};");
- dump (-1, nullstr);
+ dump_blank_line (-1);
}
}
@@ -1063,7 +1080,7 @@ dump_declarations (void)
if (sbc->type == SBC_ARRAY && sbc->narray)
{
dump (0, "/* Array indices for %s subcommand. */", sbc->name);
-
+
dump (1, "enum");
dump (1, "{");
@@ -1078,7 +1095,7 @@ dump_declarations (void)
dump (0, "%s%scount", st_upper (prefix), st_upper (sbc->prefix));
dump (-1, "};");
- dump (-1, nullstr);
+ dump_blank_line (-1);
}
}
}
@@ -1095,8 +1112,8 @@ dump_declarations (void)
int f = 0;
if (sbc != subcommands)
- dump (0, nullstr);
-
+ dump_blank_line (0);
+
dump (0, "/* %s subcommand. */", sbc->name);
dump (0, "int sbc_%s;", st_lower (sbc->name));
@@ -1106,7 +1123,7 @@ dump_declarations (void)
case SBC_PLAIN:
{
specifier *spec;
-
+
for (spec = sbc->spec; spec; spec = spec->next)
{
if (spec->s == 0)
@@ -1116,8 +1133,8 @@ dump_declarations (void)
spec->varname);
else if (f == 0)
{
- dump (0, "int a_%s[%s%scount];",
- st_lower (sbc->name),
+ dump (0, "int a_%s[%s%scount];",
+ st_lower (sbc->name),
st_upper (prefix),
st_upper (sbc->prefix)
);
@@ -1173,7 +1190,7 @@ dump_declarations (void)
}
dump (-1, "};");
- dump (-1, nullstr);
+ dump_blank_line (-1);
}
/* Write out prototypes for custom_*() functions as necessary. */
@@ -1196,7 +1213,7 @@ dump_declarations (void)
}
if (seen)
- dump (0, nullstr);
+ dump_blank_line (0);
}
/* Prototypes for parsing and freeing functions. */
@@ -1206,7 +1223,7 @@ dump_declarations (void)
make_identifier (cmdname), make_identifier (cmdname));
dump (0, "static void free_%s (struct cmd_%s *);",
make_identifier (cmdname), make_identifier (cmdname));
- dump (0, nullstr);
+ dump_blank_line (0);
}
}
@@ -1226,7 +1243,7 @@ dump_specifier_init (const specifier *spec, const subcommand *sbc)
strcpy (s, "-1");
dump (0, "p->%s%s = %s;", sbc->prefix, spec->varname, s);
}
-
+
{
setting *s;
@@ -1236,8 +1253,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 ? "LONG_MIN"
+ : s->value == VAL_DBL ? "SYSMIS"
+ : "NULL");
dump (0, "p->%s%s = %s;", sbc->prefix, st_lower (s->valname), init);
}
@@ -1252,24 +1272,24 @@ dump_vars_init (int persistent)
/* Loop through all the subcommands. */
{
subcommand *sbc;
-
+
for (sbc = subcommands; sbc; sbc = sbc->next)
{
int f = 0;
-
+
dump (0, "p->sbc_%s = 0;", st_lower (sbc->name));
- if ( ! persistent )
+ if ( ! 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, "}");
@@ -1286,12 +1306,12 @@ dump_vars_init (int persistent)
case SBC_CUSTOM:
/* nothing */
break;
-
+
case SBC_PLAIN:
case SBC_ARRAY:
{
specifier *spec;
-
+
for (spec = sbc->spec; spec; spec = spec->next)
if (spec->s == NULL)
{
@@ -1315,7 +1335,7 @@ dump_vars_init (int persistent)
dump (0, "p->%sv_%s = NULL;",
st_lower (sbc->prefix), st_lower (sbc->name));
break;
-
+
case SBC_VAR:
dump (0, "p->%sv_%s = NULL;",
st_lower (sbc->prefix), st_lower (sbc->name));
@@ -1330,7 +1350,7 @@ dump_vars_init (int persistent)
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 (0, "p->n_%s[i] = LONG_MIN;", st_lower (sbc->name));
dump (-2, "}");
break;
@@ -1353,7 +1373,7 @@ make_match (const char *t)
while (*t == '_')
t++;
-
+
if (is_keyword (t))
sprintf (s, "lex_match (lexer, T_%s)", t);
else if (!strcmp (t, "ON") || !strcmp (t, "YES"))
@@ -1364,9 +1384,15 @@ make_match (const char *t)
"|| lex_match_id (lexer, \"FALSE\"))");
else if (isdigit ((unsigned char) t[0]))
sprintf (s, "lex_match_int (lexer, %s)", t);
+ else if (strchr (t, hyphen_proxy))
+ {
+ char *c = unmunge (t);
+ sprintf (s, "lex_match_phrase (lexer, \"%s\")", c);
+ free (c);
+ }
else
sprintf (s, "lex_match_id (lexer, \"%s\")", t);
-
+
return s;
}
@@ -1383,7 +1409,7 @@ dump_specifier_parse (const specifier *spec, const subcommand *sbc)
if (spec->omit_kw && spec->omit_kw->parent->next)
error ("Default specifier is not in last specifier in `%s' "
"subcommand.", sbc->name);
-
+
for (s = spec->s; s; s = s->next)
{
int first = spec == sbc->spec && s == spec->s;
@@ -1411,13 +1437,13 @@ dump_specifier_parse (const specifier *spec, const subcommand *sbc)
{
if (spec->omit_kw != s)
dump (1, "{");
-
+
if (spec->varname)
{
dump (0, "p->%s%s = %s%s;", sbc->prefix, spec->varname,
st_upper (prefix), find_symbol (s->con)->name);
- if ( sbc->type == SBC_ARRAY )
+ 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),
@@ -1429,17 +1455,16 @@ dump_specifier_parse (const specifier *spec, const subcommand *sbc)
{
if (s->optvalue)
{
- dump (1, "if (lex_match (lexer, '('))");
+ dump (1, "if (lex_match (lexer, T_LPAREN))");
dump (1, "{");
}
else
{
- dump (1, "if (!lex_match (lexer, '('))");
+ dump (1, "if (!lex_match (lexer, T_LPAREN))");
dump (1, "{");
- dump (0, "msg (SE, _(\"`(' expected after %s "
- "specifier of %s subcommand.\"));",
- s->specname, sbc->name);
- dump (0, "goto lossage;");
+ dump (0, "lex_error_expecting (lexer, \"`('\", "
+ "NULL_SENTINEL);");
+ dump (0, "goto lossage;");
dump (-1, "}");
outdent ();
}
@@ -1447,29 +1472,29 @@ dump_specifier_parse (const specifier *spec, const subcommand *sbc)
if (s->value == VAL_INT)
{
- 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 (1, "if (!lex_force_int (lexer))");
dump (0, "goto lossage;");
- dump (-1, "}");
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 (lexer))");
- dump (1, "{");
- dump (0, "msg (SE, _(\"Number expected after %s "
- "specifier of %s subcommand.\"));",
- s->specname, sbc->name);
+ dump (1, "if (!lex_force_num (lexer))");
dump (0, "goto lossage;");
- dump (-1, "}");
dump (-1, "p->%s%s = lex_tokval (lexer);", sbc->prefix,
st_lower (s->valname));
}
-
+ else if (s->value == VAL_STRING)
+ {
+ dump (1, "if (!lex_force_string_or_id (lexer))");
+ dump (0, "goto lossage;");
+ dump (-1, "free (p->%s%s);", sbc->prefix, st_lower (s->valname));
+ dump (0, "p->%s%s = ss_xstrdup (ss_tokss (lexer));",
+ sbc->prefix, st_lower (s->valname));
+ }
+ else
+ abort ();
+
if (s->restriction)
{
{
@@ -1483,27 +1508,20 @@ dump_specifier_parse (const specifier *spec, const subcommand *sbc)
free (str);
free (str2);
}
-
+
dump (1, "{");
- dump (0, "msg (SE, _(\"Bad argument for %s "
- "specifier of %s subcommand.\"));",
- s->specname, sbc->name);
+ dump (0, "lex_error (lexer, NULL);");
dump (0, "goto lossage;");
dump (-1, "}");
outdent ();
}
-
+
dump (0, "lex_get (lexer);");
-
+
if (s->valtype == VT_PAREN)
{
- dump (1, "if (!lex_match (lexer, ')'))");
- dump (1, "{");
- dump (0, "msg (SE, _(\"`)' expected after argument for "
- "%s specifier of %s.\"));",
- s->specname, sbc->name);
+ dump (1, "if (!lex_force_match (lexer, T_RPAREN))");
dump (0, "goto lossage;");
- dump (-1, "}");
outdent ();
if (s->optvalue)
{
@@ -1511,11 +1529,11 @@ dump_specifier_parse (const specifier *spec, const subcommand *sbc)
outdent ();
}
}
-
+
if (s != spec->omit_kw)
dump (-1, "}");
}
-
+
if (s == spec->omit_kw)
{
dump (-1, "}");
@@ -1533,9 +1551,9 @@ dump_subcommand (const subcommand *sbc)
{
int count;
- dump (1, "while (lex_token (lexer) != '/' && lex_token (lexer) != '.')");
+ dump (1, "while (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD)");
dump (1, "{");
-
+
{
specifier *spec;
@@ -1560,7 +1578,7 @@ dump_subcommand (const subcommand *sbc)
}
}
}
-
+
{
specifier *spec;
setting *s;
@@ -1591,7 +1609,7 @@ dump_subcommand (const subcommand *sbc)
}
}
- dump (0, "lex_match (lexer, ',');");
+ dump (0, "lex_match (lexer, T_COMMA);");
dump (-1, "}");
outdent ();
}
@@ -1601,8 +1619,8 @@ dump_subcommand (const subcommand *sbc)
"PV_APPEND%s%s))",
st_lower (sbc->prefix), st_lower (sbc->name),
st_lower (sbc->prefix), st_lower (sbc->name),
- sbc->message ? " |" : "",
- sbc->message ? sbc->message : "");
+ sbc->pv_options ? " |" : "",
+ sbc->pv_options ? sbc->pv_options : "");
dump (0, "goto lossage;");
outdent ();
}
@@ -1617,37 +1635,19 @@ dump_subcommand (const subcommand *sbc)
}
else if (sbc->type == SBC_STRING)
{
- if (sbc->restriction)
- {
- dump (1, "{");
- dump (0, "int x;");
- }
dump (1, "if (!lex_force_string (lexer))");
dump (0, "return false;");
outdent ();
- if (sbc->restriction)
- {
- 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.\"));",
- sbc->name, sbc->message);
- dump (0, "goto lossage;");
- dump (-1, "}");
- outdent ();
- }
dump (0, "free(p->s_%s);", st_lower(sbc->name) );
- dump (0, "p->s_%s = ds_xstrdup (lex_tokstr (lexer));",
+ dump (0, "p->s_%s = ss_xstrdup (lex_tokss (lexer));",
st_lower (sbc->name));
dump (0, "lex_get (lexer);");
- if (sbc->restriction)
- dump (-1, "}");
}
else if (sbc->type == SBC_DBL)
{
dump (1, "if (!lex_force_num (lexer))");
dump (0, "goto lossage;");
- dump (-1, "p->n_%s[p->sbc_%s - 1] = lex_number (lexer);",
+ dump (-1, "p->n_%s[p->sbc_%s - 1] = lex_number (lexer);",
st_lower (sbc->name), st_lower (sbc->name) );
dump (0, "lex_get(lexer);");
}
@@ -1659,49 +1659,38 @@ dump_subcommand (const subcommand *sbc)
dump (0, "goto lossage;");
dump (-1, "x = lex_integer (lexer);");
dump (0, "lex_get(lexer);");
- if (sbc->restriction)
- {
- char buf[1024];
- dump (1, "if (!(%s))", sbc->restriction);
- dump (1, "{");
- sprintf(buf,sbc->message,sbc->name);
- if ( sbc->translatable )
- dump (0, "msg (SE, gettext(\"%s\"));",buf);
- else
- dump (0, "msg (SE, \"%s\");",buf);
- dump (0, "goto lossage;");
- dump (-1, "}");
- }
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)
{
- dump (0, "lex_match (lexer, '(');");
+ dump (0, "lex_match (lexer, T_LPAREN);");
dump (1, "if (!lex_force_int (lexer))");
dump (0, "goto lossage;");
dump (-1, "p->n_%s = lex_integer (lexer);", st_lower (sbc->name));
- dump (0, "lex_match (lexer, ')');");
+ dump (0, "lex_match (lexer, T_RPAREN);");
}
- 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, "{");
- dump (0, "msg (SE, \"No more than %%d %s subcommands allowed\",MAXLISTS);",st_lower(sbc->name));
+ dump (0, "subc_list_error (lexer, \"%s\", MAXLISTS);",
+ st_lower(sbc->name));
dump (0, "goto lossage;");
dump (-1,"}");
- dump (1, "while (lex_token (lexer) != '/' && lex_token (lexer) != '.')");
+ dump (1, "while (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD)");
dump (1, "{");
- dump (0, "lex_match (lexer, ',');");
+ dump (0, "lex_match (lexer, T_COMMA);");
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 (lexer));",
- 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 (lexer);");
dump (-1,"}");
@@ -1754,13 +1743,13 @@ dump_parser (int persistent)
{
if (def->type == SBC_VARLIST)
dump (1, "if (lex_token (lexer) == T_ID "
- "&& dict_lookup_var (dataset_dict (ds), lex_tokid (lexer)) != NULL "
- "&& lex_look_ahead (lexer) != '=')");
+ "&& dict_lookup_var (dataset_dict (ds), lex_tokcstr (lexer)) != NULL "
+ "&& lex_next_token (lexer, 1) != T_EQUALS)");
else
{
dump (0, "if ((lex_token (lexer) == T_ID "
- "&& dict_lookup_var (dataset_dict (ds), lex_tokid (lexer)) "
- "&& lex_look_ahead () != '=')");
+ "&& dict_lookup_var (dataset_dict (ds), lex_tokcstr (lexer)) "
+ "&& lex_next_token (lexer, 1) != T_EQUALS)");
dump (1, " || token == T_ALL)");
}
dump (1, "{");
@@ -1794,7 +1783,7 @@ dump_parser (int persistent)
dump (-1, "}");
outdent ();
}
-
+
{
subcommand *sbc;
@@ -1804,14 +1793,13 @@ dump_parser (int persistent)
f = 1;
dump (1, "{");
- dump (0, "lex_match (lexer, '=');");
+ dump (0, "lex_match (lexer, T_EQUALS);");
dump (0, "p->sbc_%s++;", st_lower (sbc->name));
if (sbc->arity != ARITY_MANY)
{
dump (1, "if (p->sbc_%s > 1)", st_lower (sbc->name));
dump (1, "{");
- dump (0, "msg (SE, _(\"%s subcommand may be given only once.\"));",
- sbc->name);
+ dump (0, "lex_sbc_only_once (\"%s\");", sbc->name);
dump (0, "goto lossage;");
dump (-1, "}");
outdent ();
@@ -1824,33 +1812,33 @@ dump_parser (int persistent)
/* Now deal with the /ALGORITHM subcommand implicit to all commands */
- dump(1,"else if ( get_syntax() != COMPATIBLE && lex_match_id(lexer, \"ALGORITHM\"))");
+ dump(1,"else if ( settings_get_syntax () != COMPATIBLE && lex_match_id(lexer, \"ALGORITHM\"))");
dump(1,"{");
- dump (0, "lex_match (lexer, '=');");
+ dump (0, "lex_match (lexer, T_EQUALS);");
dump(1,"if (lex_match_id(lexer, \"COMPATIBLE\"))");
- dump(0,"set_cmd_algorithm(COMPATIBLE);");
+ dump(0,"settings_set_cmd_algorithm (COMPATIBLE);");
outdent();
dump(1,"else if (lex_match_id(lexer, \"ENHANCED\"))");
- dump(0,"set_cmd_algorithm(ENHANCED);");
+ dump(0,"settings_set_cmd_algorithm (ENHANCED);");
dump (-1, "}");
outdent ();
-
- dump (1, "if (!lex_match (lexer, '/'))");
+
+ dump (1, "if (!lex_match (lexer, T_SLASH))");
dump (0, "break;");
dump (-2, "}");
outdent ();
- dump (0, nullstr);
- dump (1, "if (lex_token (lexer) != '.')");
+ dump_blank_line (0);
+ dump (1, "if (lex_token (lexer) != T_ENDCMD)");
dump (1, "{");
dump (0, "lex_error (lexer, _(\"expecting end of command\"));");
dump (0, "goto lossage;");
dump (-1, "}");
- dump (0, nullstr);
+ dump_blank_line (0);
outdent ();
@@ -1861,27 +1849,26 @@ dump_parser (int persistent)
for (sbc = subcommands; sbc; sbc = sbc->next)
{
- if ( sbc->arity == ARITY_ONCE_EXACTLY )
+ 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, "lex_sbc_missing (\"%s\");", sbc->name);
dump (0, "goto lossage;");
dump (-1, "}");
- dump (0, nullstr);
+ dump_blank_line (0);
}
}
}
dump (-1, "return true;");
- dump (0, nullstr);
+ dump_blank_line (0);
dump (-1, "lossage:");
indent ();
dump (0, "free_%s (p);", make_identifier (cmdname));
dump (0, "return false;");
dump (-1, "}");
- dump (0, nullstr);
+ dump_blank_line (0);
}
@@ -1891,7 +1878,7 @@ dump_header (void)
{
indent = 0;
dump (0, "/* %s\t\t-*- mode: c; buffer-read-only: t -*-", ofn);
- dump (0, nullstr);
+ dump_blank_line (0);
dump (0, " Generated by q2c from %s.", ifn);
dump (0, " Do not modify!");
dump (0, " */");
@@ -1907,16 +1894,12 @@ dump_free (int persistent)
indent = 0;
used = 0;
- if ( ! 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");
@@ -1924,12 +1907,12 @@ dump_free (int persistent)
make_identifier (cmdname), used ? "" : " UNUSED");
dump (1, "{");
- if ( ! persistent )
+ if ( ! persistent )
{
for (sbc = subcommands; sbc; sbc = sbc->next)
{
- switch (sbc->type)
+ switch (sbc->type)
{
case SBC_VARLIST:
dump (0, "free (p->v_%s);", st_lower (sbc->name));
@@ -1938,13 +1921,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;
}
@@ -1964,7 +1962,7 @@ recognize_directive (void)
{
static char directive[16];
char *sp, *ep;
-
+
sp = skip_ws (buf);
if (strncmp (sp, "/*", 2))
return NULL;
@@ -1983,7 +1981,7 @@ recognize_directive (void)
directive[ep - sp] = '\0';
return directive;
}
-
+
int
main (int argc, char *argv[])
{
@@ -2018,7 +2016,7 @@ main (int argc, char *argv[])
dump (0, "%s", buf);
continue;
}
-
+
dump (0, "#line %d \"%s\"", oln + 1, ofn);
if (!strcmp (directive, "specification"))
{
@@ -2036,32 +2034,33 @@ main (int argc, char *argv[])
indent = 0;
dump (0, "#include ");
- dump (0, "#include ");
- dump (0, "#include ");
- dump (0, "#include ");
- dump (0, "#include ");
- dump (0, "#include ");
- dump (0, "#include ");
- dump (0, "#include ");
- dump (0, "#include ");
- dump (0, "#include ");
- dump (0, nullstr);
-
- dump (0, "#include \"gettext.h\"");
- dump (0, "#define _(msgid) gettext (msgid)");
- dump (0, nullstr);
+ dump_blank_line (0);
+
+ dump (0, "#include \"data/settings.h\"");
+ dump (0, "#include \"data/variable.h\"");
+ dump (0, "#include \"language/lexer/lexer.h\"");
+ dump (0, "#include \"language/lexer/subcommand-list.h\"");
+ dump (0, "#include \"language/lexer/variable-parser.h\"");
+ dump (0, "#include \"libpspp/assertion.h\"");
+ dump (0, "#include \"libpspp/cast.h\"");
+ dump (0, "#include \"libpspp/message.h\"");
+ dump (0, "#include \"libpspp/str.h\"");
+ dump_blank_line (0);
+
+ dump (0, "#include \"gl/xalloc.h\"");
+ dump_blank_line (0);
}
else if (!strcmp (directive, "declarations"))
dump_declarations ();
else if (!strcmp (directive, "functions"))
{
dump_parser (0);
- dump_free (0);
+ dump_free (0);
}
else if (!strcmp (directive, "_functions"))
{
dump_parser (1);
- dump_free (1);
+ dump_free (1);
}
else
error ("unknown directive `%s'", directive);