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

  1. /* Copyright (c) 1979 Regents of the University of California */
  2. #include <stdio.h>
  3.  
  4. #define    ungetchar(c)    ungetc(c, stdin)
  5.  
  6. long    ftell();
  7. char    *calloc();
  8. /*
  9.  * mkstr - create a string error message file by massaging C source
  10.  *
  11.  * Bill Joy UCB August 1977
  12.  *
  13.  * Modified March 1978 to hash old messages to be able to recompile
  14.  * without addding messages to the message file (usually)
  15.  *
  16.  * Based on an earlier program conceived by Bill Joy and Chuck Haley
  17.  *
  18.  * Program to create a string error message file
  19.  * from a group of C programs.  Arguments are the name
  20.  * of the file where the strings are to be placed, the
  21.  * prefix of the new files where the processed source text
  22.  * is to be placed, and the files to be processed.
  23.  *
  24.  * The program looks for 'error("' in the source stream.
  25.  * Whenever it finds this, the following characters from the '"'
  26.  * to a '"' are replaced by 'seekpt' where seekpt is a
  27.  * pointer into the error message file.
  28.  * If the '(' is not immediately followed by a '"' no change occurs.
  29.  *
  30.  * The optional '-' causes strings to be added at the end of the
  31.  * existing error message file for recompilation of single routines.
  32.  */
  33.  
  34.  
  35. FILE    *mesgread, *mesgwrite;
  36. char    *progname;
  37. char    usagestr[] =    "usage: %s [ - ] mesgfile prefix file ...\n";
  38. char    name[100], *np;
  39.  
  40. main(argc, argv)
  41.     int argc;
  42.     char *argv[];
  43. {
  44.     char addon = 0;
  45.  
  46.     argc--, progname = *argv++;
  47.     if (argc > 1 && argv[0][0] == '-')
  48.         addon++, argc--, argv++;
  49.     if (argc < 3)
  50.         fprintf(stderr, usagestr, progname), exit(1);
  51.     mesgwrite = fopen(argv[0], addon ? "a" : "w");
  52.     if (mesgwrite == NULL)
  53.         perror(argv[0]), exit(1);
  54.     mesgread = fopen(argv[0], "r");
  55.     if (mesgread == NULL)
  56.         perror(argv[0]), exit(1);
  57.     inithash();
  58.     argc--, argv++;
  59.     strcpy(name, argv[0]);
  60.     np = name + strlen(name);
  61.     argc--, argv++;
  62.     do {
  63.         strcpy(np, argv[0]);
  64.         if (freopen(name, "w", stdout) == NULL)
  65.             perror(name), exit(1);
  66.         if (freopen(argv[0], "r", stdin) == NULL)
  67.             perror(argv[0]), exit(1);
  68.         process();
  69.         argc--, argv++;
  70.     } while (argc > 0);
  71.     exit(0);
  72. }
  73.  
  74. process()
  75. {
  76.     register char *cp;
  77.     register c;
  78.  
  79.     for (;;) {
  80.         c = getchar();
  81.         if (c == EOF)
  82.             return;
  83.         if (c != 'e') {
  84.             putchar(c);
  85.             continue;
  86.         }
  87.         if (match("error(")) {
  88.             printf("error(");
  89.             c = getchar();
  90.             if (c != '"')
  91.                 putchar(c);
  92.             else
  93.                 copystr();
  94.         }
  95.     }
  96. }
  97.  
  98. match(ocp)
  99.     char *ocp;
  100. {
  101.     register char *cp;
  102.     register c;
  103.  
  104.     for (cp = ocp + 1; *cp; cp++) {
  105.         c = getchar();
  106.         if (c != *cp) {
  107.             while (ocp < cp)
  108.                 putchar(*ocp++);
  109.             ungetchar(c);
  110.             return (0);
  111.         }
  112.     }
  113.     return (1);
  114. }
  115.  
  116. copystr()
  117. {
  118.     register c, ch;
  119.     char buf[512];
  120.     register char *cp = buf;
  121.  
  122.     for (;;) {
  123.         c = getchar();
  124.         if (c == EOF)
  125.             break;
  126.         switch (c) {
  127.  
  128.         case '"':
  129.             *cp++ = 0;
  130.             goto out;
  131.         case '\\':
  132.             c = getchar();
  133.             switch (c) {
  134.  
  135.             case 'b':
  136.                 c = '\b';
  137.                 break;
  138.             case 't':
  139.                 c = '\t';
  140.                 break;
  141.             case 'r':
  142.                 c = '\r';
  143.                 break;
  144.             case 'n':
  145.                 c = '\n';
  146.                 break;
  147.             case '\n':
  148.                 continue;
  149.             case 'f':
  150.                 c = '\f';
  151.                 break;
  152.             case '0':
  153.                 c = 0;
  154.                 break;
  155.             case '\\':
  156.                 break;
  157.             default:
  158.                 if (!octdigit(c))
  159.                     break;
  160.                 c -= '0';
  161.                 ch = getchar();
  162.                 if (!octdigit(ch))
  163.                     break;
  164.                 c <<= 7, c += ch - '0';
  165.                 ch = getchar();
  166.                 if (!octdigit(ch))
  167.                     break;
  168.                 c <<= 3, c+= ch - '0', ch = -1;
  169.                 break;
  170.             }
  171.         }
  172.         *cp++ = c;
  173.     }
  174. out:
  175.     *cp = 0;
  176.     printf("%d", hashit(buf, 1, NULL));
  177. }
  178.  
  179. octdigit(c)
  180.     char c;
  181. {
  182.  
  183.     return (c >= '0' && c <= '7');
  184. }
  185.  
  186. inithash()
  187. {
  188.     char buf[512];
  189.     int mesgpt = 0;
  190.  
  191.     rewind(mesgread);
  192.     while (fgetNUL(buf, sizeof buf, mesgread) != NULL) {
  193.         hashit(buf, 0, mesgpt);
  194.         mesgpt += strlen(buf) + 2;
  195.     }
  196. }
  197.  
  198. #define    NBUCKETS    511
  199.  
  200. struct    hash {
  201.     long    hval;
  202.     unsigned hpt;
  203.     struct    hash *hnext;
  204. } *bucket[NBUCKETS];
  205.  
  206. hashit(str, really, fakept)
  207.     char *str;
  208.     char really;
  209.     unsigned fakept;
  210. {
  211.     int i;
  212.     register struct hash *hp;
  213.     char buf[512];
  214.     long hashval = 0;
  215.     register char *cp;
  216.  
  217.     if (really)
  218.         fflush(mesgwrite);
  219.     for (cp = str; *cp;)
  220.         hashval = (hashval << 1) + *cp++;
  221.     i = hashval % NBUCKETS;
  222.     if (i < 0)
  223.         i += NBUCKETS;
  224.     if (really != 0)
  225.         for (hp = bucket[i]; hp != 0; hp = hp->hnext)
  226.         if (hp->hval == hashval) {
  227.             fseek(mesgread, (long) hp->hpt, 0);
  228.             fgetNUL(buf, sizeof buf, mesgread);
  229. /*
  230.             fprintf(stderr, "Got (from %d) %s\n", hp->hpt, buf);
  231. */
  232.             if (strcmp(buf, str) == 0)
  233.                 break;
  234.         }
  235.     if (!really || hp == 0) {
  236.         hp = (struct hash *) calloc(1, sizeof *hp);
  237.         hp->hnext = bucket[i];
  238.         hp->hval = hashval;
  239.         hp->hpt = really ? ftell(mesgwrite) : fakept;
  240.         if (really) {
  241.             fwrite(str, sizeof (char), strlen(str) + 1, mesgwrite);
  242.             fwrite("\n", sizeof (char), 1, mesgwrite);
  243.         }
  244.         bucket[i] = hp;
  245.     }
  246. /*
  247.     fprintf(stderr, "%s hashed to %ld at %d\n", str, hp->hval, hp->hpt);
  248. */
  249.     return (hp->hpt);
  250. }
  251.  
  252. #include <sys/types.h>
  253. #include <sys/stat.h>
  254.  
  255. fgetNUL(obuf, rmdr, file)
  256.     char *obuf;
  257.     register int rmdr;
  258.     FILE *file;
  259. {
  260.     register c;
  261.     register char *buf = obuf;
  262.  
  263.     while (--rmdr > 0 && (c = getc(file)) != 0 && c != EOF)
  264.         *buf++ = c;
  265.     *buf++ = 0;
  266.     getc(file);
  267.     return ((feof(file) || ferror(file)) ? NULL : 1);
  268. }
  269.