|
|
1.1 root 1: /* bldtab - v 1.26 of 12/5/80
2: *
3: * This program translates an input stream of nroff/troff
4: * name table entries into a hashed table description. The hash
5: * function used is defined by tdef.hd, the same definition used
6: * by the nroff/troff program.
7: */
8:
9: #include "tdef.hd" /* get hashing table definitions */
10: #include "stdio.h"
11:
12: #ifdef ebcdic
13: extern char etoa[], atoe[];
14: #endif
15:
16: char version[] = "@(#)bldtab 1.26";
17: char ntversion[] = NTVER; /* nroff/troff version */
18:
19:
20:
21: #define vallen 15 /* length of value field */
22: #define llen 80 /* input line length */
23: #define bsize 512 /* buffer size */
24: #define CH 0177 /* character mask */
25: #define TRUE 1
26: #define FALSE 0
27:
28:
29: struct table {
30: int name; /* name entry */
31: int hval; /* computed hash value */
32: char val[vallen]; /* value text */
33: } table[NN+NM];
34:
35: int htable[NN+NM]; /* hashed table */
36:
37:
38: /* global flags */
39:
40: FILE *filein; /* input from file flag */
41: int stats; /* output hashing statistics */
42: int eof; /* end of input reached */
43: int valf = -1; /* uninitialized (-1), name (FALSE), or name
44: * and value format (TRUE) */
45:
46:
47: /* global variables */
48:
49: char ibuf[bsize], obuf[bsize]; /* input and output buffers */
50: int ibp = 0, obp = 0; /* input and output buffer pointers */
51: int ibpend = -1; /* pointer to end of input buffer */
52: int rgc; /* hold argc */
53: char **rgv; /* hold argv */
54: int hits[10], dist[10]; /* statistics counters */
55: char lline[llen]; /* input line storage */
56: int lpos = 0, hlpos = 0; /* line position pointers */
57: int elpos = -1; /* pointer to end of line buffer */
58: int tsize; /* size of target table */
59: main(argc, argv)
60: int argc;
61: char **argv;
62: {
63:
64: rgc = argc; rgv = argv; /* ptrs to command line args */
65:
66: readnames(); /* read all the names */
67: btable(); /* build the hash table */
68: outable(); /* output the table */
69: exit(0);
70:
71: }
72:
73:
74: btable() /* build the hash table */
75: { register int i, j, dst;
76:
77: for (i=0; table[i].name; i++) { /* compute hash values */
78: if ((j = HASH(table[i].name,tsize)) < 0) j = -j;
79: table[i].hval = j; }
80:
81: if (stats) stat_pileup(); /* static statistics */
82:
83: for (i=0; table[i].name; i++) { /* put into hash table */
84: dst = 0; /* distance to insert name */
85: for (j=table[i].hval; htable[j]; j=((j+1)%tsize))
86: dst++; /* find where to insert */
87: dist[(dst < 10) ? dst : 9]++; /* mark how far */
88: htable[j] = i + 1 /*bias*/; }
89:
90: if (stats) stat_dist(); /* search distance statistics */
91:
92: }
93: readnames()
94: { register int i, name;
95:
96: for (i=0; (!eof && i<(NN+NM-1)); i++) { /* read all names */
97:
98: if (!eat("PAIR(")) rdferr();
99: name = gquotc(); /* get quoted character */
100:
101: if (!eat(", 0 )")) { /* second character */
102: if (!eat(",")) rdferr();
103: name = PAIR(name, gquotc()); /* get it */
104: if (!eat(")")) rdferr(); }
105:
106: table[i].name = name & NAMEMASK; /* save name */
107:
108: if (valf < 0)
109: if (eat(",")) { valf = TRUE; /* name/value format */
110: gstr(table[i].val, vallen-1); } /* first one */
111: else valf = FALSE; /* name only format */
112: else if (valf) {
113: if (!eat(",")) rdferr();
114: gstr(table[i].val, vallen-1); } /* get val string */
115:
116: if (!eat("\n")) rdferr();
117:
118: getch(); lpos--; } /* force next line or eof */
119: }
120: eat(ptr) /* eat input matching string pointed to by ptr */
121: char *ptr;
122: {
123: skip(); /* skip leading white space */
124: hlpos = lpos; /* save line position */
125: while (*ptr) {
126: if (*ptr == ' ') /* space in (ptr) -> skip white space */
127: { skip(); ptr++; }
128: else if (*ptr++ != getch()) {
129: lpos = hlpos; /* no match - restore line pointer */
130: return FALSE; }}
131:
132: return TRUE; /* matched */
133: }
134:
135:
136: skip() /* skip white space in input */
137: { register int c;
138:
139: do c = getch();
140: while ((c == ' ') || (c == '\t'));
141: lpos--;
142: }
143:
144:
145: gquotc()
146: { register int c;
147:
148: if (!eat("'")) rdferr();
149: c = getch();
150: #ifdef ebcdic
151: c = etoa[c];
152: #endif
153: if (!eat("'")) rdferr();
154: return c;
155: }
156:
157:
158: /* store input until space or comma into (ptr) of length len */
159:
160: gstr(ptr, len)
161: char *ptr;
162: int len;
163: { register int i, ch;
164:
165: skip(); /* skip leading blanks */
166: i = 0;
167: while (((ch = getch()) != '\n') && (ch != ' ') && (i++ < len))
168: *ptr++ = ch;
169: lpos--;
170: if (i >= len) rdferr();
171: *ptr = 0;
172: }
173:
174:
175: rdferr()
176: { register int i;
177:
178: lline[elpos] = 0;
179: wwrite(lline); /* output line */
180: for (i=0; i<lpos; i++)
181: if (lline[i] == '\t') wwrite(2, "\t", 1);
182: else wwrite(" ");
183: wwrite("^ format error\n");
184: exit(1);
185: }
186: getch()
187: {
188: if (lpos > elpos)
189: if (!newline()) {eof = 1; return 0;}
190: return lline[lpos++];
191: }
192:
193:
194: newline()
195: {
196: lpos = elpos = 0;
197: do {
198: if (ibp > ibpend) getblk(); /* get a new block */
199: if (ibpend < 0) return FALSE; /* no more input */
200: lline[elpos] = ibuf[ibp++]; }
201: while ((lline[elpos] != '\n') && (++elpos < llen));
202: return TRUE;
203: }
204:
205:
206: getblk()
207: { int i;
208: ibp = 0;
209: if (!filein && (rgc > 1)) nextf(); /* process option or size */
210: for (i=0; ((i<bsize)&&((ibuf[i]=getc(filein))!=EOF)); i++) ;
211: if ((ibpend=i-1) == 0)
212: if (rgc > 1) {
213: nextf(); /* next file */
214: getblk(); } /* and get a block */
215: }
216:
217:
218: nextf()
219: { register int i;
220:
221: if (--rgc <= 0) return FALSE;
222:
223: if ((**++rgv == '-') && (rgv[0][1] == 's') && (rgv[0][2] == 0)) {
224: stats++; /* turn on statistics */
225: return nextf(); }
226:
227: if (!filein) { /* first non-option argument */
228: filein = (FILE *)(tsize = getnum()); /* is the table size */
229: return nextf(); }
230:
231: if ((filein = fopen(*rgv,"r")) == NULL) {
232: wwrite("Can't open ");
233: wwrite(*rgv);
234: wwrite("\n");
235: exit(1); }
236:
237: return TRUE;
238: }
239: getnum()
240: { register int ac, i;
241:
242: ac = 0;
243: for (i=0; rgv[0][i]; i++) {
244: if ((rgv[0][i] < '0') || (rgv[0][i] > '9')) {
245: wwrite("Non-numeric size argument\n");
246: exit(1); }
247: ac = (ac * 10) + (rgv[0][i] - '0'); }
248:
249: return ac;
250: }
251: outable() /* output the hashed name table */
252: { register int i, j, k;
253:
254: for (i=0; i<tsize; i++) { /* output it */
255: if (!(k = htable[i]))
256: if (valf) put("\t0,0,\n");
257: else put("\t0,\n");
258: else {
259: k--;
260: put("\tPAIR('");
261: putccode(table[k].name & CH);
262: put("',");
263: if (j = (table[k].name>>BYTE) & CH) {
264: putchar('\'');
265: putccode(j);
266: put("')"); }
267: else put("0)");
268: if (valf) {
269: putchar(',');
270: for (j=0; table[k].val[j]!=0; j++)
271: putchar(table[k].val[j]); }
272: put(", /*");
273: #ifndef ebcdic
274: putchar(table[k].name & CH);
275: #else
276: putchar(atoe[table[k].name & CH]);
277: #endif
278: if (j = (table[k].name>>BYTE) & CH)
279: #ifndef ebcdic
280: putchar(j);
281: #else
282: putchar(atoe[j]);
283: #endif
284: put("*/\n"); }}
285: }
286:
287:
288: put(ptr)
289: char *ptr;
290: {
291: do putchar(*ptr++);
292: while (*ptr);
293: }
294:
295:
296: putccode(ch)
297: char ch;
298: {
299: putchar('\\');
300: #ifndef ebcdic
301: putchar(((ch/0100)&07)+'\060');
302: putchar(((ch/010)&07)+'\060');
303: putchar(((ch)&07)+'\060');
304: #else
305: putchar(atoe[((ch/0100)&07)+'\060']);
306: putchar(atoe[((ch/010)&07)+'\060']);
307: putchar(atoe[((ch)&07)+'\060']);
308: #endif
309: }
310:
311:
312: wwrite(str)
313: char *str;
314: { char *p;
315:
316: for (p=str; *p; p++)
317: putc(*p, stderr);
318:
319: }
320: stat_pileup() /* give static statistics */
321: { int i;
322: register int j, cnt;
323:
324: for (i=0; i<tsize; i++) {
325: cnt = 0;
326: for (j=0; table[j].name; j++)
327: if (table[j].hval == i) cnt++;
328: hits[(cnt>9) ? 9 : cnt]++; }
329:
330: for (i='0'; i<'9'; i++) {
331: wwrite("count of ");
332: putc((char)i, stderr);
333: wwrite(" hits: ");
334: wrnum(hits[i-'0']);
335: wwrite("\n"); }
336:
337: wwrite("9 or more hits: ");
338: wrnum(hits[9]);
339: wwrite("\n");
340: }
341:
342:
343: stat_dist() /* hash travel distance statistics */
344: { char i;
345:
346: for (i='0'; i<'9'; i++) {
347: wwrite("count of ");
348: putc(i, stderr);
349: wwrite(" hash travel distances: ");
350: wrnum(dist[i-'0']);
351: wwrite("\n"); }
352: wwrite("search of 9 or more slots: ");
353: wrnum(dist[9]);
354: wwrite("\n");
355: }
356: wrnum(n)
357: int n;
358: { int i;
359:
360: if (n < 0) {
361: wwrite("-");
362: i = -n; }
363: else i = n;
364: if (i / 10) wrnum(i / 10);
365: *((char *)&i) = (i % 10) + '0';
366: wwrite(&i);
367: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.