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>
#define MAX_TOK_LEN 1024
/* argv[0]. */
-char *pgmname;
+char *program_name;
/* Have the input and output files been opened yet? */
int is_open;
fclose (in);
fclose (out);
if (remove (ofn) == -1)
- fprintf (stderr, "%s: %s: remove: %s\n", pgmname, ofn, strerror (errno));
+ fprintf (stderr, "%s: %s: remove: %s\n", program_name, ofn, strerror (errno));
}
void hcf (void) NO_RETURN;
va_list args;
va_start (args, format);
- fprintf (stderr, "%s: ", pgmname);
+ fprintf (stderr, "%s: ", program_name);
vfprintf (stderr, format, args);
fprintf (stderr, "\n");
va_end (args);
symbol *iter, *sym;
int x;
- sym = xmalloc (sizeof (symbol));
+ sym = xmalloc (sizeof *sym);
sym->name = xstrdup (name);
sym->unique = unique;
sym->value = value;
#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;
}
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
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. */
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;
for (;;)
{
- *s = xmalloc (sizeof (setting));
+ *s = xmalloc (sizeof **s);
parse_setting (*s, spec);
if (token == ',' || token == ';' || token == '.')
break;
for (;;)
{
- *spec = xmalloc (sizeof (specifier));
+ *spec = xmalloc (sizeof **spec);
parse_specifier (*spec, sbc);
if (token == ';' || token == '.')
break;
static void
parse_subcommand (subcommand *sbc)
{
+ sbc->arity = ARITY_MANY;
+
if (match_token ('*'))
{
if (def)
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);
for (;;)
{
- *sbc = xmalloc (sizeof (subcommand));
+ *sbc = xmalloc (sizeof **sbc);
(*sbc)->next = NULL;
parse_subcommand (*sbc);
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));
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.\"));",
}
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.\"));",
{
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 ();
{
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();");
}
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)
);
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, "{");
outdent ();
}
}
+
+
/* Now deal with the /ALGORITHM subcommand implicit to all commands */
dump(1,"else if ( get_syntax() != COMPATIBLE && lex_match_id(\"ALGORITHM\"))");
dump(1,"{");
dump (-1, "}");
outdent ();
+
dump (1, "if (!lex_match ('/'))");
dump (0, "break;");
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);
}
{
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;
return directive;
}
-static void aux_parse (void);
-
int
main (int argc, char *argv[])
{
- pgmname = argv[0];
+ program_name = argv[0];
if (argc != 3)
fail ("Syntax: q2c input.q output.c");
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"))
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;
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;
-}
-
-