8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / xstr / xstr.c
blob7378337aa2dacf5dd262728804ca9adf24d7b5bd
1 /*
2 * Copyright 1989 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
9 /*
10 * Copyright (c) 1980 Regents of the University of California.
11 * All rights reserved. The Berkeley software License Agreement
12 * specifies the terms and conditions for redistribution.
15 #pragma ident "%Z%%M% %I% %E% SMI"
17 #include <stdio.h>
18 #include <ctype.h>
19 #include <sys/types.h>
20 #include <signal.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
26 * xstr - extract and hash strings in a C program
28 * Bill Joy UCB
29 * November, 1978
32 off_t tellpt;
33 off_t hashit(char *, int);
34 void onintr(void);
35 char *savestr(char *);
36 off_t yankstr(char **);
37 void cleanup(void);
38 void process(char *);
39 int octdigit(char);
40 void inithash(void);
41 void flushsh(void);
42 void found(int, off_t, char *);
43 void prstr(char *);
44 void xsdotc(void);
45 int fgetNUL(char *, int, FILE *);
46 int xgetc(FILE *);
47 int lastchr(char *);
48 int istail(char *, char *);
50 off_t mesgpt;
51 char *strings = "strings";
53 int cflg;
54 int vflg;
55 char *xname = "xstr";
56 int readstd;
57 int tmpfd;
59 int
60 main(int argc, char **argv)
62 argc--, argv++;
63 while (argc > 0 && argv[0][0] == '-') {
64 char *cp = &(*argv++)[1];
66 argc--;
67 if (*cp == 0) {
68 readstd++;
69 continue;
71 do switch (*cp++) {
73 case 'c':
74 cflg++;
75 continue;
77 case 'l':
78 xname = *argv++;
79 argc--;
80 continue;
82 case 'v':
83 vflg++;
84 continue;
86 default:
87 (void) fprintf(stderr,
88 "usage: xstr [ -v ] [ -c ] [ -l label ] [ - ] [ name ... ]\n");
89 } while (*cp);
91 if (signal(SIGINT, SIG_IGN) == SIG_DFL)
92 (void) signal(SIGINT, (void (*)(int))onintr);
93 if (cflg || argc == 0 && !readstd)
94 inithash();
95 else {
96 strings = savestr("/tmp/xstrXXXXXX");
97 tmpfd = mkstemp(strings);
98 if (tmpfd == -1) {
99 perror(strings);
100 (void) free(strings);
101 exit(9);
103 (void) close(tmpfd);
105 while (readstd || argc > 0) {
106 if (freopen("x.c", "w", stdout) == NULL)
107 perror("x.c"), (void) cleanup(), exit(1);
108 if (!readstd && freopen(argv[0], "r", stdin) == NULL)
109 perror(argv[0]), (void) cleanup(), exit(2);
110 process("x.c");
111 if (readstd == 0)
112 argc--, argv++;
113 else
114 readstd = 0;
116 flushsh();
117 if (cflg == 0)
118 xsdotc();
119 (void) cleanup();
120 return (0);
123 char linebuf[BUFSIZ];
125 void
126 process(char *name)
128 char *cp;
129 int c;
130 int incomm = 0;
131 int ret;
133 (void) printf("extern char\t%s[];\n", xname);
134 for (;;) {
135 if (fgets(linebuf, sizeof (linebuf), stdin) == NULL) {
136 if (ferror(stdin)) {
137 perror(name);
138 (void) cleanup();
139 exit(3);
141 break;
143 if (linebuf[0] == '#') {
144 if (linebuf[1] == ' ' && isdigit(linebuf[2]))
145 (void) printf("#line%s", &linebuf[1]);
146 else
147 (void) printf("%s", linebuf);
148 continue;
150 for (cp = linebuf; (c = *cp++) != 0; ) {
151 switch (c) {
152 case '"':
153 if (incomm)
154 goto def;
155 if ((ret = (int)yankstr(&cp)) == -1)
156 goto out;
157 (void) printf("(&%s[%d])", xname, ret);
158 break;
160 case '\'':
161 if (incomm)
162 goto def;
163 (void) putchar(c);
164 if (*cp)
165 (void) putchar(*cp++);
166 break;
168 case '/':
169 if (incomm || *cp != '*')
170 goto def;
171 incomm = 1;
172 cp++;
173 (void) printf("/*");
174 continue;
176 case '*':
177 if (incomm && *cp == '/') {
178 incomm = 0;
179 cp++;
180 (void) printf("*/");
181 continue;
183 goto def;
184 def:
185 default:
186 (void) putchar(c);
187 break;
191 out:
192 if (ferror(stdout))
193 perror("x.c"), onintr();
196 off_t
197 yankstr(char **cpp)
199 char *cp = *cpp;
200 int c, ch;
201 char dbuf[BUFSIZ];
202 char *dp = dbuf;
203 char *tp;
205 while ((c = *cp++) != 0) {
206 switch (c) {
208 case '"':
209 cp++;
210 goto out;
212 case '\\':
213 c = *cp++;
214 if (c == 0)
215 break;
216 if (c == '\n') {
217 if (fgets(linebuf, sizeof (linebuf), stdin)
218 == NULL) {
219 if (ferror(stdin)) {
220 perror("x.c");
221 (void) cleanup();
222 exit(3);
224 return (-1);
227 cp = linebuf;
228 continue;
230 for (tp = "b\bt\tr\rn\nf\f\\\\\"\""; (ch = *tp++) != 0;
231 tp++)
232 if (c == ch) {
233 c = *tp;
234 goto gotc;
236 if (!octdigit(c)) {
237 *dp++ = '\\';
238 break;
240 c -= '0';
241 if (!octdigit(*cp))
242 break;
243 c <<= 3, c += *cp++ - '0';
244 if (!octdigit(*cp))
245 break;
246 c <<= 3, c += *cp++ - '0';
247 break;
249 gotc:
250 *dp++ = c;
252 out:
253 *cpp = --cp;
254 *dp = 0;
255 return (hashit(dbuf, 1));
259 octdigit(char c)
262 return (isdigit(c) && c != '8' && c != '9');
265 void
266 inithash(void)
268 char buf[BUFSIZ];
269 FILE *mesgread = fopen(strings, "r");
271 if (mesgread == NULL)
272 return;
273 for (;;) {
274 mesgpt = tellpt;
275 if (fgetNUL(buf, sizeof (buf), mesgread) == NULL)
276 break;
277 (void) hashit(buf, 0);
279 (void) fclose(mesgread);
283 fgetNUL(char *obuf, int rmdr, FILE *file)
285 int c;
286 char *buf = obuf;
288 while (--rmdr > 0 && (c = xgetc(file)) != 0 && c != EOF)
289 *buf++ = c;
290 *buf++ = 0;
291 return ((feof(file) || ferror(file)) ? NULL : 1);
295 xgetc(FILE *file)
298 tellpt++;
299 return (getc(file));
302 #define BUCKETS 128
304 struct hash {
305 off_t hpt;
306 char *hstr;
307 struct hash *hnext;
308 short hnew;
309 } bucket[BUCKETS];
311 off_t
312 hashit(char *str, int new)
314 int i;
315 struct hash *hp, *hp0;
317 hp = hp0 = &bucket[lastchr(str) & 0177];
318 while (hp->hnext) {
319 hp = hp->hnext;
320 i = istail(str, hp->hstr);
321 if (i >= 0)
322 return (hp->hpt + i);
324 if ((hp = calloc(1, sizeof (*hp))) == NULL) {
325 perror("xstr");
326 (void) cleanup();
327 exit(8);
329 hp->hpt = mesgpt;
330 hp->hstr = savestr(str);
331 mesgpt += strlen(hp->hstr) + 1;
332 hp->hnext = hp0->hnext;
333 hp->hnew = new;
334 hp0->hnext = hp;
335 return (hp->hpt);
338 void
339 flushsh(void)
341 int i;
342 struct hash *hp;
343 FILE *mesgwrit;
344 int old = 0, new = 0;
346 for (i = 0; i < BUCKETS; i++)
347 for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext)
348 if (hp->hnew)
349 new++;
350 else
351 old++;
352 if (new == 0 && old != 0)
353 return;
354 mesgwrit = fopen(strings, old ? "r+" : "w");
355 if (mesgwrit == NULL)
356 perror(strings), (void) cleanup(), exit(4);
357 for (i = 0; i < BUCKETS; i++)
358 for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) {
359 found(hp->hnew, hp->hpt, hp->hstr);
360 if (hp->hnew) {
361 (void) fseek(mesgwrit, hp->hpt, 0);
362 (void) fwrite(hp->hstr,
363 strlen(hp->hstr) + 1, 1, mesgwrit);
364 if (ferror(mesgwrit)) {
365 perror(strings);
366 (void) cleanup();
367 exit(4);
371 if (fclose(mesgwrit) == EOF)
372 perror(strings), (void) cleanup(), exit(4);
375 void
376 found(int new, off_t off, char *str)
378 if (vflg == 0)
379 return;
380 if (!new)
381 (void) fprintf(stderr, "found at %d:", (int)off);
382 else
383 (void) fprintf(stderr, "new at %d:", (int)off);
384 prstr(str);
385 (void) fprintf(stderr, "\n");
388 void
389 prstr(char *cp)
391 int c;
393 while ((c = (*cp++ & 0377)) != 0)
394 if (c < ' ')
395 (void) fprintf(stderr, "^%c", c + '`');
396 else if (c == 0177)
397 (void) fprintf(stderr, "^?");
398 else if (c > 0200)
399 (void) fprintf(stderr, "\\%03o", c);
400 else
401 (void) fprintf(stderr, "%c", c);
404 void
405 xsdotc(void)
407 FILE *strf = fopen(strings, "r");
408 FILE *xdotcf;
410 if (strf == NULL)
411 perror(strings), exit(5);
412 xdotcf = fopen("xs.c", "w");
413 if (xdotcf == NULL)
414 perror("xs.c"), exit(6);
415 (void) fprintf(xdotcf, "char\t%s[] = {\n", xname);
416 for (;;) {
417 int i, c;
419 for (i = 0; i < 8; i++) {
420 c = getc(strf);
421 if (ferror(strf)) {
422 perror(strings);
423 onintr();
425 if (feof(strf)) {
426 (void) fprintf(xdotcf, "\n");
427 goto out;
429 (void) fprintf(xdotcf, "0x%02x,", c);
431 (void) fprintf(xdotcf, "\n");
433 out:
434 (void) fprintf(xdotcf, "};\n");
435 (void) fclose(xdotcf);
436 (void) fclose(strf);
439 char *
440 savestr(char *cp)
442 char *dp;
444 if ((dp = calloc(1, strlen(cp) + 1)) == NULL) {
445 perror("xstr");
446 exit(8);
448 return (strcpy(dp, cp));
452 lastchr(char *cp)
455 while (cp[0] && cp[1])
456 cp++;
457 return ((int)*cp);
461 istail(char *str, char *of)
463 int d = strlen(of) - strlen(str);
465 if (d < 0 || strcmp(&of[d], str) != 0)
466 return (-1);
467 return (d);
470 void
471 onintr(void)
474 (void) signal(SIGINT, SIG_IGN);
475 (void) cleanup();
476 (void) unlink("x.c");
477 (void) unlink("xs.c");
478 exit(7);
481 void
482 cleanup(void)
484 if (strings[0] == '/') {
485 (void) unlink(strings);