Separate settings and the SET command, for modularity.
[pspp-builds.git] / src / q2c.c
index 0ffc79f0ea10d4b2356d6f8ce2cc6d3eb6bf9077..f771d466ecc505a30b94fe2c0b2e01cf09f22dba 100644 (file)
--- 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 <config.h>
 #include <assert.h>
@@ -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;
 
@@ -720,7 +714,7 @@ parse_specifier (specifier *spec, subcommand *sbc)
     
     for (;;)
       {
-       *s = xmalloc (sizeof (setting));
+       *s = xmalloc (sizeof **s);
        parse_setting (*s, spec);
        if (token == ',' || token == ';' || token == '.')
          break;
@@ -745,7 +739,7 @@ parse_specifiers (subcommand *sbc)
   
   for (;;)
     {
-      *spec = xmalloc (sizeof (specifier));
+      *spec = xmalloc (sizeof **spec);
       parse_specifier (*spec, sbc);
       if (token == ';' || token == '.')
        break;
@@ -759,6 +753,8 @@ parse_specifiers (subcommand *sbc)
 static void
 parse_subcommand (subcommand *sbc)
 {
+  sbc->arity = ARITY_MANY;
+
   if (match_token ('*'))
     {
       if (def)
@@ -766,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);
@@ -883,7 +883,7 @@ parse_subcommands (void)
   
   for (;;)
     {
-      *sbc = xmalloc (sizeof (subcommand));
+      *sbc = xmalloc (sizeof **sbc);
       (*sbc)->next = NULL;
 
       parse_subcommand (*sbc);
@@ -1133,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));
@@ -1448,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.\"));",
@@ -1460,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.\"));",
@@ -1611,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 ();
@@ -1648,7 +1648,7 @@ dump_subcommand (const subcommand *sbc)
     {
       dump (1, "if (!lex_force_num ())");
       dump (0, "goto lossage;");
-      dump (-1, "p->n_%s[p->sbc_%s - 1] = lex_double ();", 
+      dump (-1, "p->n_%s[p->sbc_%s - 1] = lex_number ();", 
            st_lower (sbc->name), st_lower (sbc->name) );
       dump (0, "lex_get();");
     }
@@ -1700,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)
            );
 
@@ -1805,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, "{");
@@ -1820,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,"{");
@@ -1835,6 +1837,7 @@ dump_parser (int persistent)
   dump (-1, "}");
   outdent ();
 
+
   
   dump (1, "if (!lex_match ('/'))");
   dump (0, "break;");
@@ -1847,159 +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 (1, "{");
-      dump (0, "int i;");
-      dump (1, "for (i = 0; i < MAXLISTS; ++i)");
-      dump (0, "msg(MM,\"%s is %%ld\",p->n_%s[i]);", sbc->name,st_lower(sbc->name) ); 
-      outdent();
-      dump (-1, "}");
-    }
-  else if (sbc->type == SBC_CUSTOM)
-    {
-      dump (0, "aux_%scustom_%s(p);",st_lower(prefix),make_identifier(sbc->name));
-    }
-  else
-    assert(0);
-}
-
 
+  outdent ();
 
-/* Write out auxilliary parser. */
-static void
-dump_aux_parser (void)
-{
-  int f=0;
-  subcommand *sbc;
-  aux_subcommand *asbc;
-
-  /* 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);
 }
 
@@ -2058,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;
@@ -2103,8 +1989,6 @@ recognize_directive (void)
   return directive;
 }
   
-static void aux_parse (void);
-
 int
 main (int argc, char *argv[])
 {
@@ -2164,7 +2048,10 @@ main (int argc, char *argv[])
          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"))
@@ -2179,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;
@@ -2194,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;
-}
-
-