From owner-freebsd-standards Fri Apr 5 3:21:30 2002 Delivered-To: freebsd-standards@hub.freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id D5B7537B41A for ; Fri, 5 Apr 2002 03:20:03 -0800 (PST) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.6/8.11.6) id g35BK3o49220; Fri, 5 Apr 2002 03:20:03 -0800 (PST) (envelope-from gnats) Received: from treetop.robbins.dropbear.id.au (104.a.010.mel.iprimus.net.au [210.50.200.104]) by hub.freebsd.org (Postfix) with ESMTP id 2A54A37B404 for ; Fri, 5 Apr 2002 03:17:23 -0800 (PST) Received: from treetop.robbins.dropbear.id.au (localhost [127.0.0.1]) by treetop.robbins.dropbear.id.au (8.12.2/8.12.2) with ESMTP id g35BDfSu002186 for ; Fri, 5 Apr 2002 21:13:41 +1000 (EST) (envelope-from tim@treetop.robbins.dropbear.id.au) Received: (from tim@localhost) by treetop.robbins.dropbear.id.au (8.12.2/8.12.2/Submit) id g35BDdRZ002185; Fri, 5 Apr 2002 21:13:39 +1000 (EST) Message-Id: <200204051113.g35BDdRZ002185@treetop.robbins.dropbear.id.au> Date: Fri, 5 Apr 2002 21:13:39 +1000 (EST) From: "Tim J. Robbins" Reply-To: "Tim J. Robbins" To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: standards/36783: P1003.1-2001 -s -A -j -N -t options for od(1) (patch) Sender: owner-freebsd-standards@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG >Number: 36783 >Category: standards >Synopsis: P1003.1-2001 -s -A -j -N -t options for od(1) (patch) >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-standards >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Fri Apr 05 03:20:03 PST 2002 >Closed-Date: >Last-Modified: >Originator: Tim J. Robbins >Release: FreeBSD 4.5-STABLE i386 >Organization: >Environment: System: FreeBSD treetop.robbins.dropbear.id.au 4.5-STABLE FreeBSD 4.5-STABLE #2: Sat Mar 30 20:10:51 EST 2002 tim@treetop.robbins.dropbear.id.au:/usr/obj/usr/src/sys/GENERIC i386 >Description: 4.4BSD's (and FreeBSD's) hexdump utility is missing the -s, -A, -j, -N, and -t options in its od compatibility mode. Here is a patch to add them. >How-To-Repeat: od -Ax -tx1 /dev/null >Fix: I've renamed the `deprecated' variable to `odmode' and removed everything to do with deprecation from the program and manual pages, added the -t option then rewritten all the other output-format options in terms of that. I've also written a manual page that is much more complete than the old one. long double output (-t fL) is not supported. This bug is documented in the new manual page. Adding support for long double would require changes all over the place, I thought it would be best to get it pretty close, then add long double support for hexdump, then od. Index: conv.c =================================================================== RCS file: /home/ncvs/src/usr.bin/hexdump/conv.c,v retrieving revision 1.3 diff -u -r1.3 conv.c --- conv.c 2002/03/07 23:00:27 1.3 +++ conv.c 2002/04/05 11:04:18 @@ -48,7 +48,6 @@ PR *pr; u_char *p; { - extern int deprecated; char buf[10]; char const *str; @@ -58,7 +57,7 @@ goto strpr; /* case '\a': */ case '\007': - if (deprecated) /* od didn't know about \a */ + if (odmode) /* od didn't know about \a */ break; str = "\\a"; goto strpr; @@ -78,7 +77,7 @@ str = "\\t"; goto strpr; case '\v': - if (deprecated) + if (odmode) break; str = "\\v"; goto strpr; @@ -101,7 +100,6 @@ PR *pr; u_char *p; { - extern int deprecated; static char const * list[] = { "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", "bs", "ht", "lf", "vt", "ff", "cr", "so", "si", @@ -112,14 +110,14 @@ /* od used nl, not lf */ if (*p <= 0x1f) { *pr->cchar = 's'; - if (deprecated && *p == 0x0a) + if (odmode && *p == 0x0a) (void)printf(pr->fmt, "nl"); else (void)printf(pr->fmt, list[*p]); } else if (*p == 0x7f) { *pr->cchar = 's'; (void)printf(pr->fmt, "del"); - } else if (deprecated && *p == 0x20) { /* od replaced space with sp */ + } else if (odmode && *p == 0x20) { /* od replaced space with sp */ *pr->cchar = 's'; (void)printf(pr->fmt, " sp"); } else if (isprint(*p)) { Index: display.c =================================================================== RCS file: /home/ncvs/src/usr.bin/hexdump/display.c,v retrieving revision 1.11 diff -u -r1.11 display.c --- display.c 2002/03/22 01:22:45 1.11 +++ display.c 2002/04/05 11:04:18 @@ -228,7 +228,6 @@ u_char * get() { - extern int length; static int ateof = 1; static u_char *curp, *savp; register int n; @@ -255,6 +254,8 @@ * block and set the end flag. */ if (!length || (ateof && !next((char **)NULL))) { + if (odmode && address < skip) + errx(1, "cannot skip past end of input"); if (need == blocksize) return((u_char *)NULL); if (vflag != ALL && @@ -298,8 +299,6 @@ nread += n; } } - -extern off_t skip; /* bytes to skip */ int next(argv) Index: hexdump.h =================================================================== RCS file: /home/ncvs/src/usr.bin/hexdump/hexdump.h,v retrieving revision 1.5 diff -u -r1.5 hexdump.h --- hexdump.h 2002/03/22 01:22:45 1.5 +++ hexdump.h 2002/04/05 11:04:19 @@ -73,6 +73,9 @@ extern FS *fshead; /* head of format strings list */ extern int blocksize; /* data block size */ +extern int odmode; /* are we acting as od(1)? */ +extern int length; /* amount of data to read */ +extern off_t skip; /* amount of data to skip at start */ enum _vflag { ALL, DUP, FIRST, WAIT }; /* -v values */ void add(const char *); Index: hexsyntax.c =================================================================== RCS file: /home/ncvs/src/usr.bin/hexdump/hexsyntax.c,v retrieving revision 1.9 diff -u -r1.9 hexsyntax.c --- hexsyntax.c 2001/09/01 22:42:46 1.9 +++ hexsyntax.c 2002/04/05 11:04:19 @@ -58,7 +58,6 @@ { extern enum _vflag vflag; extern FS *fshead; - extern int length; int ch; char *p, **argv; Index: od.1 =================================================================== RCS file: /home/ncvs/src/usr.bin/hexdump/od.1,v retrieving revision 1.10 diff -u -r1.10 od.1 --- od.1 2000/12/27 16:52:29 1.10 +++ od.1 2002/04/05 11:04:19 @@ -40,7 +40,11 @@ .Nd octal, decimal, hex, ASCII dump .Sh SYNOPSIS .Nm -.Op Fl aBbcDdeFfHhIiLlOovXx +.Op Fl aBbcDdeFfHhIiLlOosvXx +.Op Fl A Ar base +.Op Fl j Ar skip +.Op Fl N Ar length +.Op Fl t Ar type .Sm off .Oo .Op Cm \&+ @@ -51,33 +55,141 @@ .Sm on .Ar file .Sh DESCRIPTION -.Nm Od -has been deprecated in favor of -.Xr hexdump 1 . -.Pp -.Nm Hexdump , -if called as -.Nm , -provides compatibility for the options listed above. +The +.Nm +utility is a filter which displays the specified files, or standard +input if no files are specified, in a user specified format. .Pp -It does not provide compatibility for the -.Fl s -option (see -.Xr strings 1 ) -or the -.Fl P , -.Fl p , +The options are as follows: +.Bl -tag -width Fl +.It Fl A Ar base +Specify the input address base. +.Ar base +may be one of +.Ql d , +.Ql o , +.Ql x +or +.Ql n , +which specify decimal, octal, hexadecimal +addresses or no address, respectively. +.It Fl a +Equivalent to +.Fl t Ar a . +.It Fl B , Fl o +Equivalent to +.Fl t Ar o2 . +.It Fl b +Equivalent to +.Fl t Ar o1 . +.It Fl c +Equivalent to +.Fl t Ar c . +.It Fl D +Equivalent to +.Fl t Ar u4 . +.It Fl e , Fl F +Equivalent to +.Fl t Ar fD . +.It Fl f +Equivalent to +.Fl t Ar fF . +.It Fl H , Fl X +Equivalent to +.Fl t Ar x4 . +.It Fl h , Fl x +Equivalent to +.Fl t Ar x2 . +.It Fl I , Fl L , Fl l +Equivalent to +.Fl t Ar dL . +.It Fl i +Equivalent to +.Fl t Ar dI . +.It Fl j Ar skip +Skip +.Ar skip +bytes of the combined input before dumping. The number may be followed by one +of +.Ql b , +.Ql k +or +.Ql m +which specify the units of the number as blocks (512 bytes), kilobytes and +megabytes, respectively. +.It Fl N Ar length +Dump at most +.Ar length +bytes of input. +.It Fl O +Equivalent to +.Fl t Ar o4 . +.It Fl s +Equivalent to +.Fl t Ar d2 . +.It Fl t Ar type +Specify the output format. +.Ar type +is a string containing one or more of the following kinds of type specifiers: +.Bl -tag -width indent +.It Cm a +Named characters +.Pq Sq ASCII . +.It Cm c +Characters. +.It Cm [d|o|u|x][C|S|I|L| Ns Ar n Ns ] +Signed decimal +.Pq Ql d , +octal +.Pq Ql o , +unsigned decimal +.Pq Ql u +or +hexadecimal +.Pq Ql x . +Followed by an optional size specifier, which may be either +.Ql C Pq "char" , +.Ql S Pq "short" , +.Ql I Pq "int" , +.Ql L Pq "long" , +or a byte count as a decimal integer. +.It Cm f[F|D|L| Ns Ar n Ns ] +Floating-point number. +Followed by an optional size specifier, which may be either +.Ql F Pq "float" , +.Ql D Pq "double" or -.Fl w -options, nor is compatibility provided for the ``label'' component -of the offset syntax. +.Ql L Pq "long double" . +.El +.It Fl v +Write all input data, instead of replacing lines of duplicate values with a +.Ql * . +.El +.Pp +Multiple options that specify output format may be used; the output will +contain one line for each format. +.Pp +If no output format is specified, +.Fl t Ar oS +is assumed. +.Sh DIAGNOSTICS +.Ex -std .Sh SEE ALSO .Xr hexdump 1 , .Xr strings 1 -.Sh BUGS -Quite a few. +.Sh STANDARDS +The +.Nm +utility is expected to conform to +.St -p1003.1-2001 . .Sh HISTORY A .Nm command appeared in .At v1 . +.Sh BUGS +The +.Sq "long double" +data type, +.Fl t Ar fL , +is not supported. Index: odsyntax.c =================================================================== RCS file: /home/ncvs/src/usr.bin/hexdump/odsyntax.c,v retrieving revision 1.10 diff -u -r1.10 odsyntax.c --- odsyntax.c 2002/03/22 01:22:45 1.10 +++ odsyntax.c 2002/04/05 11:04:20 @@ -43,16 +43,20 @@ #include #include +#include #include #include #include #include "hexdump.h" -int deprecated; +#define PADDING " " +int odmode; + +static void odadd(const char *); +static void odformat(const char *); static void odoffset(int, char ***); -static void odprecede(void); void oldsyntax(argc, argvp) @@ -62,91 +66,110 @@ extern enum _vflag vflag; extern FS *fshead; int ch; - char **argv; + char **argv, *end; + + /* Add initial (default) address format. -A may change it later. */ +#define TYPE_OFFSET 7 + add("\"%07.7_Ao\n\""); + add("\"%07.7_ao \""); - deprecated = 1; + odmode = 1; argv = *argvp; - while ((ch = getopt(argc, argv, "aBbcDdeFfHhIiLlOoPpswvXx")) != -1) + while ((ch = getopt(argc, argv, "A:aBbcDdeFfHhIij:LlN:Oost:vXx")) != -1) switch (ch) { + case 'A': + switch (*optarg) { + case 'd': + case 'o': + case 'x': + fshead->nextfu->fmt[TYPE_OFFSET] = *optarg; + fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = *optarg; + break; + case 'n': + fshead->nextfu->fmt = ""; + fshead->nextfs->nextfu->fmt = PADDING; + break; + default: + errx(1, "%s: invalid address base", optarg); + } + break; case 'a': - odprecede(); - add("16/1 \"%3_u \" \"\\n\""); + odformat("a"); break; case 'B': case 'o': - odprecede(); - add("8/2 \" %06o \" \"\\n\""); + odformat("o2"); break; case 'b': - odprecede(); - add("16/1 \"%03o \" \"\\n\""); + odformat("o1"); break; case 'c': - odprecede(); - add("16/1 \"%3_c \" \"\\n\""); + odformat("c"); break; case 'd': - odprecede(); - add("8/2 \" %05u \" \"\\n\""); + odformat("u2"); break; case 'D': - odprecede(); - add("4/4 \" %010u \" \"\\n\""); + odformat("u4"); break; case 'e': /* undocumented in od */ case 'F': - odprecede(); - add("2/8 \" %21.14e \" \"\\n\""); + odformat("fD"); break; - case 'f': - odprecede(); - add("4/4 \" %14.7e \" \"\\n\""); + odformat("fF"); break; case 'H': case 'X': - odprecede(); - add("4/4 \" %08x \" \"\\n\""); + odformat("x4"); break; case 'h': case 'x': - odprecede(); - add("8/2 \" %04x \" \"\\n\""); + odformat("x2"); break; case 'I': case 'L': case 'l': - odprecede(); - add("4/4 \" %11d \" \"\\n\""); + odformat("dL"); break; case 'i': - odprecede(); - add("8/2 \" %6d \" \"\\n\""); + odformat("dI"); + break; + case 'j': + errno = 0; + skip = (off_t)strtoul(optarg, &end, 0); + if (*end == 'b') + skip *= 512; + else if (*end == 'k') + skip *= 1024; + else if (*end == 'm') + skip *= 1048576L; + if (errno != 0 || strlen(end) > 1) + errx(1, "%s: invalid skip amount", optarg); + break; + case 'N': + if ((length = atoi(optarg)) <= 0) + errx(1, "%s: invalid length", optarg); break; case 'O': - odprecede(); - add("4/4 \" %011o \" \"\\n\""); + odformat("o4"); + break; + case 's': + odformat("d2"); break; + case 't': + odformat(optarg); + break; case 'v': vflag = ALL; break; - case 'P': - case 'p': - case 's': - case 'w': case '?': default: - warnx("od(1) has been deprecated for hexdump(1)"); - if (ch != '?') - warnx("hexdump(1) compatibility doesn't support the -%c option%s", - ch, ch == 's' ? "; see strings(1)" : ""); usage(); } - if (!fshead) { - add("\"%07.7_Ao\n\""); - add("\"%07.7_ao \" 8/2 \"%06o \" \"\\n\""); - } + if (fshead->nextfs->nextfs == NULL) + odformat("oS"); argc -= optind; *argvp += optind; @@ -160,7 +183,6 @@ int argc; char ***argvp; { - extern off_t skip; unsigned char *p, *num, *end; int base; @@ -241,7 +263,6 @@ * If the offset uses a non-octal base, the base of the offset * is changed as well. This isn't pretty, but it's easy. */ -#define TYPE_OFFSET 7 if (base == 16) { fshead->nextfu->fmt[TYPE_OFFSET] = 'x'; fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x'; @@ -254,15 +275,127 @@ (*argvp)[1] = NULL; } +static void +odformat(const char *fmt) +{ + size_t size; + unsigned long long n; + int digits; + char *hdfmt, fchar, *end; + + while (*fmt != '\0') { + switch ((fchar = *fmt++)) { + case 'a': + odadd("16/1 \"%3_u \" \"\\n\""); + break; + case 'c': + odadd("16/1 \"%3_c \" \"\\n\""); + break; + case 'o': + case 'u': + case 'd': + case 'x': + size = sizeof(int); + switch (*fmt) { + case 'C': + size = sizeof(char); + fmt++; + break; + case 'I': + size = sizeof(int); + fmt++; + break; + case 'L': + size = sizeof(long); + fmt++; + break; + case 'S': + size = sizeof(short); + fmt++; + break; + default: + if (isdigit(*fmt)) { + errno = 0; + size = strtol(fmt, &end, 10); + if (errno != 0 || size <= 0) + errx(1, "bad size"); + if (size != sizeof(char) && + size != sizeof(short) && + size != sizeof(int) && + size != sizeof(long)) + errx(1, + "unsupported int size %ld", + size); + fmt = (const char *)end; + } + } + n = (1ULL << (8 * size)) - 1; + digits = 0; + while (n != 0) { + digits++; + n >>= (fchar == 'o' || fchar == 'd') ? 3 : 4; + } + asprintf(&hdfmt, "%d/%d \"%%%s%d%c \" \"\\n\"", + 16 / size, size, fchar == 'd' ? "" : "0", + digits, fchar); + if (hdfmt == NULL) + err(1, NULL); + odadd(hdfmt); + free(hdfmt); + break; + case 'f': + size = sizeof(double); + switch (*fmt) { + case 'F': + size = sizeof(float); + fmt++; + break; + case 'D': + size = sizeof(double); + fmt++; + break; + case 'L': + size = sizeof(long double); + fmt++; + break; + default: + if (isdigit(*fmt)) { + errno = 0; + size = strtol(fmt, &end, 10); + if (errno != 0 || size <= 0) + errx(1, "bad size"); + fmt = (const char *)end; + } + } + switch (size) { + case sizeof(float): + odadd("4/4 \" %14.7e \" \"\\n\""); + break; + case sizeof(double): + odadd("2/8 \" %21.14e \" \"\\n\""); + break; + case sizeof(long double): +#ifdef notyet + odadd("1/16 \" %21.14Le \" \"\\n\""); + break; +#endif + default: + errx(1, "unsupported FP size %ld", size); + } + break; + default: + errx(1, "%s: bad format", fmt); + } + } +} + static void -odprecede() +odadd(const char *fmt) { - static int first = 1; + static int needpad; - if (first) { - first = 0; - add("\"%07.7_Ao\n\""); - add("\"%07.7_ao \""); - } else - add("\" \""); + if (needpad) + add("\""PADDING"\""); + add(fmt); + needpad = 1; } >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-standards" in the body of the message