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

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