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