|
|
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.