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