home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / spencer_2bsd.tar.gz / 2bsd.tar / src / xstr.c < prev   
C/C++ Source or Header  |  1980-02-17  |  7KB  |  431 lines

  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.     for (i = 0; i < BUCKETS; i++)
  300.         for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) {
  301.             found(hp->hnew, hp->hpt, hp->hstr);
  302.             if (hp->hnew) {
  303.                 fseek(mesgwrit, hp->hpt, 0);
  304.                 ignore(fwrite(hp->hstr, strlen(hp->hstr) + 1, 1, mesgwrit));
  305.                 if (ferror(mesgwrit))
  306.                     perror(strings), exit(4);
  307.             }
  308.         }
  309.     ignore(fclose(mesgwrit));
  310. }
  311.  
  312. found(new, off, str)
  313.     int new;
  314.     off_t off;
  315.     char *str;
  316. {
  317.     register char *cp;
  318.  
  319.     if (vflg == 0)
  320.         return;
  321.     if (!new)
  322.         fprintf(stderr, "found at %d:", (int) off);
  323.     else
  324.         fprintf(stderr, "new at %d:", (int) off);
  325.     prstr(str);
  326.     fprintf(stderr, "\n");
  327. }
  328.  
  329. prstr(cp)
  330.     register char *cp;
  331. {
  332.     register int c;
  333.  
  334.     while (c = (*cp++ & 0377))
  335.         if (c < ' ')
  336.             fprintf(stderr, "^%c", c + '`');
  337.         else if (c == 0177)
  338.             fprintf(stderr, "^?");
  339.         else if (c > 0200)
  340.             fprintf(stderr, "\\%03o", c);
  341.         else
  342.             fprintf(stderr, "%c", c);
  343. }
  344.  
  345. xsdotc()
  346. {
  347.     register FILE *strf = fopen(strings, "r");
  348.     register FILE *xdotcf;
  349.  
  350.     if (strf == NULL)
  351.         perror(strings), exit(5);
  352.     xdotcf = fopen("xs.c", "w");
  353.     if (xdotcf == NULL)
  354.         perror("xs.c"), exit(6);
  355.     fprintf(xdotcf, "char\txstr[] = {\n");
  356.     for (;;) {
  357.         register int i, c;
  358.  
  359.         for (i = 0; i < 8; i++) {
  360.             c = getc(strf);
  361.             if (ferror(strf)) {
  362.                 perror(strings);
  363.                 onintr();
  364.             }
  365.             if (feof(strf)) {
  366.                 fprintf(xdotcf, "\n");
  367.                 goto out;
  368.             }
  369.             fprintf(xdotcf, "0x%02x,", c);
  370.         }
  371.         fprintf(xdotcf, "\n");
  372.     }
  373. out:
  374.     fprintf(xdotcf, "};\n");
  375.     ignore(fclose(xdotcf));
  376.     ignore(fclose(strf));
  377. }
  378.  
  379. char *
  380. savestr(cp)
  381.     register char *cp;
  382. {
  383.     register char *dp = (char *) calloc(1, strlen(cp) + 1);
  384.  
  385.     return (strcpy(dp, cp));
  386. }
  387.  
  388. Ignore(a)
  389.     char *a;
  390. {
  391.  
  392.     a = a;
  393. }
  394.  
  395. ignorf(a)
  396.     int (*a)();
  397. {
  398.  
  399.     a = a;
  400. }
  401.  
  402. lastchr(cp)
  403.     register char *cp;
  404. {
  405.  
  406.     while (cp[0] && cp[1])
  407.         cp++;
  408.     return (*cp);
  409. }
  410.  
  411. istail(str, of)
  412.     register char *str, *of;
  413. {
  414.     register int d = strlen(of) - strlen(str);
  415.  
  416.     if (d < 0 || strcmp(&of[d], str) != 0)
  417.         return (-1);
  418.     return (d);
  419. }
  420.  
  421. onintr()
  422. {
  423.  
  424.     ignorf(signal(SIGINT, SIG_IGN));
  425.     if (strings[0] == '/')
  426.         ignore(unlink(strings));
  427.     ignore(unlink("x.c"));
  428.     ignore(unlink("xs.c"));
  429.     exit(7);
  430. }
  431.