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