Fully support lists of integer values. Add support for
authorBen Pfaff <blp@gnu.org>
Mon, 16 Apr 2007 03:59:32 +0000 (03:59 +0000)
committerBen Pfaff <blp@gnu.org>
Mon, 16 Apr 2007 03:59:32 +0000 (03:59 +0000)
lists of string values.  Add some more needed declarations to
headers.

Patch #5868.

doc/q2c.texi
po/pspp.pot
src/language/lexer/ChangeLog
src/language/lexer/q2c.c

index 280c543a4bc5bde4436a5792d95eaecdb01bcd44..514060833aec86a93f54073093ed35d83aac56e0 100644 (file)
@@ -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
index f90566c20855320340e6ec1340957b5e1ca6f11b..60a5df5b17599cb841b28fec71c7bebf13cf52ab 100644 (file)
@@ -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 <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\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 ""
index 8d69b868f7feb75660863a8c3e083f10922dea4d..a3fb55bf8092597f39321e6604b291965f7f29a3 100644 (file)
@@ -1,3 +1,9 @@
+2007-04-15  Ben Pfaff  <blp@gnu.org>
+
+       * 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  <blp@gnu.org>
 
        Better support cross-compiling by using CC_FOR_BUILD and
index 90357ebf958dbdc9cc2a74753f43b6b42f4df086..78c626d4b5624783cc4b4af0a345289958f84495 100644 (file)
@@ -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 <language/lexer/lexer.h>");
          dump (0, "#include <language/lexer/variable-parser.h>");
           dump (0, "#include <data/settings.h>");
+         dump (0, "#include <libpspp/magic.h>");
          dump (0, "#include <libpspp/str.h>");
           dump (0, "#include <language/lexer/subcommand-list.h>");
          dump (0, "#include <data/variable.h>");