[BACK]Return to xstr.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / xstr

Annotation of src/usr.bin/xstr/xstr.c, Revision 1.8

1.8     ! deraadt     1: /*     $OpenBSD: xstr.c,v 1.7 2002/02/23 21:47:32 deraadt Exp $        */
1.1       deraadt     2: /*     $NetBSD: xstr.c,v 1.5 1994/12/24 16:57:59 cgd Exp $     */
                      3:
                      4: /*
                      5:  * Copyright (c) 1980, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by the University of
                     19:  *     California, Berkeley and its contributors.
                     20:  * 4. Neither the name of the University nor the names of its contributors
                     21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  */
                     36:
                     37: #ifndef lint
                     38: static char copyright[] =
                     39: "@(#) Copyright (c) 1980, 1993\n\
                     40:        The Regents of the University of California.  All rights reserved.\n";
                     41: #endif /* not lint */
                     42:
                     43: #ifndef lint
                     44: #if 0
                     45: static char sccsid[] = "@(#)xstr.c     8.1 (Berkeley) 6/9/93";
                     46: #endif
1.8     ! deraadt    47: static char rcsid[] = "$OpenBSD: xstr.c,v 1.7 2002/02/23 21:47:32 deraadt Exp $";
1.1       deraadt    48: #endif /* not lint */
                     49:
                     50: #include <sys/types.h>
                     51: #include <signal.h>
                     52: #include <errno.h>
                     53: #include <unistd.h>
                     54: #include <stdio.h>
                     55: #include <ctype.h>
                     56: #include <string.h>
                     57: #include <stdlib.h>
                     58: #include "pathnames.h"
                     59:
                     60: /*
                     61:  * xstr - extract and hash strings in a C program
                     62:  *
                     63:  * Bill Joy UCB
                     64:  * November, 1978
                     65:  */
                     66:
1.7       deraadt    67: #define        BUCKETS 128
1.1       deraadt    68:
                     69: off_t  tellpt;
                     70: off_t  mesgpt;
1.8     ! deraadt    71: char   *strings = "strings";
        !            72: char   *array = 0;
1.1       deraadt    73:
                     74: int    cflg;
                     75: int    vflg;
                     76: int    readstd;
                     77:
1.7       deraadt    78: struct hash {
                     79:        off_t   hpt;
                     80:        char    *hstr;
                     81:        struct  hash *hnext;
                     82:        short   hnew;
                     83: } bucket[BUCKETS];
                     84:
                     85: void process(char *);
                     86: off_t yankstr(char **);
                     87: int octdigit(char);
                     88: void inithash(void);
                     89: int fgetNUL(char *, int, FILE *);
                     90: int xgetc(FILE *);
                     91: off_t hashit(char *, int);
                     92: void flushsh(void);
                     93: void found(int, off_t, char *);
                     94: void prstr(char *);
                     95: void xsdotc(void);
                     96: char lastchr(char *);
                     97: int istail(char *, char *);
                     98: void onintr(void);
                     99:
                    100: int
                    101: main(int argc, char *argv[])
1.1       deraadt   102: {
                    103:        int c;
1.4       bitblt    104:        int fdesc;
1.1       deraadt   105:
                    106:        while ((c = getopt(argc, argv, "-cvl:")) != -1)
                    107:                switch (c) {
                    108:                case '-':
                    109:                        readstd++;
                    110:                        break;
                    111:                case 'c':
                    112:                        cflg++;
                    113:                        break;
                    114:                case 'v':
                    115:                        vflg++;
                    116:                        break;
                    117:                case 'l':
                    118:                        array = optarg;
                    119:                        break;
                    120:                default:
1.8     ! deraadt   121:                        fprintf(stderr,
        !           122:                            "usage: xstr [-vc] [-l array] [-] [name ...]\n");
        !           123:                        exit(1);
1.1       deraadt   124:                }
                    125:        argc -= optind;
                    126:        argv += optind;
                    127:
                    128:        if (array == 0)
                    129:                array = "xstr";
                    130:
                    131:        if (signal(SIGINT, SIG_IGN) == SIG_DFL)
1.7       deraadt   132:                signal(SIGINT, (void(*)(int))onintr);
                    133:        if (cflg || (argc == 0 && !readstd))
1.1       deraadt   134:                inithash();
1.4       bitblt    135:        else {
                    136:                strings = strdup (_PATH_TMPFILE);
                    137:                if (strings == NULL) {
                    138:                        fprintf(stderr, "Unable to allocate memory: %s",
                    139:                            strerror (errno));
                    140:                        exit(1);
                    141:                }
                    142:                fdesc = mkstemp (strings);
                    143:                if (fdesc < 0) {
                    144:                        fprintf(stderr, "Unable to create temporary file.\n");
                    145:                        exit(1);
                    146:                }
                    147:                close (fdesc);
                    148:        }
                    149:
1.1       deraadt   150:        while (readstd || argc > 0) {
1.8     ! deraadt   151:                if (freopen("x.c", "w", stdout) == NULL) {
        !           152:                        perror("x.c");
        !           153:                        exit(1);
        !           154:                }
        !           155:                if (!readstd && freopen(argv[0], "r", stdin) == NULL) {
        !           156:                        perror(argv[0]);
        !           157:                        exit(2);
        !           158:                }
1.1       deraadt   159:                process("x.c");
                    160:                if (readstd == 0)
                    161:                        argc--, argv++;
                    162:                else
                    163:                        readstd = 0;
1.8     ! deraadt   164:        }
1.1       deraadt   165:        flushsh();
                    166:        if (cflg == 0)
                    167:                xsdotc();
                    168:        if (strings[0] == '/')
1.7       deraadt   169:                unlink(strings);
1.1       deraadt   170:        exit(0);
                    171: }
                    172:
                    173: char linebuf[BUFSIZ];
                    174:
1.7       deraadt   175: void
                    176: process(char *name)
1.1       deraadt   177: {
                    178:        char *cp;
1.6       mpech     179:        int c;
                    180:        int incomm = 0;
1.1       deraadt   181:        int ret;
                    182:
                    183:        printf("extern char\t%s[];\n", array);
                    184:        for (;;) {
                    185:                if (fgets(linebuf, sizeof linebuf, stdin) == NULL) {
                    186:                        if (ferror(stdin)) {
                    187:                                perror(name);
                    188:                                exit(3);
                    189:                        }
                    190:                        break;
                    191:                }
                    192:                if (linebuf[0] == '#') {
                    193:                        if (linebuf[1] == ' ' && isdigit(linebuf[2]))
                    194:                                printf("#line%s", &linebuf[1]);
                    195:                        else
                    196:                                printf("%s", linebuf);
                    197:                        continue;
                    198:                }
1.7       deraadt   199:                for (cp = linebuf; (c = *cp); cp++)
                    200:                        switch (c) {
                    201:                        case '"':
                    202:                                if (incomm)
                    203:                                        goto def;
                    204:                                if ((ret = (int) yankstr(&cp)) == -1)
                    205:                                        goto out;
                    206:                                printf("(&%s[%d])", array, ret);
                    207:                                break;
                    208:                        case '\'':
                    209:                                if (incomm)
                    210:                                        goto def;
                    211:                                putchar(c);
                    212:                                if (*cp)
                    213:                                        putchar(*cp++);
                    214:                                break;
                    215:                        case '/':
                    216:                                if (incomm || *cp != '*')
                    217:                                        goto def;
                    218:                                incomm = 1;
1.1       deraadt   219:                                cp++;
1.7       deraadt   220:                                printf("/*");
1.1       deraadt   221:                                continue;
1.7       deraadt   222:                        case '*':
                    223:                                if (incomm && *cp == '/') {
                    224:                                        incomm = 0;
                    225:                                        cp++;
                    226:                                        printf("*/");
                    227:                                        continue;
                    228:                                }
                    229:                                goto def;
                    230:                        def:
                    231:                        default:
                    232:                                putchar(c);
                    233:                                break;
1.1       deraadt   234:                        }
                    235:        }
                    236: out:
                    237:        if (ferror(stdout))
                    238:                perror("x.c"), onintr();
                    239: }
                    240:
                    241: off_t
1.7       deraadt   242: yankstr(char **cpp)
1.1       deraadt   243: {
1.6       mpech     244:        char *cp = *cpp;
                    245:        int c, ch;
1.1       deraadt   246:        char dbuf[BUFSIZ];
1.6       mpech     247:        char *dp = dbuf;
                    248:        char *tp;
1.1       deraadt   249:
1.7       deraadt   250:        while ((c = *cp++)) {
1.1       deraadt   251:                switch (c) {
                    252:                case '"':
                    253:                        cp++;
                    254:                        goto out;
                    255:                case '\\':
                    256:                        c = *cp++;
                    257:                        if (c == 0)
                    258:                                break;
                    259:                        if (c == '\n') {
1.8     ! deraadt   260:                                if (fgets(linebuf, sizeof linebuf, stdin)
1.1       deraadt   261:                                    == NULL) {
                    262:                                        if (ferror(stdin)) {
                    263:                                                perror("x.c");
                    264:                                                exit(3);
                    265:                                        }
                    266:                                        return(-1);
                    267:                                }
                    268:                                cp = linebuf;
                    269:                                continue;
                    270:                        }
1.7       deraadt   271:                        for (tp = "b\bt\tr\rn\nf\f\\\\\"\""; (ch = *tp++); tp++)
1.1       deraadt   272:                                if (c == ch) {
                    273:                                        c = *tp;
                    274:                                        goto gotc;
                    275:                                }
                    276:                        if (!octdigit(c)) {
                    277:                                *dp++ = '\\';
                    278:                                break;
                    279:                        }
                    280:                        c -= '0';
                    281:                        if (!octdigit(*cp))
                    282:                                break;
                    283:                        c <<= 3, c += *cp++ - '0';
                    284:                        if (!octdigit(*cp))
                    285:                                break;
                    286:                        c <<= 3, c += *cp++ - '0';
                    287:                        break;
                    288:                }
                    289: gotc:
                    290:                *dp++ = c;
                    291:        }
                    292: out:
                    293:        *cpp = --cp;
                    294:        *dp = 0;
                    295:        return (hashit(dbuf, 1));
                    296: }
                    297:
1.7       deraadt   298: int
                    299: octdigit(char c)
1.1       deraadt   300: {
                    301:
                    302:        return (isdigit(c) && c != '8' && c != '9');
                    303: }
                    304:
1.7       deraadt   305: void
                    306: inithash(void)
1.1       deraadt   307: {
                    308:        char buf[BUFSIZ];
1.6       mpech     309:        FILE *mesgread = fopen(strings, "r");
1.1       deraadt   310:
                    311:        if (mesgread == NULL)
                    312:                return;
                    313:        for (;;) {
                    314:                mesgpt = tellpt;
                    315:                if (fgetNUL(buf, sizeof buf, mesgread) == NULL)
                    316:                        break;
1.7       deraadt   317:                hashit(buf, 0);
1.1       deraadt   318:        }
1.7       deraadt   319:        fclose(mesgread);
1.1       deraadt   320: }
                    321:
1.7       deraadt   322: int
                    323: fgetNUL(char *obuf, int rmdr, FILE  *file)
1.1       deraadt   324: {
1.6       mpech     325:        int c;
                    326:        char *buf = obuf;
1.1       deraadt   327:
                    328:        while (--rmdr > 0 && (c = xgetc(file)) != 0 && c != EOF)
                    329:                *buf++ = c;
                    330:        *buf++ = 0;
                    331:        return ((feof(file) || ferror(file)) ? NULL : 1);
                    332: }
                    333:
1.7       deraadt   334: int
                    335: xgetc(FILE *file)
1.1       deraadt   336: {
                    337:
                    338:        tellpt++;
                    339:        return (getc(file));
                    340: }
                    341:
                    342:
                    343: off_t
1.7       deraadt   344: hashit(char *str, int new)
1.1       deraadt   345: {
                    346:        int i;
1.6       mpech     347:        struct hash *hp, *hp0;
1.1       deraadt   348:
                    349:        hp = hp0 = &bucket[lastchr(str) & 0177];
                    350:        while (hp->hnext) {
                    351:                hp = hp->hnext;
                    352:                i = istail(str, hp->hstr);
                    353:                if (i >= 0)
                    354:                        return (hp->hpt + i);
                    355:        }
                    356:        if ((hp = (struct hash *) calloc(1, sizeof (*hp))) == NULL) {
                    357:                perror("xstr");
                    358:                exit(8);
                    359:        }
                    360:        hp->hpt = mesgpt;
                    361:        if (!(hp->hstr = strdup(str))) {
                    362:                (void)fprintf(stderr, "xstr: %s\n", strerror(errno));
                    363:                exit(1);
                    364:        }
                    365:        mesgpt += strlen(hp->hstr) + 1;
                    366:        hp->hnext = hp0->hnext;
                    367:        hp->hnew = new;
                    368:        hp0->hnext = hp;
                    369:        return (hp->hpt);
                    370: }
                    371:
1.7       deraadt   372: void
                    373: flushsh(void)
1.1       deraadt   374: {
1.6       mpech     375:        int i;
                    376:        struct hash *hp;
                    377:        FILE *mesgwrit;
                    378:        int old = 0, new = 0;
1.1       deraadt   379:
                    380:        for (i = 0; i < BUCKETS; i++)
                    381:                for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext)
                    382:                        if (hp->hnew)
                    383:                                new++;
                    384:                        else
                    385:                                old++;
                    386:        if (new == 0 && old != 0)
                    387:                return;
                    388:        mesgwrit = fopen(strings, old ? "r+" : "w");
1.8     ! deraadt   389:        if (mesgwrit == NULL) {
        !           390:                perror(strings);
        !           391:                exit(4);
        !           392:        }
1.1       deraadt   393:        for (i = 0; i < BUCKETS; i++)
                    394:                for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) {
                    395:                        found(hp->hnew, hp->hpt, hp->hstr);
                    396:                        if (hp->hnew) {
                    397:                                fseek(mesgwrit, hp->hpt, 0);
1.7       deraadt   398:                                fwrite(hp->hstr, strlen(hp->hstr) + 1, 1, mesgwrit);
1.8     ! deraadt   399:                                if (ferror(mesgwrit)) {
        !           400:                                        perror(strings);
        !           401:                                        exit(4);
        !           402:                                }
1.1       deraadt   403:                        }
                    404:                }
1.8     ! deraadt   405:        if (fclose(mesgwrit) == EOF) {
        !           406:                perror(strings);
        !           407:                exit(4);
        !           408:        }
1.1       deraadt   409: }
                    410:
1.7       deraadt   411: void
                    412: found(int new, off_t off, char *str)
1.1       deraadt   413: {
                    414:        if (vflg == 0)
                    415:                return;
                    416:        if (!new)
                    417:                fprintf(stderr, "found at %d:", (int) off);
                    418:        else
                    419:                fprintf(stderr, "new at %d:", (int) off);
                    420:        prstr(str);
                    421:        fprintf(stderr, "\n");
                    422: }
                    423:
1.7       deraadt   424: void
                    425: prstr(char *cp)
1.1       deraadt   426: {
1.6       mpech     427:        int c;
1.1       deraadt   428:
1.7       deraadt   429:        while ((c = (*cp++ & 0377)))
1.1       deraadt   430:                if (c < ' ')
                    431:                        fprintf(stderr, "^%c", c + '`');
                    432:                else if (c == 0177)
                    433:                        fprintf(stderr, "^?");
                    434:                else if (c > 0200)
                    435:                        fprintf(stderr, "\\%03o", c);
                    436:                else
                    437:                        fprintf(stderr, "%c", c);
                    438: }
                    439:
1.7       deraadt   440: void
                    441: xsdotc(void)
1.1       deraadt   442: {
1.6       mpech     443:        FILE *strf = fopen(strings, "r");
                    444:        FILE *xdotcf;
1.1       deraadt   445:
1.8     ! deraadt   446:        if (strf == NULL) {
        !           447:                perror(strings);
        !           448:                exit(5);
        !           449:        }
1.1       deraadt   450:        xdotcf = fopen("xs.c", "w");
1.8     ! deraadt   451:        if (xdotcf == NULL) {
        !           452:                perror("xs.c");
        !           453:                exit(6);
        !           454:        }
1.1       deraadt   455:        fprintf(xdotcf, "char\t%s[] = {\n", array);
                    456:        for (;;) {
1.6       mpech     457:                int i, c;
1.1       deraadt   458:
                    459:                for (i = 0; i < 8; i++) {
                    460:                        c = getc(strf);
                    461:                        if (ferror(strf)) {
                    462:                                perror(strings);
                    463:                                onintr();
                    464:                        }
                    465:                        if (feof(strf)) {
                    466:                                fprintf(xdotcf, "\n");
                    467:                                goto out;
                    468:                        }
                    469:                        fprintf(xdotcf, "0x%02x,", c);
                    470:                }
                    471:                fprintf(xdotcf, "\n");
                    472:        }
                    473: out:
                    474:        fprintf(xdotcf, "};\n");
1.7       deraadt   475:        fclose(xdotcf);
                    476:        fclose(strf);
1.1       deraadt   477: }
                    478:
1.7       deraadt   479: char
                    480: lastchr(char *cp)
1.1       deraadt   481: {
                    482:
                    483:        while (cp[0] && cp[1])
                    484:                cp++;
                    485:        return (*cp);
                    486: }
                    487:
1.7       deraadt   488: int
                    489: istail(char *str, char *of)
1.1       deraadt   490: {
1.6       mpech     491:        int d = strlen(of) - strlen(str);
1.1       deraadt   492:
                    493:        if (d < 0 || strcmp(&of[d], str) != 0)
                    494:                return (-1);
                    495:        return (d);
                    496: }
                    497:
                    498: void
1.7       deraadt   499: onintr(void)
1.1       deraadt   500: {
                    501:
1.7       deraadt   502:        signal(SIGINT, SIG_IGN);
1.1       deraadt   503:        if (strings[0] == '/')
1.7       deraadt   504:                unlink(strings);
                    505:        unlink("x.c");
                    506:        unlink("xs.c");
1.5       deraadt   507:        _exit(7);
1.1       deraadt   508: }