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