From 80e4b4e85d2159c3ac6bcb8c22b895c58f0c5b0d Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 16 Apr 2007 03:59:32 +0000 Subject: [PATCH] Fully support lists of integer values. Add support for lists of string values. Add some more needed declarations to headers. Patch #5868. --- doc/q2c.texi | 26 +++++++---- po/pspp.pot | 22 +++++----- src/language/lexer/ChangeLog | 6 +++ src/language/lexer/q2c.c | 84 ++++++++++++++++++++++++++---------- 4 files changed, 96 insertions(+), 42 deletions(-) diff --git a/doc/q2c.texi b/doc/q2c.texi index 280c543a..51406083 100644 --- a/doc/q2c.texi +++ b/doc/q2c.texi @@ -112,15 +112,23 @@ themselves. The syntax of the grammar rules is as follows: @example -grammar-rules ::= ID : subcommands . +grammar-rules ::= command-name opt-prefix : subcommands . +command-name ::= ID + ::= STRING +opt-prefix ::= + ::= ( ID ) subcommands ::= subcommand ::= subcommands ; subcommand @end example -The syntax begins with an ID or STRING token that gives the name of the -procedure to be parsed. The rest of the syntax consists of subcommands -separated by semicolons (@samp{;}) and terminated with a full stop -(@samp{.}). +The syntax begins with an ID token that gives the name of the +procedure to be parsed. For command names that contain multiple +words, a STRING token may be used instead, e.g.@: @samp{"FILE +HANDLE"}. Optionally, an ID in parentheses specifies a prefix used +for all file-scope identifiers declared by the emitted code. + +The rest of the syntax consists of subcommands separated by semicolons +(@samp{;}) and terminated with a full stop (@samp{.}). @example subcommand ::= default-opt arity-opt ID sbc-defn @@ -132,8 +140,6 @@ arity-opt ::= sbc-defn ::= opt-prefix = specifiers ::= [ ID ] = array-sbc ::= opt-prefix = sbc-special-form -opt-prefix ::= - ::= ( ID ) @end example A subcommand that begins with an asterisk (@samp{*}) is the default @@ -211,14 +217,16 @@ setting-value-options ::= ::= * setting-value-type ::= N ::= D + ::= S setting-value-restriction ::= ::= , STRING @end example Settings may have values. If the value must be enclosed in parentheses, then enclose the value declaration in parentheses. Declare the setting -type as @samp{n} or @samp{d} for integer or floating point type, -respectively. The given @code{ID} is used to construct a variable name. +type as @samp{n}, @samp{d}, or @samp{s} for integer, floating-point, +or string type, respectively. The given @code{ID} is used to +construct a variable name. If option @samp{*} is given, then the value is optional; otherwise it must be specified whenever the corresponding setting is specified. A ``restriction'' can also be specified which is a string giving a C diff --git a/po/pspp.pot b/po/pspp.pot index f90566c2..60a5df5b 100644 --- a/po/pspp.pot +++ b/po/pspp.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n" -"POT-Creation-Date: 2007-04-15 17:51-0700\n" +"POT-Creation-Date: 2007-04-15 20:40-0700\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -323,8 +323,8 @@ msgstr "" #: src/data/sys-file-reader.c:1028 #: src/language/dictionary/apply-dictionary.c:77 #: src/language/dictionary/apply-dictionary.c:78 -#: src/language/xforms/recode.c:467 src/language/xforms/recode.c:468 -#: src/language/xforms/recode.c:480 src/language/xforms/recode.c:481 +#: src/language/xforms/recode.c:468 src/language/xforms/recode.c:469 +#: src/language/xforms/recode.c:481 src/language/xforms/recode.c:482 msgid "numeric" msgstr "" @@ -332,8 +332,8 @@ msgstr "" #: src/data/sys-file-reader.c:1028 #: src/language/dictionary/apply-dictionary.c:77 #: src/language/dictionary/apply-dictionary.c:78 -#: src/language/xforms/recode.c:467 src/language/xforms/recode.c:468 -#: src/language/xforms/recode.c:480 src/language/xforms/recode.c:481 +#: src/language/xforms/recode.c:468 src/language/xforms/recode.c:469 +#: src/language/xforms/recode.c:481 src/language/xforms/recode.c:482 msgid "string" msgstr "" @@ -3636,34 +3636,34 @@ msgid "" "all string." msgstr "" -#: src/language/xforms/recode.c:268 +#: src/language/xforms/recode.c:269 msgid "CONVERT requires string input values and numeric output values." msgstr "" -#: src/language/xforms/recode.c:386 +#: src/language/xforms/recode.c:387 msgid "expecting output value" msgstr "" -#: src/language/xforms/recode.c:435 +#: src/language/xforms/recode.c:436 #, c-format msgid "" "%u variable(s) cannot be recoded into %u variable(s). Specify the same " "number of variables as source and target variables." msgstr "" -#: src/language/xforms/recode.c:450 +#: src/language/xforms/recode.c:451 #, c-format msgid "" "There is no variable named %s. (All string variables specified on INTO must " "already exist. Use the STRING command to create a string variable.)" msgstr "" -#: src/language/xforms/recode.c:465 +#: src/language/xforms/recode.c:466 #, c-format msgid "INTO is required with %s input values and %s output values." msgstr "" -#: src/language/xforms/recode.c:478 +#: src/language/xforms/recode.c:479 #, c-format msgid "Type mismatch. Cannot store %s data in %s variable %s." msgstr "" diff --git a/src/language/lexer/ChangeLog b/src/language/lexer/ChangeLog index 8d69b868..a3fb55bf 100644 --- a/src/language/lexer/ChangeLog +++ b/src/language/lexer/ChangeLog @@ -1,3 +1,9 @@ +2007-04-15 Ben Pfaff + + * q2c.c: Fully support lists of integer values. Add support for + lists of string values. Add some more needed declarations to + headers. + Fri Feb 16 11:14:42 2007 Ben Pfaff Better support cross-compiling by using CC_FOR_BUILD and diff --git a/src/language/lexer/q2c.c b/src/language/lexer/q2c.c index 90357ebf..78c626d4 100644 --- a/src/language/lexer/q2c.c +++ b/src/language/lexer/q2c.c @@ -472,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. */ @@ -642,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 (':'); @@ -952,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)); } @@ -1003,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; @@ -1236,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); } @@ -1263,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, "}"); @@ -1457,7 +1468,7 @@ dump_specifier_parse (const specifier *spec, const subcommand *sbc) 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, "{"); @@ -1469,6 +1480,22 @@ dump_specifier_parse (const specifier *spec, const subcommand *sbc) 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) { @@ -1683,7 +1710,7 @@ dump_subcommand (const subcommand *sbc) 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, "{"); @@ -1699,9 +1726,10 @@ 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_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,"}"); @@ -1910,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"); @@ -1938,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; } @@ -2042,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 "); -- 2.30.2