summaryrefslogtreecommitdiff
path: root/usr.bin/hexdump/parse.c
diff options
context:
space:
mode:
authorPeter Valchev <pvalchev@cvs.openbsd.org>2001-12-30 08:17:33 +0000
committerPeter Valchev <pvalchev@cvs.openbsd.org>2001-12-30 08:17:33 +0000
commitd5d19f2d773d90fe05e2a93c2878ece3b2a4a7fc (patch)
treeeabe05d107d7761a7d3ce8ea9f04236ef4a93b64 /usr.bin/hexdump/parse.c
parent80376a6f4b8ec8fa3670cc0fade14a38c69d5a10 (diff)
Changes come from NetBSD, Lite-2 and me. ok deraadt
od(1): - Enable support for printing 8-byte integers. - Added -C option for hexadecimal+ASCII display. - Fix od so it displays short files containing nulls. - POSIXification: The C, S, I and L modifiers now behave correctly, specifying output in units of a char, short, int and long (as defined by the host system) respectively. Support -N, equivalent to hexdump's -n (format only COUNT bytes of input). Add -j option which does the same thing as -s in hexdump (skipping some of the input). hexdump(1): - POSIX.2 doesn't specify hexdump so it can't be compatible with it... - add missing trailing \n in usage() printf
Diffstat (limited to 'usr.bin/hexdump/parse.c')
-rw-r--r--usr.bin/hexdump/parse.c257
1 files changed, 143 insertions, 114 deletions
diff --git a/usr.bin/hexdump/parse.c b/usr.bin/hexdump/parse.c
index af4144820a9..e3198ab99bb 100644
--- a/usr.bin/hexdump/parse.c
+++ b/usr.bin/hexdump/parse.c
@@ -1,8 +1,9 @@
-/* $OpenBSD: parse.c,v 1.8 2001/11/19 19:02:14 mpech Exp $ */
+/* $OpenBSD: parse.c,v 1.9 2001/12/30 08:17:32 pvalchev Exp $ */
+/* $NetBSD: parse.c,v 1.12 2001/12/07 13:37:39 bjh21 Exp $ */
/*
- * Copyright (c) 1989 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,23 +36,21 @@
#ifndef lint
/*static char sccsid[] = "from: @(#)parse.c 5.6 (Berkeley) 3/9/91";*/
-static char rcsid[] = "$OpenBSD: parse.c,v 1.8 2001/11/19 19:02:14 mpech Exp $";
+static char rcsid[] = "$OpenBSD: parse.c,v 1.9 2001/12/30 08:17:32 pvalchev Exp $";
#endif /* not lint */
#include <sys/types.h>
#include <sys/file.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
-#include <ctype.h>
#include <string.h>
-#include <err.h>
-#include "hexdump.h"
-void addfile __P((char *));
-void add __P((char *));
-int size __P((FS *));
-void rewrite __P((FS *));
-void escape __P((char *));
+#include "hexdump.h"
FU *endfu; /* format at end-of-data */
@@ -61,18 +60,19 @@ addfile(name)
{
char *p;
FILE *fp;
- size_t len;
-
- if (!(fp = fopen(name, "r")))
- err(1, "%s", name);
- while ((p = fgetln(fp, &len))) {
- if (*(p + len - 1) == '\n')
- *(p + len - 1) = '\0';
- else {
- warnx("incomplete line");
+ int ch;
+ char buf[2048 + 1];
+
+ if ((fp = fopen(name, "r")) == NULL)
+ err(1, "fopen %s", name);
+ while (fgets(buf, sizeof(buf), fp)) {
+ if (!(p = strchr(buf, '\n'))) {
+ warnx("line too long.");
+ while ((ch = getchar()) != '\n' && ch != EOF);
continue;
}
- for (; *p && isspace(*p); ++p);
+ *p = '\0';
+ for (p = buf; *p && isspace((unsigned char)*p); ++p);
if (!*p || *p == '#')
continue;
add(p);
@@ -82,17 +82,16 @@ addfile(name)
void
add(fmt)
- char *fmt;
+ const char *fmt;
{
- char *p;
+ const char *p;
static FS **nextfs;
FS *tfs;
FU *tfu, **nextfu;
- char *savep, *emalloc();
+ const char *savep;
/* start new linked list of format units */
- /* NOSTRICT */
- tfs = (FS *)emalloc(sizeof(FS));
+ tfs = emalloc(sizeof(FS));
if (!fshead)
fshead = tfs;
else
@@ -103,62 +102,59 @@ add(fmt)
/* take the format string and break it up into format units */
for (p = fmt;;) {
/* skip leading white space */
- for (; isspace(*p); ++p);
+ for (; isspace((unsigned char)*p); ++p);
if (!*p)
break;
/* allocate a new format unit and link it in */
- /* NOSTRICT */
- tfu = (FU *)emalloc(sizeof(FU));
+ tfu = emalloc(sizeof(FU));
*nextfu = tfu;
nextfu = &tfu->nextfu;
tfu->reps = 1;
/* if leading digit, repetition count */
- if (isdigit(*p)) {
- for (savep = p; isdigit(*p); ++p);
- if (!isspace(*p) && *p != '/')
- errx(1, "bad format {%s}", fmt);
+ if (isdigit((unsigned char)*p)) {
+ for (savep = p; isdigit((unsigned char)*p); ++p);
+ if (!isspace((unsigned char)*p) && *p != '/')
+ badfmt(fmt);
/* may overwrite either white space or slash */
tfu->reps = atoi(savep);
tfu->flags = F_SETREP;
/* skip trailing white space */
- for (++p; isspace(*p); ++p);
+ for (++p; isspace((unsigned char)*p); ++p);
}
/* skip slash and trailing white space */
if (*p == '/')
- while (isspace(*++p));
+ while (isspace((unsigned char)*++p));
/* byte count */
- if (isdigit(*p)) {
- for (savep = p; isdigit(*p); ++p);
- if (!isspace(*p))
- errx(1, "bad format {%s}", fmt);
+ if (isdigit((unsigned char)*p)) {
+ for (savep = p; isdigit((unsigned char)*p); ++p);
+ if (!isspace((unsigned char)*p))
+ badfmt(fmt);
tfu->bcnt = atoi(savep);
/* skip trailing white space */
- for (++p; isspace(*p); ++p);
+ for (++p; isspace((unsigned char)*p); ++p);
}
/* format */
if (*p != '"')
- errx(1, "bad format {%s}", fmt);
+ badfmt(fmt);
for (savep = ++p; *p != '"';)
if (*p++ == 0)
- errx(1, "bad format {%s}", fmt);
+ badfmt(fmt);
if (!(tfu->fmt = malloc(p - savep + 1)))
- err(1, "malloc");
+ nomem();
(void) strncpy(tfu->fmt, savep, p - savep);
tfu->fmt[p - savep] = '\0';
escape(tfu->fmt);
p++;
}
- /* no single fu in fmt */
- if (tfs->nextfu == NULL)
- errx(1, "bad format {%s}", fmt);
}
static const char *spec = ".#-+ 0123456789";
+
int
size(fs)
FS *fs;
@@ -182,9 +178,9 @@ size(fs)
* case it's a %s format.
*/
while (strchr(spec + 1, *++fmt));
- if (*fmt == '.' && isdigit(*++fmt)) {
+ if (*fmt == '.' && isdigit((unsigned char)*++fmt)) {
prec = atoi(fmt);
- while (isdigit(*++fmt));
+ while (isdigit((unsigned char)*++fmt));
}
switch(*fmt) {
case 'c':
@@ -210,7 +206,7 @@ size(fs)
}
cursize += bcnt * fu->reps;
}
- return(cursize);
+ return (cursize);
}
void
@@ -221,26 +217,27 @@ rewrite(fs)
PR *pr, **nextpr;
FU *fu;
char *p1, *p2;
- char savech, *fmtp;
+ char savech, *fmtp, cs[3];
int nconv, prec;
+ nextpr = NULL;
+ prec = 0;
for (fu = fs->nextfu; fu; fu = fu->nextfu) {
/*
- * break each format unit into print units; each
- * conversion character gets its own.
+ * Break each format unit into print units; each conversion
+ * character gets its own.
*/
for (nconv = 0, fmtp = fu->fmt; *fmtp; nextpr = &pr->nextpr) {
- /* NOSTRICT */
- pr = (PR *)emalloc(sizeof(PR));
+ pr = emalloc(sizeof(PR));
if (!fu->nextpr)
fu->nextpr = pr;
else
*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);
- /* only text in the string */
+ /* Only text in the string. */
if (!*p1) {
pr->fmt = fmtp;
pr->flags = F_TEXT;
@@ -248,33 +245,36 @@ rewrite(fs)
}
/*
- * get precision for %s -- if have a byte count, don't
+ * Get precision for %s -- if have a byte count, don't
* need it.
*/
if (fu->bcnt) {
sokay = USEBCNT;
- /* skip to conversion character */
+ /* Skip to conversion character. */
for (++p1; strchr(spec, *p1); ++p1);
} else {
- /* skip any special chars, field width */
+ /* Skip any special chars, field width. */
while (strchr(spec + 1, *++p1));
- if (*p1 == '.' && isdigit(*++p1)) {
+ if (*p1 == '.' &&
+ isdigit((unsigned char)*++p1)) {
sokay = USEPREC;
prec = atoi(p1);
- while (isdigit(*++p1));
- }
- else
+ while (isdigit((unsigned char)*++p1))
+ continue;
+ } else
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-
* padding for end of data.
*/
- switch(*p1) {
+ switch(cs[0]) {
case 'c':
pr->flags = F_CHAR;
switch(fu->bcnt) {
@@ -282,31 +282,19 @@ rewrite(fs)
pr->bcnt = 1;
break;
default:
- errx(1, "bad byte count for conversion character \'%c\'", *p1);
+ p1[1] = '\0';
+ badcnt(p1);
}
break;
case 'd': case 'i':
pr->flags = F_INT;
- goto sw1;
- 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 */
+ goto isint;
case 'o': case 'u': case 'x': case 'X':
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:
pr->bcnt = 4;
break;
@@ -316,8 +304,12 @@ sw1: switch(fu->bcnt) {
case 2:
pr->bcnt = 2;
break;
+ case 8:
+ pr->bcnt = 8;
+ break;
default:
- errx(1, "bad byte count for conversion character \'%c\'", *p1);
+ p1[1] = '\0';
+ badcnt(p1);
}
break;
case 'e': case 'E': case 'f': case 'g': case 'G':
@@ -330,14 +322,15 @@ sw1: switch(fu->bcnt) {
pr->bcnt = 4;
break;
default:
- errx(1, "bad byte count for conversion character \'%c\'", *p1);
+ p1[1] = '\0';
+ badcnt(p1);
}
break;
case 's':
pr->flags = F_STR;
switch(sokay) {
case NOTOKAY:
- errx(1, "%%s requires a precision or a byte count");
+ badsfmt();
case USEBCNT:
pr->bcnt = fu->bcnt;
break;
@@ -358,62 +351,65 @@ sw1: switch(fu->bcnt) {
++p2;
switch(p1[2]) {
case 'd': case 'o': case'x':
- *p1 = 'q';
- p1[1] = p1[2];
+ cs[0] = 'q';
+ cs[1] = p1[2];
+ cs[2] = '\0';
break;
default:
p1[3] = '\0';
- errx(1, "bad conversion character %%%s", p1);
+ badconv(p1);
}
break;
case 'c':
pr->flags = F_C;
- /* *p1 = 'c'; set in conv_c */
- goto sw2;
+ /* cs[0] = 'c'; set in conv_c */
+ goto isint2;
case 'p':
pr->flags = F_P;
- *p1 = 'c';
- goto sw2;
+ cs[0] = 'c';
+ goto isint2;
case 'u':
pr->flags = F_U;
- /* *p1 = 'c'; set in conv_u */
-sw2: switch(fu->bcnt) {
+ /* cs[0] = 'c'; set in conv_u */
+isint2: switch(fu->bcnt) {
case 0: case 1:
pr->bcnt = 1;
break;
default:
p1[2] = '\0';
- errx(1, "bad byte count for conversion character \'%s\'", p1);
+ badcnt(p1);
}
break;
default:
p1[2] = '\0';
- errx(1, "bad conversion character %%%s", p1);
+ badconv(p1);
}
break;
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.
*/
savech = *p2;
- p1[(pr->flags&F_ADDRESS)?2:1] = '\0';
- if (!(pr->fmt = strdup(fmtp)))
- err(1, "malloc");
+ p1[0] = '\0';
+ pr->fmt = emalloc(strlen(fmtp) + strlen(cs) + 1);
+ (void)strcpy(pr->fmt, fmtp);
+ (void)strcat(pr->fmt, cs);
*p2 = savech;
pr->cchar = pr->fmt + (p1 - fmtp);
fmtp = p2;
- /* only one conversion character if byte count */
+ /* Only one conversion character if byte count. */
if (!(pr->flags&F_ADDRESS) && fu->bcnt && nconv++)
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.
*/
if (!fu->bcnt)
@@ -421,15 +417,15 @@ sw2: switch(fu->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
* interprets any data at all, and has no iteration count,
* 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.
*/
- for (fu = fs->nextfu;; fu = fu->nextfu) {
+ for (fu = fs->nextfu; fu; fu = fu->nextfu) {
if (!fu->nextfu && fs->bcnt < blocksize &&
!(fu->flags&F_SETREP) && fu->bcnt)
fu->reps += (blocksize - fs->bcnt) / fu->bcnt;
@@ -438,13 +434,19 @@ sw2: switch(fu->bcnt) {
if (!pr->nextpr)
break;
for (p1 = pr->fmt, p2 = NULL; *p1; ++p1)
- p2 = isspace(*p1) ? p1 : NULL;
+ p2 = isspace((unsigned char)*p1) ? p1 : NULL;
if (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
@@ -489,3 +491,30 @@ escape(p1)
}
}
}
+
+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);
+}