home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / xstr / xstr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-16  |  8.8 KB  |  472 lines

  1. /*
  2.  * Copyright (c) 1980 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1980 The Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)xstr.c    5.7 (Berkeley) 2/26/91";
  42. #endif /* not lint */
  43.  
  44. #include <sys/types.h>
  45. #include <signal.h>
  46. #include <errno.h>
  47. #include <unistd.h>
  48. #include <stdio.h>
  49. #include <ctype.h>
  50. #include <string.h>
  51. #include "pathnames.h"
  52.  
  53. /*
  54.  * xstr - extract and hash strings in a C program
  55.  *
  56.  * Bill Joy UCB
  57.  * November, 1978
  58.  */
  59.  
  60. #define    ignore(a)    ((void) a)
  61.  
  62. off_t    tellpt;
  63. off_t    hashit();
  64. void    onintr();
  65. char    *savestr();
  66. off_t    yankstr();
  67.  
  68. off_t    mesgpt;
  69. char    *strings =    "strings";
  70.  
  71. int    cflg;
  72. int    vflg;
  73. int    readstd;
  74.  
  75. main(argc, argv)
  76.     int argc;
  77.     char *argv[];
  78. {
  79.  
  80.     argc--, argv++;
  81.     while (argc > 0 && argv[0][0] == '-') {
  82.         register char *cp = &(*argv++)[1];
  83.  
  84.         argc--;
  85.         if (*cp == 0) {
  86.             readstd++;
  87.             continue;
  88.         }
  89.         do switch (*cp++) {
  90.  
  91.         case 'c':
  92.             cflg++;
  93.             continue;
  94.  
  95.         case 'v':
  96.             vflg++;
  97.             continue;
  98.  
  99.         default:
  100.             fprintf(stderr, "usage: xstr [ -v ] [ -c ] [ - ] [ name ... ]\n");
  101.         } while (*cp);
  102.     }
  103.     if (signal(SIGINT, SIG_IGN) == SIG_DFL)
  104.         signal(SIGINT, onintr);
  105.     if (cflg || argc == 0 && !readstd)
  106.         inithash();
  107.     else
  108.         strings = mktemp(strdup(_PATH_TMP));
  109.     while (readstd || argc > 0) {
  110.         if (freopen("x.c", "w", stdout) == NULL)
  111.             perror("x.c"), exit(1);
  112.         if (!readstd && freopen(argv[0], "r", stdin) == NULL)
  113.             perror(argv[0]), exit(2);
  114.         process("x.c");
  115.         if (readstd == 0)
  116.             argc--, argv++;
  117.         else
  118.             readstd = 0;
  119.     };
  120.     flushsh();
  121.     if (cflg == 0)
  122.         xsdotc();
  123.     if (strings[0] == '/')
  124.         ignore(unlink(strings));
  125.     exit(0);
  126. }
  127.  
  128. char linebuf[BUFSIZ];
  129.  
  130. process(name)
  131.     char *name;
  132. {
  133.     char *cp;
  134.     register int c;
  135.     register int incomm = 0;
  136.     int ret;
  137.  
  138.     printf("extern char\txstr[];\n");
  139.     for (;;) {
  140.         if (fgets(linebuf, sizeof linebuf, stdin) == NULL) {
  141.             if (ferror(stdin)) {
  142.                 perror(name);
  143.                 exit(3);
  144.             }
  145.             break;
  146.         }
  147.         if (linebuf[0] == '#') {
  148.             if (linebuf[1] == ' ' && isdigit(linebuf[2]))
  149.                 printf("#line%s", &linebuf[1]);
  150.             else
  151.                 printf("%s", linebuf);
  152.             continue;
  153.         }
  154.         for (cp = linebuf; c = *cp++;) switch (c) {
  155.             
  156.         case '"':
  157.             if (incomm)
  158.                 goto def;
  159.             if ((ret = (int) yankstr(&cp)) == -1)
  160.                 goto out;
  161.             printf("(&xstr[%d])", ret);
  162.             break;
  163.  
  164.         case '\'':
  165.             if (incomm)
  166.                 goto def;
  167.             putchar(c);
  168.             if (*cp)
  169.                 putchar(*cp++);
  170.             break;
  171.  
  172.         case '/':
  173.             if (incomm || *cp != '*')
  174.                 goto def;
  175.             incomm = 1;
  176.             cp++;
  177.             printf("/*");
  178.             continue;
  179.  
  180.         case '*':
  181.             if (incomm && *cp == '/') {
  182.                 incomm = 0;
  183.                 cp++;
  184.                 printf("*/");
  185.                 continue;
  186.             }
  187.             goto def;
  188.         
  189. def:
  190.         default:
  191.             putchar(c);
  192.             break;
  193.         }
  194.     }
  195. out:
  196.     if (ferror(stdout))
  197.         perror("x.c"), onintr();
  198. }
  199.  
  200. off_t
  201. yankstr(cpp)
  202.     register char **cpp;
  203. {
  204.     register char *cp = *cpp;
  205.     register int c, ch;
  206.     char dbuf[BUFSIZ];
  207.     register char *dp = dbuf;
  208.     register char *tp;
  209.  
  210.     while (c = *cp++) {
  211.         switch (c) {
  212.  
  213.         case '"':
  214.             cp++;
  215.             goto out;
  216.  
  217.         case '\\':
  218.             c = *cp++;
  219.             if (c == 0)
  220.                 break;
  221.             if (c == '\n') {
  222.                 if (fgets(linebuf, sizeof linebuf, stdin) 
  223.                     == NULL) {
  224.                     if (ferror(stdin)) {
  225.                         perror("x.c");
  226.                         exit(3);
  227.                     }
  228.                     return(-1);
  229.                 }
  230.                 cp = linebuf;
  231.                 continue;
  232.             }
  233.             for (tp = "b\bt\tr\rn\nf\f\\\\\"\""; ch = *tp++; tp++)
  234.                 if (c == ch) {
  235.                     c = *tp;
  236.                     goto gotc;
  237.                 }
  238.             if (!octdigit(c)) {
  239.                 *dp++ = '\\';
  240.                 break;
  241.             }
  242.             c -= '0';
  243.             if (!octdigit(*cp))
  244.                 break;
  245.             c <<= 3, c += *cp++ - '0';
  246.             if (!octdigit(*cp))
  247.                 break;
  248.             c <<= 3, c += *cp++ - '0';
  249.             break;
  250.         }
  251. gotc:
  252.         *dp++ = c;
  253.     }
  254. out:
  255.     *cpp = --cp;
  256.     *dp = 0;
  257.     return (hashit(dbuf, 1));
  258. }
  259.  
  260. octdigit(c)
  261.     char c;
  262. {
  263.  
  264.     return (isdigit(c) && c != '8' && c != '9');
  265. }
  266.  
  267. inithash()
  268. {
  269.     char buf[BUFSIZ];
  270.     register FILE *mesgread = fopen(strings, "r");
  271.  
  272.     if (mesgread == NULL)
  273.         return;
  274.     for (;;) {
  275.         mesgpt = tellpt;
  276.         if (fgetNUL(buf, sizeof buf, mesgread) == NULL)
  277.             break;
  278.         ignore(hashit(buf, 0));
  279.     }
  280.     ignore(fclose(mesgread));
  281. }
  282.  
  283. fgetNUL(obuf, rmdr, file)
  284.     char *obuf;
  285.     register int rmdr;
  286.     FILE *file;
  287. {
  288.     register c;
  289.     register char *buf = obuf;
  290.  
  291.     while (--rmdr > 0 && (c = xgetc(file)) != 0 && c != EOF)
  292.         *buf++ = c;
  293.     *buf++ = 0;
  294.     return ((feof(file) || ferror(file)) ? NULL : 1);
  295. }
  296.  
  297. xgetc(file)
  298.     FILE *file;
  299. {
  300.  
  301.     tellpt++;
  302.     return (getc(file));
  303. }
  304.  
  305. #define    BUCKETS    128
  306.  
  307. struct    hash {
  308.     off_t    hpt;
  309.     char    *hstr;
  310.     struct    hash *hnext;
  311.     short    hnew;
  312. } bucket[BUCKETS];
  313.  
  314. off_t
  315. hashit(str, new)
  316.     char *str;
  317.     int new;
  318. {
  319.     int i;
  320.     register struct hash *hp, *hp0;
  321.  
  322.     hp = hp0 = &bucket[lastchr(str) & 0177];
  323.     while (hp->hnext) {
  324.         hp = hp->hnext;
  325.         i = istail(str, hp->hstr);
  326.         if (i >= 0)
  327.             return (hp->hpt + i);
  328.     }
  329.     if ((hp = (struct hash *) calloc(1, sizeof (*hp))) == NULL) {
  330.         perror("xstr");
  331.         exit(8);
  332.     }
  333.     hp->hpt = mesgpt;
  334.     if (!(hp->hstr = strdup(str))) {
  335.         (void)fprintf(stderr, "xstr: %s\n", strerror(errno));
  336.         exit(1);
  337.     }
  338.     mesgpt += strlen(hp->hstr) + 1;
  339.     hp->hnext = hp0->hnext;
  340.     hp->hnew = new;
  341.     hp0->hnext = hp;
  342.     return (hp->hpt);
  343. }
  344.  
  345. flushsh()
  346. {
  347.     register int i;
  348.     register struct hash *hp;
  349.     register FILE *mesgwrit;
  350.     register int old = 0, new = 0;
  351.  
  352.     for (i = 0; i < BUCKETS; i++)
  353.         for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext)
  354.             if (hp->hnew)
  355.                 new++;
  356.             else
  357.                 old++;
  358.     if (new == 0 && old != 0)
  359.         return;
  360.     mesgwrit = fopen(strings, old ? "r+" : "w");
  361.     if (mesgwrit == NULL)
  362.         perror(strings), exit(4);
  363.     for (i = 0; i < BUCKETS; i++)
  364.         for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) {
  365.             found(hp->hnew, hp->hpt, hp->hstr);
  366.             if (hp->hnew) {
  367.                 fseek(mesgwrit, hp->hpt, 0);
  368.                 ignore(fwrite(hp->hstr, strlen(hp->hstr) + 1, 1, mesgwrit));
  369.                 if (ferror(mesgwrit))
  370.                     perror(strings), exit(4);
  371.             }
  372.         }
  373.     if (fclose(mesgwrit) == EOF)
  374.         perror(strings), exit(4);
  375. }
  376.  
  377. found(new, off, str)
  378.     int new;
  379.     off_t off;
  380.     char *str;
  381. {
  382.     if (vflg == 0)
  383.         return;
  384.     if (!new)
  385.         fprintf(stderr, "found at %d:", (int) off);
  386.     else
  387.         fprintf(stderr, "new at %d:", (int) off);
  388.     prstr(str);
  389.     fprintf(stderr, "\n");
  390. }
  391.  
  392. prstr(cp)
  393.     register char *cp;
  394. {
  395.     register int c;
  396.  
  397.     while (c = (*cp++ & 0377))
  398.         if (c < ' ')
  399.             fprintf(stderr, "^%c", c + '`');
  400.         else if (c == 0177)
  401.             fprintf(stderr, "^?");
  402.         else if (c > 0200)
  403.             fprintf(stderr, "\\%03o", c);
  404.         else
  405.             fprintf(stderr, "%c", c);
  406. }
  407.  
  408. xsdotc()
  409. {
  410.     register FILE *strf = fopen(strings, "r");
  411.     register FILE *xdotcf;
  412.  
  413.     if (strf == NULL)
  414.         perror(strings), exit(5);
  415.     xdotcf = fopen("xs.c", "w");
  416.     if (xdotcf == NULL)
  417.         perror("xs.c"), exit(6);
  418.     fprintf(xdotcf, "char\txstr[] = {\n");
  419.     for (;;) {
  420.         register int i, c;
  421.  
  422.         for (i = 0; i < 8; i++) {
  423.             c = getc(strf);
  424.             if (ferror(strf)) {
  425.                 perror(strings);
  426.                 onintr();
  427.             }
  428.             if (feof(strf)) {
  429.                 fprintf(xdotcf, "\n");
  430.                 goto out;
  431.             }
  432.             fprintf(xdotcf, "0x%02x,", c);
  433.         }
  434.         fprintf(xdotcf, "\n");
  435.     }
  436. out:
  437.     fprintf(xdotcf, "};\n");
  438.     ignore(fclose(xdotcf));
  439.     ignore(fclose(strf));
  440. }
  441.  
  442. lastchr(cp)
  443.     register char *cp;
  444. {
  445.  
  446.     while (cp[0] && cp[1])
  447.         cp++;
  448.     return (*cp);
  449. }
  450.  
  451. istail(str, of)
  452.     register char *str, *of;
  453. {
  454.     register int d = strlen(of) - strlen(str);
  455.  
  456.     if (d < 0 || strcmp(&of[d], str) != 0)
  457.         return (-1);
  458.     return (d);
  459. }
  460.  
  461. void
  462. onintr()
  463. {
  464.  
  465.     ignore(signal(SIGINT, SIG_IGN));
  466.     if (strings[0] == '/')
  467.         ignore(unlink(strings));
  468.     ignore(unlink("x.c"));
  469.     ignore(unlink("xs.c"));
  470.     exit(7);
  471. }
  472.