Annotation of src/usr.bin/xstr/xstr.c, Revision 1.6
1.6 ! mpech 1: /* $OpenBSD: xstr.c,v 1.5 2001/07/20 14:20:29 deraadt Exp $ */
1.1 deraadt 2: /* $NetBSD: xstr.c,v 1.5 1994/12/24 16:57:59 cgd 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[] = "@(#)xstr.c 8.1 (Berkeley) 6/9/93";
46: #endif
1.6 ! mpech 47: static char rcsid[] = "$OpenBSD: xstr.c,v 1.5 2001/07/20 14:20:29 deraadt Exp $";
1.1 deraadt 48: #endif /* not lint */
49:
50: #include <sys/types.h>
51: #include <signal.h>
52: #include <errno.h>
53: #include <unistd.h>
54: #include <stdio.h>
55: #include <ctype.h>
56: #include <string.h>
57: #include <stdlib.h>
58: #include "pathnames.h"
59:
60: /*
61: * xstr - extract and hash strings in a C program
62: *
63: * Bill Joy UCB
64: * November, 1978
65: */
66:
67: #define ignore(a) ((void) a)
68:
69: off_t tellpt;
70: off_t hashit();
71: void onintr();
72: char *savestr();
73: off_t yankstr();
74:
75: off_t mesgpt;
76: char *strings = "strings";
77:
78: char *array = 0;
79:
80: int cflg;
81: int vflg;
82: int readstd;
83:
84: main(argc, argv)
85: int argc;
86: char *argv[];
87: {
88: int c;
1.4 bitblt 89: int fdesc;
1.1 deraadt 90:
91: while ((c = getopt(argc, argv, "-cvl:")) != -1)
92: switch (c) {
93: case '-':
94: readstd++;
95: break;
96: case 'c':
97: cflg++;
98: break;
99: case 'v':
100: vflg++;
101: break;
102: case 'l':
103: array = optarg;
104: break;
105: default:
106: fprintf(stderr, "usage: xstr [ -v ] [ -c ] [ -l array ] [ - ] [ name ... ]\n");
107: exit (1);
108: }
109: argc -= optind;
110: argv += optind;
111:
112: if (array == 0)
113: array = "xstr";
114:
115: if (signal(SIGINT, SIG_IGN) == SIG_DFL)
116: signal(SIGINT, onintr);
117: if (cflg || argc == 0 && !readstd)
118: inithash();
1.4 bitblt 119: else {
120: strings = strdup (_PATH_TMPFILE);
121: if (strings == NULL) {
122: fprintf(stderr, "Unable to allocate memory: %s",
123: strerror (errno));
124: exit(1);
125: }
126: fdesc = mkstemp (strings);
127: if (fdesc < 0) {
128: fprintf(stderr, "Unable to create temporary file.\n");
129: exit(1);
130: }
131: close (fdesc);
132: }
133:
1.1 deraadt 134: while (readstd || argc > 0) {
135: if (freopen("x.c", "w", stdout) == NULL)
136: perror("x.c"), exit(1);
137: if (!readstd && freopen(argv[0], "r", stdin) == NULL)
138: perror(argv[0]), exit(2);
139: process("x.c");
140: if (readstd == 0)
141: argc--, argv++;
142: else
143: readstd = 0;
144: };
145: flushsh();
146: if (cflg == 0)
147: xsdotc();
148: if (strings[0] == '/')
149: ignore(unlink(strings));
150: exit(0);
151: }
152:
153: char linebuf[BUFSIZ];
154:
155: process(name)
156: char *name;
157: {
158: char *cp;
1.6 ! mpech 159: int c;
! 160: int incomm = 0;
1.1 deraadt 161: int ret;
162:
163: printf("extern char\t%s[];\n", array);
164: for (;;) {
165: if (fgets(linebuf, sizeof linebuf, stdin) == NULL) {
166: if (ferror(stdin)) {
167: perror(name);
168: exit(3);
169: }
170: break;
171: }
172: if (linebuf[0] == '#') {
173: if (linebuf[1] == ' ' && isdigit(linebuf[2]))
174: printf("#line%s", &linebuf[1]);
175: else
176: printf("%s", linebuf);
177: continue;
178: }
179: for (cp = linebuf; c = *cp++;) switch (c) {
180:
181: case '"':
182: if (incomm)
183: goto def;
184: if ((ret = (int) yankstr(&cp)) == -1)
185: goto out;
186: printf("(&%s[%d])", array, ret);
187: break;
188:
189: case '\'':
190: if (incomm)
191: goto def;
192: putchar(c);
193: if (*cp)
194: putchar(*cp++);
195: break;
196:
197: case '/':
198: if (incomm || *cp != '*')
199: goto def;
200: incomm = 1;
201: cp++;
202: printf("/*");
203: continue;
204:
205: case '*':
206: if (incomm && *cp == '/') {
207: incomm = 0;
208: cp++;
209: printf("*/");
210: continue;
211: }
212: goto def;
213:
214: def:
215: default:
216: putchar(c);
217: break;
218: }
219: }
220: out:
221: if (ferror(stdout))
222: perror("x.c"), onintr();
223: }
224:
225: off_t
226: yankstr(cpp)
1.6 ! mpech 227: char **cpp;
1.1 deraadt 228: {
1.6 ! mpech 229: char *cp = *cpp;
! 230: int c, ch;
1.1 deraadt 231: char dbuf[BUFSIZ];
1.6 ! mpech 232: char *dp = dbuf;
! 233: char *tp;
1.1 deraadt 234:
235: while (c = *cp++) {
236: switch (c) {
237:
238: case '"':
239: cp++;
240: goto out;
241:
242: case '\\':
243: c = *cp++;
244: if (c == 0)
245: break;
246: if (c == '\n') {
247: if (fgets(linebuf, sizeof linebuf, stdin)
248: == NULL) {
249: if (ferror(stdin)) {
250: perror("x.c");
251: exit(3);
252: }
253: return(-1);
254: }
255: cp = linebuf;
256: continue;
257: }
258: for (tp = "b\bt\tr\rn\nf\f\\\\\"\""; ch = *tp++; tp++)
259: if (c == ch) {
260: c = *tp;
261: goto gotc;
262: }
263: if (!octdigit(c)) {
264: *dp++ = '\\';
265: break;
266: }
267: c -= '0';
268: if (!octdigit(*cp))
269: break;
270: c <<= 3, c += *cp++ - '0';
271: if (!octdigit(*cp))
272: break;
273: c <<= 3, c += *cp++ - '0';
274: break;
275: }
276: gotc:
277: *dp++ = c;
278: }
279: out:
280: *cpp = --cp;
281: *dp = 0;
282: return (hashit(dbuf, 1));
283: }
284:
285: octdigit(c)
286: char c;
287: {
288:
289: return (isdigit(c) && c != '8' && c != '9');
290: }
291:
292: inithash()
293: {
294: char buf[BUFSIZ];
1.6 ! mpech 295: FILE *mesgread = fopen(strings, "r");
1.1 deraadt 296:
297: if (mesgread == NULL)
298: return;
299: for (;;) {
300: mesgpt = tellpt;
301: if (fgetNUL(buf, sizeof buf, mesgread) == NULL)
302: break;
303: ignore(hashit(buf, 0));
304: }
305: ignore(fclose(mesgread));
306: }
307:
308: fgetNUL(obuf, rmdr, file)
309: char *obuf;
1.6 ! mpech 310: int rmdr;
1.1 deraadt 311: FILE *file;
312: {
1.6 ! mpech 313: int c;
! 314: char *buf = obuf;
1.1 deraadt 315:
316: while (--rmdr > 0 && (c = xgetc(file)) != 0 && c != EOF)
317: *buf++ = c;
318: *buf++ = 0;
319: return ((feof(file) || ferror(file)) ? NULL : 1);
320: }
321:
322: xgetc(file)
323: FILE *file;
324: {
325:
326: tellpt++;
327: return (getc(file));
328: }
329:
330: #define BUCKETS 128
331:
332: struct hash {
333: off_t hpt;
334: char *hstr;
335: struct hash *hnext;
336: short hnew;
337: } bucket[BUCKETS];
338:
339: off_t
340: hashit(str, new)
341: char *str;
342: int new;
343: {
344: int i;
1.6 ! mpech 345: struct hash *hp, *hp0;
1.1 deraadt 346:
347: hp = hp0 = &bucket[lastchr(str) & 0177];
348: while (hp->hnext) {
349: hp = hp->hnext;
350: i = istail(str, hp->hstr);
351: if (i >= 0)
352: return (hp->hpt + i);
353: }
354: if ((hp = (struct hash *) calloc(1, sizeof (*hp))) == NULL) {
355: perror("xstr");
356: exit(8);
357: }
358: hp->hpt = mesgpt;
359: if (!(hp->hstr = strdup(str))) {
360: (void)fprintf(stderr, "xstr: %s\n", strerror(errno));
361: exit(1);
362: }
363: mesgpt += strlen(hp->hstr) + 1;
364: hp->hnext = hp0->hnext;
365: hp->hnew = new;
366: hp0->hnext = hp;
367: return (hp->hpt);
368: }
369:
370: flushsh()
371: {
1.6 ! mpech 372: int i;
! 373: struct hash *hp;
! 374: FILE *mesgwrit;
! 375: int old = 0, new = 0;
1.1 deraadt 376:
377: for (i = 0; i < BUCKETS; i++)
378: for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext)
379: if (hp->hnew)
380: new++;
381: else
382: old++;
383: if (new == 0 && old != 0)
384: return;
385: mesgwrit = fopen(strings, old ? "r+" : "w");
386: if (mesgwrit == NULL)
387: perror(strings), exit(4);
388: for (i = 0; i < BUCKETS; i++)
389: for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) {
390: found(hp->hnew, hp->hpt, hp->hstr);
391: if (hp->hnew) {
392: fseek(mesgwrit, hp->hpt, 0);
393: ignore(fwrite(hp->hstr, strlen(hp->hstr) + 1, 1, mesgwrit));
394: if (ferror(mesgwrit))
395: perror(strings), exit(4);
396: }
397: }
398: if (fclose(mesgwrit) == EOF)
399: perror(strings), exit(4);
400: }
401:
402: found(new, off, str)
403: int new;
404: off_t off;
405: char *str;
406: {
407: if (vflg == 0)
408: return;
409: if (!new)
410: fprintf(stderr, "found at %d:", (int) off);
411: else
412: fprintf(stderr, "new at %d:", (int) off);
413: prstr(str);
414: fprintf(stderr, "\n");
415: }
416:
417: prstr(cp)
1.6 ! mpech 418: char *cp;
1.1 deraadt 419: {
1.6 ! mpech 420: int c;
1.1 deraadt 421:
422: while (c = (*cp++ & 0377))
423: if (c < ' ')
424: fprintf(stderr, "^%c", c + '`');
425: else if (c == 0177)
426: fprintf(stderr, "^?");
427: else if (c > 0200)
428: fprintf(stderr, "\\%03o", c);
429: else
430: fprintf(stderr, "%c", c);
431: }
432:
433: xsdotc()
434: {
1.6 ! mpech 435: FILE *strf = fopen(strings, "r");
! 436: FILE *xdotcf;
1.1 deraadt 437:
438: if (strf == NULL)
439: perror(strings), exit(5);
440: xdotcf = fopen("xs.c", "w");
441: if (xdotcf == NULL)
442: perror("xs.c"), exit(6);
443: fprintf(xdotcf, "char\t%s[] = {\n", array);
444: for (;;) {
1.6 ! mpech 445: int i, c;
1.1 deraadt 446:
447: for (i = 0; i < 8; i++) {
448: c = getc(strf);
449: if (ferror(strf)) {
450: perror(strings);
451: onintr();
452: }
453: if (feof(strf)) {
454: fprintf(xdotcf, "\n");
455: goto out;
456: }
457: fprintf(xdotcf, "0x%02x,", c);
458: }
459: fprintf(xdotcf, "\n");
460: }
461: out:
462: fprintf(xdotcf, "};\n");
463: ignore(fclose(xdotcf));
464: ignore(fclose(strf));
465: }
466:
467: lastchr(cp)
1.6 ! mpech 468: char *cp;
1.1 deraadt 469: {
470:
471: while (cp[0] && cp[1])
472: cp++;
473: return (*cp);
474: }
475:
476: istail(str, of)
1.6 ! mpech 477: char *str, *of;
1.1 deraadt 478: {
1.6 ! mpech 479: int d = strlen(of) - strlen(str);
1.1 deraadt 480:
481: if (d < 0 || strcmp(&of[d], str) != 0)
482: return (-1);
483: return (d);
484: }
485:
486: void
487: onintr()
488: {
489:
490: ignore(signal(SIGINT, SIG_IGN));
491: if (strings[0] == '/')
492: ignore(unlink(strings));
493: ignore(unlink("x.c"));
494: ignore(unlink("xs.c"));
1.5 deraadt 495: _exit(7);
1.1 deraadt 496: }