|
|
1.1 root 1: /*
2: * Copyright (c) 1980 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that: (1) source distributions retain this entire copyright
7: * notice and comment, and (2) distributions including binaries display
8: * the following acknowledgement: ``This product includes software
9: * developed by the University of California, Berkeley and its contributors''
10: * in the documentation or other materials provided with the distribution
11: * and in all advertising materials mentioning features or use of this
12: * software. Neither the name of the University nor the names of its
13: * contributors may be used to endorse or promote products derived
14: * from this software without specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: char copyright[] =
22: "@(#) Copyright (c) 1980 The Regents of the University of California.\n\
23: All rights reserved.\n";
24: #endif /* not lint */
25:
26: #ifndef lint
27: static char sccsid[] = "@(#)xstr.c 5.6 (Berkeley) 6/1/90";
28: #endif /* not lint */
29:
30: #include <sys/types.h>
31: #include <signal.h>
32: #include <stdio.h>
33: #include <ctype.h>
34: #include "pathnames.h"
35:
36: /*
37: * xstr - extract and hash strings in a C program
38: *
39: * Bill Joy UCB
40: * November, 1978
41: */
42:
43: #define ignore(a) ((void) a)
44:
45: char *calloc();
46: off_t tellpt;
47: off_t hashit();
48: char *mktemp();
49: int onintr();
50: char *savestr();
51: char *strcat();
52: char *strcpy();
53: off_t yankstr();
54:
55: off_t mesgpt;
56: char *strings = "strings";
57:
58: int cflg;
59: int vflg;
60: int readstd;
61:
62: main(argc, argv)
63: int argc;
64: char *argv[];
65: {
66:
67: argc--, argv++;
68: while (argc > 0 && argv[0][0] == '-') {
69: register char *cp = &(*argv++)[1];
70:
71: argc--;
72: if (*cp == 0) {
73: readstd++;
74: continue;
75: }
76: do switch (*cp++) {
77:
78: case 'c':
79: cflg++;
80: continue;
81:
82: case 'v':
83: vflg++;
84: continue;
85:
86: default:
87: fprintf(stderr, "usage: xstr [ -v ] [ -c ] [ - ] [ name ... ]\n");
88: } while (*cp);
89: }
90: if (signal(SIGINT, SIG_IGN) == SIG_DFL)
91: signal(SIGINT, onintr);
92: if (cflg || argc == 0 && !readstd)
93: inithash();
94: else
95: strings = mktemp(savestr(_PATH_TMP));
96: while (readstd || argc > 0) {
97: if (freopen("x.c", "w", stdout) == NULL)
98: perror("x.c"), exit(1);
99: if (!readstd && freopen(argv[0], "r", stdin) == NULL)
100: perror(argv[0]), exit(2);
101: process("x.c");
102: if (readstd == 0)
103: argc--, argv++;
104: else
105: readstd = 0;
106: };
107: flushsh();
108: if (cflg == 0)
109: xsdotc();
110: if (strings[0] == '/')
111: ignore(unlink(strings));
112: exit(0);
113: }
114:
115: char linebuf[BUFSIZ];
116:
117: process(name)
118: char *name;
119: {
120: char *cp;
121: register int c;
122: register int incomm = 0;
123: int ret;
124:
125: printf("extern char\txstr[];\n");
126: for (;;) {
127: if (fgets(linebuf, sizeof linebuf, stdin) == NULL) {
128: if (ferror(stdin)) {
129: perror(name);
130: exit(3);
131: }
132: break;
133: }
134: if (linebuf[0] == '#') {
135: if (linebuf[1] == ' ' && isdigit(linebuf[2]))
136: printf("#line%s", &linebuf[1]);
137: else
138: printf("%s", linebuf);
139: continue;
140: }
141: for (cp = linebuf; c = *cp++;) switch (c) {
142:
143: case '"':
144: if (incomm)
145: goto def;
146: if ((ret = (int) yankstr(&cp)) == -1)
147: goto out;
148: printf("(&xstr[%d])", ret);
149: break;
150:
151: case '\'':
152: if (incomm)
153: goto def;
154: putchar(c);
155: if (*cp)
156: putchar(*cp++);
157: break;
158:
159: case '/':
160: if (incomm || *cp != '*')
161: goto def;
162: incomm = 1;
163: cp++;
164: printf("/*");
165: continue;
166:
167: case '*':
168: if (incomm && *cp == '/') {
169: incomm = 0;
170: cp++;
171: printf("*/");
172: continue;
173: }
174: goto def;
175:
176: def:
177: default:
178: putchar(c);
179: break;
180: }
181: }
182: out:
183: if (ferror(stdout))
184: perror("x.c"), onintr();
185: }
186:
187: off_t
188: yankstr(cpp)
189: register char **cpp;
190: {
191: register char *cp = *cpp;
192: register int c, ch;
193: char dbuf[BUFSIZ];
194: register char *dp = dbuf;
195: register char *tp;
196:
197: while (c = *cp++) {
198: switch (c) {
199:
200: case '"':
201: cp++;
202: goto out;
203:
204: case '\\':
205: c = *cp++;
206: if (c == 0)
207: break;
208: if (c == '\n') {
209: if (fgets(linebuf, sizeof linebuf, stdin)
210: == NULL) {
211: if (ferror(stdin)) {
212: perror("x.c");
213: exit(3);
214: }
215: return(-1);
216: }
217: cp = linebuf;
218: continue;
219: }
220: for (tp = "b\bt\tr\rn\nf\f\\\\\"\""; ch = *tp++; tp++)
221: if (c == ch) {
222: c = *tp;
223: goto gotc;
224: }
225: if (!octdigit(c)) {
226: *dp++ = '\\';
227: break;
228: }
229: c -= '0';
230: if (!octdigit(*cp))
231: break;
232: c <<= 3, c += *cp++ - '0';
233: if (!octdigit(*cp))
234: break;
235: c <<= 3, c += *cp++ - '0';
236: break;
237: }
238: gotc:
239: *dp++ = c;
240: }
241: out:
242: *cpp = --cp;
243: *dp = 0;
244: return (hashit(dbuf, 1));
245: }
246:
247: octdigit(c)
248: char c;
249: {
250:
251: return (isdigit(c) && c != '8' && c != '9');
252: }
253:
254: inithash()
255: {
256: char buf[BUFSIZ];
257: register FILE *mesgread = fopen(strings, "r");
258:
259: if (mesgread == NULL)
260: return;
261: for (;;) {
262: mesgpt = tellpt;
263: if (fgetNUL(buf, sizeof buf, mesgread) == NULL)
264: break;
265: ignore(hashit(buf, 0));
266: }
267: ignore(fclose(mesgread));
268: }
269:
270: fgetNUL(obuf, rmdr, file)
271: char *obuf;
272: register int rmdr;
273: FILE *file;
274: {
275: register c;
276: register char *buf = obuf;
277:
278: while (--rmdr > 0 && (c = xgetc(file)) != 0 && c != EOF)
279: *buf++ = c;
280: *buf++ = 0;
281: return ((feof(file) || ferror(file)) ? NULL : 1);
282: }
283:
284: xgetc(file)
285: FILE *file;
286: {
287:
288: tellpt++;
289: return (getc(file));
290: }
291:
292: #define BUCKETS 128
293:
294: struct hash {
295: off_t hpt;
296: char *hstr;
297: struct hash *hnext;
298: short hnew;
299: } bucket[BUCKETS];
300:
301: off_t
302: hashit(str, new)
303: char *str;
304: int new;
305: {
306: int i;
307: register struct hash *hp, *hp0;
308:
309: hp = hp0 = &bucket[lastchr(str) & 0177];
310: while (hp->hnext) {
311: hp = hp->hnext;
312: i = istail(str, hp->hstr);
313: if (i >= 0)
314: return (hp->hpt + i);
315: }
316: if ((hp = (struct hash *) calloc(1, sizeof (*hp))) == NULL) {
317: perror("xstr");
318: exit(8);
319: }
320: hp->hpt = mesgpt;
321: hp->hstr = savestr(str);
322: mesgpt += strlen(hp->hstr) + 1;
323: hp->hnext = hp0->hnext;
324: hp->hnew = new;
325: hp0->hnext = hp;
326: return (hp->hpt);
327: }
328:
329: flushsh()
330: {
331: register int i;
332: register struct hash *hp;
333: register FILE *mesgwrit;
334: register int old = 0, new = 0;
335:
336: for (i = 0; i < BUCKETS; i++)
337: for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext)
338: if (hp->hnew)
339: new++;
340: else
341: old++;
342: if (new == 0 && old != 0)
343: return;
344: mesgwrit = fopen(strings, old ? "r+" : "w");
345: if (mesgwrit == NULL)
346: perror(strings), exit(4);
347: for (i = 0; i < BUCKETS; i++)
348: for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) {
349: found(hp->hnew, hp->hpt, hp->hstr);
350: if (hp->hnew) {
351: fseek(mesgwrit, hp->hpt, 0);
352: ignore(fwrite(hp->hstr, strlen(hp->hstr) + 1, 1, mesgwrit));
353: if (ferror(mesgwrit))
354: perror(strings), exit(4);
355: }
356: }
357: if (fclose(mesgwrit) == EOF)
358: perror(strings), exit(4);
359: }
360:
361: found(new, off, str)
362: int new;
363: off_t off;
364: char *str;
365: {
366: if (vflg == 0)
367: return;
368: if (!new)
369: fprintf(stderr, "found at %d:", (int) off);
370: else
371: fprintf(stderr, "new at %d:", (int) off);
372: prstr(str);
373: fprintf(stderr, "\n");
374: }
375:
376: prstr(cp)
377: register char *cp;
378: {
379: register int c;
380:
381: while (c = (*cp++ & 0377))
382: if (c < ' ')
383: fprintf(stderr, "^%c", c + '`');
384: else if (c == 0177)
385: fprintf(stderr, "^?");
386: else if (c > 0200)
387: fprintf(stderr, "\\%03o", c);
388: else
389: fprintf(stderr, "%c", c);
390: }
391:
392: xsdotc()
393: {
394: register FILE *strf = fopen(strings, "r");
395: register FILE *xdotcf;
396:
397: if (strf == NULL)
398: perror(strings), exit(5);
399: xdotcf = fopen("xs.c", "w");
400: if (xdotcf == NULL)
401: perror("xs.c"), exit(6);
402: fprintf(xdotcf, "char\txstr[] = {\n");
403: for (;;) {
404: register int i, c;
405:
406: for (i = 0; i < 8; i++) {
407: c = getc(strf);
408: if (ferror(strf)) {
409: perror(strings);
410: onintr();
411: }
412: if (feof(strf)) {
413: fprintf(xdotcf, "\n");
414: goto out;
415: }
416: fprintf(xdotcf, "0x%02x,", c);
417: }
418: fprintf(xdotcf, "\n");
419: }
420: out:
421: fprintf(xdotcf, "};\n");
422: ignore(fclose(xdotcf));
423: ignore(fclose(strf));
424: }
425:
426: char *
427: savestr(cp)
428: register char *cp;
429: {
430: register char *dp;
431:
432: if ((dp = (char *) calloc(1, strlen(cp) + 1)) == NULL) {
433: perror("xstr");
434: exit(8);
435: }
436: return (strcpy(dp, cp));
437: }
438:
439: lastchr(cp)
440: register char *cp;
441: {
442:
443: while (cp[0] && cp[1])
444: cp++;
445: return (*cp);
446: }
447:
448: istail(str, of)
449: register char *str, *of;
450: {
451: register int d = strlen(of) - strlen(str);
452:
453: if (d < 0 || strcmp(&of[d], str) != 0)
454: return (-1);
455: return (d);
456: }
457:
458: onintr()
459: {
460:
461: ignore(signal(SIGINT, SIG_IGN));
462: if (strings[0] == '/')
463: ignore(unlink(strings));
464: ignore(unlink("x.c"));
465: ignore(unlink("xs.c"));
466: exit(7);
467: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.