Date: Fri, 5 Apr 2002 21:13:39 +1000 (EST) From: "Tim J. Robbins" <tim@robbins.dropbear.id.au> To: FreeBSD-gnats-submit@FreeBSD.org Subject: standards/36783: P1003.1-2001 -s -A -j -N -t options for od(1) (patch) Message-ID: <200204051113.g35BDdRZ002185@treetop.robbins.dropbear.id.au>
next in thread | raw e-mail | index | archive | help
>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 <ctype.h>
#include <err.h>
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200204051113.g35BDdRZ002185>
