1 /* $NetBSD: xstr.c,v 1.23 2009/04/14 09:18:41 lukem Exp $ */
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
34 __COPYRIGHT("@(#) Copyright (c) 1980, 1993\
35 The Regents of the University of California. All rights reserved.");
40 static char sccsid
[] = "@(#)xstr.c 8.1 (Berkeley) 6/9/93";
42 __RCSID("$NetBSD: xstr.c,v 1.23 2009/04/14 09:18:41 lukem Exp $");
46 #include <sys/param.h>
55 #include "pathnames.h"
58 * xstr - extract and hash strings in a C program
64 static off_t
hashit(const char *, int);
65 static void onintr(int);
66 static off_t
yankstr(char **);
67 static int octdigit(char);
68 static void inithash(void);
69 static int fgetNUL(char *, int, FILE *);
70 static int xgetc(FILE *);
71 static void flushsh(void);
72 static void found(int, off_t
, const char *);
73 static void prstr(const char *);
74 static void xsdotc(void);
75 static char lastchr(const char *);
76 static int istail(const char *, const char *);
77 static void process(const char *);
78 static void usage(void);
82 static char stringtmpfile
[MAXPATHLEN
];
83 static const char *strings
= "strings";
84 static const char *array
= 0;
88 static char linebuf
[8192];
99 int main(int, char *[]);
102 main(int argc
, char *argv
[])
106 while ((c
= getopt(argc
, argv
, "-cvl:")) != -1)
129 if (signal(SIGINT
, SIG_IGN
) == SIG_DFL
)
130 (void)signal(SIGINT
, onintr
);
131 if (cflg
|| (argc
== 0 && !readstd
))
136 snprintf(stringtmpfile
, sizeof(stringtmpfile
),
137 "%s%s.XXXXXX", _PATH_TMP
, "xstr");
138 strings
= stringtmpfile
;
139 fd
= mkstemp(stringtmpfile
);
141 err(1, "mkstemp failed");
144 while (readstd
|| argc
> 0) {
145 if (freopen("x.c", "w", stdout
) == NULL
)
146 err(1, "Cannot open `%s'", "x.c");
147 if (!readstd
&& freopen(argv
[0], "r", stdin
) == NULL
)
148 err(1, "Cannot open `%s'", argv
[0]);
158 if (strings
[0] == '/')
159 (void)unlink(strings
);
164 process(const char *name
)
173 printf("extern char\t%s[];\n", array
);
175 if (fgets(linebuf
, sizeof linebuf
, stdin
) == NULL
) {
177 err(1, "Error reading `%s'", name
);
180 if (linebuf
[0] == '#') {
181 printf("%s", linebuf
);
184 for (cp
= linebuf
; (c
= *cp
++);)
190 if ((ret
= (int) yankstr(&cp
)) == -1)
192 printf("(&%s[%d])", array
, ret
);
204 if (incomm
|| *cp
!= '*')
212 if (incomm
&& *cp
== '/') {
221 if (!incomm
&& inasm
)
226 if (!incomm
&& inasm
&& !--asmparnest
)
233 if (!strncmp(cp
, "_asm", 4)) {
236 if (!strncmp(cp
, "__", 2)) {
240 if (isalnum((unsigned char)*cp
) ||
255 if (ferror(stdout
)) {
256 warn("Error reading `%s'", "x.c");
266 char *dbuf
, *dp
, *edp
;
269 size_t bsiz
= BUFSIZ
;
271 if ((dp
= dbuf
= malloc(bsiz
)) == NULL
)
275 while ((c
= *cp
++) != '\0') {
279 /* Look for a concatenated string */
281 while (isspace((unsigned char)*cp
))
285 sizeof linebuf
, stdin
) == NULL
) {
288 "Error reading `x.c'");
314 if (fgets(linebuf
, sizeof linebuf
, stdin
)
317 err(1, "Error reading `x.c'");
323 for (tp
= "b\bt\tr\rn\nf\f\\\\\"\""; (ch
= *tp
++); tp
++)
335 c
<<= 3, c
+= *cp
++ - '0';
338 c
<<= 3, c
+= *cp
++ - '0';
345 if ((nbuf
= realloc(dbuf
, bsiz
)) == NULL
) {
349 dp
= nbuf
+ (dp
- dbuf
);
358 hash
= hashit(dbuf
, 1);
367 return (isdigit((unsigned char)c
) && c
!= '8' && c
!= '9');
374 FILE *mesgread
= fopen(strings
, "r");
376 if (mesgread
== NULL
)
380 if (fgetNUL(buf
, sizeof buf
, mesgread
) == 0)
382 (void)hashit(buf
, 0);
384 (void)fclose(mesgread
);
388 fgetNUL(char *obuf
, int rmdr
, FILE *file
)
393 c
= 0; /* XXXGCC -Wuninitialized */
395 while (--rmdr
> 0 && (c
= xgetc(file
) != 0 && c
!= EOF
))
398 return (feof(file
) || ferror(file
)) ? 0 : 1;
411 hashit(const char *str
, int new)
414 struct hash
*hp
, *hp0
;
416 hp
= hp0
= &bucket
[lastchr(str
) & 0177];
419 i
= istail(str
, hp
->hstr
);
421 return (hp
->hpt
+ i
);
423 if ((hp
= calloc(1, sizeof (*hp
))) == NULL
)
426 if ((hp
->hstr
= strdup(str
)) == NULL
)
428 mesgpt
+= strlen(hp
->hstr
) + 1;
429 hp
->hnext
= hp0
->hnext
;
441 int old
= 0, new = 0;
443 for (i
= 0; i
< BUCKETS
; i
++)
444 for (hp
= bucket
[i
].hnext
; hp
!= NULL
; hp
= hp
->hnext
)
449 if (new == 0 && old
!= 0)
451 mesgwrit
= fopen(strings
, old
? "r+" : "w");
452 if (mesgwrit
== NULL
)
453 err(1, "Cannot open `%s'", strings
);
454 for (i
= 0; i
< BUCKETS
; i
++)
455 for (hp
= bucket
[i
].hnext
; hp
!= NULL
; hp
= hp
->hnext
) {
456 found(hp
->hnew
, hp
->hpt
, hp
->hstr
);
458 (void)fseek(mesgwrit
, hp
->hpt
, 0);
459 (void)fwrite(hp
->hstr
, strlen(hp
->hstr
) + 1, 1,
461 if (ferror(mesgwrit
))
462 err(1, "Error writing `%s'", strings
);
465 if (fclose(mesgwrit
) == EOF
)
466 err(1, "Error closing `%s'", strings
);
470 found(int new, off_t off
, const char *str
)
475 (void)fprintf(stderr
, "found at %d:", (int) off
);
477 (void)fprintf(stderr
, "new at %d:", (int) off
);
479 (void)fprintf(stderr
, "\n");
483 prstr(const char *cp
)
487 while ((c
= (*cp
++ & 0377)) != '\0')
489 (void)fprintf(stderr
, "^%c", c
+ '`');
491 (void)fprintf(stderr
, "^?");
493 (void)fprintf(stderr
, "\\%03o", c
);
495 (void)fprintf(stderr
, "%c", c
);
501 FILE *strf
= fopen(strings
, "r");
505 err(1, "Cannot open `%s'", strings
);
506 xdotcf
= fopen("xs.c", "w");
508 err(1, "Cannot open `%s'", "xs.c");
509 (void)fprintf(xdotcf
, "char\t%s[] = {\n", array
);
513 for (i
= 0; i
< 8; i
++) {
516 warn("Error reading `%s'", strings
);
520 (void)fprintf(xdotcf
, "\n");
523 (void)fprintf(xdotcf
, "0x%02x,", c
);
525 (void)fprintf(xdotcf
, "\n");
528 (void)fprintf(xdotcf
, "};\n");
529 (void)fclose(xdotcf
);
534 lastchr(const char *cp
)
537 while (cp
[0] && cp
[1])
543 istail(const char *str
, const char *of
)
545 int d
= strlen(of
) - strlen(str
);
547 if (d
< 0 || strcmp(&of
[d
], str
) != 0)
556 (void)signal(SIGINT
, SIG_IGN
);
557 if (strings
[0] == '/')
558 (void)unlink(strings
);
560 (void)unlink("xs.c");
568 (void)fprintf(stderr
, "usage: %s [-cv] [-l array] [-] [<name> ...]\n",