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>
#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. */
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);
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 (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);
+
+ 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:");
{
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;