|
|
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.