1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 2: static char rcsid[]= "$Header: mkboot.c,v 1.1 85/08/22 15:44:31 timo Exp $"; 3: 4: /* 5: * B editor -- Program to create the "boot.h" file (the grammar tables). 6: */ 7: 8: #include "b.h" 9: #include "node.h" 10: #include "gram.h" 11: #include "tabl.h" 12: 13: #include <ctype.h> 14: 15: 16: /* 17: * Test whether sym is in the given class. 18: */ 19: 20: Visible bool 21: isinclass(sym, ci) 22: int sym; 23: struct classinfo *ci; 24: { 25: classptr cp; 26: 27: Assert(ci && ci->c_class); 28: if (sym == Hole) 29: return !isinclass(Optional, ci); 30: for (cp = ci->c_class; *cp; ++cp) 31: if (sym == *cp) 32: return Yes; 33: return No; 34: } 35: 36: 37: main() 38: { 39: int sym; 40: int nch; 41: struct classinfo **cp; 42: struct classinfo *sp; 43: 44: printf("/* boot.h -- data file for grammar tables. */\n\n"); 45: 46: /* Check the representations. 47: The code assumes Optional and Hole are the last symbols 48: in the table, i.e. the first processed by the loop. */ 49: 50: for (sym = TABLEN-1; sym >= 0; --sym) { 51: if (table[sym].r_symbol != sym) { 52: if (sym != Hole && sym != Optional 53: && table[sym].r_symbol == 0) 54: continue; /* Disabled table entry */ 55: syserr("initgram: table order (%s=%d, should be %d)", 56: table[sym].r_name, table[sym].r_symbol, sym); 57: } 58: cp = table[sym].r_class; 59: for (nch = 0; nch < MAXCHILD && (sp = cp[nch]); ++nch) 60: ; 61: ckrepr(table[sym].r_repr, nch); 62: } 63: 64: initcodes(); 65: initclasses(); 66: dumptable(); 67: exit(0); 68: } 69: 70: 71: /* 72: * Check a representation array (subroutine for initgram). 73: */ 74: 75: Hidden Procedure 76: ckrepr(rp, nch) 77: string *rp; 78: int nch; 79: { 80: string cp; 81: int i; 82: int ich; 83: 84: for (ich = 0; ich <= nch; ++ich) { 85: cp = rp[ich]; 86: if (!cp) 87: continue; 88: for (i = 0; cp[i]; ++i) { 89: switch (cp[i]) { 90: case '\n': 91: case '\r': 92: if (i || ich) 93: syserr("initgram (ckrepr): badly placed \\n/\\r"); 94: break; 95: case '\t': 96: case '\b': 97: if (cp[i+1]) 98: syserr("initgram (ckrepr): badly placed \\t/\\b"); 99: break; 100: default: 101: if (cp[i] < ' ' || cp[i] >= 0177) 102: syserr("initgram (ckrepr): illegal control char"); 103: } 104: } 105: } 106: } 107: 108: 109: /* 110: * Compaction scheme for characters to save space in grammar tables 111: * by combining characters with similar properties (digits, l.c. letters). 112: */ 113: 114: #define RANGE 128 /* ASCII characters are in {0 .. RANGE-1} */ 115: 116: Visible char code_array[RANGE]; 117: Visible char invcode_array[RANGE]; 118: Visible int lastcode; 119: 120: Hidden Procedure 121: initcodes() 122: { 123: int c; 124: 125: code_array['\n'] = ++lastcode; 126: invcode_array[lastcode] = '\n'; 127: for (c = ' '; c <= '0'; ++c) { 128: code_array[c] = ++lastcode; 129: invcode_array[lastcode] = c; 130: } 131: for (; c <= '9'; ++c) 132: code_array[c] = lastcode; 133: for (; c <= 'a'; ++c) { 134: code_array[c] = ++lastcode; 135: invcode_array[lastcode] = c; 136: } 137: for (; c <= 'z'; ++c) 138: code_array[c] = lastcode; 139: for (; c < RANGE; ++c) { 140: code_array[c] = ++lastcode; 141: invcode_array[lastcode] = c; 142: } 143: } 144: 145: 146: /* 147: * Initialization routine for the 'struct classinfo' stuff. 148: * 149: * "Suggestion" is skipped: 150: * what can be inserted there is not computed from this table. 151: */ 152: 153: Hidden Procedure 154: initclasses() 155: { 156: int i; 157: int j; 158: struct table *tp; 159: 160: for (i = 0; i < TABLEN; ++i) { 161: tp = &table[i]; 162: if (tp->r_symbol != i || i == Suggestion) 163: continue; /* Dead entry */ 164: for (j = 0; j < MAXCHILD && tp->r_class[j]; ++j) { 165: if (!tp->r_class[j]->c_insert) 166: defclass(tp->r_class[j]); 167: } 168: } 169: } 170: 171: classptr makelist(); /* Forward */ 172: 173: Hidden Procedure 174: defclass(p) 175: struct classinfo *p; 176: { 177: int c; 178: struct table *tp; 179: classptr cp; 180: classptr cp1; 181: classelem insert[1024]; 182: classelem append[1024]; 183: classelem join[1024]; 184: int inslen = 0; 185: int applen = 0; 186: int joinlen = 0; 187: string *rp; 188: int fw1; 189: 190: cp = p->c_class; 191: Assert(cp); 192: 193: for (; *cp; ++cp) { 194: if (*cp == Optional) 195: continue; 196: if (*cp >= TABLEN) { /* Insert direct lexical item */ 197: for (c = 1; c <= lastcode; ++c) { 198: if (maystart(Invcode(c), *cp)) { 199: Assert(inslen+3 < sizeof insert / sizeof insert[0]); 200: insert[inslen] = c; 201: insert[inslen+1] = *cp; 202: inslen += 2; 203: } 204: } 205: continue; 206: } 207: tp = &table[*cp]; 208: rp = tp->r_repr; 209: if (!Fw_zero(rp[0])) { /* Insert fixed text */ 210: c = Code(rp[0][0]); 211: Assert(inslen+3 < sizeof insert / sizeof insert[0]); 212: insert[inslen] = c; 213: insert[inslen+1] = *cp; 214: inslen += 2; 215: continue; 216: } 217: Assert(tp->r_class[0]); 218: cp1 = tp->r_class[0]->c_class; 219: Assert(cp1); 220: for (; *cp1; ++cp1) { 221: if (*cp1 < TABLEN) 222: continue; 223: for (c = 1; c <= lastcode; ++c) { /* Insert indir. lex. items */ 224: if (maystart(Invcode(c), *cp1)) { 225: Assert(inslen+3 < sizeof insert / sizeof insert[0]); 226: insert[inslen] = c; 227: insert[inslen+1] = *cp; 228: inslen += 2; 229: } 230: } 231: } 232: fw1 = Fwidth(rp[1]); 233: if (fw1) { /* Append */ 234: c = rp[1][0]; 235: Assert(c > 0 && c < RANGE); 236: if (c == ' ') { 237: c = rp[1][1]; 238: if (!c || c == '\b' || c == '\t') 239: c = ' '; 240: else 241: c |= 0200; 242: } 243: Assert(applen+3 < sizeof append / sizeof append[0]); 244: append[applen] = c; 245: append[applen+1] = *cp; 246: applen += 2; 247: } 248: if ((!fw1 || fw1 == 1 && rp[1][0] == ' ') 249: && tp->r_class[1]) { /* Join */ 250: Assert(joinlen+3 < sizeof join / sizeof join[0]); 251: join[joinlen] = 1 + fw1; 252: join[joinlen+1] = *cp; 253: joinlen += 2; 254: } 255: } 256: 257: Assert(inslen); /* Dead alley */ 258: insert[inslen] = 0; 259: p->c_insert = makelist(insert, inslen + 1); 260: if (applen) { 261: append[applen] = 0; 262: p->c_append = makelist(append, applen + 1); 263: } 264: if (joinlen) { 265: join[joinlen] = 0; 266: p->c_join = makelist(join, joinlen + 1); 267: } 268: } 269: 270: Hidden classptr 271: makelist(list, len) 272: classptr list; 273: int len; 274: { 275: classptr cp = 276: (classptr) malloc((unsigned) (len*sizeof(classelem))); 277: int i; 278: 279: if (!cp) 280: syserr("makelist: malloc"); 281: for (i = 0; i < len; ++i, ++list) 282: cp[i] = *list; 283: #ifndef NDEBUG 284: if (index(cp, '\0') != cp+len-1) 285: printf("makelist: zero in string!\n"); 286: #endif 287: return cp; 288: } 289: 290: #define MAXLOOKUP 1000 291: 292: Hidden struct classinfo **known; 293: Hidden int nknown; 294: 295: Hidden Procedure 296: dumptable() 297: { 298: int sym; 299: 300: getclassinfos(); 301: printf("Hidden struct table b_grammar[%d] = {\n", TABLEN); 302: for (sym= 0; sym < TABLEN; ++sym) 303: dumpentry(table+sym); 304: printf("};\n"); 305: free(known); 306: } 307: 308: Hidden Procedure 309: getclassinfos() 310: { 311: int sym, k; 312: 313: known= (struct classinfo **) malloc(MAXLOOKUP * sizeof(struct classinfo*)); 314: if (known == NULL) 315: syserr("getclassinfos: can't malloc 'known' array"); 316: nknown= 0; 317: printf("Hidden struct classinfo cl[] = {\n"); 318: for (sym= 0; sym < TABLEN; ++sym) { 319: for (k= 0; k < MAXCHILD; ++k) 320: lookup(table[sym].r_class[k]); 321: } 322: printf("};\n\n"); 323: } 324: 325: Hidden int 326: lookup(ci) 327: struct classinfo *ci; 328: { 329: int k; 330: 331: if (ci == NULL) 332: return -1; 333: for (k= 0; k < nknown; ++k) { 334: if (known[k] == ci) 335: return k; 336: } 337: if (k < MAXLOOKUP) { 338: ++nknown; 339: known[k]= ci; 340: printf("/*%d*/", k); 341: dumpclassinfo(ci); 342: } 343: } 344: 345: Hidden Procedure 346: dumpclassinfo(ci) 347: struct classinfo *ci; 348: { 349: printf("\t{"); 350: dumpstring(ci->c_class); 351: printf("\n\t"); 352: dumpstring(ci->c_insert); 353: printf("\n\t"); 354: dumpstring(ci->c_append); 355: printf("\n\t"); 356: dumpstring(ci->c_join); 357: printf("},\n"); 358: } 359: 360: Hidden Procedure 361: dumpentry(p) 362: struct table *p; 363: { 364: int k; 365: 366: printf("\t{%2d, ", p->r_symbol); 367: dumpstring(p->r_name); 368: printf(" {"); 369: for (k= 0; k <= MAXCHILD; ++k) 370: dumpstring(p->r_repr[k]); 371: printf("}, {"); 372: for (k= 0; k < MAXCHILD; ++k) 373: refclassinfo(p->r_class[k]); 374: printf("}, 0},\n"); 375: } 376: 377: Hidden Procedure 378: dumpstring(s) 379: string s; 380: { 381: char c; 382: 383: if (s == NULL) { 384: printf("0, "); 385: return; 386: } 387: printf("\""); 388: for (; (c= *s) != '\0'; ++s) { 389: if (c >= ' ' && c < 0177) { 390: if (c == '\\' || c == '"') 391: printf("\\"); 392: printf("%c", c); 393: } 394: else if (c == '\t') 395: printf("\\t"); 396: else if (c == '\b') 397: printf("\\b"); 398: else 399: printf("\\%03o", c&0377); 400: } 401: printf("\", "); 402: } 403: 404: Hidden Procedure 405: refclassinfo(ci) 406: struct classinfo ci; 407: { 408: int k= lookup(ci); 409: 410: if (k >= 0) 411: printf("&cl[%d], ", k); 412: else 413: printf("0, "); 414: } 415: 416: 417: /* 418: * Yield the width of a piece of fixed text as found in a node's repr, 419: * excluding \b or \t. If \n or \r is found, -1 is returned. 420: * It assumes that \n or \r only occur as first 421: * character, and \b or \t only as last. 422: */ 423: 424: Visible int 425: fwidth(str) 426: register string str; 427: { 428: register int c; 429: register int n = 0; 430: 431: if (!str) 432: return 0; 433: c = str[0]; 434: if (c == '\r' || c == '\n') 435: return -1; 436: for (; c; c = *++str) 437: ++n; 438: if (n > 0) { 439: c = str[-1]; 440: if (c == '\t' || c == '\b') 441: --n; 442: } 443: return n; 444: } 445: 446: 447: Visible Procedure 448: syserr(fmt, a1, a2, a3, a4, a5) 449: string fmt; 450: { 451: fprintf(stderr, "mkboot system error:\n"); 452: fprintf(stderr, fmt, a1, a2, a3, a4, a5); 453: fprintf(stderr, "\n"); 454: exit(1); 455: } 456: 457: 458: Visible Procedure 459: asserr(file, line) 460: string file; 461: int line; 462: { 463: syserr("assertion error: %s, line %d", file, line); 464: }