|
|
1.1 root 1: static char *sccsid = "@(#)xstr.c 4.1 (Berkeley) 10/1/80";
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 ? "a" : "w");
298: for (i = 0; i < BUCKETS; i++)
299: for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) {
300: found(hp->hnew, hp->hpt, hp->hstr);
301: if (hp->hnew) {
302: fseek(mesgwrit, hp->hpt, 0);
303: ignore(fwrite(hp->hstr, strlen(hp->hstr) + 1, 1, mesgwrit));
304: if (ferror(mesgwrit))
305: perror(strings), exit(4);
306: }
307: }
308: ignore(fclose(mesgwrit));
309: }
310:
311: found(new, off, str)
312: int new;
313: off_t off;
314: char *str;
315: {
316: register char *cp;
317:
318: if (vflg == 0)
319: return;
320: if (!new)
321: fprintf(stderr, "found at %d:", (int) off);
322: else
323: fprintf(stderr, "new at %d:", (int) off);
324: prstr(str);
325: fprintf(stderr, "\n");
326: }
327:
328: prstr(cp)
329: register char *cp;
330: {
331: register int c;
332:
333: while (c = (*cp++ & 0377))
334: if (c < ' ')
335: fprintf(stderr, "^%c", c + '`');
336: else if (c == 0177)
337: fprintf(stderr, "^?");
338: else if (c > 0200)
339: fprintf(stderr, "\\%03o", c);
340: else
341: fprintf(stderr, "%c", c);
342: }
343:
344: xsdotc()
345: {
346: register FILE *strf = fopen(strings, "r");
347: register FILE *xdotcf;
348:
349: if (strf == NULL)
350: perror(strings), exit(5);
351: xdotcf = fopen("xs.c", "w");
352: if (xdotcf == NULL)
353: perror("xs.c"), exit(6);
354: fprintf(xdotcf, "char\txstr[] = {\n");
355: for (;;) {
356: register int i, c;
357:
358: for (i = 0; i < 8; i++) {
359: c = getc(strf);
360: if (ferror(strf)) {
361: perror(strings);
362: onintr();
363: }
364: if (feof(strf)) {
365: fprintf(xdotcf, "\n");
366: goto out;
367: }
368: fprintf(xdotcf, "0x%02x,", c);
369: }
370: fprintf(xdotcf, "\n");
371: }
372: out:
373: fprintf(xdotcf, "};\n");
374: ignore(fclose(xdotcf));
375: ignore(fclose(strf));
376: }
377:
378: char *
379: savestr(cp)
380: register char *cp;
381: {
382: register char *dp = (char *) calloc(1, strlen(cp) + 1);
383:
384: return (strcpy(dp, cp));
385: }
386:
387: Ignore(a)
388: char *a;
389: {
390:
391: a = a;
392: }
393:
394: ignorf(a)
395: int (*a)();
396: {
397:
398: a = a;
399: }
400:
401: lastchr(cp)
402: register char *cp;
403: {
404:
405: while (cp[0] && cp[1])
406: cp++;
407: return (*cp);
408: }
409:
410: istail(str, of)
411: register char *str, *of;
412: {
413: register int d = strlen(of) - strlen(str);
414:
415: if (d < 0 || strcmp(&of[d], str) != 0)
416: return (-1);
417: return (d);
418: }
419:
420: onintr()
421: {
422:
423: ignorf(signal(SIGINT, SIG_IGN));
424: if (strings[0] == '/')
425: ignore(unlink(strings));
426: ignore(unlink("x.c"));
427: ignore(unlink("xs.c"));
428: exit(7);
429: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.