1 /* $NetBSD: xstr.c,v 1.25 2011/09/16 15:39:31 joerg 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.25 2011/09/16 15:39:31 joerg 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 __dead
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 __dead
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];
100 main(int argc
, char *argv
[])
104 while ((c
= getopt(argc
, argv
, "-cvl:")) != -1)
127 if (signal(SIGINT
, SIG_IGN
) == SIG_DFL
)
128 (void)signal(SIGINT
, onintr
);
129 if (cflg
|| (argc
== 0 && !readstd
))
134 snprintf(stringtmpfile
, sizeof(stringtmpfile
),
135 "%s%s.XXXXXX", _PATH_TMP
, "xstr");
136 strings
= stringtmpfile
;
137 fd
= mkstemp(stringtmpfile
);
139 err(1, "mkstemp failed");
142 while (readstd
|| argc
> 0) {
143 if (freopen("x.c", "w", stdout
) == NULL
)
144 err(1, "Cannot open `%s'", "x.c");
145 if (!readstd
&& freopen(argv
[0], "r", stdin
) == NULL
)
146 err(1, "Cannot open `%s'", argv
[0]);
156 if (strings
[0] == '/')
157 (void)unlink(strings
);
162 process(const char *name
)
171 printf("extern char\t%s[];\n", array
);
173 if (fgets(linebuf
, sizeof linebuf
, stdin
) == NULL
) {
175 err(1, "Error reading `%s'", name
);
178 if (linebuf
[0] == '#') {
179 printf("%s", linebuf
);
182 for (cp
= linebuf
; (c
= *cp
++);)
188 if ((ret
= (int) yankstr(&cp
)) == -1)
190 printf("(&%s[%d])", array
, ret
);
202 if (incomm
|| *cp
!= '*')
210 if (incomm
&& *cp
== '/') {
219 if (!incomm
&& inasm
)
224 if (!incomm
&& inasm
&& !--asmparnest
)
231 if (!strncmp(cp
, "_asm", 4)) {
234 if (!strncmp(cp
, "__", 2)) {
238 if (isalnum((unsigned char)*cp
) ||
253 if (ferror(stdout
)) {
254 warn("Error reading `%s'", "x.c");
264 char *dbuf
, *dp
, *edp
;
267 size_t bsiz
= BUFSIZ
;
269 if ((dp
= dbuf
= malloc(bsiz
)) == NULL
)
273 while ((c
= *cp
++) != '\0') {
277 /* Look for a concatenated string */
279 while (isspace((unsigned char)*cp
))
283 sizeof linebuf
, stdin
) == NULL
) {
286 "Error reading `x.c'");
312 if (fgets(linebuf
, sizeof linebuf
, stdin
)
315 err(1, "Error reading `x.c'");
321 for (tp
= "b\bt\tr\rn\nf\f\\\\\"\""; (ch
= *tp
++); tp
++)
333 c
<<= 3, c
+= *cp
++ - '0';
336 c
<<= 3, c
+= *cp
++ - '0';
343 if ((nbuf
= realloc(dbuf
, bsiz
)) == NULL
) {
347 dp
= nbuf
+ (dp
- dbuf
);
356 hash
= hashit(dbuf
, 1);
365 return (isdigit((unsigned char)c
) && c
!= '8' && c
!= '9');
372 FILE *mesgread
= fopen(strings
, "r");
374 if (mesgread
== NULL
)
378 if (fgetNUL(buf
, sizeof buf
, mesgread
) == 0)
380 (void)hashit(buf
, 0);
382 (void)fclose(mesgread
);
386 fgetNUL(char *obuf
, int rmdr
, FILE *file
)
391 c
= 0; /* XXXGCC -Wuninitialized */
393 while (--rmdr
> 0 && (c
= xgetc(file
) != 0 && c
!= EOF
))
396 return (feof(file
) || ferror(file
)) ? 0 : 1;
409 hashit(const char *str
, int new)
412 struct hash
*hp
, *hp0
;
414 hp
= hp0
= &bucket
[lastchr(str
) & 0177];
417 i
= istail(str
, hp
->hstr
);
419 return (hp
->hpt
+ i
);
421 if ((hp
= calloc(1, sizeof (*hp
))) == NULL
)
424 if ((hp
->hstr
= strdup(str
)) == NULL
)
426 mesgpt
+= strlen(hp
->hstr
) + 1;
427 hp
->hnext
= hp0
->hnext
;
439 int old
= 0, new = 0;
441 for (i
= 0; i
< BUCKETS
; i
++)
442 for (hp
= bucket
[i
].hnext
; hp
!= NULL
; hp
= hp
->hnext
)
447 if (new == 0 && old
!= 0)
449 mesgwrit
= fopen(strings
, old
? "r+" : "w");
450 if (mesgwrit
== NULL
)
451 err(1, "Cannot open `%s'", strings
);
452 for (i
= 0; i
< BUCKETS
; i
++)
453 for (hp
= bucket
[i
].hnext
; hp
!= NULL
; hp
= hp
->hnext
) {
454 found(hp
->hnew
, hp
->hpt
, hp
->hstr
);
456 (void)fseek(mesgwrit
, hp
->hpt
, 0);
457 (void)fwrite(hp
->hstr
, strlen(hp
->hstr
) + 1, 1,
459 if (ferror(mesgwrit
))
460 err(1, "Error writing `%s'", strings
);
463 if (fclose(mesgwrit
) == EOF
)
464 err(1, "Error closing `%s'", strings
);
468 found(int new, off_t off
, const char *str
)
473 (void)fprintf(stderr
, "found at %d:", (int) off
);
475 (void)fprintf(stderr
, "new at %d:", (int) off
);
477 (void)fprintf(stderr
, "\n");
481 prstr(const char *cp
)
485 while ((c
= (*cp
++ & 0377)) != '\0')
487 (void)fprintf(stderr
, "^%c", c
+ '`');
489 (void)fprintf(stderr
, "^?");
491 (void)fprintf(stderr
, "\\%03o", c
);
493 (void)fprintf(stderr
, "%c", c
);
499 FILE *strf
= fopen(strings
, "r");
503 err(1, "Cannot open `%s'", strings
);
504 xdotcf
= fopen("xs.c", "w");
506 err(1, "Cannot open `%s'", "xs.c");
507 (void)fprintf(xdotcf
, "char\t%s[] = {\n", array
);
511 for (i
= 0; i
< 8; i
++) {
514 warn("Error reading `%s'", strings
);
518 (void)fprintf(xdotcf
, "\n");
521 (void)fprintf(xdotcf
, "0x%02x,", c
);
523 (void)fprintf(xdotcf
, "\n");
526 (void)fprintf(xdotcf
, "};\n");
527 (void)fclose(xdotcf
);
532 lastchr(const char *cp
)
535 while (cp
[0] && cp
[1])
541 istail(const char *str
, const char *of
)
543 int d
= strlen(of
) - strlen(str
);
545 if (d
< 0 || strcmp(&of
[d
], str
) != 0)
554 (void)signal(SIGINT
, SIG_IGN
);
555 if (strings
[0] == '/')
556 (void)unlink(strings
);
558 (void)unlink("xs.c");
566 (void)fprintf(stderr
, "usage: %s [-cv] [-l array] [-] [<name> ...]\n",