[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.6

1.6     ! mpech       1: /*     $OpenBSD: xstr.c,v 1.5 2001/07/20 14:20:29 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.6     ! mpech      47: static char rcsid[] = "$OpenBSD: xstr.c,v 1.5 2001/07/20 14:20:29 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:
                     67: #define        ignore(a)       ((void) a)
                     68:
                     69: off_t  tellpt;
                     70: off_t  hashit();
                     71: void   onintr();
                     72: char   *savestr();
                     73: off_t  yankstr();
                     74:
                     75: off_t  mesgpt;
                     76: char   *strings =      "strings";
                     77:
                     78: char   *array =        0;
                     79:
                     80: int    cflg;
                     81: int    vflg;
                     82: int    readstd;
                     83:
                     84: main(argc, argv)
                     85:        int argc;
                     86:        char *argv[];
                     87: {
                     88:        int c;
1.4       bitblt     89:        int fdesc;
1.1       deraadt    90:
                     91:        while ((c = getopt(argc, argv, "-cvl:")) != -1)
                     92:                switch (c) {
                     93:                case '-':
                     94:                        readstd++;
                     95:                        break;
                     96:                case 'c':
                     97:                        cflg++;
                     98:                        break;
                     99:                case 'v':
                    100:                        vflg++;
                    101:                        break;
                    102:                case 'l':
                    103:                        array = optarg;
                    104:                        break;
                    105:                default:
                    106:                        fprintf(stderr, "usage: xstr [ -v ] [ -c ] [ -l array ] [ - ] [ name ... ]\n");
                    107:                        exit (1);
                    108:                }
                    109:        argc -= optind;
                    110:        argv += optind;
                    111:
                    112:        if (array == 0)
                    113:                array = "xstr";
                    114:
                    115:        if (signal(SIGINT, SIG_IGN) == SIG_DFL)
                    116:                signal(SIGINT, onintr);
                    117:        if (cflg || argc == 0 && !readstd)
                    118:                inithash();
1.4       bitblt    119:        else {
                    120:                strings = strdup (_PATH_TMPFILE);
                    121:                if (strings == NULL) {
                    122:                        fprintf(stderr, "Unable to allocate memory: %s",
                    123:                            strerror (errno));
                    124:                        exit(1);
                    125:                }
                    126:                fdesc = mkstemp (strings);
                    127:                if (fdesc < 0) {
                    128:                        fprintf(stderr, "Unable to create temporary file.\n");
                    129:                        exit(1);
                    130:                }
                    131:                close (fdesc);
                    132:        }
                    133:
1.1       deraadt   134:        while (readstd || argc > 0) {
                    135:                if (freopen("x.c", "w", stdout) == NULL)
                    136:                        perror("x.c"), exit(1);
                    137:                if (!readstd && freopen(argv[0], "r", stdin) == NULL)
                    138:                        perror(argv[0]), exit(2);
                    139:                process("x.c");
                    140:                if (readstd == 0)
                    141:                        argc--, argv++;
                    142:                else
                    143:                        readstd = 0;
                    144:        };
                    145:        flushsh();
                    146:        if (cflg == 0)
                    147:                xsdotc();
                    148:        if (strings[0] == '/')
                    149:                ignore(unlink(strings));
                    150:        exit(0);
                    151: }
                    152:
                    153: char linebuf[BUFSIZ];
                    154:
                    155: process(name)
                    156:        char *name;
                    157: {
                    158:        char *cp;
1.6     ! mpech     159:        int c;
        !           160:        int incomm = 0;
1.1       deraadt   161:        int ret;
                    162:
                    163:        printf("extern char\t%s[];\n", array);
                    164:        for (;;) {
                    165:                if (fgets(linebuf, sizeof linebuf, stdin) == NULL) {
                    166:                        if (ferror(stdin)) {
                    167:                                perror(name);
                    168:                                exit(3);
                    169:                        }
                    170:                        break;
                    171:                }
                    172:                if (linebuf[0] == '#') {
                    173:                        if (linebuf[1] == ' ' && isdigit(linebuf[2]))
                    174:                                printf("#line%s", &linebuf[1]);
                    175:                        else
                    176:                                printf("%s", linebuf);
                    177:                        continue;
                    178:                }
                    179:                for (cp = linebuf; c = *cp++;) switch (c) {
                    180:
                    181:                case '"':
                    182:                        if (incomm)
                    183:                                goto def;
                    184:                        if ((ret = (int) yankstr(&cp)) == -1)
                    185:                                goto out;
                    186:                        printf("(&%s[%d])", array, ret);
                    187:                        break;
                    188:
                    189:                case '\'':
                    190:                        if (incomm)
                    191:                                goto def;
                    192:                        putchar(c);
                    193:                        if (*cp)
                    194:                                putchar(*cp++);
                    195:                        break;
                    196:
                    197:                case '/':
                    198:                        if (incomm || *cp != '*')
                    199:                                goto def;
                    200:                        incomm = 1;
                    201:                        cp++;
                    202:                        printf("/*");
                    203:                        continue;
                    204:
                    205:                case '*':
                    206:                        if (incomm && *cp == '/') {
                    207:                                incomm = 0;
                    208:                                cp++;
                    209:                                printf("*/");
                    210:                                continue;
                    211:                        }
                    212:                        goto def;
                    213:
                    214: def:
                    215:                default:
                    216:                        putchar(c);
                    217:                        break;
                    218:                }
                    219:        }
                    220: out:
                    221:        if (ferror(stdout))
                    222:                perror("x.c"), onintr();
                    223: }
                    224:
                    225: off_t
                    226: yankstr(cpp)
1.6     ! mpech     227:        char **cpp;
1.1       deraadt   228: {
1.6     ! mpech     229:        char *cp = *cpp;
        !           230:        int c, ch;
1.1       deraadt   231:        char dbuf[BUFSIZ];
1.6     ! mpech     232:        char *dp = dbuf;
        !           233:        char *tp;
1.1       deraadt   234:
                    235:        while (c = *cp++) {
                    236:                switch (c) {
                    237:
                    238:                case '"':
                    239:                        cp++;
                    240:                        goto out;
                    241:
                    242:                case '\\':
                    243:                        c = *cp++;
                    244:                        if (c == 0)
                    245:                                break;
                    246:                        if (c == '\n') {
                    247:                                if (fgets(linebuf, sizeof linebuf, stdin)
                    248:                                    == NULL) {
                    249:                                        if (ferror(stdin)) {
                    250:                                                perror("x.c");
                    251:                                                exit(3);
                    252:                                        }
                    253:                                        return(-1);
                    254:                                }
                    255:                                cp = linebuf;
                    256:                                continue;
                    257:                        }
                    258:                        for (tp = "b\bt\tr\rn\nf\f\\\\\"\""; ch = *tp++; tp++)
                    259:                                if (c == ch) {
                    260:                                        c = *tp;
                    261:                                        goto gotc;
                    262:                                }
                    263:                        if (!octdigit(c)) {
                    264:                                *dp++ = '\\';
                    265:                                break;
                    266:                        }
                    267:                        c -= '0';
                    268:                        if (!octdigit(*cp))
                    269:                                break;
                    270:                        c <<= 3, c += *cp++ - '0';
                    271:                        if (!octdigit(*cp))
                    272:                                break;
                    273:                        c <<= 3, c += *cp++ - '0';
                    274:                        break;
                    275:                }
                    276: gotc:
                    277:                *dp++ = c;
                    278:        }
                    279: out:
                    280:        *cpp = --cp;
                    281:        *dp = 0;
                    282:        return (hashit(dbuf, 1));
                    283: }
                    284:
                    285: octdigit(c)
                    286:        char c;
                    287: {
                    288:
                    289:        return (isdigit(c) && c != '8' && c != '9');
                    290: }
                    291:
                    292: inithash()
                    293: {
                    294:        char buf[BUFSIZ];
1.6     ! mpech     295:        FILE *mesgread = fopen(strings, "r");
1.1       deraadt   296:
                    297:        if (mesgread == NULL)
                    298:                return;
                    299:        for (;;) {
                    300:                mesgpt = tellpt;
                    301:                if (fgetNUL(buf, sizeof buf, mesgread) == NULL)
                    302:                        break;
                    303:                ignore(hashit(buf, 0));
                    304:        }
                    305:        ignore(fclose(mesgread));
                    306: }
                    307:
                    308: fgetNUL(obuf, rmdr, file)
                    309:        char *obuf;
1.6     ! mpech     310:        int rmdr;
1.1       deraadt   311:        FILE *file;
                    312: {
1.6     ! mpech     313:        int c;
        !           314:        char *buf = obuf;
1.1       deraadt   315:
                    316:        while (--rmdr > 0 && (c = xgetc(file)) != 0 && c != EOF)
                    317:                *buf++ = c;
                    318:        *buf++ = 0;
                    319:        return ((feof(file) || ferror(file)) ? NULL : 1);
                    320: }
                    321:
                    322: xgetc(file)
                    323:        FILE *file;
                    324: {
                    325:
                    326:        tellpt++;
                    327:        return (getc(file));
                    328: }
                    329:
                    330: #define        BUCKETS 128
                    331:
                    332: struct hash {
                    333:        off_t   hpt;
                    334:        char    *hstr;
                    335:        struct  hash *hnext;
                    336:        short   hnew;
                    337: } bucket[BUCKETS];
                    338:
                    339: off_t
                    340: hashit(str, new)
                    341:        char *str;
                    342:        int new;
                    343: {
                    344:        int i;
1.6     ! mpech     345:        struct hash *hp, *hp0;
1.1       deraadt   346:
                    347:        hp = hp0 = &bucket[lastchr(str) & 0177];
                    348:        while (hp->hnext) {
                    349:                hp = hp->hnext;
                    350:                i = istail(str, hp->hstr);
                    351:                if (i >= 0)
                    352:                        return (hp->hpt + i);
                    353:        }
                    354:        if ((hp = (struct hash *) calloc(1, sizeof (*hp))) == NULL) {
                    355:                perror("xstr");
                    356:                exit(8);
                    357:        }
                    358:        hp->hpt = mesgpt;
                    359:        if (!(hp->hstr = strdup(str))) {
                    360:                (void)fprintf(stderr, "xstr: %s\n", strerror(errno));
                    361:                exit(1);
                    362:        }
                    363:        mesgpt += strlen(hp->hstr) + 1;
                    364:        hp->hnext = hp0->hnext;
                    365:        hp->hnew = new;
                    366:        hp0->hnext = hp;
                    367:        return (hp->hpt);
                    368: }
                    369:
                    370: flushsh()
                    371: {
1.6     ! mpech     372:        int i;
        !           373:        struct hash *hp;
        !           374:        FILE *mesgwrit;
        !           375:        int old = 0, new = 0;
1.1       deraadt   376:
                    377:        for (i = 0; i < BUCKETS; i++)
                    378:                for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext)
                    379:                        if (hp->hnew)
                    380:                                new++;
                    381:                        else
                    382:                                old++;
                    383:        if (new == 0 && old != 0)
                    384:                return;
                    385:        mesgwrit = fopen(strings, old ? "r+" : "w");
                    386:        if (mesgwrit == NULL)
                    387:                perror(strings), exit(4);
                    388:        for (i = 0; i < BUCKETS; i++)
                    389:                for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) {
                    390:                        found(hp->hnew, hp->hpt, hp->hstr);
                    391:                        if (hp->hnew) {
                    392:                                fseek(mesgwrit, hp->hpt, 0);
                    393:                                ignore(fwrite(hp->hstr, strlen(hp->hstr) + 1, 1, mesgwrit));
                    394:                                if (ferror(mesgwrit))
                    395:                                        perror(strings), exit(4);
                    396:                        }
                    397:                }
                    398:        if (fclose(mesgwrit) == EOF)
                    399:                perror(strings), exit(4);
                    400: }
                    401:
                    402: found(new, off, str)
                    403:        int new;
                    404:        off_t off;
                    405:        char *str;
                    406: {
                    407:        if (vflg == 0)
                    408:                return;
                    409:        if (!new)
                    410:                fprintf(stderr, "found at %d:", (int) off);
                    411:        else
                    412:                fprintf(stderr, "new at %d:", (int) off);
                    413:        prstr(str);
                    414:        fprintf(stderr, "\n");
                    415: }
                    416:
                    417: prstr(cp)
1.6     ! mpech     418:        char *cp;
1.1       deraadt   419: {
1.6     ! mpech     420:        int c;
1.1       deraadt   421:
                    422:        while (c = (*cp++ & 0377))
                    423:                if (c < ' ')
                    424:                        fprintf(stderr, "^%c", c + '`');
                    425:                else if (c == 0177)
                    426:                        fprintf(stderr, "^?");
                    427:                else if (c > 0200)
                    428:                        fprintf(stderr, "\\%03o", c);
                    429:                else
                    430:                        fprintf(stderr, "%c", c);
                    431: }
                    432:
                    433: xsdotc()
                    434: {
1.6     ! mpech     435:        FILE *strf = fopen(strings, "r");
        !           436:        FILE *xdotcf;
1.1       deraadt   437:
                    438:        if (strf == NULL)
                    439:                perror(strings), exit(5);
                    440:        xdotcf = fopen("xs.c", "w");
                    441:        if (xdotcf == NULL)
                    442:                perror("xs.c"), exit(6);
                    443:        fprintf(xdotcf, "char\t%s[] = {\n", array);
                    444:        for (;;) {
1.6     ! mpech     445:                int i, c;
1.1       deraadt   446:
                    447:                for (i = 0; i < 8; i++) {
                    448:                        c = getc(strf);
                    449:                        if (ferror(strf)) {
                    450:                                perror(strings);
                    451:                                onintr();
                    452:                        }
                    453:                        if (feof(strf)) {
                    454:                                fprintf(xdotcf, "\n");
                    455:                                goto out;
                    456:                        }
                    457:                        fprintf(xdotcf, "0x%02x,", c);
                    458:                }
                    459:                fprintf(xdotcf, "\n");
                    460:        }
                    461: out:
                    462:        fprintf(xdotcf, "};\n");
                    463:        ignore(fclose(xdotcf));
                    464:        ignore(fclose(strf));
                    465: }
                    466:
                    467: lastchr(cp)
1.6     ! mpech     468:        char *cp;
1.1       deraadt   469: {
                    470:
                    471:        while (cp[0] && cp[1])
                    472:                cp++;
                    473:        return (*cp);
                    474: }
                    475:
                    476: istail(str, of)
1.6     ! mpech     477:        char *str, *of;
1.1       deraadt   478: {
1.6     ! mpech     479:        int d = strlen(of) - strlen(str);
1.1       deraadt   480:
                    481:        if (d < 0 || strcmp(&of[d], str) != 0)
                    482:                return (-1);
                    483:        return (d);
                    484: }
                    485:
                    486: void
                    487: onintr()
                    488: {
                    489:
                    490:        ignore(signal(SIGINT, SIG_IGN));
                    491:        if (strings[0] == '/')
                    492:                ignore(unlink(strings));
                    493:        ignore(unlink("x.c"));
                    494:        ignore(unlink("xs.c"));
1.5       deraadt   495:        _exit(7);
1.1       deraadt   496: }