2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // KWGEN.C - Keyword & Mnemonic Definition and State Machine Creation Tool
4 // Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source Utilised with the Kind Permission of Landon Dyer
10 * keyword transition-table generation utility
15 * SYNOPSIS: kw basename <file1 >file2
17 * `-d' turns on debugging messages
19 * Accepts a list of keywords and corresponding values. Lines
20 * beginning with '#' are comments. Values may be empty (resulting
21 * in a default value of the previous item's value plus 1, or zero
22 * if there is no previous item), decimal numbers, or characters
23 * enclosed between single quotes.
30 * The `basename' is a string prepended to the beginning of each of
31 * the output array names, and should be one or two characters.
43 #define TABSIZE 1024 /* state table size */
44 #define NSTRINGS 500 /* maximum number of keywords */
45 #define STRPOOLSIZ (NSTRINGS * 10) /* size of string pool */
51 #define EOS '\0' /* null */
52 #define UNUSED -1 /* slot in ktab[] is unused */
53 #define MARKED -2 /* slot in ktab[] is used, not assigned yet */
57 * Table-building tables
59 int kmax = 0; /* largest index into ktab */
60 int ktab[TABSIZE]; /* next state number (or -1) */
61 int kcheck[TABSIZE]; /* check state number (or -1) */
62 int kaccept[TABSIZE]; /* accept (or -1) */
63 int kbase[TABSIZE]; /* ktab[] index for a state `i' */
64 int nstates; /* number of states in kbase[] */
69 int tab[128]; /* tmp table for building ktab[] */
70 int accept[128]; /* tmp table for building accept[] */
73 char *nstr; /* -> name string */
74 int nval; /* = name's value */
77 int nnames; /* number of keywords */
78 char strpool[STRPOOLSIZ]; /* pool for keyword text */
79 char *basename; /* -> string to prepend to array names */
80 char uppername[100]; /* all-uppercase version of basename */
81 int debug = 0; /* 1, enable debugging messages */
85 int nmatch(int, char *, char *);
87 void print_tables(void);
88 void dumptab(char *, char *, int *, int);
91 int main(int argc, char **argv) {
92 register int i, /*j,*/ k, w;
101 panic("bad commandline");
105 for (s = basename, s1 = uppername; *s; ++s, ++s1)
106 *s1 = (char)toupper(*s);
112 for (i = 0; i < TABSIZE; ++i)
126 // while (gets(s) != NULL)
127 while (fgets(s, STRPOOLSIZ, stdin) != NULL)
129 if (*s == '#' || !*s) /* ignore comment and empty lines */
132 namtab[nnames].nstr = s;
133 while (*s && !isspace(*s))
142 if (*s && isspace(*s))
146 while (*s1 && isspace(*s1))
151 empty: /* use previous entry + 1 */
152 if (!nnames) /* complain if no previous entry */
153 namtab[nnames].nval = 0;
154 else namtab[nnames].nval = namtab[nnames-1].nval + 1;
156 else if (isdigit(*s1))
157 namtab[nnames].nval = atoi(s1);
158 else if (*s1 == '\'')
159 namtab[nnames].nval = *++s1;
161 { /* same as previous entry */
162 if (!nnames) /* zero for first entry */
163 namtab[nnames].nval = 0;
164 else namtab[nnames].nval = namtab[nnames-1].nval;
168 fprintf(stderr, "bad expression at '%s'\n", namtab[nnames].nstr);
173 if (nnames >= NSTRINGS)
174 panic("name table overflow");
175 if (s >= &strpool[STRPOOLSIZ-100])
176 panic("string table overflow");
179 qsort(namtab, nnames, sizeof(struct name_entry), comp_entry);
182 * compute table start indices
186 for (k = 1; found1; ++k)
190 for (w = 0; w <= nnames; ++w)
194 !nmatch(k-1, namtab[w].nstr, namtab[w-1].nstr))
204 for (i = 0; i < k-2; ++i)
206 if (ktab[kbase[state] + *(namtab[w-1].nstr + i)] < 0)
207 panic("table build error");
208 else state = ktab[kbase[state] +
209 *(namtab[w-1].nstr + i)];
212 ktab[kbase[state] + *(namtab[w-1].nstr + k-2)] = nstates;
218 for (i = 0; i < 128; ++i)
228 (int)strlen(namtab[w].nstr) < k)
233 tab[*(namtab[w].nstr + k-1)] = MARKED;
234 if (*(namtab[w].nstr + k) == '\0')
236 accept[*(namtab[w].nstr + k-1)] = namtab[w].nval;
250 * find position for set of characters;
253 void wiredown(void) {
257 for (base = 0; base < TABSIZE-128; ++base)
259 for (i = 0; i < 128; ++i)
260 if (ktab[base+i] != UNUSED &&
267 if (base >= TABSIZE-128)
268 panic("Cannot build table (won't fit in tables)\n");
270 for (i = 0; i < 128; ++i)
271 if (tab[i] == MARKED)
273 ktab[base + i] = MARKED;
274 kaccept[base + i] = accept[i];
275 kcheck[base + i] = nstates;
277 kbase[nstates] = base;
284 void print_tables(void) {
287 printf("\n#ifdef DECL_%s\n", uppername);
288 printf("/*\n * keyword state-machine tables\n *\n */\n");
289 dumptab("base", basename, kbase, nstates);
290 dumptab("tab", basename, ktab, kmax + 128);
291 dumptab("check", basename, kcheck, kmax + 128);
292 dumptab("accept", basename, kaccept, kmax + 128);
297 void dumptab(char *tabname, char *tabprefix, int *table, int tabsize) {
300 printf("\nint %s%s[%d] = {\n",
301 tabprefix, tabname, tabsize);
303 for (i = j = 0; i < tabsize; ++i)
305 printf(" %d", table[i]);
320 int comp_entry(struct name_entry *ent1, struct name_entry *ent2) {
321 return strcmp(ent1->nstr, ent2->nstr);
325 int nmatch(int len, char *s1, char *s2) {
336 void traverse(int state) {
337 register int base, i;//, j;
342 printf("#ifdef DEF_%s\n", uppername);
343 printf("/*\n * Keyword definitions\n */\n");
349 for (i = 0; i < 128; ++i)
350 if (kcheck[base + i] == state)
355 for (s = nam; *s; ++s)
359 if (kaccept[base + i] >= 0 &&
362 printf("#define\t%s_", uppername);
363 for (s = nam; (c = *s); ++s)
367 else if ((c >= 'a') && (c <= 'z'))
371 printf("\t%d\n", kaccept[base + i]);
374 if (ktab[base + i] >= 0)
375 traverse(ktab[base + i]);
384 void panic(char *s) {
385 fprintf(stderr, "Panic: %s\n", s);