1 ////////////////////////////////////////////////////////////////////////////////////////////////////
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
9 * keyword transition-table generation utility
14 * SYNOPSIS: kw basename <file1 >file2
16 * `-d' turns on debugging messages
18 * Accepts a list of keywords and corresponding values. Lines
19 * beginning with '#' are comments. Values may be empty (resulting
20 * in a default value of the previous item's value plus 1, or zero
21 * if there is no previous item), decimal numbers, or characters
22 * enclosed between single quotes.
29 * The `basename' is a string prepended to the beginning of each of
30 * the output array names, and should be one or two characters.
42 #define TABSIZE 1024 /* state table size */
43 #define NSTRINGS 500 /* maximum number of keywords */
44 #define STRPOOLSIZ (NSTRINGS * 10) /* size of string pool */
50 #define EOS '\0' /* null */
51 #define UNUSED -1 /* slot in ktab[] is unused */
52 #define MARKED -2 /* slot in ktab[] is used, not assigned yet */
56 * Table-building tables
58 int kmax = 0; /* largest index into ktab */
59 int ktab[TABSIZE]; /* next state number (or -1) */
60 int kcheck[TABSIZE]; /* check state number (or -1) */
61 int kaccept[TABSIZE]; /* accept (or -1) */
62 int kbase[TABSIZE]; /* ktab[] index for a state `i' */
63 int nstates; /* number of states in kbase[] */
68 int tab[128]; /* tmp table for building ktab[] */
69 int accept[128]; /* tmp table for building accept[] */
72 char *nstr; /* -> name string */
73 int nval; /* = name's value */
76 int nnames; /* number of keywords */
77 char strpool[STRPOOLSIZ]; /* pool for keyword text */
78 char *basename; /* -> string to prepend to array names */
79 char uppername[100]; /* all-uppercase version of basename */
80 int debug = 0; /* 1, enable debugging messages */
84 int nmatch(int, char *, char *);
86 void print_tables(void);
87 void dumptab(char *, char *, int *, int);
90 int main(int argc, char **argv) {
91 register int i, /*j,*/ k, w;
100 panic("bad commandline");
104 for (s = basename, s1 = uppername; *s; ++s, ++s1)
105 *s1 = (char)toupper(*s);
111 for (i = 0; i < TABSIZE; ++i)
124 while (gets(s) != NULL)
126 if (*s == '#' || !*s) /* ignore comment and empty lines */
129 namtab[nnames].nstr = s;
130 while (*s && !isspace(*s))
139 if (*s && isspace(*s))
143 while (*s1 && isspace(*s1))
148 empty: /* use previous entry + 1 */
149 if (!nnames) /* complain if no previous entry */
150 namtab[nnames].nval = 0;
151 else namtab[nnames].nval = namtab[nnames-1].nval + 1;
153 else if (isdigit(*s1))
154 namtab[nnames].nval = atoi(s1);
155 else if (*s1 == '\'')
156 namtab[nnames].nval = *++s1;
158 { /* same as previous entry */
159 if (!nnames) /* zero for first entry */
160 namtab[nnames].nval = 0;
161 else namtab[nnames].nval = namtab[nnames-1].nval;
165 fprintf(stderr, "bad expression at '%s'\n", namtab[nnames].nstr);
170 if (nnames >= NSTRINGS)
171 panic("name table overflow");
172 if (s >= &strpool[STRPOOLSIZ-100])
173 panic("string table overflow");
176 qsort(namtab, nnames, sizeof(struct name_entry), comp_entry);
179 * compute table start indices
183 for (k = 1; found1; ++k)
187 for (w = 0; w <= nnames; ++w)
191 !nmatch(k-1, namtab[w].nstr, namtab[w-1].nstr))
201 for (i = 0; i < k-2; ++i)
203 if (ktab[kbase[state] + *(namtab[w-1].nstr + i)] < 0)
204 panic("table build error");
205 else state = ktab[kbase[state] +
206 *(namtab[w-1].nstr + i)];
209 ktab[kbase[state] + *(namtab[w-1].nstr + k-2)] = nstates;
215 for (i = 0; i < 128; ++i)
225 (int)strlen(namtab[w].nstr) < k)
230 tab[*(namtab[w].nstr + k-1)] = MARKED;
231 if (*(namtab[w].nstr + k) == '\0')
233 accept[*(namtab[w].nstr + k-1)] = namtab[w].nval;
247 * find position for set of characters;
250 void wiredown(void) {
254 for (base = 0; base < TABSIZE-128; ++base)
256 for (i = 0; i < 128; ++i)
257 if (ktab[base+i] != UNUSED &&
264 if (base >= TABSIZE-128)
265 panic("Cannot build table (won't fit in tables)\n");
267 for (i = 0; i < 128; ++i)
268 if (tab[i] == MARKED)
270 ktab[base + i] = MARKED;
271 kaccept[base + i] = accept[i];
272 kcheck[base + i] = nstates;
274 kbase[nstates] = base;
281 void print_tables(void) {
284 printf("\n#ifdef DECL_%s\n", uppername);
285 printf("/*\n * keyword state-machine tables\n *\n */\n");
286 dumptab("base", basename, kbase, nstates);
287 dumptab("tab", basename, ktab, kmax + 128);
288 dumptab("check", basename, kcheck, kmax + 128);
289 dumptab("accept", basename, kaccept, kmax + 128);
294 void dumptab(char *tabname, char *tabprefix, int *table, int tabsize) {
297 printf("\nint %s%s[%d] = {\n",
298 tabprefix, tabname, tabsize);
300 for (i = j = 0; i < tabsize; ++i)
302 printf(" %d", table[i]);
317 int comp_entry(struct name_entry *ent1, struct name_entry *ent2) {
318 return strcmp(ent1->nstr, ent2->nstr);
322 int nmatch(int len, char *s1, char *s2) {
333 void traverse(int state) {
334 register int base, i;//, j;
339 printf("#ifdef DEF_%s\n", uppername);
340 printf("/*\n * Keyword definitions\n */\n");
346 for (i = 0; i < 128; ++i)
347 if (kcheck[base + i] == state)
352 for (s = nam; *s; ++s)
356 if (kaccept[base + i] >= 0 &&
359 printf("#define\t%s_", uppername);
360 for (s = nam; (c = *s); ++s)
364 else if ((c >= 'a') && (c <= 'z'))
368 printf("\t%d\n", kaccept[base + i]);
371 if (ktab[base + i] >= 0)
372 traverse(ktab[base + i]);
381 void panic(char *s) {
382 fprintf(stderr, "Panic: %s\n", s);