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: }

Defined functions

Ignore defined in line 392; used 1 times
  • in line 15
fgetNUL defined in line 227; used 1 times
flushsh defined in line 283; used 1 times
  • in line 79
found defined in line 316; used 1 times
hashit defined in line 258; used 3 times
ignorf defined in line 399; used 1 times
inithash defined in line 211; used 1 times
  • in line 65
istail defined in line 415; used 1 times
lastchr defined in line 406; used 1 times
main defined in line 34; never used
octdigit defined in line 204; used 3 times
onintr defined in line 425; used 4 times
process defined in line 87; used 1 times
  • in line 73
prstr defined in line 333; used 1 times
savestr defined in line 383; used 3 times
xgetc defined in line 241; used 1 times
xsdotc defined in line 349; used 1 times
  • in line 81
yankstr defined in line 154; used 2 times

Defined variables

bucket defined in line 256; used 3 times
cflg defined in line 30; used 3 times
mesgpt defined in line 27; used 3 times
readstd defined in line 32; used 6 times
strings defined in line 28; used 12 times
tellpt defined in line 18; used 2 times
vflg defined in line 31; used 2 times

Defined struct's

hash defined in line 251; used 8 times

Defined macros

BUCKETS defined in line 249; used 3 times
ignore defined in line 15; used 10 times
Last modified: 1983-10-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1428
Valid CSS Valid XHTML 1.0 Strict