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