535 |
} |
} |
536 |
subcommand_type; |
subcommand_type; |
537 |
|
|
538 |
|
typedef enum |
539 |
|
{ |
540 |
|
ARITY_ONCE_EXACTLY, /* must occur exactly once */ |
541 |
|
ARITY_ONCE_ONLY, /* zero or once */ |
542 |
|
ARITY_MANY /* 0, 1, ... , inf */ |
543 |
|
}subcommand_arity; |
544 |
|
|
545 |
/* A single subcommand. */ |
/* A single subcommand. */ |
546 |
typedef struct subcommand subcommand; |
typedef struct subcommand subcommand; |
547 |
struct subcommand |
struct subcommand |
549 |
subcommand *next; /* Next in the chain. */ |
subcommand *next; /* Next in the chain. */ |
550 |
char *name; /* Subcommand name. */ |
char *name; /* Subcommand name. */ |
551 |
subcommand_type type; /* One of SBC_*. */ |
subcommand_type type; /* One of SBC_*. */ |
552 |
int once; /* 1=Subcommand may appear only once. */ |
subcommand_arity arity; /* How many times should the subcommand occur*/ |
553 |
int narray; /* Index of next array element. */ |
int narray; /* Index of next array element. */ |
554 |
const char *prefix; /* Prefix for variable and constant names. */ |
const char *prefix; /* Prefix for variable and constant names. */ |
555 |
specifier *spec; /* Array of specifiers. */ |
specifier *spec; /* Array of specifiers. */ |
766 |
static void |
static void |
767 |
parse_subcommand (subcommand *sbc) |
parse_subcommand (subcommand *sbc) |
768 |
{ |
{ |
769 |
|
sbc->arity = ARITY_MANY; |
770 |
|
|
771 |
if (match_token ('*')) |
if (match_token ('*')) |
772 |
{ |
{ |
773 |
if (def) |
if (def) |
775 |
def = sbc; |
def = sbc; |
776 |
} |
} |
777 |
|
|
778 |
sbc->once = match_token ('+'); |
if ( match_token('+')) |
779 |
|
sbc->arity = ARITY_ONCE_ONLY ; |
780 |
|
else if (match_token('^')) |
781 |
|
sbc->arity = ARITY_ONCE_EXACTLY ; |
782 |
|
|
783 |
|
|
784 |
force_id (); |
force_id (); |
785 |
sbc->name = xstrdup (tokstr); |
sbc->name = xstrdup (tokstr); |
1818 |
|
|
1819 |
dump (0, "lex_match ('=');"); |
dump (0, "lex_match ('=');"); |
1820 |
dump (0, "p->sbc_%s++;", st_lower (sbc->name)); |
dump (0, "p->sbc_%s++;", st_lower (sbc->name)); |
1821 |
if (sbc->once) |
if (sbc->arity != ARITY_MANY) |
1822 |
{ |
{ |
1823 |
dump (1, "if (p->sbc_%s > 1)", st_lower (sbc->name)); |
dump (1, "if (p->sbc_%s > 1)", st_lower (sbc->name)); |
1824 |
dump (1, "{"); |
dump (1, "{"); |
1833 |
outdent (); |
outdent (); |
1834 |
} |
} |
1835 |
} |
} |
1836 |
|
|
1837 |
|
|
1838 |
/* Now deal with the /ALGORITHM subcommand implicit to all commands */ |
/* Now deal with the /ALGORITHM subcommand implicit to all commands */ |
1839 |
dump(1,"else if ( get_syntax() != COMPATIBLE && lex_match_id(\"ALGORITHM\"))"); |
dump(1,"else if ( get_syntax() != COMPATIBLE && lex_match_id(\"ALGORITHM\"))"); |
1840 |
dump(1,"{"); |
dump(1,"{"); |
1850 |
dump (-1, "}"); |
dump (-1, "}"); |
1851 |
outdent (); |
outdent (); |
1852 |
|
|
1853 |
|
|
1854 |
|
|
1855 |
dump (1, "if (!lex_match ('/'))"); |
dump (1, "if (!lex_match ('/'))"); |
1856 |
dump (0, "break;"); |
dump (0, "break;"); |
1863 |
dump (0, "goto lossage;"); |
dump (0, "goto lossage;"); |
1864 |
dump (-1, "}"); |
dump (-1, "}"); |
1865 |
dump (0, nullstr); |
dump (0, nullstr); |
1866 |
|
|
1867 |
|
outdent (); |
1868 |
|
|
1869 |
|
{ |
1870 |
|
/* Check that mandatory subcommands have been specified */ |
1871 |
|
subcommand *sbc; |
1872 |
|
|
1873 |
|
for (sbc = subcommands; sbc; sbc = sbc->next) |
1874 |
|
{ |
1875 |
|
|
1876 |
|
if ( sbc->arity == ARITY_ONCE_EXACTLY ) |
1877 |
|
{ |
1878 |
|
dump (0, "if ( 0 == p->sbc_%s)", st_lower (sbc->name)); |
1879 |
|
dump (1, "{"); |
1880 |
|
dump (0, "msg (SE, _(\"%s subcommand must be given.\"));", |
1881 |
|
sbc->name); |
1882 |
|
dump (0, "goto lossage;"); |
1883 |
|
dump (-1, "}"); |
1884 |
|
dump (0, nullstr); |
1885 |
|
} |
1886 |
|
} |
1887 |
|
} |
1888 |
|
|
1889 |
dump (-1, "return 1;"); |
dump (-1, "return 1;"); |
1890 |
dump (0, nullstr); |
dump (0, nullstr); |
1891 |
dump (-1, "lossage:"); |
dump (-1, "lossage:"); |