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