/* q2c - parser generator for PSPP procedures.
Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
- Written by Ben Pfaff <blp@gnu.org>.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
#include <time.h>
#include <errno.h>
#include <unistd.h>
+#include <libpspp/assertion.h>
#include <libpspp/compiler.h>
#include <libpspp/str.h>
#include "exit.h"
#define MAX_TOK_LEN 1024
/* argv[0]. */
-char *program_name;
+static char *program_name;
/* Have the input and output files been opened yet? */
-int 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
};
/* Current token: either one of the above, or a single character. */
-int token;
+static int token;
/* Token string value. */
-char *tokstr;
+static char *tokstr;
\f
/* Utility functions. */
-char nullstr[] = "";
+static char nullstr[] = "";
/* Close all open files and delete the output file, on failure. */
static void
{
if (!is_open)
return;
- is_open = 0;
+ is_open = false;
fclose (in);
fclose (out);
if (remove (ofn) == -1)
/* Read one line from the input file into buf. Lines having special
formats are handled specially. */
-static int
+static bool
get_line (void)
{
ln++;
{
if (ferror (in))
fail ("%s: fgets: %s", ifn, strerror (errno));
- return 0;
+ return false;
}
cp = strchr (buf, '\n');
*cp = '\0';
cp = buf;
- return 1;
+ return true;
}
\f
/* Symbol table manager. */
}
/* Checks whether the current token is the identifier S; if so, skips
- the token and returns 1; otherwise, returns 0. */
-static int
+ the token and returns true; otherwise, returns false. */
+static bool
match_id (const char *s)
{
if (token == T_ID && !strcmp (tokstr, s))
{
lex_get ();
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/* Checks whether the current token is T. If so, skips the token and
- returns 1; otherwise, returns 0. */
-static int
+ returns true; otherwise, returns false. */
+static bool
match_token (int t)
{
if (token == t)
{
lex_get ();
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/* Force the current token to be T, and skip it. */
static void
parse_subcommand (subcommand *sbc)
{
- sbc->arity = ARITY_MANY;
-
if (match_token ('*'))
{
if (def)
def = sbc;
}
+ sbc->arity = ARITY_ONCE_ONLY;
if ( match_token('+'))
- sbc->arity = ARITY_ONCE_ONLY ;
+ sbc->arity = ARITY_MANY;
else if (match_token('^'))
sbc->arity = ARITY_ONCE_EXACTLY ;
}
}
-/* Returns 1 if string T is a PSPP keyword, 0 otherwise. */
-static int
+/* Returns true if string T is a PSPP keyword, false otherwise. */
+static bool
is_keyword (const char *t)
{
static const char *kw[] =
for (cp = kw; *cp; cp++)
if (!strcmp (t, *cp))
- return 1;
- return 0;
+ return true;
+ return false;
}
/* Transforms a string NAME into a valid C identifier: makes
/* Write out prototypes for custom_*() functions as necessary. */
{
- int seen = 0;
+ bool seen = false;
subcommand *sbc;
for (sbc = subcommands; sbc; sbc = sbc->next)
{
if (!seen)
{
- seen = 1;
+ seen = true;
dump (0, "/* Prototype for custom subcommands of %s. */",
cmdname);
}
- dump (0, "static int %scustom_%s (struct cmd_%s *);",
+ dump (0, "static int %scustom_%s (struct lexer *, struct dataset *, struct cmd_%s *, void *);",
st_lower (prefix), st_lower (sbc->name),
make_identifier (cmdname));
}
/* Prototypes for parsing and freeing functions. */
{
dump (0, "/* Command parsing functions. */");
- dump (0, "static int parse_%s (struct cmd_%s *);",
+ 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));
break;
default:
- assert (0);
+ NOT_REACHED ();
}
}
}
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;
}
{
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.\"));",
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
{
- 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));
}
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.\"));",
{
int count;
- dump (1, "while (token != '/' && token != '.')");
+ dump (1, "while (lex_token (lexer) != '/' && lex_token (lexer) != '.')");
dump (1, "{");
{
{
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 (default_dict, &p->%sv_%s, &p->%sn_%s, "
+ dump (1, "if (!parse_variables (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),
}
else if (sbc->type == SBC_VAR)
{
- dump (0, "p->%sv_%s = parse_variable ();",
+ 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));
dump (1, "{");
dump (0, "int x;");
}
- dump (1, "if (!lex_force_string ())");
- dump (0, "return 0;");
+ 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.\"));",
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];
}
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)
{
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_double_push (&p->dl_%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);");
dump (-1,"}");
}
else if (sbc->type == SBC_CUSTOM)
{
- dump (1, "switch (%scustom_%s (p))",
+ dump (1, "switch (%scustom_%s (lexer, ds, p, aux))",
st_lower (prefix), st_lower (sbc->name));
dump (0, "{");
dump (1, "case 0:");
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 ();
- dump (0, "assert (0);");
+ dump (0, "NOT_REACHED ();");
dump (-1, "}");
outdent ();
}
indent = 0;
dump (0, "static int");
- dump (0, "parse_%s (struct cmd_%s *p)", make_identifier (cmdname),
+ 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));
dump (1, "{");
if (def && (def->type == SBC_VARLIST))
{
if (def->type == SBC_VARLIST)
- dump (1, "if (token == T_ID "
- "&& dict_lookup_var (default_dict, 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 (default_dict, 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 (default_dict, &p->%sv_%s, &p->%sn_%s, "
+ dump (1, "if (!parse_variables (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));
}
else if (def && def->type == SBC_CUSTOM)
{
- dump (1, "switch (%scustom_%s (p))",
+ dump (1, "switch (%scustom_%s (lexer, ds, p, aux))",
st_lower (prefix), st_lower (def->name));
dump (0, "{");
dump (1, "case 0:");
dump (0, "break;");
dump (-1, "default:");
indent ();
- dump (0, "assert (0);");
+ dump (0, "NOT_REACHED ();");
dump (-1, "}");
outdent ();
}
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)
{
/* 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, "}");
- 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);
}
}
- dump (-1, "return 1;");
+ dump (-1, "return true;");
dump (0, nullstr);
dump (-1, "lossage:");
indent ();
dump (0, "free_%s (p);", make_identifier (cmdname));
- dump (0, "return 0;");
+ dump (0, "return false;");
dump (-1, "}");
dump (0, nullstr);
}
dump (0, "free (p->s_%s);", st_lower (sbc->name));
break;
case SBC_DBL_LIST:
- 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));
+ 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 (0, "}");
outdent();
break;
default:
if (!out)
fail ("%s: open: %s.", ofn, strerror (errno));
- is_open = 1;
+ is_open = true;
buf = xmalloc (MAX_LINE_LEN);
tokstr = xmalloc (MAX_TOK_LEN);
dump (0, "#include <stdlib.h>");
dump (0, "#include <libpspp/alloc.h>");
+ dump (0, "#include <libpspp/assertion.h>");
dump (0, "#include <libpspp/message.h>");
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/str.h>");
dump (0, "#include <language/lexer/subcommand-list.h>");
dump (0, "#line %d \"%s\"", ln + 1, ifn);
}
-
-
return EXIT_SUCCESS;
}