Annotation of src/usr.bin/mkstr/mkstr.c, Revision 1.3
1.3 ! deraadt 1: /* $OpenBSD: mkstr.c,v 1.2 1996/06/26 05:37:13 deraadt Exp $ */
1.1 deraadt 2: /* $NetBSD: mkstr.c,v 1.4 1995/09/28 06:22:20 tls Exp $ */
3:
4: /*
5: * Copyright (c) 1980, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: #ifndef lint
38: static char copyright[] =
39: "@(#) Copyright (c) 1980, 1993\n\
40: The Regents of the University of California. All rights reserved.\n";
41: #endif /* not lint */
42:
43: #ifndef lint
44: #if 0
45: static char sccsid[] = "@(#)mkstr.c 8.1 (Berkeley) 6/6/93";
46: #else
1.3 ! deraadt 47: static char rcsid[] = "$OpenBSD: mkstr.c,v 1.2 1996/06/26 05:37:13 deraadt Exp $";
1.1 deraadt 48: #endif
49: #endif /* not lint */
50:
1.3 ! deraadt 51: #include <sys/types.h>
! 52: #include <sys/stat.h>
1.1 deraadt 53: #include <stdio.h>
54: #include <stdlib.h>
55: #include <string.h>
56:
57: #define ungetchar(c) ungetc(c, stdin)
58:
59: /*
60: * mkstr - create a string error message file by massaging C source
61: *
62: * Bill Joy UCB August 1977
63: *
64: * Modified March 1978 to hash old messages to be able to recompile
65: * without addding messages to the message file (usually)
66: *
67: * Based on an earlier program conceived by Bill Joy and Chuck Haley
68: *
69: * Program to create a string error message file
70: * from a group of C programs. Arguments are the name
71: * of the file where the strings are to be placed, the
72: * prefix of the new files where the processed source text
73: * is to be placed, and the files to be processed.
74: *
75: * The program looks for 'error("' in the source stream.
76: * Whenever it finds this, the following characters from the '"'
77: * to a '"' are replaced by 'seekpt' where seekpt is a
78: * pointer into the error message file.
79: * If the '(' is not immediately followed by a '"' no change occurs.
80: *
81: * The optional '-' causes strings to be added at the end of the
82: * existing error message file for recompilation of single routines.
83: */
84:
85:
86: FILE *mesgread, *mesgwrite;
87: char *progname;
88: char usagestr[] = "usage: %s [ - ] mesgfile prefix file ...\n";
89: char name[100], *np;
90:
1.3 ! deraadt 91: void inithash __P((void));
! 92: void process __P((void));
! 93: int match __P((char *));
! 94: void copystr __P((void));
! 95: int octdigit __P((char));
! 96: unsigned hashit __P((char *, char, unsigned));
! 97: int fgetNUL __P((char *, int, FILE *));
! 98:
! 99: int
1.1 deraadt 100: main(argc, argv)
101: int argc;
102: char *argv[];
103: {
104: char addon = 0;
105:
106: argc--, progname = *argv++;
107: if (argc > 1 && argv[0][0] == '-')
108: addon++, argc--, argv++;
109: if (argc < 3)
110: fprintf(stderr, usagestr, progname), exit(1);
111: mesgwrite = fopen(argv[0], addon ? "a" : "w");
112: if (mesgwrite == NULL)
113: perror(argv[0]), exit(1);
114: mesgread = fopen(argv[0], "r");
115: if (mesgread == NULL)
116: perror(argv[0]), exit(1);
117: inithash();
118: argc--, argv++;
119: strcpy(name, argv[0]);
120: np = name + strlen(name);
121: argc--, argv++;
122: do {
123: strcpy(np, argv[0]);
124: if (freopen(name, "w", stdout) == NULL)
125: perror(name), exit(1);
126: if (freopen(argv[0], "r", stdin) == NULL)
127: perror(argv[0]), exit(1);
128: process();
129: argc--, argv++;
130: } while (argc > 0);
1.3 ! deraadt 131: return 0;
1.1 deraadt 132: }
133:
1.3 ! deraadt 134: void
1.1 deraadt 135: process()
136: {
137: register c;
138:
139: for (;;) {
140: c = getchar();
141: if (c == EOF)
142: return;
143: if (c != 'e') {
144: putchar(c);
145: continue;
146: }
147: if (match("error(")) {
148: printf("error(");
149: c = getchar();
150: if (c != '"')
151: putchar(c);
152: else
153: copystr();
154: }
155: }
156: }
157:
1.3 ! deraadt 158: int
1.1 deraadt 159: match(ocp)
160: char *ocp;
161: {
162: register char *cp;
163: register c;
164:
165: for (cp = ocp + 1; *cp; cp++) {
166: c = getchar();
167: if (c != *cp) {
168: while (ocp < cp)
169: putchar(*ocp++);
170: ungetchar(c);
171: return (0);
172: }
173: }
174: return (1);
175: }
176:
1.3 ! deraadt 177: void
1.1 deraadt 178: copystr()
179: {
180: register c, ch;
181: char buf[512];
182: register char *cp = buf;
183:
184: for (;;) {
185: c = getchar();
186: if (c == EOF)
187: break;
188: switch (c) {
189:
190: case '"':
191: *cp++ = 0;
192: goto out;
193: case '\\':
194: c = getchar();
195: switch (c) {
196:
197: case 'b':
198: c = '\b';
199: break;
200: case 't':
201: c = '\t';
202: break;
203: case 'r':
204: c = '\r';
205: break;
206: case 'n':
207: c = '\n';
208: break;
209: case '\n':
210: continue;
211: case 'f':
212: c = '\f';
213: break;
214: case '0':
215: c = 0;
216: break;
217: case '\\':
218: break;
219: default:
220: if (!octdigit(c))
221: break;
222: c -= '0';
223: ch = getchar();
224: if (!octdigit(ch))
225: break;
226: c <<= 7, c += ch - '0';
227: ch = getchar();
228: if (!octdigit(ch))
229: break;
230: c <<= 3, c+= ch - '0', ch = -1;
231: break;
232: }
233: }
234: *cp++ = c;
235: }
236: out:
237: *cp = 0;
1.3 ! deraadt 238: printf("%d", hashit(buf, 1, 0));
1.1 deraadt 239: }
240:
1.3 ! deraadt 241: int
1.1 deraadt 242: octdigit(c)
243: char c;
244: {
245:
246: return (c >= '0' && c <= '7');
247: }
248:
1.3 ! deraadt 249: void
1.1 deraadt 250: inithash()
251: {
252: char buf[512];
253: int mesgpt = 0;
254:
255: rewind(mesgread);
1.3 ! deraadt 256: while (fgetNUL(buf, sizeof buf, mesgread) != 0) {
1.1 deraadt 257: hashit(buf, 0, mesgpt);
258: mesgpt += strlen(buf) + 2;
259: }
260: }
261:
262: #define NBUCKETS 511
263:
264: struct hash {
265: long hval;
266: unsigned hpt;
267: struct hash *hnext;
268: } *bucket[NBUCKETS];
269:
1.3 ! deraadt 270: unsigned
1.1 deraadt 271: hashit(str, really, fakept)
272: char *str;
273: char really;
274: unsigned fakept;
275: {
276: int i;
277: register struct hash *hp;
278: char buf[512];
279: long hashval = 0;
280: register char *cp;
281:
282: if (really)
283: fflush(mesgwrite);
284: for (cp = str; *cp;)
285: hashval = (hashval << 1) + *cp++;
286: i = hashval % NBUCKETS;
287: if (i < 0)
288: i += NBUCKETS;
289: if (really != 0)
290: for (hp = bucket[i]; hp != 0; hp = hp->hnext)
291: if (hp->hval == hashval) {
292: fseek(mesgread, (long) hp->hpt, 0);
293: fgetNUL(buf, sizeof buf, mesgread);
294: /*
295: fprintf(stderr, "Got (from %d) %s\n", hp->hpt, buf);
296: */
297: if (strcmp(buf, str) == 0)
298: break;
299: }
300: if (!really || hp == 0) {
301: hp = (struct hash *) calloc(1, sizeof *hp);
302: hp->hnext = bucket[i];
303: hp->hval = hashval;
304: hp->hpt = really ? ftell(mesgwrite) : fakept;
305: if (really) {
306: fwrite(str, sizeof (char), strlen(str) + 1, mesgwrite);
307: fwrite("\n", sizeof (char), 1, mesgwrite);
308: }
309: bucket[i] = hp;
310: }
311: /*
312: fprintf(stderr, "%s hashed to %ld at %d\n", str, hp->hval, hp->hpt);
313: */
314: return (hp->hpt);
315: }
316:
1.3 ! deraadt 317: int
1.1 deraadt 318: fgetNUL(obuf, rmdr, file)
319: char *obuf;
320: register int rmdr;
321: FILE *file;
322: {
323: register c;
324: register char *buf = obuf;
325:
326: while (--rmdr > 0 && (c = getc(file)) != 0 && c != EOF)
327: *buf++ = c;
328: *buf++ = 0;
329: getc(file);
1.3 ! deraadt 330: return ((feof(file) || ferror(file)) ? 0 : 1);
1.1 deraadt 331: }