Annotation of 43BSDReno/usr.bin/hexdump/parse.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1989 The Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms are permitted
        !             6:  * provided that: (1) source distributions retain this entire copyright
        !             7:  * notice and comment, and (2) distributions including binaries display
        !             8:  * the following acknowledgement:  ``This product includes software
        !             9:  * developed by the University of California, Berkeley and its contributors''
        !            10:  * in the documentation or other materials provided with the distribution
        !            11:  * and in all advertising materials mentioning features or use of this
        !            12:  * software. Neither the name of the University nor the names of its
        !            13:  * contributors may be used to endorse or promote products derived
        !            14:  * from this software without specific prior written permission.
        !            15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !            16:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !            17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            18:  */
        !            19: 
        !            20: #ifndef lint
        !            21: static char sccsid[] = "@(#)parse.c    5.4 (Berkeley) 6/1/90";
        !            22: #endif /* not lint */
        !            23: 
        !            24: #include <sys/types.h>
        !            25: #include <sys/file.h>
        !            26: #include <stdio.h>
        !            27: #include <ctype.h>
        !            28: #include <string.h>
        !            29: #include "hexdump.h"
        !            30: 
        !            31: FU *endfu;                                     /* format at end-of-data */
        !            32: 
        !            33: addfile(name)
        !            34:        char *name;
        !            35: {
        !            36:        register char *p;
        !            37:        FILE *fp;
        !            38:        int ch;
        !            39:        char buf[2048 + 1];
        !            40: 
        !            41:        if (!(fp = fopen(name, "r"))) {
        !            42:                (void)fprintf(stderr, "hexdump: can't read %s.\n", name);
        !            43:                exit(1);
        !            44:        }
        !            45:        while (fgets(buf, sizeof(buf), fp)) {
        !            46:                if (!(p = index(buf, '\n'))) {
        !            47:                        (void)fprintf(stderr, "hexdump: line too long.\n");
        !            48:                        while ((ch = getchar()) != '\n' && ch != EOF);
        !            49:                        continue;
        !            50:                }
        !            51:                *p = '\0';
        !            52:                for (p = buf; *p && isspace(*p); ++p);
        !            53:                if (!*p || *p == '#')
        !            54:                        continue;
        !            55:                add(p);
        !            56:        }
        !            57:        (void)fclose(fp);
        !            58: }
        !            59: 
        !            60: add(fmt)
        !            61:        char *fmt;
        !            62: {
        !            63:        register char *p;
        !            64:        static FS **nextfs;
        !            65:        FS *tfs;
        !            66:        FU *tfu, **nextfu;
        !            67:        char savech, *savep, *emalloc(), *strdup();
        !            68: 
        !            69:        /* start new linked list of format units */
        !            70:        /* NOSTRICT */
        !            71:        tfs = (FS *)emalloc(sizeof(FS));
        !            72:        if (!fshead)
        !            73:                fshead = tfs;
        !            74:        else
        !            75:                *nextfs = tfs;
        !            76:        nextfs = &tfs->nextfs;
        !            77:        nextfu = &tfs->nextfu;
        !            78: 
        !            79:        /* take the format string and break it up into format units */
        !            80:        for (p = fmt;;) {
        !            81:                /* skip leading white space */
        !            82:                for (; isspace(*p); ++p);
        !            83:                if (!*p)
        !            84:                        break;
        !            85: 
        !            86:                /* allocate a new format unit and link it in */
        !            87:                /* NOSTRICT */
        !            88:                tfu = (FU *)emalloc(sizeof(FU));
        !            89:                *nextfu = tfu;
        !            90:                nextfu = &tfu->nextfu;
        !            91:                tfu->reps = 1;
        !            92: 
        !            93:                /* if leading digit, repetition count */
        !            94:                if (isdigit(*p)) {
        !            95:                        for (savep = p; isdigit(*p); ++p);
        !            96:                        if (!isspace(*p) && *p != '/')
        !            97:                                badfmt(fmt);
        !            98:                        /* may overwrite either white space or slash */
        !            99:                        savech = *p;
        !           100:                        *p = '\0';
        !           101:                        tfu->reps = atoi(savep);
        !           102:                        tfu->flags = F_SETREP;
        !           103:                        *p = savech;
        !           104:                        /* skip trailing white space */
        !           105:                        for (++p; isspace(*p); ++p);
        !           106:                }
        !           107: 
        !           108:                /* skip slash and trailing white space */
        !           109:                if (*p == '/')
        !           110:                        while (isspace(*++p));
        !           111: 
        !           112:                /* byte count */
        !           113:                if (isdigit(*p)) {
        !           114:                        for (savep = p; isdigit(*p); ++p);
        !           115:                        if (!isspace(*p))
        !           116:                                badfmt(fmt);
        !           117:                        savech = *p;
        !           118:                        *p = '\0';
        !           119:                        tfu->bcnt = atoi(savep);
        !           120:                        *p = savech;
        !           121:                        /* skip trailing white space */
        !           122:                        for (++p; isspace(*p); ++p);
        !           123:                }
        !           124: 
        !           125:                /* format */
        !           126:                if (*p != '"')
        !           127:                        badfmt(fmt);
        !           128:                for (savep = ++p; *p != '"'; ++p);
        !           129:                if (*p != '"')
        !           130:                        badfmt(fmt);
        !           131:                savech = *p;
        !           132:                *p = '\0';
        !           133:                if (!(tfu->fmt = strdup(savep)))
        !           134:                        nomem();
        !           135:                escape(tfu->fmt);
        !           136:                *p++ = savech;
        !           137:        }
        !           138: }
        !           139: 
        !           140: static char *spec = ".#-+ 0123456789";
        !           141: size(fs)
        !           142:        FS *fs;
        !           143: {
        !           144:        register FU *fu;
        !           145:        register int bcnt, cursize;
        !           146:        register char *fmt;
        !           147:        int prec;
        !           148: 
        !           149:        /* figure out the data block size needed for each format unit */
        !           150:        for (cursize = 0, fu = fs->nextfu; fu; fu = fu->nextfu) {
        !           151:                if (fu->bcnt) {
        !           152:                        cursize += fu->bcnt * fu->reps;
        !           153:                        continue;
        !           154:                }
        !           155:                for (bcnt = prec = 0, fmt = fu->fmt; *fmt; ++fmt) {
        !           156:                        if (*fmt != '%')
        !           157:                                continue;
        !           158:                        /*
        !           159:                         * skip any special chars -- save precision in
        !           160:                         * case it's a %s format.
        !           161:                         */
        !           162:                        while (index(spec + 1, *++fmt));
        !           163:                        if (*fmt == '.' && isdigit(*++fmt)) {
        !           164:                                prec = atoi(fmt);
        !           165:                                while (isdigit(*++fmt));
        !           166:                        }
        !           167:                        switch(*fmt) {
        !           168:                        case 'c':
        !           169:                                bcnt += 1;
        !           170:                                break;
        !           171:                        case 'd': case 'i': case 'o': case 'u':
        !           172:                        case 'x': case 'X':
        !           173:                                bcnt += 4;
        !           174:                                break;
        !           175:                        case 'e': case 'E': case 'f': case 'g': case 'G':
        !           176:                                bcnt += 8;
        !           177:                                break;
        !           178:                        case 's':
        !           179:                                bcnt += prec;
        !           180:                                break;
        !           181:                        case '_':
        !           182:                                switch(*++fmt) {
        !           183:                                case 'c': case 'p': case 'u':
        !           184:                                        bcnt += 1;
        !           185:                                        break;
        !           186:                                }
        !           187:                        }
        !           188:                }
        !           189:                cursize += bcnt * fu->reps;
        !           190:        }
        !           191:        return(cursize);
        !           192: }
        !           193: 
        !           194: rewrite(fs)
        !           195:        FS *fs;
        !           196: {
        !           197:        enum { NOTOKAY, USEBCNT, USEPREC } sokay;
        !           198:        register PR *pr, **nextpr;
        !           199:        register FU *fu;
        !           200:        register char *p1, *p2;
        !           201:        char savech, *fmtp;
        !           202:        int nconv, prec;
        !           203: 
        !           204:        for (fu = fs->nextfu; fu; fu = fu->nextfu) {
        !           205:                /*
        !           206:                 * break each format unit into print units; each
        !           207:                 * conversion character gets its own.
        !           208:                 */
        !           209:                for (nconv = 0, fmtp = fu->fmt; *fmtp; nextpr = &pr->nextpr) {
        !           210:                        /* NOSTRICT */
        !           211:                        pr = (PR *)emalloc(sizeof(PR));
        !           212:                        if (!fu->nextpr)
        !           213:                                fu->nextpr = pr;
        !           214:                        else
        !           215:                                *nextpr = pr;
        !           216: 
        !           217:                        /* skip preceding text and up to the next % sign */
        !           218:                        for (p1 = fmtp; *p1 && *p1 != '%'; ++p1);
        !           219: 
        !           220:                        /* only text in the string */
        !           221:                        if (!*p1) {
        !           222:                                pr->fmt = fmtp;
        !           223:                                pr->flags = F_TEXT;
        !           224:                                break;
        !           225:                        }
        !           226: 
        !           227:                        /*
        !           228:                         * get precision for %s -- if have a byte count, don't
        !           229:                         * need it.
        !           230:                         */
        !           231:                        if (fu->bcnt) {
        !           232:                                sokay = USEBCNT;
        !           233:                                /* skip to conversion character */
        !           234:                                for (++p1; index(spec, *p1); ++p1);
        !           235:                        } else {
        !           236:                                /* skip any special chars, field width */
        !           237:                                while (index(spec + 1, *++p1));
        !           238:                                if (*p1 == '.' && isdigit(*++p1)) {
        !           239:                                        sokay = USEPREC;
        !           240:                                        prec = atoi(p1);
        !           241:                                        while (isdigit(*++p1));
        !           242:                                }
        !           243:                                else
        !           244:                                        sokay = NOTOKAY;
        !           245:                        }
        !           246: 
        !           247:                        p2 = p1 + 1;            /* set end pointer */
        !           248: 
        !           249:                        /*
        !           250:                         * figure out the byte count for each conversion;
        !           251:                         * rewrite the format as necessary, set up blank-
        !           252:                         * padding for end of data.
        !           253:                         */
        !           254:                        switch(*p1) {
        !           255:                        case 'c':
        !           256:                                pr->flags = F_CHAR;
        !           257:                                switch(fu->bcnt) {
        !           258:                                case 0: case 1:
        !           259:                                        pr->bcnt = 1;
        !           260:                                        break;
        !           261:                                default:
        !           262:                                        p1[1] = '\0';
        !           263:                                        badcnt(p1);
        !           264:                                }
        !           265:                                break;
        !           266:                        case 'd': case 'i':
        !           267:                                pr->flags = F_INT;
        !           268:                                goto sw1;
        !           269:                        case 'l':
        !           270:                                ++p2;
        !           271:                                switch(p1[1]) {
        !           272:                                case 'd': case 'i':
        !           273:                                        ++p1;
        !           274:                                        pr->flags = F_INT;
        !           275:                                        goto sw1;
        !           276:                                case 'o': case 'u': case 'x': case 'X':
        !           277:                                        ++p1;
        !           278:                                        pr->flags = F_UINT;
        !           279:                                        goto sw1;
        !           280:                                default:
        !           281:                                        p1[2] = '\0';
        !           282:                                        badconv(p1);
        !           283:                                }
        !           284:                                /* NOTREACHED */
        !           285:                        case 'o': case 'u': case 'x': case 'X':
        !           286:                                pr->flags = F_UINT;
        !           287: sw1:                           switch(fu->bcnt) {
        !           288:                                case 0: case 4:
        !           289:                                        pr->bcnt = 4;
        !           290:                                        break;
        !           291:                                case 1:
        !           292:                                        pr->bcnt = 1;
        !           293:                                        break;
        !           294:                                case 2:
        !           295:                                        pr->bcnt = 2;
        !           296:                                        break;
        !           297:                                default:
        !           298:                                        p1[1] = '\0';
        !           299:                                        badcnt(p1);
        !           300:                                }
        !           301:                                break;
        !           302:                        case 'e': case 'E': case 'f': case 'g': case 'G':
        !           303:                                pr->flags = F_DBL;
        !           304:                                switch(fu->bcnt) {
        !           305:                                case 0: case 8:
        !           306:                                        pr->bcnt = 8;
        !           307:                                        break;
        !           308:                                case 4:
        !           309:                                        pr->bcnt = 4;
        !           310:                                        break;
        !           311:                                default:
        !           312:                                        p1[1] = '\0';
        !           313:                                        badcnt(p1);
        !           314:                                }
        !           315:                                break;
        !           316:                        case 's':
        !           317:                                pr->flags = F_STR;
        !           318:                                switch(sokay) {
        !           319:                                case NOTOKAY:
        !           320:                                        badsfmt();
        !           321:                                case USEBCNT:
        !           322:                                        pr->bcnt = fu->bcnt;
        !           323:                                        break;
        !           324:                                case USEPREC:
        !           325:                                        pr->bcnt = prec;
        !           326:                                        break;
        !           327:                                }
        !           328:                                break;
        !           329:                        case '_':
        !           330:                                ++p2;
        !           331:                                switch(p1[1]) {
        !           332:                                case 'A':
        !           333:                                        endfu = fu;
        !           334:                                        fu->flags |= F_IGNORE;
        !           335:                                        /* FALLTHROUGH */
        !           336:                                case 'a':
        !           337:                                        pr->flags = F_ADDRESS;
        !           338:                                        ++p2;
        !           339:                                        switch(p1[2]) {
        !           340:                                        case 'd': case 'o': case'x':
        !           341:                                                *p1 = p1[2];
        !           342:                                                break;
        !           343:                                        default:
        !           344:                                                p1[3] = '\0';
        !           345:                                                badconv(p1);
        !           346:                                        }
        !           347:                                        break;
        !           348:                                case 'c':
        !           349:                                        pr->flags = F_C;
        !           350:                                        /* *p1 = 'c';   set in conv_c */
        !           351:                                        goto sw2;
        !           352:                                case 'p':
        !           353:                                        pr->flags = F_P;
        !           354:                                        *p1 = 'c';
        !           355:                                        goto sw2;
        !           356:                                case 'u':
        !           357:                                        pr->flags = F_U;
        !           358:                                        /* *p1 = 'c';   set in conv_u */
        !           359: sw2:                                   switch(fu->bcnt) {
        !           360:                                        case 0: case 1:
        !           361:                                                pr->bcnt = 1;
        !           362:                                                break;
        !           363:                                        default:
        !           364:                                                p1[2] = '\0';
        !           365:                                                badcnt(p1);
        !           366:                                        }
        !           367:                                        break;
        !           368:                                default:
        !           369:                                        p1[2] = '\0';
        !           370:                                        badconv(p1);
        !           371:                                }
        !           372:                                break;
        !           373:                        default:
        !           374:                                p1[1] = '\0';
        !           375:                                badconv(p1);
        !           376:                        }
        !           377: 
        !           378:                        /*
        !           379:                         * copy to PR format string, set conversion character
        !           380:                         * pointer, update original.
        !           381:                         */
        !           382:                        savech = *p2;
        !           383:                        p1[1] = '\0';
        !           384:                        if (!(pr->fmt = strdup(fmtp)))
        !           385:                                nomem();
        !           386:                        *p2 = savech;
        !           387:                        pr->cchar = pr->fmt + (p1 - fmtp);
        !           388:                        fmtp = p2;
        !           389: 
        !           390:                        /* only one conversion character if byte count */
        !           391:                        if (!(pr->flags&F_ADDRESS) && fu->bcnt && nconv++) {
        !           392:                                (void)fprintf(stderr,
        !           393:                                    "hexdump: byte count with multiple conversion characters.\n");
        !           394:                                exit(1);
        !           395:                        }
        !           396:                }
        !           397:                /*
        !           398:                 * if format unit byte count not specified, figure it out
        !           399:                 * so can adjust rep count later.
        !           400:                 */
        !           401:                if (!fu->bcnt)
        !           402:                        for (pr = fu->nextpr; pr; pr = pr->nextpr)
        !           403:                                fu->bcnt += pr->bcnt;
        !           404:        }
        !           405:        /*
        !           406:         * if the format string interprets any data at all, and it's
        !           407:         * not the same as the blocksize, and its last format unit
        !           408:         * interprets any data at all, and has no iteration count,
        !           409:         * repeat it as necessary.
        !           410:         *
        !           411:         * if, rep count is greater than 1, no trailing whitespace
        !           412:         * gets output from the last iteration of the format unit.
        !           413:         */
        !           414:        for (fu = fs->nextfu;; fu = fu->nextfu) {
        !           415:                if (!fu->nextfu && fs->bcnt < blocksize &&
        !           416:                    !(fu->flags&F_SETREP) && fu->bcnt)
        !           417:                        fu->reps += (blocksize - fs->bcnt) / fu->bcnt;
        !           418:                if (fu->reps > 1) {
        !           419:                        for (pr = fu->nextpr;; pr = pr->nextpr)
        !           420:                                if (!pr->nextpr)
        !           421:                                        break;
        !           422:                        for (p1 = pr->fmt, p2 = NULL; *p1; ++p1)
        !           423:                                p2 = isspace(*p1) ? p1 : NULL;
        !           424:                        if (p2)
        !           425:                                pr->nospace = p2;
        !           426:                }
        !           427:                if (!fu->nextfu)
        !           428:                        break;
        !           429:        }
        !           430: }
        !           431: 
        !           432: 
        !           433: escape(p1)
        !           434:        register char *p1;
        !           435: {
        !           436:        register char *p2;
        !           437: 
        !           438:        /* alphabetic escape sequences have to be done in place */
        !           439:        for (p2 = p1;; ++p1, ++p2) {
        !           440:                if (!*p1) {
        !           441:                        *p2 = *p1;
        !           442:                        break;
        !           443:                }
        !           444:                if (*p1 == '\\')
        !           445:                        switch(*++p1) {
        !           446:                        case 'a':
        !           447:                             /* *p2 = '\a'; */
        !           448:                                *p2 = '\007';
        !           449:                                break;
        !           450:                        case 'b':
        !           451:                                *p2 = '\b';
        !           452:                                break;
        !           453:                        case 'f':
        !           454:                                *p2 = '\f';
        !           455:                                break;
        !           456:                        case 'n':
        !           457:                                *p2 = '\n';
        !           458:                                break;
        !           459:                        case 'r':
        !           460:                                *p2 = '\r';
        !           461:                                break;
        !           462:                        case 't':
        !           463:                                *p2 = '\t';
        !           464:                                break;
        !           465:                        case 'v':
        !           466:                                *p2 = '\v';
        !           467:                                break;
        !           468:                        default:
        !           469:                                *p2 = *p1;
        !           470:                                break;
        !           471:                        }
        !           472:        }
        !           473: }
        !           474: 
        !           475: badcnt(s)
        !           476:        char *s;
        !           477: {
        !           478:        (void)fprintf(stderr,
        !           479:            "hexdump: bad byte count for conversion character %s.\n", s);
        !           480:        exit(1);
        !           481: }
        !           482: 
        !           483: badsfmt()
        !           484: {
        !           485:        (void)fprintf(stderr,
        !           486:            "hexdump: %%s requires a precision or a byte count.\n");
        !           487:        exit(1);
        !           488: }
        !           489: 
        !           490: badfmt(fmt)
        !           491:        char *fmt;
        !           492: {
        !           493:        (void)fprintf(stderr, "hexdump: bad format {%s}\n", fmt);
        !           494:        exit(1);
        !           495: }
        !           496: 
        !           497: badconv(ch)
        !           498:        char *ch;
        !           499: {
        !           500:        (void)fprintf(stderr, "hexdump: bad conversion character %%%s.\n", ch);
        !           501:        exit(1);
        !           502: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.