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