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

Diff for /src/usr.bin/hexdump/parse.c between version 1.8 and 1.9

version 1.8, 2001/11/19 19:02:14 version 1.9, 2001/12/30 08:17:32
Line 1 
Line 1 
 /*      $OpenBSD$       */  /*      $OpenBSD$       */
   /*      $NetBSD: parse.c,v 1.12 2001/12/07 13:37:39 bjh21 Exp $ */
   
 /*  /*
  * Copyright (c) 1989 The Regents of the University of California.   * Copyright (c) 1989, 1993
  * All rights reserved.   *      The Regents of the University of California.  All rights reserved.
  *   *
  * Redistribution and use in source and binary forms, with or without   * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions   * modification, are permitted provided that the following conditions
Line 40 
Line 41 
   
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/file.h>  #include <sys/file.h>
   
   #include <ctype.h>
   #include <err.h>
   #include <errno.h>
   #include <fcntl.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <ctype.h>  
 #include <string.h>  #include <string.h>
 #include <err.h>  
 #include "hexdump.h"  #include "hexdump.h"
   
 void addfile __P((char *));  
 void add __P((char *));  
 int size __P((FS *));  
 void rewrite __P((FS *));  
 void escape __P((char *));  
   
 FU *endfu;                                      /* format at end-of-data */  FU *endfu;                                      /* format at end-of-data */
   
 void  void
Line 61 
Line 60 
 {  {
         char *p;          char *p;
         FILE *fp;          FILE *fp;
         size_t len;          int ch;
           char buf[2048 + 1];
   
         if (!(fp = fopen(name, "r")))          if ((fp = fopen(name, "r")) == NULL)
                 err(1, "%s", name);                  err(1, "fopen %s", name);
         while ((p = fgetln(fp, &len))) {          while (fgets(buf, sizeof(buf), fp)) {
                 if (*(p + len - 1) == '\n')                  if (!(p = strchr(buf, '\n'))) {
                         *(p + len - 1) = '\0';                          warnx("line too long.");
                 else {                          while ((ch = getchar()) != '\n' && ch != EOF);
                         warnx("incomplete line");  
                         continue;                          continue;
                 }                  }
                 for (; *p && isspace(*p); ++p);                  *p = '\0';
                   for (p = buf; *p && isspace((unsigned char)*p); ++p);
                 if (!*p || *p == '#')                  if (!*p || *p == '#')
                         continue;                          continue;
                 add(p);                  add(p);
Line 82 
Line 82 
   
 void  void
 add(fmt)  add(fmt)
         char *fmt;          const char *fmt;
 {  {
         char *p;          const char *p;
         static FS **nextfs;          static FS **nextfs;
         FS *tfs;          FS *tfs;
         FU *tfu, **nextfu;          FU *tfu, **nextfu;
         char *savep, *emalloc();          const char *savep;
   
         /* start new linked list of format units */          /* start new linked list of format units */
         /* NOSTRICT */          tfs = emalloc(sizeof(FS));
         tfs = (FS *)emalloc(sizeof(FS));  
         if (!fshead)          if (!fshead)
                 fshead = tfs;                  fshead = tfs;
         else          else
Line 103 
Line 102 
         /* take the format string and break it up into format units */          /* take the format string and break it up into format units */
         for (p = fmt;;) {          for (p = fmt;;) {
                 /* skip leading white space */                  /* skip leading white space */
                 for (; isspace(*p); ++p);                  for (; isspace((unsigned char)*p); ++p);
                 if (!*p)                  if (!*p)
                         break;                          break;
   
                 /* allocate a new format unit and link it in */                  /* allocate a new format unit and link it in */
                 /* NOSTRICT */                  tfu = emalloc(sizeof(FU));
                 tfu = (FU *)emalloc(sizeof(FU));  
                 *nextfu = tfu;                  *nextfu = tfu;
                 nextfu = &tfu->nextfu;                  nextfu = &tfu->nextfu;
                 tfu->reps = 1;                  tfu->reps = 1;
   
                 /* if leading digit, repetition count */                  /* if leading digit, repetition count */
                 if (isdigit(*p)) {                  if (isdigit((unsigned char)*p)) {
                         for (savep = p; isdigit(*p); ++p);                          for (savep = p; isdigit((unsigned char)*p); ++p);
                         if (!isspace(*p) && *p != '/')                          if (!isspace((unsigned char)*p) && *p != '/')
                                 errx(1, "bad format {%s}", fmt);                                  badfmt(fmt);
                         /* may overwrite either white space or slash */                          /* may overwrite either white space or slash */
                         tfu->reps = atoi(savep);                          tfu->reps = atoi(savep);
                         tfu->flags = F_SETREP;                          tfu->flags = F_SETREP;
                         /* skip trailing white space */                          /* skip trailing white space */
                         for (++p; isspace(*p); ++p);                          for (++p; isspace((unsigned char)*p); ++p);
                 }                  }
   
                 /* skip slash and trailing white space */                  /* skip slash and trailing white space */
                 if (*p == '/')                  if (*p == '/')
                         while (isspace(*++p));                          while (isspace((unsigned char)*++p));
   
                 /* byte count */                  /* byte count */
                 if (isdigit(*p)) {                  if (isdigit((unsigned char)*p)) {
                         for (savep = p; isdigit(*p); ++p);                          for (savep = p; isdigit((unsigned char)*p); ++p);
                         if (!isspace(*p))                          if (!isspace((unsigned char)*p))
                                 errx(1, "bad format {%s}", fmt);                                  badfmt(fmt);
                         tfu->bcnt = atoi(savep);                          tfu->bcnt = atoi(savep);
                         /* skip trailing white space */                          /* skip trailing white space */
                         for (++p; isspace(*p); ++p);                          for (++p; isspace((unsigned char)*p); ++p);
                 }                  }
   
                 /* format */                  /* format */
                 if (*p != '"')                  if (*p != '"')
                         errx(1, "bad format {%s}", fmt);                          badfmt(fmt);
                 for (savep = ++p; *p != '"';)                  for (savep = ++p; *p != '"';)
                         if (*p++ == 0)                          if (*p++ == 0)
                                 errx(1, "bad format {%s}", fmt);                                  badfmt(fmt);
                 if (!(tfu->fmt = malloc(p - savep + 1)))                  if (!(tfu->fmt = malloc(p - savep + 1)))
                         err(1, "malloc");                          nomem();
                 (void) strncpy(tfu->fmt, savep, p - savep);                  (void) strncpy(tfu->fmt, savep, p - savep);
                 tfu->fmt[p - savep] = '\0';                  tfu->fmt[p - savep] = '\0';
                 escape(tfu->fmt);                  escape(tfu->fmt);
                 p++;                  p++;
         }          }
         /* no single fu in fmt */  
         if (tfs->nextfu == NULL)  
                 errx(1, "bad format {%s}", fmt);  
 }  }
   
 static const char *spec = ".#-+ 0123456789";  static const char *spec = ".#-+ 0123456789";
   
 int  int
 size(fs)  size(fs)
         FS *fs;          FS *fs;
Line 182 
Line 178 
                          * case it's a %s format.                           * case it's a %s format.
                          */                           */
                         while (strchr(spec + 1, *++fmt));                          while (strchr(spec + 1, *++fmt));
                         if (*fmt == '.' && isdigit(*++fmt)) {                          if (*fmt == '.' && isdigit((unsigned char)*++fmt)) {
                                 prec = atoi(fmt);                                  prec = atoi(fmt);
                                 while (isdigit(*++fmt));                                  while (isdigit((unsigned char)*++fmt));
                         }                          }
                         switch(*fmt) {                          switch(*fmt) {
                         case 'c':                          case 'c':
Line 210 
Line 206 
                 }                  }
                 cursize += bcnt * fu->reps;                  cursize += bcnt * fu->reps;
         }          }
         return(cursize);          return (cursize);
 }  }
   
 void  void
Line 221 
Line 217 
         PR *pr, **nextpr;          PR *pr, **nextpr;
         FU *fu;          FU *fu;
         char *p1, *p2;          char *p1, *p2;
         char savech, *fmtp;          char savech, *fmtp, cs[3];
         int nconv, prec;          int nconv, prec;
   
           nextpr = NULL;
           prec = 0;
         for (fu = fs->nextfu; fu; fu = fu->nextfu) {          for (fu = fs->nextfu; fu; fu = fu->nextfu) {
                 /*                  /*
                  * break each format unit into print units; each                   * Break each format unit into print units; each conversion
                  * conversion character gets its own.                   * character gets its own.
                  */                   */
                 for (nconv = 0, fmtp = fu->fmt; *fmtp; nextpr = &pr->nextpr) {                  for (nconv = 0, fmtp = fu->fmt; *fmtp; nextpr = &pr->nextpr) {
                         /* NOSTRICT */                          pr = emalloc(sizeof(PR));
                         pr = (PR *)emalloc(sizeof(PR));  
                         if (!fu->nextpr)                          if (!fu->nextpr)
                                 fu->nextpr = pr;                                  fu->nextpr = pr;
                         else                          else
                                 *nextpr = pr;                                  *nextpr = pr;
   
                         /* skip preceding text and up to the next % sign */                          /* Skip preceding text and up to the next % sign. */
                         for (p1 = fmtp; *p1 && *p1 != '%'; ++p1);                          for (p1 = fmtp; *p1 && *p1 != '%'; ++p1);
   
                         /* only text in the string */                          /* Only text in the string. */
                         if (!*p1) {                          if (!*p1) {
                                 pr->fmt = fmtp;                                  pr->fmt = fmtp;
                                 pr->flags = F_TEXT;                                  pr->flags = F_TEXT;
Line 248 
Line 245 
                         }                          }
   
                         /*                          /*
                          * get precision for %s -- if have a byte count, don't                           * Get precision for %s -- if have a byte count, don't
                          * need it.                           * need it.
                          */                           */
                         if (fu->bcnt) {                          if (fu->bcnt) {
                                 sokay = USEBCNT;                                  sokay = USEBCNT;
                                 /* skip to conversion character */                                  /* Skip to conversion character. */
                                 for (++p1; strchr(spec, *p1); ++p1);                                  for (++p1; strchr(spec, *p1); ++p1);
                         } else {                          } else {
                                 /* skip any special chars, field width */                                  /* Skip any special chars, field width. */
                                 while (strchr(spec + 1, *++p1));                                  while (strchr(spec + 1, *++p1));
                                 if (*p1 == '.' && isdigit(*++p1)) {                                  if (*p1 == '.' &&
                                       isdigit((unsigned char)*++p1)) {
                                         sokay = USEPREC;                                          sokay = USEPREC;
                                         prec = atoi(p1);                                          prec = atoi(p1);
                                         while (isdigit(*++p1));                                          while (isdigit((unsigned char)*++p1))
                                 }                                                  continue;
                                 else                                  } else
                                         sokay = NOTOKAY;                                          sokay = NOTOKAY;
                         }                          }
   
                         p2 = p1 + 1;            /* set end pointer */                          p2 = p1 + 1;            /* Set end pointer. */
                           cs[0] = *p1;            /* Set conversion string. */
                           cs[1] = '\0';
   
                         /*                          /*
                          * figure out the byte count for each conversion;                           * Figure out the byte count for each conversion;
                          * rewrite the format as necessary, set up blank-                           * rewrite the format as necessary, set up blank-
                          * padding for end of data.                           * padding for end of data.
                          */                           */
                         switch(*p1) {                          switch(cs[0]) {
                         case 'c':                          case 'c':
                                 pr->flags = F_CHAR;                                  pr->flags = F_CHAR;
                                 switch(fu->bcnt) {                                  switch(fu->bcnt) {
Line 282 
Line 282 
                                         pr->bcnt = 1;                                          pr->bcnt = 1;
                                         break;                                          break;
                                 default:                                  default:
                                         errx(1, "bad byte count for conversion character \'%c\'", *p1);                                          p1[1] = '\0';
                                           badcnt(p1);
                                 }                                  }
                                 break;                                  break;
                         case 'd': case 'i':                          case 'd': case 'i':
                                 pr->flags = F_INT;                                  pr->flags = F_INT;
                                 goto sw1;                                  goto isint;
                         case 'l':  
                                 ++p2;  
                                 switch(p1[1]) {  
                                 case 'd': case 'i':  
                                         ++p1;  
                                         pr->flags = F_INT;  
                                         goto sw1;  
                                 case 'o': case 'u': case 'x': case 'X':  
                                         ++p1;  
                                         pr->flags = F_UINT;  
                                         goto sw1;  
                                 default:  
                                         p1[2] = '\0';  
                                         errx(1, "bad conversion character %%%s", p1);  
                                 }  
                                 /* NOTREACHED */  
                         case 'o': case 'u': case 'x': case 'X':                          case 'o': case 'u': case 'x': case 'X':
                                 pr->flags = F_UINT;                                  pr->flags = F_UINT;
 sw1:                            switch(fu->bcnt) {  isint:                          cs[2] = '\0';
                                   cs[1] = cs[0];
                                   cs[0] = 'q';
                                   switch(fu->bcnt) {
                                 case 0: case 4:                                  case 0: case 4:
                                         pr->bcnt = 4;                                          pr->bcnt = 4;
                                         break;                                          break;
Line 316 
Line 304 
                                 case 2:                                  case 2:
                                         pr->bcnt = 2;                                          pr->bcnt = 2;
                                         break;                                          break;
                                   case 8:
                                           pr->bcnt = 8;
                                           break;
                                 default:                                  default:
                                         errx(1, "bad byte count for conversion character \'%c\'", *p1);                                          p1[1] = '\0';
                                           badcnt(p1);
                                 }                                  }
                                 break;                                  break;
                         case 'e': case 'E': case 'f': case 'g': case 'G':                          case 'e': case 'E': case 'f': case 'g': case 'G':
Line 330 
Line 322 
                                         pr->bcnt = 4;                                          pr->bcnt = 4;
                                         break;                                          break;
                                 default:                                  default:
                                         errx(1, "bad byte count for conversion character \'%c\'", *p1);                                          p1[1] = '\0';
                                           badcnt(p1);
                                 }                                  }
                                 break;                                  break;
                         case 's':                          case 's':
                                 pr->flags = F_STR;                                  pr->flags = F_STR;
                                 switch(sokay) {                                  switch(sokay) {
                                 case NOTOKAY:                                  case NOTOKAY:
                                         errx(1, "%%s requires a precision or a byte count");                                          badsfmt();
                                 case USEBCNT:                                  case USEBCNT:
                                         pr->bcnt = fu->bcnt;                                          pr->bcnt = fu->bcnt;
                                         break;                                          break;
Line 358 
Line 351 
                                         ++p2;                                          ++p2;
                                         switch(p1[2]) {                                          switch(p1[2]) {
                                         case 'd': case 'o': case'x':                                          case 'd': case 'o': case'x':
                                                 *p1 = 'q';                                                  cs[0] = 'q';
                                                 p1[1] = p1[2];                                                  cs[1] = p1[2];
                                                   cs[2] = '\0';
                                                 break;                                                  break;
                                         default:                                          default:
                                                 p1[3] = '\0';                                                  p1[3] = '\0';
                                                 errx(1, "bad conversion character %%%s", p1);                                                  badconv(p1);
                                         }                                          }
                                         break;                                          break;
                                 case 'c':                                  case 'c':
                                         pr->flags = F_C;                                          pr->flags = F_C;
                                         /* *p1 = 'c';   set in conv_c */                                          /* cs[0] = 'c'; set in conv_c */
                                         goto sw2;                                          goto isint2;
                                 case 'p':                                  case 'p':
                                         pr->flags = F_P;                                          pr->flags = F_P;
                                         *p1 = 'c';                                          cs[0] = 'c';
                                         goto sw2;                                          goto isint2;
                                 case 'u':                                  case 'u':
                                         pr->flags = F_U;                                          pr->flags = F_U;
                                         /* *p1 = 'c';   set in conv_u */                                          /* cs[0] = 'c'; set in conv_u */
 sw2:                                    switch(fu->bcnt) {  isint2:                                 switch(fu->bcnt) {
                                         case 0: case 1:                                          case 0: case 1:
                                                 pr->bcnt = 1;                                                  pr->bcnt = 1;
                                                 break;                                                  break;
                                         default:                                          default:
                                                 p1[2] = '\0';                                                  p1[2] = '\0';
                                                 errx(1, "bad byte count for conversion character \'%s\'", p1);                                                  badcnt(p1);
                                         }                                          }
                                         break;                                          break;
                                 default:                                  default:
                                         p1[2] = '\0';                                          p1[2] = '\0';
                                         errx(1, "bad conversion character %%%s", p1);                                          badconv(p1);
                                 }                                  }
                                 break;                                  break;
                         default:                          default:
                                 errx(1, "bad conversion character %%%c", *p1);                                  p1[1] = '\0';
                                   badconv(p1);
                         }                          }
   
                         /*                          /*
                          * copy to PR format string, set conversion character                           * Copy to PR format string, set conversion character
                          * pointer, update original.                           * pointer, update original.
                          */                           */
                         savech = *p2;                          savech = *p2;
                         p1[(pr->flags&F_ADDRESS)?2:1] = '\0';                          p1[0] = '\0';
                         if (!(pr->fmt = strdup(fmtp)))                          pr->fmt = emalloc(strlen(fmtp) + strlen(cs) + 1);
                                 err(1, "malloc");                          (void)strcpy(pr->fmt, fmtp);
                           (void)strcat(pr->fmt, cs);
                         *p2 = savech;                          *p2 = savech;
                         pr->cchar = pr->fmt + (p1 - fmtp);                          pr->cchar = pr->fmt + (p1 - fmtp);
                         fmtp = p2;                          fmtp = p2;
   
                         /* only one conversion character if byte count */                          /* Only one conversion character if byte count. */
                         if (!(pr->flags&F_ADDRESS) && fu->bcnt && nconv++)                          if (!(pr->flags&F_ADDRESS) && fu->bcnt && nconv++)
                                 errx(1,                                  errx(1,
                                     "byte count with multiple conversion characters");                              "byte count with multiple conversion characters");
                 }                  }
                 /*                  /*
                  * if format unit byte count not specified, figure it out                   * If format unit byte count not specified, figure it out
                  * so can adjust rep count later.                   * so can adjust rep count later.
                  */                   */
                 if (!fu->bcnt)                  if (!fu->bcnt)
Line 421 
Line 417 
                                 fu->bcnt += pr->bcnt;                                  fu->bcnt += pr->bcnt;
         }          }
         /*          /*
          * if the format string interprets any data at all, and it's           * If the format string interprets any data at all, and it's
          * not the same as the blocksize, and its last format unit           * not the same as the blocksize, and its last format unit
          * interprets any data at all, and has no iteration count,           * interprets any data at all, and has no iteration count,
          * repeat it as necessary.           * repeat it as necessary.
          *           *
          * if, rep count is greater than 1, no trailing whitespace           * If, rep count is greater than 1, no trailing whitespace
          * gets output from the last iteration of the format unit.           * gets output from the last iteration of the format unit.
          */           */
         for (fu = fs->nextfu;; fu = fu->nextfu) {          for (fu = fs->nextfu; fu; fu = fu->nextfu) {
                 if (!fu->nextfu && fs->bcnt < blocksize &&                  if (!fu->nextfu && fs->bcnt < blocksize &&
                     !(fu->flags&F_SETREP) && fu->bcnt)                      !(fu->flags&F_SETREP) && fu->bcnt)
                         fu->reps += (blocksize - fs->bcnt) / fu->bcnt;                          fu->reps += (blocksize - fs->bcnt) / fu->bcnt;
Line 438 
Line 434 
                                 if (!pr->nextpr)                                  if (!pr->nextpr)
                                         break;                                          break;
                         for (p1 = pr->fmt, p2 = NULL; *p1; ++p1)                          for (p1 = pr->fmt, p2 = NULL; *p1; ++p1)
                                 p2 = isspace(*p1) ? p1 : NULL;                                  p2 = isspace((unsigned char)*p1) ? p1 : NULL;
                         if (p2)                          if (p2)
                                 pr->nospace = p2;                                  pr->nospace = p2;
                 }                  }
                 if (!fu->nextfu)  
                         break;  
         }          }
   #ifdef DEBUG
           for (fu = fs->nextfu; fu; fu = fu->nextfu) {
                   (void)printf("fmt:");
                   for (pr = fu->nextpr; pr; pr = pr->nextpr)
                           (void)printf(" {%s}", pr->fmt);
                   (void)printf("\n");
           }
   #endif
 }  }
   
 void  void
Line 488 
Line 490 
                                 break;                                  break;
                         }                          }
         }          }
   }
   
   void
   badcnt(s)
           char *s;
   {
           errx(1, "%s: bad byte count", s);
   }
   
   void
   badsfmt()
   {
           errx(1, "%%s: requires a precision or a byte count\n");
   }
   
   void
   badfmt(fmt)
           const char *fmt;
   {
           errx(1, "\"%s\": bad format\n", fmt);
   }
   
   void
   badconv(ch)
           char *ch;
   {
           errx(1, "%%%s: bad conversion character\n", ch);
 }  }

Legend:
Removed from v.1.8  
changed lines
  Added in v.1.9