unused function; lint cleanup; non-portable char comparison
[unix-history] / usr / src / usr.bin / xstr / xstr.c
CommitLineData
f42904bc
DF
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
8char 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
40b83fad 14static char sccsid[] = "@(#)xstr.c 5.4 (Berkeley) %G%";
f42904bc
DF
15#endif not lint
16
4db42f7f
BJ
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
654d8cfc 29#define ignore(a) ((void) a)
4db42f7f
BJ
30
31char *calloc();
32off_t tellpt;
33off_t hashit();
34char *mktemp();
35int onintr();
36char *savestr();
37char *strcat();
38char *strcpy();
39off_t yankstr();
40
41off_t mesgpt;
42char *strings = "strings";
43
44int cflg;
45int vflg;
46int readstd;
47
48main(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
48b802d7
JB
101char linebuf[BUFSIZ];
102
4db42f7f
BJ
103process(name)
104 char *name;
105{
106 char *cp;
4db42f7f
BJ
107 register int c;
108 register int incomm = 0;
48b802d7 109 int ret;
4db42f7f 110
48b802d7 111 printf("extern char\txstr[];\n");
4db42f7f
BJ
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;
48b802d7
JB
132 if ((ret = (int) yankstr(&cp)) == -1)
133 goto out;
134 printf("(&xstr[%d])", ret);
4db42f7f
BJ
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
162def:
163 default:
164 putchar(c);
165 break;
166 }
167 }
48b802d7 168out:
4db42f7f
BJ
169 if (ferror(stdout))
170 perror("x.c"), onintr();
171}
172
173off_t
174yankstr(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;
48b802d7
JB
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;
4db42f7f 204 continue;
48b802d7 205 }
4db42f7f
BJ
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 }
224gotc:
225 *dp++ = c;
226 }
227out:
228 *cpp = --cp;
229 *dp = 0;
230 return (hashit(dbuf, 1));
231}
232
233octdigit(c)
234 char c;
235{
236
237 return (isdigit(c) && c != '8' && c != '9');
238}
239
240inithash()
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
256fgetNUL(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
270xgetc(file)
271 FILE *file;
272{
273
274 tellpt++;
275 return (getc(file));
276}
277
278#define BUCKETS 128
279
280struct hash {
281 off_t hpt;
282 char *hstr;
283 struct hash *hnext;
284 short hnew;
285} bucket[BUCKETS];
286
287off_t
288hashit(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 }
654d8cfc
KM
302 if ((hp = (struct hash *) calloc(1, sizeof (*hp))) == NULL) {
303 perror("xstr");
304 exit(8);
305 }
4db42f7f
BJ
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
315flushsh()
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;
dd558f1f 330 mesgwrit = fopen(strings, old ? "r+" : "w");
f5affc92
BJ
331 if (mesgwrit == NULL)
332 perror(strings), exit(4);
4db42f7f
BJ
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 }
654d8cfc
KM
343 if (fclose(mesgwrit) == EOF)
344 perror(strings), exit(4);
4db42f7f
BJ
345}
346
347found(new, off, str)
348 int new;
349 off_t off;
350 char *str;
351{
4db42f7f
BJ
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
362prstr(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
378xsdotc()
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 }
406out:
407 fprintf(xdotcf, "};\n");
408 ignore(fclose(xdotcf));
409 ignore(fclose(strf));
410}
411
412char *
413savestr(cp)
414 register char *cp;
415{
654d8cfc 416 register char *dp;
4db42f7f 417
654d8cfc
KM
418 if ((dp = (char *) calloc(1, strlen(cp) + 1)) == NULL) {
419 perror("xstr");
420 exit(8);
421 }
4db42f7f
BJ
422 return (strcpy(dp, cp));
423}
424
4db42f7f
BJ
425lastchr(cp)
426 register char *cp;
427{
428
429 while (cp[0] && cp[1])
430 cp++;
431 return (*cp);
432}
433
434istail(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
444onintr()
445{
446
654d8cfc 447 ignore(signal(SIGINT, SIG_IGN));
4db42f7f
BJ
448 if (strings[0] == '/')
449 ignore(unlink(strings));
450 ignore(unlink("x.c"));
451 ignore(unlink("xs.c"));
452 exit(7);
453}