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