# 2.11BSD#431 - /usr/src/new/PORT/hexdump/parse.c

##### Functions

    add               X
    addfile           X
    badcnt            X
    badconv           X
    badfmt            X
    badsfmt           X
    escape            X
    rewrite           X
    size              X

##### Variables

    endfu             X

       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: }

#### Defined functions

add defined in line 60; used 68 times

- in line 55
- in /usr/src/new/PORT/hexdump/hexsyntax.c line 45-57(7), 70-71(2), 95-96(2), 104-105(2)
- in /usr/src/new/PORT/hexdump/odsyntax.c line 48-129(40), 135-155(12), 176-177(2)

addfile defined in line 33; used 1 times

- in /usr/src/new/PORT/hexdump/hexsyntax.c line 60

badcnt defined in line 475; used 4 times

- in line 263, 299, 313, 365

badconv defined in line 497; used 4 times

- in line 282, 345, 370-375(2)

badfmt defined in line 490; used 4 times

- in line 97, 116, 127-130(2)

badsfmt defined in line 483; used 1 times

- in line 320

escape defined in line 433; used 1 times

- in line 135

rewrite defined in line 194; used 1 times

- in /usr/src/new/PORT/hexdump/hexdump.c line 60

size defined in line 141; used 1 times

- in /usr/src/new/PORT/hexdump/hexdump.c line 54

#### Defined variables

endfu defined in line 31; used 1 times

- in line 333

sccsid defined in line 21; never used
spec defined in line 140; used 3 times

- in line 162, 234-237(2)

Last modified: 1990-06-02 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1963 |