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