1: /* Copyright (c) 1979 Regents of the University of California */ 2: #include <stdio.h> 3: #include <ctype.h> 4: #include <sys/types.h> 5: #include <signal.h> 6: 7: int lseek(); /* Chicanery */ 8: /* 9: * xstr - extract and hash strings in a C program 10: * 11: * Bill Joy UCB 12: * November, 1978 13: */ 14: 15: #define ignore(a) Ignore((char *) a) 16: 17: char *calloc(); 18: off_t tellpt; 19: off_t hashit(); 20: char *mktemp(); 21: int onintr(); 22: char *savestr(); 23: char *strcat(); 24: char *strcpy(); 25: off_t yankstr(); 26: 27: off_t mesgpt; 28: char *strings = "strings"; 29: 30: int cflg; 31: int vflg; 32: int readstd; 33: 34: main(argc, argv) 35: int argc; 36: char *argv[]; 37: { 38: 39: argc--, argv++; 40: while (argc > 0 && argv[0][0] == '-') { 41: register char *cp = &(*argv++)[1]; 42: 43: argc--; 44: if (*cp == 0) { 45: readstd++; 46: continue; 47: } 48: do switch (*cp++) { 49: 50: case 'c': 51: cflg++; 52: continue; 53: 54: case 'v': 55: vflg++; 56: continue; 57: 58: default: 59: fprintf(stderr, "usage: xstr [ -v ] [ -c ] [ - ] [ name ... ]\n"); 60: } while (*cp); 61: } 62: if (signal(SIGINT, SIG_IGN) == SIG_DFL) 63: signal(SIGINT, onintr); 64: if (cflg || argc == 0 && !readstd) 65: inithash(); 66: else 67: strings = mktemp(savestr("/tmp/xstrXXXXXX")); 68: while (readstd || argc > 0) { 69: if (freopen("x.c", "w", stdout) == NULL) 70: perror("x.c"), exit(1); 71: if (!readstd && freopen(argv[0], "r", stdin) == NULL) 72: perror(argv[0]), exit(2); 73: process("x.c"); 74: if (readstd == 0) 75: argc--, argv++; 76: else 77: readstd = 0; 78: }; 79: flushsh(); 80: if (cflg == 0) 81: xsdotc(); 82: if (strings[0] == '/') 83: ignore(unlink(strings)); 84: exit(0); 85: } 86: 87: process(name) 88: char *name; 89: { 90: char *cp; 91: char linebuf[BUFSIZ]; 92: register int c; 93: register int incomm = 0; 94: 95: printf("char\txstr[];\n"); 96: for (;;) { 97: if (fgets(linebuf, sizeof linebuf, stdin) == NULL) { 98: if (ferror(stdin)) { 99: perror(name); 100: exit(3); 101: } 102: break; 103: } 104: if (linebuf[0] == '#') { 105: if (linebuf[1] == ' ' && isdigit(linebuf[2])) 106: printf("#line%s", &linebuf[1]); 107: else 108: printf("%s", linebuf); 109: continue; 110: } 111: for (cp = linebuf; c = *cp++;) switch (c) { 112: 113: case '"': 114: if (incomm) 115: goto def; 116: printf("(&xstr[%d])", (int) yankstr(&cp)); 117: break; 118: 119: case '\'': 120: if (incomm) 121: goto def; 122: putchar(c); 123: if (*cp) 124: putchar(*cp++); 125: break; 126: 127: case '/': 128: if (incomm || *cp != '*') 129: goto def; 130: incomm = 1; 131: cp++; 132: printf("/*"); 133: continue; 134: 135: case '*': 136: if (incomm && *cp == '/') { 137: incomm = 0; 138: cp++; 139: printf("*/"); 140: continue; 141: } 142: goto def; 143: 144: def: 145: default: 146: putchar(c); 147: break; 148: } 149: } 150: if (ferror(stdout)) 151: perror("x.c"), onintr(); 152: } 153: 154: off_t 155: yankstr(cpp) 156: register char **cpp; 157: { 158: register char *cp = *cpp; 159: register int c, ch; 160: char dbuf[BUFSIZ]; 161: register char *dp = dbuf; 162: register char *tp; 163: 164: while (c = *cp++) { 165: switch (c) { 166: 167: case '"': 168: cp++; 169: goto out; 170: 171: case '\\': 172: c = *cp++; 173: if (c == 0) 174: break; 175: if (c == '\n') 176: continue; 177: for (tp = "b\bt\tr\rn\nf\f\\\\\"\""; ch = *tp++; tp++) 178: if (c == ch) { 179: c = *tp; 180: goto gotc; 181: } 182: if (!octdigit(c)) { 183: *dp++ = '\\'; 184: break; 185: } 186: c -= '0'; 187: if (!octdigit(*cp)) 188: break; 189: c <<= 3, c += *cp++ - '0'; 190: if (!octdigit(*cp)) 191: break; 192: c <<= 3, c += *cp++ - '0'; 193: break; 194: } 195: gotc: 196: *dp++ = c; 197: } 198: out: 199: *cpp = --cp; 200: *dp = 0; 201: return (hashit(dbuf, 1)); 202: } 203: 204: octdigit(c) 205: char c; 206: { 207: 208: return (isdigit(c) && c != '8' && c != '9'); 209: } 210: 211: inithash() 212: { 213: char buf[BUFSIZ]; 214: register FILE *mesgread = fopen(strings, "r"); 215: 216: if (mesgread == NULL) 217: return; 218: for (;;) { 219: mesgpt = tellpt; 220: if (fgetNUL(buf, sizeof buf, mesgread) == NULL) 221: break; 222: ignore(hashit(buf, 0)); 223: } 224: ignore(fclose(mesgread)); 225: } 226: 227: fgetNUL(obuf, rmdr, file) 228: char *obuf; 229: register int rmdr; 230: FILE *file; 231: { 232: register c; 233: register char *buf = obuf; 234: 235: while (--rmdr > 0 && (c = xgetc(file)) != 0 && c != EOF) 236: *buf++ = c; 237: *buf++ = 0; 238: return ((feof(file) || ferror(file)) ? NULL : 1); 239: } 240: 241: xgetc(file) 242: FILE *file; 243: { 244: 245: tellpt++; 246: return (getc(file)); 247: } 248: 249: #define BUCKETS 128 250: 251: struct hash { 252: off_t hpt; 253: char *hstr; 254: struct hash *hnext; 255: short hnew; 256: } bucket[BUCKETS]; 257: 258: off_t 259: hashit(str, new) 260: char *str; 261: int new; 262: { 263: int i; 264: register struct hash *hp, *hp0; 265: 266: hp = hp0 = &bucket[lastchr(str) & 0177]; 267: while (hp->hnext) { 268: hp = hp->hnext; 269: i = istail(str, hp->hstr); 270: if (i >= 0) 271: return (hp->hpt + i); 272: } 273: hp = (struct hash *) calloc(1, sizeof (*hp)); 274: hp->hpt = mesgpt; 275: hp->hstr = savestr(str); 276: mesgpt += strlen(hp->hstr) + 1; 277: hp->hnext = hp0->hnext; 278: hp->hnew = new; 279: hp0->hnext = hp; 280: return (hp->hpt); 281: } 282: 283: flushsh() 284: { 285: register int i; 286: register struct hash *hp; 287: register FILE *mesgwrit; 288: register int old = 0, new = 0; 289: 290: for (i = 0; i < BUCKETS; i++) 291: for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) 292: if (hp->hnew) 293: new++; 294: else 295: old++; 296: if (new == 0 && old != 0) 297: return; 298: mesgwrit = fopen(strings, old ? "a" : "w"); 299: if (mesgwrit == (FILE *) NULL) { 300: perror(strings); 301: exit(8); 302: } 303: for (i = 0; i < BUCKETS; i++) 304: for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) { 305: found(hp->hnew, hp->hpt, hp->hstr); 306: if (hp->hnew) { 307: fseek(mesgwrit, hp->hpt, 0); 308: ignore(fwrite(hp->hstr, strlen(hp->hstr) + 1, 1, mesgwrit)); 309: if (ferror(mesgwrit)) 310: perror(strings), exit(4); 311: } 312: } 313: ignore(fclose(mesgwrit)); 314: } 315: 316: found(new, off, str) 317: int new; 318: off_t off; 319: char *str; 320: { 321: register char *cp; 322: 323: if (vflg == 0) 324: return; 325: if (!new) 326: fprintf(stderr, "found at %d:", (int) off); 327: else 328: fprintf(stderr, "new at %d:", (int) off); 329: prstr(str); 330: fprintf(stderr, "\n"); 331: } 332: 333: prstr(cp) 334: register char *cp; 335: { 336: register int c; 337: 338: while (c = (*cp++ & 0377)) 339: if (c < ' ') 340: fprintf(stderr, "^%c", c + '`'); 341: else if (c == 0177) 342: fprintf(stderr, "^?"); 343: else if (c > 0200) 344: fprintf(stderr, "\\%03o", c); 345: else 346: fprintf(stderr, "%c", c); 347: } 348: 349: xsdotc() 350: { 351: register FILE *strf = fopen(strings, "r"); 352: register FILE *xdotcf; 353: 354: if (strf == NULL) 355: perror(strings), exit(5); 356: xdotcf = fopen("xs.c", "w"); 357: if (xdotcf == NULL) 358: perror("xs.c"), exit(6); 359: fprintf(xdotcf, "char\txstr[] = {\n"); 360: for (;;) { 361: register int i, c; 362: 363: for (i = 0; i < 8; i++) { 364: c = getc(strf); 365: if (ferror(strf)) { 366: perror(strings); 367: onintr(); 368: } 369: if (feof(strf)) { 370: fprintf(xdotcf, "\n"); 371: goto out; 372: } 373: fprintf(xdotcf, "0x%02x,", c); 374: } 375: fprintf(xdotcf, "\n"); 376: } 377: out: 378: fprintf(xdotcf, "};\n"); 379: ignore(fclose(xdotcf)); 380: ignore(fclose(strf)); 381: } 382: 383: char * 384: savestr(cp) 385: register char *cp; 386: { 387: register char *dp = (char *) calloc(1, strlen(cp) + 1); 388: 389: return (strcpy(dp, cp)); 390: } 391: 392: Ignore(a) 393: char *a; 394: { 395: 396: a = a; 397: } 398: 399: ignorf(a) 400: int (*a)(); 401: { 402: 403: a = a; 404: } 405: 406: lastchr(cp) 407: register char *cp; 408: { 409: 410: while (cp[0] && cp[1]) 411: cp++; 412: return (*cp); 413: } 414: 415: istail(str, of) 416: register char *str, *of; 417: { 418: register int d = strlen(of) - strlen(str); 419: 420: if (d < 0 || strcmp(&of[d], str) != 0) 421: return (-1); 422: return (d); 423: } 424: 425: onintr() 426: { 427: 428: ignorf(signal(SIGINT, SIG_IGN)); 429: if (strings[0] == '/') 430: ignore(unlink(strings)); 431: ignore(unlink("x.c")); 432: ignore(unlink("xs.c")); 433: exit(7); 434: }