Mercurial > hg > early-roguelike
comparison rogue4/xstr.c @ 12:9535a08ddc39
Import Rogue 5.2 from the Roguelike Restoration Project (r1490)
author | edwarj4 |
---|---|
date | Sat, 24 Oct 2009 16:52:52 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
11:949d558c2162 | 12:9535a08ddc39 |
---|---|
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 { | |