// // RMAC - Renamed Macro Assembler for all Atari computers // KWGEN.C - Keyword & Mnemonic Definition and State Machine Creation Tool // Copyright (C) 199x Landon Dyer, 2011-2021 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // /* * keyword transition-table generation utility * * *---------------- * * SYNOPSIS: kw basename file2 * * `-d' turns on debugging messages * * Accepts a list of keywords and corresponding values. Lines * beginning with '#' are comments. Values may be empty (resulting * in a default value of the previous item's value plus 1, or zero * if there is no previous item), decimal numbers, or characters * enclosed between single quotes. * * # this is a comment * .byte 34 * .word 'A' * .long * * The `basename' is a string prepended to the beginning of each of * the output array names, and should be one or two characters. * */ #include #include #include #include /* * Tunable definitions * */ #define TABSIZE 2048 /* state table size */ #define NSTRINGS 1024 /* maximum number of keywords */ #define STRPOOLSIZ (NSTRINGS * 10) /* size of string pool */ /* * Do not change these */ #define EOS '\0' /* null */ #define UNUSED -1 /* slot in ktab[] is unused */ #define MARKED -2 /* slot in ktab[] is used, not assigned yet */ /* * Table-building tables */ int kmax = 0; /* largest index into ktab */ int ktab[TABSIZE]; /* next state number (or -1) */ int kcheck[TABSIZE]; /* check state number (or -1) */ int kaccept[TABSIZE]; /* accept (or -1) */ int kbase[TABSIZE]; /* ktab[] index for a state `i' */ int nstates; /* number of states in kbase[] */ /* * Temporary tables */ int tab[128]; /* tmp table for building ktab[] */ int accept[128]; /* tmp table for building accept[] */ struct name_entry { char *nstr; /* -> name string */ int nval; /* = name's value */ } namtab[NSTRINGS]; int nnames; /* number of keywords */ char strpool[STRPOOLSIZ]; /* pool for keyword text */ char *basename; /* -> string to prepend to array names */ char uppername[100]; /* all-uppercase version of basename */ int debug = 0; /* 1, enable debugging messages */ int comp_entry(); void panic(char *); int nmatch(int, char *, char *); void wiredown(void); void print_tables(void); void dumptab(char *, char *, int *, int); void traverse(int); int main(int argc, char ** argv) { register int i, /*j,*/ k, w; char *s, *s1; int found1; int valid = 0; //int base; int state; if (argc != 2) { panic("bad commandline"); } basename = argv[1]; for(s=basename, s1=uppername; *s; ++s, ++s1) *s1 = (char)toupper(*s); *s1 = EOS; /* * init tables */ for(i=0; i= NSTRINGS) panic("name table overflow"); if (s >= &strpool[STRPOOLSIZ-100]) panic("string table overflow"); } qsort(namtab, nnames, sizeof(struct name_entry), comp_entry); /* * compute table start indices */ found1 = 1; for(k=1; found1; ++k) { found1 = 0; for(w=0; w<=nnames; ++w) { if (w == 0 || w == nnames || !nmatch(k-1, namtab[w].nstr, namtab[w-1].nstr)) { if (w != 0 && valid != 0) { wiredown(); if (k > 1) { state = 0; for(i=0; i= nnames || (int)strlen(namtab[w].nstr) < k) { continue; } tab[*(namtab[w].nstr + k-1)] = MARKED; if (*(namtab[w].nstr + k) == '\0') { accept[*(namtab[w].nstr + k-1)] = namtab[w].nval; } valid = 1; } } traverse(0); print_tables(); return 0; } /* * find position for set of characters; * */ void wiredown(void) { register int base; register int i; for(base=0; base= 128) break; } if (base >= TABSIZE-128) panic("Cannot build table (won't fit in tables)\n"); for(i=0; i<128; ++i) { if (tab[i] == MARKED) { ktab[base + i] = MARKED; kaccept[base + i] = accept[i]; kcheck[base + i] = nstates; } } kbase[nstates] = base; if (kmax < base) kmax = base; } void print_tables(void) { // int i; printf("\n#ifdef DECL_%s\n", uppername); printf("/*\n * keyword state-machine tables\n *\n */\n"); dumptab("base", basename, kbase, nstates); dumptab("tab", basename, ktab, kmax + 128); dumptab("check", basename, kcheck, kmax + 128); dumptab("accept", basename, kaccept, kmax + 128); printf("#endif\n"); } void dumptab(char * tabname, char * tabprefix, int * table, int tabsize) { int i, j; printf("\nint %s%s[%d] = {\n", tabprefix, tabname, tabsize); for(i=j=0; instr, ent2->nstr); } int nmatch(int len, char * s1, char * s2) { while (len--) { if (*s1++ != *s2++) return 0; } return 1; } char nam[128]; char * pnam; void traverse(int state) { register int base, i;//, j; char * s, c; if (state == 0) { printf("#ifdef DEF_%s\n", uppername); printf("/*\n * Keyword definitions\n */\n"); pnam = nam; *pnam = 0; } base = kbase[state]; for(i=0; i<128; ++i) { if (kcheck[base + i] == state) { *pnam++ = (char)i; *pnam = '\0'; for(s=nam; *s; ++s) { if (isupper(*s)) break; } if (kaccept[base + i] >= 0 && !isupper(*s)) { printf("#define\t%s_", uppername); for(s=nam; (c=*s); ++s) { if (c == '.') c = '_'; else if ((c >= 'a') && (c <= 'z')) c -= 32; printf("%c", c); } printf("\t%d\n", kaccept[base + i]); } if (ktab[base + i] >= 0) traverse(ktab[base + i]); *--pnam = '\0'; } } if (state == 0) printf("#endif\n"); } void panic(char * s) { fprintf(stderr, "Panic: %s\n", s); exit(1); }