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>
#endif
#include "str.h"
+
/* Brokenness. */
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#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. */
}
skip_token (':');
+ if ( sbc->type == SBC_ARRAY && token == T_ID )
+ {
+ spec->varname = xstrdup (st_lower (tokstr));
+ spec->index = sbc->narray;
+ sbc->narray++;
+ }
+
+
+
/* Parse all the settings. */
{
setting **s = &spec->s;
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);
sbc->type = SBC_ARRAY;
parse_specifiers (sbc);
+
}
else
{
else if (match_id ("PINT"))
sbc->type = SBC_PINT;
else if (match_id ("DOUBLE"))
- sbc->type = match_id ("LIST") ? SBC_DBL_LIST : SBC_DBL;
+ {
+ if ( match_id ("LIST") )
+ sbc->type = SBC_DBL_LIST;
+ else
+ sbc->type = SBC_DBL;
+ }
else if (match_id ("STRING"))
{
sbc->type = SBC_STRING;
}
}
+ /* Write out some type definitions */
+ {
+ dump (0, "#define MAXLISTS 10");
+ }
+
+
/* For every array subcommand, write out the associated enumerated
values. */
{
specifier *spec;
for (spec = sbc->spec; spec; spec = spec->next)
- if (!spec->s)
dump (0, "%s%s%s = %d,",
st_upper (prefix), st_upper (sbc->prefix),
st_upper (spec->varname), spec->index);
spec->varname);
else if (f == 0)
{
- dump (0, "int a_%s[%d];",
- st_lower (sbc->name), sbc->narray);
+ dump (0, "int a_%s[%s%scount];",
+ st_lower (sbc->name),
+ st_upper (prefix),
+ st_upper (sbc->prefix)
+ );
+
f = 1;
}
}
case SBC_INT:
case SBC_PINT:
- dump (0, "long n_%s;", st_lower (sbc->name));
+ dump (0, "long n_%s[MAXLISTS];", st_lower (sbc->name));
break;
case SBC_DBL:
- dump (0, "double n_%s;", st_lower (sbc->name));
+ dump (0, "double n_%s[MAXLISTS];", st_lower (sbc->name));
+ break;
+
+ case SBC_DBL_LIST:
+ dump (0, "subc_list_double dl_%s[MAXLISTS];",
+ st_lower(sbc->name));
+ break;
+
+ case SBC_INT_LIST:
+ dump (0, "subc_list_int il_%s[MAXLISTS];",
+ st_lower(sbc->name));
break;
+
default:;
/* nothing */
}
{
switch (sbc->type)
{
- case SBC_DBL:
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]) ;",
+ st_lower (sbc->name)
+ );
+ dump (-2, "}");
+ break;
+
+ case SBC_DBL:
+ dump (1, "{");
+ dump (0, "int i;");
+ dump (1, "for (i = 0; i < MAXLISTS; ++i)");
+ dump (0, "p->n_%s[i] = SYSMIS;", st_lower (sbc->name));
+ dump (-2, "}");
+ break;
+
case SBC_CUSTOM:
/* nothing */
break;
case SBC_INT:
case SBC_PINT:
- dump (0, "p->n_%s = NOT_LONG;", st_lower (sbc->name));
+ dump (1, "{");
+ dump (0, "int i;");
+ dump (1, "for (i = 0; i < MAXLISTS; ++i)");
+ dump (0, "p->n_%s[i] = NOT_LONG;", st_lower (sbc->name));
+ dump (-2, "}");
break;
default:
dump (1, "%sif (%s)", first ? "" : "else ",
make_match (s->specname));
+
/* Handle values. */
if (s->value == VAL_NONE)
dump (0, "p->%s%s = %s%s;", sbc->prefix, spec->varname,
dump (1, "{");
if (spec->varname)
- dump (0, "p->%s%s = %s%s;", sbc->prefix, spec->varname,
- st_upper (prefix), find_symbol (s->con)->name);
-
+ {
+ dump (0, "p->%s%s = %s%s;", sbc->prefix, spec->varname,
+ st_upper (prefix), find_symbol (s->con)->name);
+
+ if ( sbc->type == SBC_ARRAY )
+ dump (0, "p->a_%s[%s%s%s] = 1;",
+ st_lower (sbc->name),
+ st_upper (prefix), st_upper (sbc->prefix),
+ st_upper (spec->varname));
+ }
+
+
if (s->valtype == VT_PAREN)
{
if (s->optvalue)
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 ();
outdent ();
}
dump (0, "free(p->s_%s);", st_lower(sbc->name) );
- dump (0, "p->s_%s = xstrdup (ds_value (&tokstr));",
+ dump (0, "p->s_%s = xstrdup (ds_c_str (&tokstr));",
st_lower (sbc->name));
dump (0, "lex_get ();");
if (sbc->restriction)
{
dump (1, "if (!lex_force_num ())");
dump (0, "goto lossage;");
- dump (-1, "p->n_%s = lex_double ();", st_lower (sbc->name));
+ dump (-1, "p->n_%s[p->sbc_%s - 1] = lex_number ();",
+ st_lower (sbc->name), st_lower (sbc->name) );
dump (0, "lex_get();");
}
else if (sbc->type == SBC_INT)
{
char buf[1024];
dump (1, "if (!(%s))", sbc->restriction);
- dump (1, "{");
+ dump (1, "{");
sprintf(buf,sbc->message,sbc->name);
if ( sbc->translatable )
dump (0, "msg (SE, gettext(\"%s\"));",buf);
dump (0, "goto lossage;");
dump (-1, "}");
}
- dump (-1, "p->n_%s = x;", st_lower (sbc->name));
+ dump (0, "p->n_%s[p->sbc_%s - 1] = x;", st_lower (sbc->name), st_lower(sbc->name) );
dump (-1,"}");
}
else if (sbc->type == SBC_PINT)
dump (-1, "p->n_%s = lex_integer ();", st_lower (sbc->name));
dump (0, "lex_match (')');");
}
+ else if (sbc->type == SBC_DBL_LIST)
+ {
+ dump (0, "if ( p->sbc_%s > MAXLISTS)",st_lower(sbc->name));
+ dump (1, "{");
+ dump (0, "msg (SE, \"No more than %%d %s subcommands allowed\",MAXLISTS);",st_lower(sbc->name));
+ dump (0, "goto lossage;");
+ dump (-1,"}");
+
+ dump (1, "while (token != '/' && token != '.')");
+ dump (1, "{");
+ dump (0, "lex_match(',');");
+ dump (0, "if (!lex_force_num ())");
+ 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, "lex_get();");
+ dump (-1,"}");
+
+ }
else if (sbc->type == SBC_CUSTOM)
{
dump (1, "switch (%scustom_%s (p))",
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 (0, "lex_match ('=');");
+
+ dump(1,"if (lex_match_id(\"COMPATIBLE\"))");
+ dump(0,"set_cmd_algorithm(COMPATIBLE);");
+ outdent();
+ dump(1,"else if (lex_match_id(\"ENHANCED\"))");
+ dump(0,"set_cmd_algorithm(ENHANCED);");
+
+ dump (-1, "}");
+ outdent ();
+
+
dump (1, "if (!lex_match ('/'))");
dump (0, "break;");
dump (0, "goto lossage;");
dump (-1, "}");
dump (0, nullstr);
+
+ outdent ();
+
+ {
+ /* Check that mandatory subcommands have been specified */
+ subcommand *sbc;
+
+ for (sbc = subcommands; sbc; sbc = sbc->next)
+ {
+
+ 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);
+ }
+ }
+ }
+
dump (-1, "return 1;");
dump (0, nullstr);
dump (-1, "lossage:");
}
else if (sbc->type == SBC_INT)
{
- dump (0, "msg(MM,\"%s is %%ld\",p->n_%s);", sbc->name,st_lower(sbc->name) );
+ 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, " Generated by q2c from %s on %s.", ifn, timep);
dump (0, " Do not modify!");
dump (0, " */");
- dump (0, nullstr);
}
/* Write out commands to free variable state. */
if ( ! persistent )
{
for (sbc = subcommands; sbc; sbc = sbc->next)
+ {
if (sbc->type == SBC_STRING)
used = 1;
+ if (sbc->type == SBC_DBL_LIST)
+ used = 1;
+ }
+
}
dump (0, "static void");
{
for (sbc = subcommands; sbc; sbc = sbc->next)
- if (sbc->type == SBC_STRING)
- dump (0, "free (p->s_%s);", st_lower (sbc->name));
+ {
+ 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, "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;
+ }
+ }
}
dump (-1, "}");
dump_header ();
+
indent = 0;
dump (0, "#line %d \"%s\"", ln + 1, ifn);
while (get_line ())
continue;
}
- dump (0, "#line %d \"%s\"", oln - 1, ofn);
+ dump (0, "#line %d \"%s\"", oln + 1, ofn);
if (!strcmp (directive, "specification"))
{
/* Skip leading slash-star line. */
{
indent = 0;
- dump (0, "#include <assert.h>");
dump (0, "#include <stdlib.h>");
dump (0, "#include \"alloc.h\"");
dump (0, "#include \"error.h\"");
dump (0, "#include \"lexer.h\"");
+ dump (0, "#include \"settings.h\"");
dump (0, "#include \"str.h\"");
+ dump (0, "#include \"subclist.h\"");
dump (0, "#include \"var.h\"");
+
dump (0, nullstr);
}
else if (!strcmp (directive, "declarations"))
dump (0, "#line %d \"%s\"", ln + 1, ifn);
}
+
+
return EXIT_SUCCESS;
}