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