Import hexdump(1) from NetBSD
This commit is contained in:
parent
de231a713e
commit
c9d500e9fd
|
@ -41,4 +41,9 @@ SUBDIR+= atnormalize dosread fdisk loadfont \
|
|||
SUBDIR+= acd asmconv gas2ack
|
||||
.endif
|
||||
|
||||
# Build only with clang and GCC
|
||||
.if ${COMPILER_TYPE} == "gnu"
|
||||
SUBDIR+= hexdump
|
||||
.endif
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
|
15
commands/hexdump/Makefile
Normal file
15
commands/hexdump/Makefile
Normal file
|
@ -0,0 +1,15 @@
|
|||
# $NetBSD: Makefile,v 1.13 2009/04/14 22:15:21 lukem Exp $
|
||||
# from: @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
|
||||
PROG= hexdump
|
||||
SRCS= conv.c display.c hexdump.c hexsyntax.c odsyntax.c parse.c
|
||||
MAN= hexdump.1 #od.1
|
||||
|
||||
.ifndef HOSTPROG
|
||||
LDADD+=-lutil
|
||||
DPADD+=${LIBUTIL}
|
||||
|
||||
#LINKS= ${BINDIR}/hexdump ${BINDIR}/od
|
||||
.endif
|
||||
|
||||
.include <bsd.prog.mk>
|
134
commands/hexdump/conv.c
Normal file
134
commands/hexdump/conv.c
Normal file
|
@ -0,0 +1,134 @@
|
|||
/* $NetBSD: conv.c,v 1.13 2010/02/09 14:06:37 drochner Exp $ */
|
||||
|
||||
/*
|
||||
* 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
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if 0
|
||||
#if !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)conv.c 8.1 (Berkeley) 6/6/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: conv.c,v 1.13 2010/02/09 14:06:37 drochner Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "hexdump.h"
|
||||
|
||||
void
|
||||
conv_c(PR *pr, u_char *p)
|
||||
{
|
||||
char buf[10];
|
||||
char const *str;
|
||||
|
||||
switch(*p) {
|
||||
case '\0':
|
||||
str = "\\0";
|
||||
goto strpr;
|
||||
/* case '\a': */
|
||||
case '\007':
|
||||
if (odmode) /* od doesn't know about \a */
|
||||
break;
|
||||
str = "\\a";
|
||||
goto strpr;
|
||||
case '\b':
|
||||
str = "\\b";
|
||||
goto strpr;
|
||||
case '\f':
|
||||
str = "\\f";
|
||||
goto strpr;
|
||||
case '\n':
|
||||
str = "\\n";
|
||||
goto strpr;
|
||||
case '\r':
|
||||
str = "\\r";
|
||||
goto strpr;
|
||||
case '\t':
|
||||
str = "\\t";
|
||||
goto strpr;
|
||||
case '\v':
|
||||
if (odmode)
|
||||
break;
|
||||
str = "\\v";
|
||||
goto strpr;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (isprint(*p)) {
|
||||
*pr->cchar = 'c';
|
||||
(void)printf(pr->fmt, *p);
|
||||
} else {
|
||||
(void)sprintf(buf, "%03o", (int)*p);
|
||||
str = buf;
|
||||
strpr: *pr->cchar = 's';
|
||||
(void)printf(pr->fmt, str);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
conv_u(PR *pr, u_char *p)
|
||||
{
|
||||
static const char *list[] = {
|
||||
"nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
|
||||
"bs", "ht", "lf", "vt", "ff", "cr", "so", "si",
|
||||
"dle", "dcl", "dc2", "dc3", "dc4", "nak", "syn", "etb",
|
||||
"can", "em", "sub", "esc", "fs", "gs", "rs", "us",
|
||||
};
|
||||
|
||||
/* od used nl, not lf */
|
||||
if (*p <= 0x1f) {
|
||||
*pr->cchar = 's';
|
||||
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 (odmode && *p == 0x20) { /* od replaces space with sp */
|
||||
*pr->cchar = 's';
|
||||
(void)printf(pr->fmt, " sp");
|
||||
} else if (isprint(*p)) {
|
||||
*pr->cchar = 'c';
|
||||
(void)printf(pr->fmt, *p);
|
||||
} else {
|
||||
*pr->cchar = 'x';
|
||||
(void)printf(pr->fmt, (int)*p);
|
||||
}
|
||||
}
|
362
commands/hexdump/display.c
Normal file
362
commands/hexdump/display.c
Normal file
|
@ -0,0 +1,362 @@
|
|||
/* $NetBSD: display.c,v 1.21 2009/01/18 21:34:32 apb Exp $ */
|
||||
|
||||
/*
|
||||
* 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
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if 0
|
||||
#if !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)display.c 8.1 (Berkeley) 6/6/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: display.c,v 1.21 2009/01/18 21:34:32 apb Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <util.h>
|
||||
|
||||
#include "hexdump.h"
|
||||
|
||||
enum _vflag vflag = FIRST;
|
||||
|
||||
static off_t address; /* address/offset in stream */
|
||||
static off_t eaddress; /* end address */
|
||||
|
||||
static inline void print(PR *, u_char *);
|
||||
|
||||
void
|
||||
display(void)
|
||||
{
|
||||
FS *fs;
|
||||
FU *fu;
|
||||
PR *pr;
|
||||
int cnt;
|
||||
u_char *bp;
|
||||
off_t saveaddress;
|
||||
u_char savech, *savebp;
|
||||
|
||||
savech = 0;
|
||||
while ((bp = get()) != NULL)
|
||||
for (fs = fshead, savebp = bp, saveaddress = address; fs;
|
||||
fs = fs->nextfs, bp = savebp, address = saveaddress)
|
||||
for (fu = fs->nextfu; fu; fu = fu->nextfu) {
|
||||
if (fu->flags&F_IGNORE)
|
||||
break;
|
||||
for (cnt = fu->reps; cnt; --cnt)
|
||||
for (pr = fu->nextpr; pr; address += pr->bcnt,
|
||||
bp += pr->bcnt, pr = pr->nextpr) {
|
||||
if (eaddress && address >= eaddress &&
|
||||
!(pr->flags & (F_TEXT|F_BPAD)))
|
||||
bpad(pr);
|
||||
if (cnt == 1 && pr->nospace) {
|
||||
savech = *pr->nospace;
|
||||
*pr->nospace = '\0';
|
||||
}
|
||||
print(pr, bp);
|
||||
if (cnt == 1 && pr->nospace)
|
||||
*pr->nospace = savech;
|
||||
}
|
||||
}
|
||||
if (endfu) {
|
||||
/*
|
||||
* If eaddress not set, error or file size was multiple of
|
||||
* blocksize, and no partial block ever found.
|
||||
*/
|
||||
if (!eaddress) {
|
||||
if (!address)
|
||||
return;
|
||||
eaddress = address;
|
||||
}
|
||||
for (pr = endfu->nextpr; pr; pr = pr->nextpr)
|
||||
switch(pr->flags) {
|
||||
case F_ADDRESS:
|
||||
(void)printf(pr->fmt, (int64_t)eaddress);
|
||||
break;
|
||||
case F_TEXT:
|
||||
(void)printf("%s", pr->fmt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
print(PR *pr, u_char *bp)
|
||||
{
|
||||
double f8;
|
||||
float f4;
|
||||
int16_t s2;
|
||||
int32_t s4;
|
||||
int64_t s8;
|
||||
uint16_t u2;
|
||||
uint32_t u4;
|
||||
uint64_t u8;
|
||||
|
||||
switch(pr->flags) {
|
||||
case F_ADDRESS:
|
||||
(void)printf(pr->fmt, (int64_t)address);
|
||||
break;
|
||||
case F_BPAD:
|
||||
(void)printf(pr->fmt, "");
|
||||
break;
|
||||
case F_C:
|
||||
conv_c(pr, bp);
|
||||
break;
|
||||
case F_CHAR:
|
||||
(void)printf(pr->fmt, *bp);
|
||||
break;
|
||||
case F_DBL:
|
||||
switch(pr->bcnt) {
|
||||
case 4:
|
||||
memmove(&f4, bp, sizeof(f4));
|
||||
(void)printf(pr->fmt, f4);
|
||||
break;
|
||||
case 8:
|
||||
memmove(&f8, bp, sizeof(f8));
|
||||
(void)printf(pr->fmt, f8);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case F_INT:
|
||||
switch(pr->bcnt) {
|
||||
case 1:
|
||||
(void)printf(pr->fmt, (int64_t)*bp);
|
||||
break;
|
||||
case 2:
|
||||
memmove(&s2, bp, sizeof(s2));
|
||||
(void)printf(pr->fmt, (int64_t)s2);
|
||||
break;
|
||||
case 4:
|
||||
memmove(&s4, bp, sizeof(s4));
|
||||
(void)printf(pr->fmt, (int64_t)s4);
|
||||
break;
|
||||
case 8:
|
||||
memmove(&s8, bp, sizeof(s8));
|
||||
(void)printf(pr->fmt, (int64_t)s8);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case F_P:
|
||||
(void)printf(pr->fmt, isprint(*bp) ? *bp : '.');
|
||||
break;
|
||||
case F_STR:
|
||||
(void)printf(pr->fmt, (char *)bp);
|
||||
break;
|
||||
case F_TEXT:
|
||||
(void)printf("%s", pr->fmt);
|
||||
break;
|
||||
case F_U:
|
||||
conv_u(pr, bp);
|
||||
break;
|
||||
case F_UINT:
|
||||
switch(pr->bcnt) {
|
||||
case 1:
|
||||
(void)printf(pr->fmt, (uint64_t)*bp);
|
||||
break;
|
||||
case 2:
|
||||
memmove(&u2, bp, sizeof(u2));
|
||||
(void)printf(pr->fmt, (uint64_t)u2);
|
||||
break;
|
||||
case 4:
|
||||
memmove(&u4, bp, sizeof(u4));
|
||||
(void)printf(pr->fmt, (uint64_t)u4);
|
||||
break;
|
||||
case 8:
|
||||
memmove(&u8, bp, sizeof(u8));
|
||||
(void)printf(pr->fmt, (uint64_t)u8);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bpad(PR *pr)
|
||||
{
|
||||
static const char *spec = " -0+#";
|
||||
char *p1, *p2;
|
||||
|
||||
/*
|
||||
* Remove all conversion flags; '-' is the only one valid
|
||||
* with %s, and it's not useful here.
|
||||
*/
|
||||
pr->flags = F_BPAD;
|
||||
pr->cchar[0] = 's';
|
||||
pr->cchar[1] = '\0';
|
||||
for (p1 = pr->fmt; *p1 != '%'; ++p1);
|
||||
for (p2 = ++p1; *p1 && strchr(spec, *p1); ++p1);
|
||||
while ((*p2++ = *p1++) != '\0');
|
||||
}
|
||||
|
||||
static char **_argv;
|
||||
|
||||
u_char *
|
||||
get(void)
|
||||
{
|
||||
static int ateof = 1;
|
||||
static u_char *curp, *savp;
|
||||
int n;
|
||||
int need, nread;
|
||||
u_char *tmpp;
|
||||
|
||||
if (!curp) {
|
||||
curp = ecalloc(blocksize, 1);
|
||||
savp = ecalloc(blocksize, 1);
|
||||
} else {
|
||||
tmpp = curp;
|
||||
curp = savp;
|
||||
savp = tmpp;
|
||||
address += blocksize;
|
||||
}
|
||||
for (need = blocksize, nread = 0;;) {
|
||||
/*
|
||||
* if read the right number of bytes, or at EOF for one file,
|
||||
* and no other files are available, zero-pad the rest of the
|
||||
* block and set the end flag.
|
||||
*/
|
||||
if (!length || (ateof && !next(NULL))) {
|
||||
if (need == blocksize)
|
||||
return(NULL);
|
||||
if (!need && vflag != ALL &&
|
||||
!memcmp(curp, savp, nread)) {
|
||||
if (vflag != DUP)
|
||||
(void)printf("*\n");
|
||||
return(NULL);
|
||||
}
|
||||
memset((char *)curp + nread, 0, need);
|
||||
eaddress = address + nread;
|
||||
return(curp);
|
||||
}
|
||||
n = fread((char *)curp + nread, sizeof(u_char),
|
||||
length == -1 ? need : MIN(length, need), stdin);
|
||||
if (!n) {
|
||||
if (ferror(stdin))
|
||||
warn("%s", _argv[-1]);
|
||||
ateof = 1;
|
||||
continue;
|
||||
}
|
||||
ateof = 0;
|
||||
if (length != -1)
|
||||
length -= n;
|
||||
if (!(need -= n)) {
|
||||
if (vflag == ALL || vflag == FIRST ||
|
||||
memcmp(curp, savp, blocksize)) {
|
||||
if (vflag == DUP || vflag == FIRST)
|
||||
vflag = WAIT;
|
||||
return(curp);
|
||||
}
|
||||
if (vflag == WAIT)
|
||||
(void)printf("*\n");
|
||||
vflag = DUP;
|
||||
address += blocksize;
|
||||
need = blocksize;
|
||||
nread = 0;
|
||||
}
|
||||
else
|
||||
nread += n;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
next(char **argv)
|
||||
{
|
||||
static int done;
|
||||
int statok;
|
||||
|
||||
if (argv) {
|
||||
_argv = argv;
|
||||
return(1);
|
||||
}
|
||||
for (;;) {
|
||||
if (*_argv) {
|
||||
if (!(freopen(*_argv, "r", stdin))) {
|
||||
warn("%s", *_argv);
|
||||
exitval = 1;
|
||||
++_argv;
|
||||
continue;
|
||||
}
|
||||
statok = done = 1;
|
||||
} else {
|
||||
if (done++)
|
||||
return(0);
|
||||
statok = 0;
|
||||
}
|
||||
if (skip)
|
||||
doskip(statok ? *_argv : "stdin", statok);
|
||||
if (*_argv)
|
||||
++_argv;
|
||||
if (!skip)
|
||||
return(1);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
void
|
||||
doskip(const char *fname, int statok)
|
||||
{
|
||||
int cnt;
|
||||
struct stat sb;
|
||||
|
||||
if (statok) {
|
||||
if (fstat(fileno(stdin), &sb))
|
||||
err(1, "fstat %s", fname);
|
||||
if (S_ISREG(sb.st_mode) && skip >= sb.st_size) {
|
||||
address += sb.st_size;
|
||||
skip -= sb.st_size;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (S_ISREG(sb.st_mode)) {
|
||||
if (fseek(stdin, skip, SEEK_SET))
|
||||
err(1, "fseek %s", fname);
|
||||
address += skip;
|
||||
skip = 0;
|
||||
} else {
|
||||
for (cnt = 0; cnt < skip; ++cnt)
|
||||
if (getchar() == EOF)
|
||||
break;
|
||||
address += cnt;
|
||||
skip -= cnt;
|
||||
}
|
||||
}
|
325
commands/hexdump/hexdump.1
Normal file
325
commands/hexdump/hexdump.1
Normal file
|
@ -0,0 +1,325 @@
|
|||
.\" $NetBSD: hexdump.1,v 1.20 2010/02/27 10:45:23 mbalmer Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1989, 1990, 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
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" from: @(#)hexdump.1 8.2 (Berkeley) 4/18/94
|
||||
.\"
|
||||
.Dd February 27, 2010
|
||||
.Dt HEXDUMP 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm hexdump
|
||||
.Nd ascii, decimal, hexadecimal, octal dump
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl bcCdovx
|
||||
.Bk -words
|
||||
.Op Fl e Ar format_string
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl f Ar format_file
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl n Ar length
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl s Ar skip
|
||||
.Ek
|
||||
.Ar file ...
|
||||
.Sh DESCRIPTION
|
||||
The hexdump utility is a filter which displays the specified files, or
|
||||
the standard input, if no files are specified, in a user specified
|
||||
format.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Fl
|
||||
.It Fl b
|
||||
.Em One-byte octal display .
|
||||
Display the input offset in hexadecimal, followed by sixteen
|
||||
space-separated, three column, zero-filled, bytes of input data,
|
||||
in octal, per line.
|
||||
.It Fl c
|
||||
.Em One-byte character display .
|
||||
Display the input offset in hexadecimal, followed by sixteen
|
||||
space-separated, three column, space-filled, characters of input
|
||||
data per line.
|
||||
.It Fl C
|
||||
.Em Canonical hex+ASCII display .
|
||||
Display the input offset in hexadecimal, followed by sixteen
|
||||
space-separated, two column, hexadecimal bytes, followed by the
|
||||
same sixteen bytes in %_p format enclosed in ``|'' characters.
|
||||
.It Fl d
|
||||
.Em Two-byte decimal display .
|
||||
Display the input offset in hexadecimal, followed by eight
|
||||
space-separated, five column, zero-filled, two-byte units
|
||||
of input data, in unsigned decimal, per line.
|
||||
.It Fl e Ar format_string
|
||||
Specify a format string to be used for displaying data.
|
||||
.It Fl f Ar format_file
|
||||
Specify a file that contains one or more newline separated format strings.
|
||||
Empty lines and lines whose first non-blank character is a hash mark
|
||||
.Pf ( Cm \&# )
|
||||
are ignored.
|
||||
.It Fl n Ar length
|
||||
Interpret only
|
||||
.Ar length
|
||||
bytes of input.
|
||||
.It Fl o
|
||||
.Em Two-byte octal display .
|
||||
Display the input offset in hexadecimal, followed by eight
|
||||
space-separated, six column, zero-filled, two byte quantities of
|
||||
input data, in octal, per line.
|
||||
.It Fl s Ar offset
|
||||
Skip
|
||||
.Ar offset
|
||||
bytes from the beginning of the input.
|
||||
By default,
|
||||
.Ar offset
|
||||
is interpreted as a decimal number.
|
||||
With a leading
|
||||
.Cm 0x
|
||||
or
|
||||
.Cm 0X ,
|
||||
.Ar offset
|
||||
is interpreted as a hexadecimal number,
|
||||
otherwise, with a leading
|
||||
.Cm 0 ,
|
||||
.Ar offset
|
||||
is interpreted as an octal number.
|
||||
Appending the character
|
||||
.Cm b ,
|
||||
.Cm k ,
|
||||
or
|
||||
.Cm m
|
||||
to
|
||||
.Ar offset
|
||||
causes it to be interpreted as a multiple of
|
||||
.Li 512 ,
|
||||
.Li 1024 ,
|
||||
or
|
||||
.Li 1048576 ,
|
||||
respectively.
|
||||
.It Fl v
|
||||
The
|
||||
.Fl v
|
||||
option causes hexdump to display all input data.
|
||||
Without the
|
||||
.Fl v
|
||||
option, any number of groups of output lines, which would be
|
||||
identical to the immediately preceding group of output lines (except
|
||||
for the input offsets), are replaced with a line containing a
|
||||
single asterisk.
|
||||
.It Fl x
|
||||
.Em Two-byte hexadecimal display .
|
||||
Display the input offset in hexadecimal, followed by eight, space
|
||||
separated, four column, zero-filled, two-byte quantities of input
|
||||
data, in hexadecimal, per line.
|
||||
.El
|
||||
.Pp
|
||||
For each input file,
|
||||
.Nm
|
||||
sequentially copies the input to standard output, transforming the
|
||||
data according to the format strings specified by the
|
||||
.Fl e
|
||||
and
|
||||
.Fl f
|
||||
options, in the order that they were specified.
|
||||
.Ss Formats
|
||||
A format string contains any number of format units, separated by
|
||||
whitespace.
|
||||
A format unit contains up to three items: an iteration count, a byte
|
||||
count, and a format.
|
||||
.Pp
|
||||
The iteration count is an optional positive integer, which defaults to
|
||||
one.
|
||||
Each format is applied iteration count times.
|
||||
.Pp
|
||||
The byte count is an optional positive integer.
|
||||
If specified it defines the number of bytes to be interpreted by
|
||||
each iteration of the format.
|
||||
.Pp
|
||||
If an iteration count and/or a byte count is specified, a single slash
|
||||
must be placed after the iteration count and/or before the byte count
|
||||
to disambiguate them.
|
||||
Any whitespace before or after the slash is ignored.
|
||||
.Pp
|
||||
The format is required and must be surrounded by double quote
|
||||
(" ") marks.
|
||||
It is interpreted as a fprintf-style format string (see
|
||||
.Xr fprintf 3 ) ,
|
||||
with the
|
||||
following exceptions:
|
||||
.Bl -bullet -offset indent
|
||||
.It
|
||||
An asterisk (*) may not be used as a field width or precision.
|
||||
.It
|
||||
A byte count or field precision
|
||||
.Em is
|
||||
required for each ``s'' conversion
|
||||
character (unlike the
|
||||
.Xr fprintf 3
|
||||
default which prints the entire string if the precision is unspecified).
|
||||
.It
|
||||
The conversion characters ``h'', ``l'', ``n'', ``p'' and ``q'' are
|
||||
not supported.
|
||||
.It
|
||||
The single character escape sequences
|
||||
described in the C standard are supported:
|
||||
.Bd -ragged -offset indent -compact
|
||||
.Bl -column \*[Lt]alert_character\*[Gt]
|
||||
.It NUL \e0
|
||||
.It \*[Lt]alert character\*[Gt] \ea
|
||||
.It \*[Lt]backspace\*[Gt] \eb
|
||||
.It \*[Lt]form-feed\*[Gt] \ef
|
||||
.It \*[Lt]newline\*[Gt] \en
|
||||
.It \*[Lt]carriage return\*[Gt] \er
|
||||
.It \*[Lt]tab\*[Gt] \et
|
||||
.It \*[Lt]vertical tab\*[Gt] \ev
|
||||
.El
|
||||
.Ed
|
||||
.El
|
||||
.Pp
|
||||
Hexdump also supports the following additional conversion strings:
|
||||
.Bl -tag -width Fl
|
||||
.It Cm \&_a Ns Op Cm dox
|
||||
Display the input offset, cumulative across input files, of the
|
||||
next byte to be displayed.
|
||||
The appended characters
|
||||
.Cm d ,
|
||||
.Cm o ,
|
||||
and
|
||||
.Cm x
|
||||
specify the display base
|
||||
as decimal, octal or hexadecimal respectively.
|
||||
.It Cm \&_A Ns Op Cm dox
|
||||
Identical to the
|
||||
.Cm \&_a
|
||||
conversion string except that it is only performed
|
||||
once, when all of the input data has been processed.
|
||||
.It Cm \&_c
|
||||
Output characters in the default character set.
|
||||
Nonprinting characters are displayed in three character, zero-padded
|
||||
octal, except for those representable by standard escape notation
|
||||
(see above),
|
||||
which are displayed as two character strings.
|
||||
.It Cm _p
|
||||
Output characters in the default character set.
|
||||
Nonprinting characters are displayed as a single
|
||||
.Dq Cm \&. .
|
||||
.It Cm _u
|
||||
Output US ASCII characters, with the exception that control characters are
|
||||
displayed using the following, lower-case, names.
|
||||
Characters greater than 0xff, hexadecimal, are displayed as hexadecimal
|
||||
strings.
|
||||
.Bl -column \&000_nu \&001_so \&002_st \&003_et \&004_eo
|
||||
.It \&000\ nul\t001\ soh\t002\ stx\t003\ etx\t004\ eot\t005\ enq
|
||||
.It \&006\ ack\t007\ bel\t008\ bs\t009\ ht\t00A\ lf\t00B\ vt
|
||||
.It \&00C\ ff\t00D\ cr\t00E\ so\t00F\ si\t010\ dle\t011\ dc1
|
||||
.It \&012\ dc2\t013\ dc3\t014\ dc4\t015\ nak\t016\ syn\t017\ etb
|
||||
.It \&018\ can\t019\ em\t01A\ sub\t01B\ esc\t01C\ fs\t01D\ gs
|
||||
.It \&01E\ rs\t01F\ us\t07F\ del
|
||||
.El
|
||||
.El
|
||||
.Pp
|
||||
The default and supported byte counts for the conversion characters
|
||||
are as follows:
|
||||
.Bl -tag -width "Xc,_Xc,_Xc,_Xc,_Xc,_Xc" -offset indent
|
||||
.It Li \&%_c , \&%_p , \&%_u , \&%c
|
||||
One byte counts only.
|
||||
.It Li \&%d , \&%i , \&%o , \&%u , \&%X , \&%x
|
||||
Four byte default, one, two, four and eight byte counts supported.
|
||||
.It Li \&%E , \&%e , \&%f , \&%G , \&%g
|
||||
Eight byte default, four byte counts supported.
|
||||
.El
|
||||
.Pp
|
||||
The amount of data interpreted by each format string is the sum of the
|
||||
data required by each format unit, which is the iteration count times the
|
||||
byte count, or the iteration count times the number of bytes required by
|
||||
the format if the byte count is not specified.
|
||||
.Pp
|
||||
The input is manipulated in ``blocks'', where a block is defined as the
|
||||
largest amount of data specified by any format string.
|
||||
Format strings interpreting less than an input block's worth of data,
|
||||
whose last format unit both interprets some number of bytes and does
|
||||
not have a specified iteration count, have the iteration count
|
||||
incremented until the entire input block has been processed or there
|
||||
is not enough data remaining in the block to satisfy the format string.
|
||||
.Pp
|
||||
If, either as a result of user specification or hexdump modifying
|
||||
the iteration count as described above, an iteration count is
|
||||
greater than one, no trailing whitespace characters are output
|
||||
during the last iteration.
|
||||
.Pp
|
||||
It is an error to specify a byte count as well as multiple conversion
|
||||
characters or strings unless all but one of the conversion characters
|
||||
or strings is
|
||||
.Cm \&_a
|
||||
or
|
||||
.Cm \&_A .
|
||||
.Pp
|
||||
If, as a result of the specification of the
|
||||
.Fl n
|
||||
option or end-of-file being reached, input data only partially
|
||||
satisfies a format string, the input block is zero-padded sufficiently
|
||||
to display all available data (i.e. any format units overlapping the
|
||||
end of data will display some number of the zero bytes).
|
||||
.Pp
|
||||
Further output by such format strings is replaced by an equivalent
|
||||
number of spaces.
|
||||
An equivalent number of spaces is defined as the number of spaces
|
||||
output by an
|
||||
.Cm s
|
||||
conversion character with the same field width
|
||||
and precision as the original conversion character or conversion
|
||||
string but with any
|
||||
.Dq Li \&+ ,
|
||||
.Dq \&\ \& ,
|
||||
.Dq Li \&#
|
||||
conversion flag characters
|
||||
removed, and referencing a NULL string.
|
||||
.Pp
|
||||
If no format strings are specified, the default display is equivalent
|
||||
to specifying the
|
||||
.Fl x
|
||||
option.
|
||||
.Pp
|
||||
.Nm
|
||||
exits 0 on success and \*[Gt]0 if an error occurred.
|
||||
.Sh EXAMPLES
|
||||
Display the input in perusal format:
|
||||
.Bd -literal -offset indent
|
||||
"%06.6_ao " 12/1 "%3_u "
|
||||
"\et\et" "%_p "
|
||||
"\en"
|
||||
.Ed
|
||||
.Pp
|
||||
Implement the \-x option:
|
||||
.Bd -literal -offset indent
|
||||
"%07.7_Ax\en"
|
||||
"%07.7_ax " 8/2 "%04x " "\en"
|
||||
.Ed
|
92
commands/hexdump/hexdump.c
Normal file
92
commands/hexdump/hexdump.c
Normal file
|
@ -0,0 +1,92 @@
|
|||
/* $NetBSD: hexdump.c,v 1.15 2010/02/09 14:06:37 drochner Exp $ */
|
||||
|
||||
/*
|
||||
* 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
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if 0
|
||||
#if !defined(lint)
|
||||
__COPYRIGHT("@(#) Copyright (c) 1989, 1993\
|
||||
The Regents of the University of California. All rights reserved.");
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)hexdump.c 8.1 (Berkeley) 6/6/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: hexdump.c,v 1.15 2010/02/09 14:06:37 drochner Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hexdump.h"
|
||||
|
||||
FS *fshead; /* head of format strings */
|
||||
int blocksize; /* data block size */
|
||||
int exitval; /* final exit value */
|
||||
int length = -1; /* max bytes to read */
|
||||
|
||||
int main(int, char **);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
FS *tfs;
|
||||
char *p;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
if (!(p = strrchr(argv[0], 'o')) || strcmp(p, "od"))
|
||||
newsyntax(argc, &argv);
|
||||
else
|
||||
odsyntax(argc, &argv);
|
||||
|
||||
/* figure out the data block size */
|
||||
for (blocksize = 0, tfs = fshead; tfs; tfs = tfs->nextfs) {
|
||||
tfs->bcnt = size(tfs);
|
||||
if (blocksize < tfs->bcnt)
|
||||
blocksize = tfs->bcnt;
|
||||
}
|
||||
/* rewrite the rules, do syntax checking */
|
||||
for (tfs = fshead; tfs; tfs = tfs->nextfs)
|
||||
rewrite(tfs);
|
||||
|
||||
(void)next(argv);
|
||||
display();
|
||||
exit(exitval);
|
||||
}
|
101
commands/hexdump/hexdump.h
Normal file
101
commands/hexdump/hexdump.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
/* $NetBSD: hexdump.h,v 1.11 2010/02/09 14:06:37 drochner Exp $ */
|
||||
|
||||
/*
|
||||
* 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
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)hexdump.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
typedef struct _pr {
|
||||
struct _pr *nextpr; /* next print unit */
|
||||
#define F_ADDRESS 0x001 /* print offset */
|
||||
#define F_BPAD 0x002 /* blank pad */
|
||||
#define F_C 0x004 /* %_c */
|
||||
#define F_CHAR 0x008 /* %c */
|
||||
#define F_DBL 0x010 /* %[EefGf] */
|
||||
#define F_INT 0x020 /* %[di] */
|
||||
#define F_P 0x040 /* %_p */
|
||||
#define F_STR 0x080 /* %s */
|
||||
#define F_U 0x100 /* %_u */
|
||||
#define F_UINT 0x200 /* %[ouXx] */
|
||||
#define F_TEXT 0x400 /* no conversions */
|
||||
u_int flags; /* flag values */
|
||||
int bcnt; /* byte count */
|
||||
char *cchar; /* conversion character */
|
||||
char *fmt; /* printf format */
|
||||
char *nospace; /* no whitespace version */
|
||||
} PR;
|
||||
|
||||
typedef struct _fu {
|
||||
struct _fu *nextfu; /* next format unit */
|
||||
struct _pr *nextpr; /* next print unit */
|
||||
#define F_IGNORE 0x01 /* %_A */
|
||||
#define F_SETREP 0x02 /* rep count set, not default */
|
||||
u_int flags; /* flag values */
|
||||
int reps; /* repetition count */
|
||||
int bcnt; /* byte count */
|
||||
char *fmt; /* format string */
|
||||
} FU;
|
||||
|
||||
typedef struct _fs { /* format strings */
|
||||
struct _fs *nextfs; /* linked list of format strings */
|
||||
struct _fu *nextfu; /* linked list of format units */
|
||||
int bcnt;
|
||||
} FS;
|
||||
|
||||
enum _vflag { ALL, DUP, FIRST, WAIT }; /* -v values */
|
||||
|
||||
extern int blocksize; /* data block size */
|
||||
extern int odmode; /* od compatibility */
|
||||
extern FU *endfu; /* format at end-of-data */
|
||||
extern int exitval; /* final exit value */
|
||||
extern FS *fshead; /* head of format strings list */
|
||||
extern int length; /* max bytes to read */
|
||||
extern off_t skip; /* bytes to skip */
|
||||
extern enum _vflag vflag;
|
||||
|
||||
void add(const char *);
|
||||
void addfile(char *);
|
||||
void badcnt(char *);
|
||||
void badconv(char *);
|
||||
void badfmt(const char *);
|
||||
void badsfmt(void);
|
||||
void bpad(PR *);
|
||||
void conv_c(PR *, u_char *);
|
||||
void conv_u(PR *, u_char *);
|
||||
void display(void);
|
||||
void doskip(const char *, int);
|
||||
/*void err(const char *, ...);*/
|
||||
void escape(char *);
|
||||
u_char *get(void);
|
||||
void newsyntax(int, char ***);
|
||||
int next(char **);
|
||||
void odsyntax(int, char ***);
|
||||
void rewrite(FS *);
|
||||
int size(FS *);
|
||||
void usage(void);
|
140
commands/hexdump/hexsyntax.c
Normal file
140
commands/hexdump/hexsyntax.c
Normal file
|
@ -0,0 +1,140 @@
|
|||
/* $NetBSD: hexsyntax.c,v 1.13 2006/01/04 01:30:21 perry Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 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
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if 0
|
||||
#if !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)hexsyntax.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: hexsyntax.c,v 1.13 2006/01/04 01:30:21 perry Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "hexdump.h"
|
||||
|
||||
off_t skip; /* bytes to skip */
|
||||
|
||||
void
|
||||
newsyntax(int argc, char ***argvp)
|
||||
{
|
||||
int ch;
|
||||
char *p, **argv;
|
||||
|
||||
argv = *argvp;
|
||||
while ((ch = getopt(argc, argv, "bcCde:f:n:os:vx")) != -1)
|
||||
switch (ch) {
|
||||
case 'b':
|
||||
add("\"%07.7_Ax\n\"");
|
||||
add("\"%07.7_ax \" 16/1 \"%03o \" \"\\n\"");
|
||||
break;
|
||||
case 'c':
|
||||
add("\"%07.7_Ax\n\"");
|
||||
add("\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\"");
|
||||
break;
|
||||
case 'C':
|
||||
add("\"%08.8_Ax\n\"");
|
||||
add("\"%08.8_ax \" 8/1 \"%02x \" \" \" 8/1 \"%02x \" ");
|
||||
add("\" |\" 16/1 \"%_p\" \"|\\n\"");
|
||||
break;
|
||||
case 'd':
|
||||
add("\"%07.7_Ax\n\"");
|
||||
add("\"%07.7_ax \" 8/2 \" %05u \" \"\\n\"");
|
||||
break;
|
||||
case 'e':
|
||||
add(optarg);
|
||||
break;
|
||||
case 'f':
|
||||
addfile(optarg);
|
||||
break;
|
||||
case 'n':
|
||||
if ((length = atoi(optarg)) < 0)
|
||||
errx(1, "%s: bad length value", optarg);
|
||||
break;
|
||||
case 'o':
|
||||
add("\"%07.7_Ax\n\"");
|
||||
add("\"%07.7_ax \" 8/2 \" %06o \" \"\\n\"");
|
||||
break;
|
||||
case 's':
|
||||
if ((skip = strtol(optarg, &p, 0)) < 0)
|
||||
errx(1, "%s: bad skip value", optarg);
|
||||
switch(*p) {
|
||||
case 'b':
|
||||
skip *= 512;
|
||||
break;
|
||||
case 'k':
|
||||
skip *= 1024;
|
||||
break;
|
||||
case 'm':
|
||||
skip *= 1048576;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
vflag = ALL;
|
||||
break;
|
||||
case 'x':
|
||||
add("\"%07.7_Ax\n\"");
|
||||
add("\"%07.7_ax \" 8/2 \" %04x \" \"\\n\"");
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
}
|
||||
|
||||
if (!fshead) {
|
||||
add("\"%07.7_Ax\n\"");
|
||||
add("\"%07.7_ax \" 8/2 \"%04x \" \"\\n\"");
|
||||
}
|
||||
|
||||
*argvp += optind;
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"hexdump: [-bcCdovx] [-e fmt] [-f fmt_file] [-n length] [-s skip] [file ...]\n"
|
||||
);
|
||||
exit(1);
|
||||
}
|
303
commands/hexdump/od.1
Normal file
303
commands/hexdump/od.1
Normal file
|
@ -0,0 +1,303 @@
|
|||
.\" $NetBSD: od.1,v 1.25 2010/02/09 14:25:39 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||
.\" by Andrew Brown.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"/
|
||||
.Dd February 9, 2010
|
||||
.Dt OD 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm od
|
||||
.Nd octal, decimal, hex, ascii dump
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl aBbcDdeFfHhIiLlOovXx
|
||||
.Bk -words
|
||||
.Op Fl A Ar base
|
||||
.Op Fl j Ar skip
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl N Ar length
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl t Ar type_string
|
||||
.Ek
|
||||
.Sm off
|
||||
.Oo
|
||||
.Op Cm \&+
|
||||
.Li offset
|
||||
.Op Cm \&.
|
||||
.Op Cm Bb
|
||||
.Sm on
|
||||
.Oc
|
||||
.Ar file ...
|
||||
.Sh DESCRIPTION
|
||||
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
|
||||
.Em One-byte character display .
|
||||
Display the input offset in octal, followed by sixteen
|
||||
space-separated, three column, space-filled, characters of input data
|
||||
per line.
|
||||
Control characters are printed as their names instead of as
|
||||
C-style escapes.
|
||||
.It Fl B
|
||||
Same as
|
||||
.Fl o .
|
||||
.It Fl b
|
||||
.Em One-byte octal display .
|
||||
Display the input offset in octal, followed by sixteen
|
||||
space-separated, three column, zero-filled, bytes of input data, in
|
||||
octal, per line.
|
||||
This is the default output style if no other is
|
||||
selected.
|
||||
.It Fl c
|
||||
.Em One-byte character display .
|
||||
Display the input offset in octal, followed by sixteen
|
||||
space-separated, three column, space-filled, characters of input data
|
||||
per line.
|
||||
Control characters are printed at C-style escapes, or as
|
||||
three octal digits, if no C escape exists for the character.
|
||||
.It Fl d
|
||||
.Em Two-byte decimal display .
|
||||
Display the input offset in octal, followed by eight
|
||||
space-separated, five column, zero-filled, two-byte units
|
||||
of input data, in unsigned decimal, per line.
|
||||
.It Fl e
|
||||
.Em Eight-byte floating point display .
|
||||
Display the input offset in octal, followed by two space-separated,
|
||||
twenty-one column, space filled, eight byte units of input data, in
|
||||
floating point, per line.
|
||||
.It Fl F
|
||||
Same as
|
||||
.Fl e .
|
||||
.It Fl f
|
||||
.Em Four-byte floating point display .
|
||||
Display the input offset in octal, followed by four space-separated,
|
||||
14 column, space filled, four byte units of input data, in floating
|
||||
point, per line.
|
||||
.It Fl H
|
||||
.Em Four-byte hex display .
|
||||
Display the input offset in octal, followed by four space-separated,
|
||||
eight column, zero filled, four byte units of input data, in hex,
|
||||
per line.
|
||||
.It Fl h
|
||||
.Em Two-byte hex display .
|
||||
Display the input offset in octal, followed by eight space-separated,
|
||||
four column, zero filled, two byte units of input data, in hex,
|
||||
per line.
|
||||
.It Fl I
|
||||
.Em Four-byte decimal display .
|
||||
Display the input offset in octal, followed by four space-separated,
|
||||
eleven column, space filled, four byte units of input data, in
|
||||
decimal, per line.
|
||||
.It Fl i
|
||||
.Em Two-byte decimal display .
|
||||
Display the input offset in octal, followed by eight space-separated,
|
||||
six column, space filled, two-byte units of input data, in decimal,
|
||||
per line.
|
||||
.It Fl j Ar offset
|
||||
Skip
|
||||
.Ar offset
|
||||
bytes from the beginning of the input.
|
||||
By default,
|
||||
.Ar offset
|
||||
is interpreted as a decimal number.
|
||||
With a leading
|
||||
.Cm 0x
|
||||
or
|
||||
.Cm 0X ,
|
||||
.Ar offset
|
||||
is interpreted as a hexadecimal number,
|
||||
otherwise, with a leading
|
||||
.Cm 0 ,
|
||||
.Ar offset
|
||||
is interpreted as an octal number.
|
||||
Appending the character
|
||||
.Cm b ,
|
||||
.Cm k ,
|
||||
or
|
||||
.Cm m
|
||||
to
|
||||
.Ar offset
|
||||
causes it to be interpreted as a multiple of
|
||||
.Li 512 ,
|
||||
.Li 1024 ,
|
||||
or
|
||||
.Li 1048576 ,
|
||||
respectively.
|
||||
.It Fl L
|
||||
Same as
|
||||
.Fl I .
|
||||
.It Fl l
|
||||
Same as
|
||||
.Fl I .
|
||||
.It Fl N Ar length
|
||||
Interpret only
|
||||
.Ar length
|
||||
bytes of input.
|
||||
.It Fl O
|
||||
.Em Four-byte octal display .
|
||||
Display the input offset in octal, followed by four
|
||||
space-separated, eleven column, zero-filled, four-byte units
|
||||
of input data, in octal, per line.
|
||||
.It Fl o
|
||||
.Em Two-byte octal display .
|
||||
Display the input offset in octal, followed by eight
|
||||
space-separated, six column, zero-filled, two-byte units
|
||||
of input data, in octal, per line.
|
||||
.It Fl t Ar type_string
|
||||
Specify one or more output types.
|
||||
The
|
||||
.Em type_string
|
||||
option-argument must be a string specifying the types to be used when
|
||||
writing the input data.
|
||||
The string must consist of the type specification characters:
|
||||
.Pp
|
||||
.Cm a
|
||||
selects US-ASCII output, with control characters replaced with their
|
||||
names instead of as C escape sequences.
|
||||
See also the
|
||||
.Cm _u
|
||||
conversion provided by hexdump(1).
|
||||
.Pp
|
||||
.Cm c
|
||||
selects a standard character based conversion.
|
||||
See also the
|
||||
.Cm _c
|
||||
conversion provided by hexdump(1).
|
||||
.Pp
|
||||
.Cm f
|
||||
selects the floating point output format.
|
||||
This type character can be optionally followed by the characters
|
||||
.Cm 4
|
||||
or
|
||||
.Cm F
|
||||
to specify four byte floating point output, or
|
||||
.Cm 8
|
||||
or
|
||||
.Cm L
|
||||
to specify eight byte floating point output.
|
||||
The default output format is eight byte floats.
|
||||
See also the
|
||||
.Cm e
|
||||
conversion provided by hexdump(1).
|
||||
.Pp
|
||||
.Cm d ,
|
||||
.Cm o ,
|
||||
.Cm u ,
|
||||
or
|
||||
.Cm x
|
||||
select decimal, octal, unsigned decimal, or hex output respectively.
|
||||
These types can optionally be followed by
|
||||
.Cm C
|
||||
to specify
|
||||
.Em char Ns -sized
|
||||
output,
|
||||
.Cm S
|
||||
to specify
|
||||
.Em short Ns -sized
|
||||
output,
|
||||
.Cm I
|
||||
to specify
|
||||
.Em int Ns -sized
|
||||
output,
|
||||
.Cm L
|
||||
to specify
|
||||
.Em long Ns -sized
|
||||
output,
|
||||
.Cm 1
|
||||
to specify one-byte output,
|
||||
.Cm 2
|
||||
to specify two-byte output,
|
||||
.Cm 4
|
||||
to specify four-byte output, or
|
||||
.Cm 8
|
||||
to specify eight-byte output.
|
||||
The default output format is in four-byte quantities.
|
||||
See also the
|
||||
.Cm d ,
|
||||
.Cm o ,
|
||||
.Cm u ,
|
||||
and
|
||||
.Cm x
|
||||
conversions provided by hexdump(1).
|
||||
.\"(a|c|f[FLD]?|[doux][C1S2I4L8]?)*
|
||||
.It Fl v
|
||||
The
|
||||
.Fl v
|
||||
option causes
|
||||
.Nm
|
||||
to display all input data.
|
||||
Without the
|
||||
.Fl v
|
||||
option, any number of groups of output lines, which would be
|
||||
identical to the immediately preceding group of output lines (except
|
||||
for the input offsets), are replaced with a line comprised of a
|
||||
single asterisk.
|
||||
.It Fl X
|
||||
Same as
|
||||
.Fl H .
|
||||
.It Fl x
|
||||
Same as
|
||||
.Fl h .
|
||||
.El
|
||||
.Pp
|
||||
For each input file,
|
||||
.Nm
|
||||
sequentially copies the input to standard output, transforming the
|
||||
data according to the options given.
|
||||
If no options are specified, the
|
||||
default display is equivalent to specifying the
|
||||
.Fl o
|
||||
option.
|
||||
.Pp
|
||||
.Nm
|
||||
exits 0 on success and \*[Gt]0 if an error occurred.
|
||||
.Sh SEE ALSO
|
||||
.Xr hexdump 1 ,
|
||||
.Xr strings 1
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
command appears in
|
||||
.At v1 .
|
||||
.Pp
|
||||
This man page was written in February 2001 by Andrew Brown, shortly
|
||||
after he augmented the deprecated od syntax to include things he felt
|
||||
had been missing for a long time.
|
400
commands/hexdump/odsyntax.c
Normal file
400
commands/hexdump/odsyntax.c
Normal file
|
@ -0,0 +1,400 @@
|
|||
/* $NetBSD: odsyntax.c,v 1.26 2010/02/09 14:06:37 drochner Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 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
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if 0
|
||||
#if !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)odsyntax.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: odsyntax.c,v 1.26 2010/02/09 14:06:37 drochner Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <util.h>
|
||||
|
||||
#include "hexdump.h"
|
||||
|
||||
#define PADDING " "
|
||||
|
||||
struct odformat {
|
||||
char type;
|
||||
int nbytes;
|
||||
char const *format;
|
||||
int minwidth;
|
||||
};
|
||||
|
||||
struct odaddrformat {
|
||||
char type;
|
||||
char const *format1;
|
||||
char const *format2;
|
||||
};
|
||||
|
||||
int odmode;
|
||||
|
||||
static void odoffset(int, char ***);
|
||||
static void posixtypes(char const *);
|
||||
|
||||
void
|
||||
odsyntax(int argc, char ***argvp)
|
||||
{
|
||||
static char empty[] = "", padding[] = PADDING;
|
||||
int ch;
|
||||
char *p, **argv;
|
||||
|
||||
#define TYPE_OFFSET 7
|
||||
add("\"%07.7_Ao\n\"");
|
||||
add("\"%07.7_ao \"");
|
||||
|
||||
odmode = 1;
|
||||
argv = *argvp;
|
||||
while ((ch = getopt(argc, argv,
|
||||
"A:aBbcDdeFfHhIij:LlN:Oot: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 = empty;
|
||||
fshead->nextfs->nextfu->fmt = padding;
|
||||
break;
|
||||
default:
|
||||
errx(1, "%s: invalid address base", optarg);
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
posixtypes("a");
|
||||
break;
|
||||
case 'B':
|
||||
case 'o':
|
||||
posixtypes("o2");
|
||||
break;
|
||||
case 'b':
|
||||
posixtypes("o1");
|
||||
break;
|
||||
case 'c':
|
||||
posixtypes("c");
|
||||
break;
|
||||
case 'd':
|
||||
posixtypes("u2");
|
||||
break;
|
||||
case 'D':
|
||||
posixtypes("u4");
|
||||
break;
|
||||
case 'e': /* undocumented in od */
|
||||
case 'F':
|
||||
posixtypes("f8");
|
||||
break;
|
||||
case 'f':
|
||||
posixtypes("f4");
|
||||
break;
|
||||
case 'H':
|
||||
case 'X':
|
||||
posixtypes("x4");
|
||||
break;
|
||||
case 'h':
|
||||
case 'x':
|
||||
posixtypes("x2");
|
||||
break;
|
||||
case 'I':
|
||||
case 'L':
|
||||
case 'l':
|
||||
posixtypes("d4");
|
||||
break;
|
||||
case 'i':
|
||||
posixtypes("d2");
|
||||
break;
|
||||
case 'j':
|
||||
if ((skip = strtol(optarg, &p, 0)) < 0)
|
||||
errx(1, "%s: bad skip value", optarg);
|
||||
switch(*p) {
|
||||
case 'b':
|
||||
skip *= 512;
|
||||
break;
|
||||
case 'k':
|
||||
skip *= 1024;
|
||||
break;
|
||||
case 'm':
|
||||
skip *= 1048576;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'N':
|
||||
if ((length = atoi(optarg)) < 0)
|
||||
errx(1, "%s: bad length value", optarg);
|
||||
break;
|
||||
case 'O':
|
||||
posixtypes("o4");
|
||||
break;
|
||||
case 't':
|
||||
posixtypes(optarg);
|
||||
break;
|
||||
case 'v':
|
||||
vflag = ALL;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
if (fshead->nextfs->nextfs == NULL)
|
||||
posixtypes("oS");
|
||||
|
||||
argc -= optind;
|
||||
*argvp += optind;
|
||||
|
||||
if (argc)
|
||||
odoffset(argc, argvp);
|
||||
}
|
||||
|
||||
/* formats used for -t */
|
||||
|
||||
static const struct odformat odftab[] = {
|
||||
{ 'a', 1, "%3_u", 4 },
|
||||
{ 'c', 1, "%3_c", 4 },
|
||||
{ 'd', 1, "%4d", 5 },
|
||||
{ 'd', 2, "%6d", 6 },
|
||||
{ 'd', 4, "%11d", 11 },
|
||||
{ 'd', 8, "%20d", 20 },
|
||||
{ 'o', 1, "%03o", 4 },
|
||||
{ 'o', 2, "%06o", 7 },
|
||||
{ 'o', 4, "%011o", 12 },
|
||||
{ 'o', 8, "%022o", 23 },
|
||||
{ 'u', 1, "%03u" , 4 },
|
||||
{ 'u', 2, "%05u" , 6 },
|
||||
{ 'u', 4, "%010u", 11 },
|
||||
{ 'u', 8, "%020u", 21 },
|
||||
{ 'x', 1, "%02x", 3 },
|
||||
{ 'x', 2, "%04x", 5 },
|
||||
{ 'x', 4, "%08x", 9 },
|
||||
{ 'x', 8, "%016x", 17 },
|
||||
{ 'f', 4, "%14.7e", 15 },
|
||||
{ 'f', 8, "%21.14e", 22 },
|
||||
{ 0, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* Interpret a POSIX-style -t argument.
|
||||
*/
|
||||
static void
|
||||
posixtypes(char const *type_string)
|
||||
{
|
||||
int nbytes = 0;
|
||||
char *fmt, type, *tmp;
|
||||
struct odformat const *odf;
|
||||
|
||||
while (*type_string) {
|
||||
switch ((type = *type_string++)) {
|
||||
case 'a':
|
||||
case 'c':
|
||||
nbytes = 1;
|
||||
break;
|
||||
case 'f':
|
||||
if (isupper((unsigned char)*type_string)) {
|
||||
switch(*type_string) {
|
||||
case 'F':
|
||||
nbytes = sizeof(float);
|
||||
break;
|
||||
case 'D':
|
||||
nbytes = sizeof(double);
|
||||
break;
|
||||
case 'L':
|
||||
nbytes = sizeof(long double);
|
||||
break;
|
||||
default:
|
||||
warnx("Bad type-size qualifier '%c'",
|
||||
*type_string);
|
||||
usage();
|
||||
}
|
||||
type_string++;
|
||||
} else if (isdigit((unsigned char)*type_string)) {
|
||||
nbytes = strtol(type_string, &tmp, 10);
|
||||
type_string = tmp;
|
||||
} else
|
||||
nbytes = 8;
|
||||
break;
|
||||
case 'd':
|
||||
case 'o':
|
||||
case 'u':
|
||||
case 'x':
|
||||
if (isupper((unsigned char)*type_string)) {
|
||||
switch(*type_string) {
|
||||
case 'C':
|
||||
nbytes = sizeof(char);
|
||||
break;
|
||||
case 'S':
|
||||
nbytes = sizeof(short);
|
||||
break;
|
||||
case 'I':
|
||||
nbytes = sizeof(int);
|
||||
break;
|
||||
case 'L':
|
||||
nbytes = sizeof(long);
|
||||
break;
|
||||
default:
|
||||
warnx("Bad type-size qualifier '%c'",
|
||||
*type_string);
|
||||
usage();
|
||||
}
|
||||
type_string++;
|
||||
} else if (isdigit((unsigned char)*type_string)) {
|
||||
nbytes = strtol(type_string, &tmp, 10);
|
||||
type_string = tmp;
|
||||
} else
|
||||
nbytes = 4;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
for (odf = odftab; odf->type != 0; odf++)
|
||||
if (odf->type == type && odf->nbytes == nbytes)
|
||||
break;
|
||||
if (odf->type == 0)
|
||||
errx(1, "%c%d: format not supported", type, nbytes);
|
||||
(void)easprintf(&fmt, "%d/%d \"%*s%s \" \"\\n\"",
|
||||
16 / nbytes, nbytes,
|
||||
4 * nbytes - odf->minwidth, "", odf->format);
|
||||
add(fmt);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
odoffset(int argc, char ***argvp)
|
||||
{
|
||||
char *num, *p;
|
||||
int base;
|
||||
char *end;
|
||||
|
||||
/*
|
||||
* The offset syntax of od(1) was genuinely bizarre. First, if
|
||||
* it started with a plus it had to be an offset. Otherwise, if
|
||||
* there were at least two arguments, a number or lower-case 'x'
|
||||
* followed by a number makes it an offset. By default it was
|
||||
* octal; if it started with 'x' or '0x' it was hex. If it ended
|
||||
* in a '.', it was decimal. If a 'b' or 'B' was appended, it
|
||||
* multiplied the number by 512 or 1024 byte units. There was
|
||||
* no way to assign a block count to a hex offset.
|
||||
*
|
||||
* We assume it's a file if the offset is bad.
|
||||
*/
|
||||
p = argc == 1 ? (*argvp)[0] : (*argvp)[1];
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
if (*p != '+' && (argc < 2 ||
|
||||
(!isdigit((unsigned char)p[0]) &&
|
||||
(p[0] != 'x' || !isxdigit((unsigned char)p[1])))))
|
||||
return;
|
||||
|
||||
base = 0;
|
||||
/*
|
||||
* skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
|
||||
* set base.
|
||||
*/
|
||||
if (p[0] == '+')
|
||||
++p;
|
||||
if (p[0] == 'x' && isxdigit((unsigned char)p[1])) {
|
||||
++p;
|
||||
base = 16;
|
||||
} else if (p[0] == '0' && p[1] == 'x') {
|
||||
p += 2;
|
||||
base = 16;
|
||||
}
|
||||
|
||||
/* skip over the number */
|
||||
if (base == 16)
|
||||
for (num = p; isxdigit((unsigned char)*p); ++p);
|
||||
else
|
||||
for (num = p; isdigit((unsigned char)*p); ++p);
|
||||
|
||||
/* check for no number */
|
||||
if (num == p)
|
||||
return;
|
||||
|
||||
/* if terminates with a '.', base is decimal */
|
||||
if (*p == '.') {
|
||||
if (base)
|
||||
return;
|
||||
base = 10;
|
||||
}
|
||||
|
||||
skip = strtol(num, &end, base ? base : 8);
|
||||
|
||||
/* if end isn't the same as p, we got a non-octal digit */
|
||||
if (end != p) {
|
||||
skip = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (*p) {
|
||||
if (*p == 'B') {
|
||||
skip *= 1024;
|
||||
++p;
|
||||
} else if (*p == 'b') {
|
||||
skip *= 512;
|
||||
++p;
|
||||
}
|
||||
}
|
||||
if (*p) {
|
||||
skip = 0;
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
if (base == 16) {
|
||||
fshead->nextfu->fmt[TYPE_OFFSET] = 'x';
|
||||
fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x';
|
||||
} else if (base == 10) {
|
||||
fshead->nextfu->fmt[TYPE_OFFSET] = 'd';
|
||||
fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd';
|
||||
}
|
||||
|
||||
/* Terminate file list. */
|
||||
(*argvp)[1] = NULL;
|
||||
}
|
545
commands/hexdump/parse.c
Normal file
545
commands/hexdump/parse.c
Normal file
|
@ -0,0 +1,545 @@
|
|||
/* $NetBSD: parse.c,v 1.26 2009/01/18 21:34:32 apb Exp $ */
|
||||
|
||||
/*
|
||||
* 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
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if 0
|
||||
#if !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/6/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: parse.c,v 1.26 2009/01/18 21:34:32 apb Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <util.h>
|
||||
|
||||
#include "hexdump.h"
|
||||
|
||||
FU *endfu; /* format at end-of-data */
|
||||
|
||||
void
|
||||
addfile(char *name)
|
||||
{
|
||||
char *p;
|
||||
FILE *fp;
|
||||
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;
|
||||
}
|
||||
*p = '\0';
|
||||
for (p = buf; *p && isspace((unsigned char)*p); ++p);
|
||||
if (!*p || *p == '#')
|
||||
continue;
|
||||
add(p);
|
||||
}
|
||||
(void)fclose(fp);
|
||||
}
|
||||
|
||||
void
|
||||
add(const char *fmt)
|
||||
{
|
||||
const char *p;
|
||||
static FS **nextfs;
|
||||
FS *tfs;
|
||||
FU *tfu, **nextfu;
|
||||
const char *savep;
|
||||
|
||||
/* start new linked list of format units */
|
||||
tfs = ecalloc(1, sizeof(FS));
|
||||
if (!fshead)
|
||||
fshead = tfs;
|
||||
else
|
||||
*nextfs = tfs;
|
||||
nextfs = &tfs->nextfs;
|
||||
nextfu = &tfs->nextfu;
|
||||
|
||||
/* take the format string and break it up into format units */
|
||||
for (p = fmt;;) {
|
||||
/* skip leading white space */
|
||||
for (; isspace((unsigned char)*p); ++p);
|
||||
if (!*p)
|
||||
break;
|
||||
|
||||
/* allocate a new format unit and link it in */
|
||||
tfu = ecalloc(1, sizeof(FU));
|
||||
*nextfu = tfu;
|
||||
nextfu = &tfu->nextfu;
|
||||
tfu->reps = 1;
|
||||
|
||||
/* if leading digit, repetition count */
|
||||
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((unsigned char)*p); ++p);
|
||||
}
|
||||
|
||||
/* skip slash and trailing white space */
|
||||
if (*p == '/')
|
||||
while (isspace((unsigned char)*++p));
|
||||
|
||||
/* byte count */
|
||||
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((unsigned char)*p); ++p);
|
||||
}
|
||||
|
||||
/* format */
|
||||
if (*p != '"')
|
||||
badfmt(fmt);
|
||||
for (savep = ++p; *p != '"';)
|
||||
if (*p++ == 0)
|
||||
badfmt(fmt);
|
||||
tfu->fmt = emalloc(p - savep + 1);
|
||||
(void) strncpy(tfu->fmt, savep, p - savep);
|
||||
tfu->fmt[p - savep] = '\0';
|
||||
escape(tfu->fmt);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *spec = ".#-+ 0123456789";
|
||||
|
||||
int
|
||||
size(FS *fs)
|
||||
{
|
||||
FU *fu;
|
||||
int bcnt, cursize;
|
||||
char *fmt;
|
||||
int prec;
|
||||
|
||||
/* figure out the data block size needed for each format unit */
|
||||
for (cursize = 0, fu = fs->nextfu; fu; fu = fu->nextfu) {
|
||||
if (fu->bcnt) {
|
||||
cursize += fu->bcnt * fu->reps;
|
||||
continue;
|
||||
}
|
||||
for (bcnt = prec = 0, fmt = fu->fmt; *fmt; ++fmt) {
|
||||
if (*fmt != '%')
|
||||
continue;
|
||||
/*
|
||||
* skip any special chars -- save precision in
|
||||
* case it's a %s format.
|
||||
*/
|
||||
while (strchr(spec + 1, *++fmt));
|
||||
if (*fmt == '.' && isdigit((unsigned char)*++fmt)) {
|
||||
prec = atoi(fmt);
|
||||
while (isdigit((unsigned char)*++fmt));
|
||||
}
|
||||
switch(*fmt) {
|
||||
case 'c':
|
||||
bcnt += 1;
|
||||
break;
|
||||
case 'd': case 'i': case 'o': case 'u':
|
||||
case 'x': case 'X':
|
||||
bcnt += 4;
|
||||
break;
|
||||
case 'e': case 'E': case 'f': case 'g': case 'G':
|
||||
bcnt += 8;
|
||||
break;
|
||||
case 's':
|
||||
bcnt += prec;
|
||||
break;
|
||||
case '_':
|
||||
switch(*++fmt) {
|
||||
case 'c': case 'p': case 'u':
|
||||
bcnt += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
cursize += bcnt * fu->reps;
|
||||
}
|
||||
return (cursize);
|
||||
}
|
||||
|
||||
void
|
||||
rewrite(FS *fs)
|
||||
{
|
||||
enum { NOTOKAY, USEBCNT, USEPREC } sokay;
|
||||
PR *pr, **nextpr;
|
||||
FU *fu;
|
||||
char *p1, *p2;
|
||||
char savech, *fmtp, cs[sizeof(PRId64)];
|
||||
int nconv, prec;
|
||||
|
||||
prec = 0;
|
||||
for (fu = fs->nextfu; fu; fu = fu->nextfu) {
|
||||
/*
|
||||
* Break each format unit into print units; each conversion
|
||||
* character gets its own.
|
||||
*/
|
||||
nextpr = &fu->nextpr;
|
||||
for (nconv = 0, fmtp = fu->fmt; *fmtp; nextpr = &pr->nextpr) {
|
||||
pr = ecalloc(1, sizeof(*pr));
|
||||
*nextpr = pr;
|
||||
|
||||
/* Skip preceding text and up to the next % sign. */
|
||||
for (p1 = fmtp; *p1 && *p1 != '%'; ++p1);
|
||||
|
||||
/* Only text in the string. */
|
||||
if (!*p1) {
|
||||
pr->fmt = fmtp;
|
||||
pr->flags = F_TEXT;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get precision for %s -- if have a byte count, don't
|
||||
* need it.
|
||||
*/
|
||||
if (fu->bcnt) {
|
||||
sokay = USEBCNT;
|
||||
/* Skip to conversion character. */
|
||||
for (++p1; *p1 && strchr(spec, *p1); ++p1);
|
||||
} else {
|
||||
/* Skip any special chars, field width. */
|
||||
while (*++p1 && strchr(spec + 1, *p1));
|
||||
if (*p1 == '.' &&
|
||||
isdigit((unsigned char)*++p1)) {
|
||||
sokay = USEPREC;
|
||||
prec = atoi(p1);
|
||||
while (isdigit((unsigned char)*++p1))
|
||||
continue;
|
||||
} else
|
||||
sokay = NOTOKAY;
|
||||
}
|
||||
|
||||
p2 = *p1 ? p1 + 1 : p1; /* Set end pointer. */
|
||||
cs[0] = *p1; /* Set conversion string. */
|
||||
cs[1] = '\0';
|
||||
|
||||
/*
|
||||
* Figure out the byte count for each conversion;
|
||||
* rewrite the format as necessary, set up blank-
|
||||
* padding for end of data.
|
||||
*/
|
||||
switch(cs[0]) {
|
||||
case 'c':
|
||||
pr->flags = F_CHAR;
|
||||
switch(fu->bcnt) {
|
||||
case 0: case 1:
|
||||
pr->bcnt = 1;
|
||||
break;
|
||||
default:
|
||||
p1[1] = '\0';
|
||||
badcnt(p1);
|
||||
}
|
||||
break;
|
||||
case 'd': case 'i':
|
||||
pr->flags = F_INT;
|
||||
goto isint;
|
||||
case 'o': case 'u': case 'x': case 'X':
|
||||
pr->flags = F_UINT;
|
||||
isint:
|
||||
/*
|
||||
* Regardless of pr->bcnt, all integer
|
||||
* values are cast to [u]int64_t before
|
||||
* being printed by display(). We
|
||||
* therefore need to use PRI?64 as the
|
||||
* format, where '?' could actually
|
||||
* be any of [diouxX]. We make the
|
||||
* assumption (not guaranteed by the
|
||||
* C99 standard) that we can derive
|
||||
* all the other PRI?64 values from
|
||||
* PRId64 simply by changing the last
|
||||
* character. For example, if PRId64 is
|
||||
* "lld" or "qd", and cs[0] is 'o', then
|
||||
* we end up with "llo" or "qo".
|
||||
*/
|
||||
savech = cs[0];
|
||||
strncpy(cs, PRId64, sizeof(PRId64) - 2);
|
||||
cs[sizeof(PRId64) - 2] = savech;
|
||||
cs[sizeof(PRId64) - 1] = '\0';
|
||||
switch(fu->bcnt) {
|
||||
case 0: case 4:
|
||||
pr->bcnt = 4;
|
||||
break;
|
||||
case 1:
|
||||
pr->bcnt = 1;
|
||||
break;
|
||||
case 2:
|
||||
pr->bcnt = 2;
|
||||
break;
|
||||
case 8:
|
||||
pr->bcnt = 8;
|
||||
break;
|
||||
default:
|
||||
p1[1] = '\0';
|
||||
badcnt(p1);
|
||||
}
|
||||
break;
|
||||
case 'e': case 'E': case 'f': case 'g': case 'G':
|
||||
pr->flags = F_DBL;
|
||||
switch(fu->bcnt) {
|
||||
case 0: case 8:
|
||||
pr->bcnt = 8;
|
||||
break;
|
||||
case 4:
|
||||
pr->bcnt = 4;
|
||||
break;
|
||||
default:
|
||||
p1[1] = '\0';
|
||||
badcnt(p1);
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
pr->flags = F_STR;
|
||||
switch(sokay) {
|
||||
case NOTOKAY:
|
||||
badsfmt();
|
||||
case USEBCNT:
|
||||
pr->bcnt = fu->bcnt;
|
||||
break;
|
||||
case USEPREC:
|
||||
pr->bcnt = prec;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case '_':
|
||||
++p2;
|
||||
switch(p1[1]) {
|
||||
case 'A':
|
||||
endfu = fu;
|
||||
fu->flags |= F_IGNORE;
|
||||
/* FALLTHROUGH */
|
||||
case 'a':
|
||||
pr->flags = F_ADDRESS;
|
||||
++p2;
|
||||
switch(p1[2]) {
|
||||
case 'd': case 'o': case'x':
|
||||
/*
|
||||
* See comments above for
|
||||
* the way we use PRId64.
|
||||
*/
|
||||
strncpy(cs, PRId64,
|
||||
sizeof(PRId64) - 2);
|
||||
cs[sizeof(PRId64) - 2] = p1[2];
|
||||
cs[sizeof(PRId64) - 1] = '\0';
|
||||
break;
|
||||
default:
|
||||
p1[3] = '\0';
|
||||
badconv(p1);
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
pr->flags = F_C;
|
||||
/* cs[0] = 'c'; set in conv_c */
|
||||
goto isint2;
|
||||
case 'p':
|
||||
pr->flags = F_P;
|
||||
cs[0] = 'c';
|
||||
goto isint2;
|
||||
case 'u':
|
||||
pr->flags = F_U;
|
||||
/* cs[0] = 'c'; set in conv_u */
|
||||
isint2: switch(fu->bcnt) {
|
||||
case 0: case 1:
|
||||
pr->bcnt = 1;
|
||||
break;
|
||||
default:
|
||||
p1[2] = '\0';
|
||||
badcnt(p1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
p1[2] = '\0';
|
||||
badconv(p1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
p1[1] = '\0';
|
||||
badconv(p1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy to PR format string, set conversion character
|
||||
* pointer, update original.
|
||||
*/
|
||||
savech = *p2;
|
||||
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. */
|
||||
if (!(pr->flags&F_ADDRESS) && fu->bcnt && nconv++)
|
||||
errx(1,
|
||||
"byte count with multiple conversion characters");
|
||||
}
|
||||
/*
|
||||
* If format unit byte count not specified, figure it out
|
||||
* so can adjust rep count later.
|
||||
*/
|
||||
if (!fu->bcnt)
|
||||
for (pr = fu->nextpr; pr; pr = pr->nextpr)
|
||||
fu->bcnt += pr->bcnt;
|
||||
}
|
||||
/*
|
||||
* 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
|
||||
* gets output from the last iteration of the format unit.
|
||||
*/
|
||||
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;
|
||||
if (fu->reps > 1) {
|
||||
if (!fu->nextpr)
|
||||
break;
|
||||
for (pr = fu->nextpr;; pr = pr->nextpr)
|
||||
if (!pr->nextpr)
|
||||
break;
|
||||
for (p1 = pr->fmt, p2 = NULL; *p1; ++p1)
|
||||
p2 = isspace((unsigned char)*p1) ? p1 : NULL;
|
||||
if (p2)
|
||||
pr->nospace = p2;
|
||||
}
|
||||
}
|
||||
#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
|
||||
escape(char *p1)
|
||||
{
|
||||
char *p2;
|
||||
|
||||
/* alphabetic escape sequences have to be done in place */
|
||||
for (p2 = p1;; ++p1, ++p2) {
|
||||
if (!*p1) {
|
||||
*p2 = *p1;
|
||||
break;
|
||||
}
|
||||
if (*p1 == '\\')
|
||||
switch(*++p1) {
|
||||
case '\0':
|
||||
*p2 = '\\';
|
||||
*++p2 = '\0';
|
||||
return; /* incomplete escape sequence */
|
||||
case 'a':
|
||||
/* *p2 = '\a'; */
|
||||
*p2 = '\007';
|
||||
break;
|
||||
case 'b':
|
||||
*p2 = '\b';
|
||||
break;
|
||||
case 'f':
|
||||
*p2 = '\f';
|
||||
break;
|
||||
case 'n':
|
||||
*p2 = '\n';
|
||||
break;
|
||||
case 'r':
|
||||
*p2 = '\r';
|
||||
break;
|
||||
case 't':
|
||||
*p2 = '\t';
|
||||
break;
|
||||
case 'v':
|
||||
*p2 = '\v';
|
||||
break;
|
||||
default:
|
||||
*p2 = *p1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
*p2 = *p1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
badcnt(char *s)
|
||||
{
|
||||
errx(1, "%s: bad byte count", s);
|
||||
}
|
||||
|
||||
void
|
||||
badsfmt(void)
|
||||
{
|
||||
errx(1, "%%s: requires a precision or a byte count");
|
||||
}
|
||||
|
||||
void
|
||||
badfmt(const char *fmt)
|
||||
{
|
||||
errx(1, "\"%s\": bad format", fmt);
|
||||
}
|
||||
|
||||
void
|
||||
badconv(char *ch)
|
||||
{
|
||||
errx(1, "%%%s: bad conversion character", ch);
|
||||
}
|
Loading…
Reference in a new issue