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

Defined functions

fgetNUL defined in line 256; used 1 times
flushsh defined in line 315; used 1 times
  • in line 93
found defined in line 347; used 1 times
hashit defined in line 287; used 3 times
inithash defined in line 240; used 1 times
  • in line 79
istail defined in line 434; used 1 times
lastchr defined in line 425; used 1 times
main defined in line 48; never used
octdigit defined in line 233; used 3 times
onintr defined in line 444; used 4 times
process defined in line 103; used 1 times
  • in line 87
prstr defined in line 362; used 1 times
savestr defined in line 412; used 3 times
xgetc defined in line 270; used 1 times
xsdotc defined in line 378; used 1 times
  • in line 95
yankstr defined in line 173; used 2 times

Defined variables

bucket defined in line 285; used 3 times
cflg defined in line 44; used 3 times
copyright defined in line 8; never used
linebuf defined in line 101; used 11 times
readstd defined in line 46; used 6 times
sccsid defined in line 14; never used
strings defined in line 42; used 13 times
vflg defined in line 45; used 2 times

Defined struct's

hash defined in line 280; used 8 times

Defined macros

BUCKETS defined in line 278; used 3 times
ignore defined in line 29; used 10 times
Last modified: 1986-01-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1593
Valid CSS Valid XHTML 1.0 Strict