xref: /minix3/usr.bin/xstr/xstr.c (revision 3179b9b918b79627288341afcb230649990f9e9c)
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