static char *sccsid
= "@(#)od.c 5.12 (Berkeley) %G%";
* od -- octal, hex, decimal, character dump of data in a file.
* usage: od [-abBcdDefFhHiIlLopPs[n]vw[n]xX] [file] [[+]offset[.][b] [label]]
* where the option flags have the following meaning:
* character object radix signed?
* a byte (10) (n.a.) ASCII named byte stream
* c byte (8) (no) character with octal non-graphic bytes
* e,F double (10) double precision floating pt.
* f float (10) single precision floating pt.
* o,B short 8 no (default conversion)
* s[n] string (8) ASCII graphic strings
* p indicate EVEN parity on 'a' conversion
* P indicate ODD parity on 'a' conversion
* v show all data - don't skip like lines.
* w[n] bytes per display line
* More than one format character may be given.
* If {file} is not specified, standard input is read.
* If {file} is not specified, then {offset} must start with '+'.
* {Offset} may be HEX (0xnnn), OCTAL (0nn), or decimal (nnn.).
* The default is octal. The same radix will be used to display the address.
int df_field
; /* external field required for object */
int df_size
; /* size (bytes) of object */
int df_radix
; /* conversion radix */
int df_signed
; /* signed? flag */
int df_paddr
; /* "put address on each line?" flag */
int (*df_put
)(); /* function to output object */
char *df_fmt
; /* output string format */
} *conv_vec
[32]; /* vector of conversions to be done */
struct dfmt ascii
= { 3, sizeof (char), 10, 0, PADDR
, a_put
, 0};
struct dfmt byte
= { 3, sizeof (char), 8, UNSIGNED
, PADDR
, b_put
, 0};
struct dfmt cchar
= { 3, sizeof (char), 8, UNSIGNED
, PADDR
, c_put
, 0};
struct dfmt u_s_oct
= { 6, sizeof (short), 8, UNSIGNED
, PADDR
, us_put
, 0};
struct dfmt u_s_dec
= { 5, sizeof (short), 10, UNSIGNED
, PADDR
, us_put
, 0};
struct dfmt u_s_hex
= { 4, sizeof (short), 16, UNSIGNED
, PADDR
, us_put
, 0};
struct dfmt u_l_oct
= {11, sizeof (long), 8, UNSIGNED
, PADDR
, l_put
, 0};
struct dfmt u_l_dec
= {10, sizeof (long), 10, UNSIGNED
, PADDR
, l_put
, 0};
struct dfmt u_l_hex
= { 8, sizeof (long), 16, UNSIGNED
, PADDR
, l_put
, 0};
struct dfmt s_s_dec
= { 6, sizeof (short), 10, SIGNED
, PADDR
, s_put
, 0};
struct dfmt s_l_dec
= {11, sizeof (long), 10, SIGNED
, PADDR
, l_put
, 0};
struct dfmt flt
= {14, sizeof (float), 10, SIGNED
, PADDR
, f_put
, 0};
struct dfmt dble
= {21, sizeof (double), 10, SIGNED
, PADDR
, d_put
, 0};
struct dfmt string
= { 0, 0, 8, 0, NO
, st_put
, 0};
char usage
[] ="usage: od [-abcdfhilopswvx] [file] [[+]offset[.][b] [label]]";
char lastdbuf
[DBUF_SIZE
];
int addr_base
= 8; /* default address base is OCTAL */
long addr
= 0L; /* current file offset */
long label
= -1L; /* current label; -1 is "off" */
int dbuf_size
= 16; /* file bytes / display line */
int _parity
= NO
; /* show parity on ascii bytes */
char fmt
[] = " %s"; /* 12 blanks */
#define isdigit(c) (_ctype[c] & D)
#define isascii(c) (_ctype[c] & A)
#define isgraphic(c) (_ctype[c] & G)
#define isprint(c) (_ctype[c] & P)
#define ishex(c) (_ctype[c] & (X|D))
/* 000 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 010 */ A
, A
, A
, 0, A
, A
, 0, 0,
/* 020 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 030 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 040 */ P
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
,
/* 050 */ P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
,
/* 060 */ P
|G
|D
|A
,P
|G
|D
|A
,P
|G
|D
|A
,P
|G
|D
|A
,P
|G
|D
|A
,P
|G
|D
|A
,P
|G
|D
|A
,P
|G
|D
|A
,
/* 070 */ P
|G
|D
|A
,P
|G
|D
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
,
/* 100 */ P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
,
/* 110 */ P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
,
/* 120 */ P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
,
/* 130 */ P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
,
/* 140 */ P
|G
|A
,X
|P
|G
|A
,X
|P
|G
|A
,X
|P
|G
|A
,X
|P
|G
|A
,X
|P
|G
|A
,X
|P
|G
|A
, P
|G
|A
,
/* 150 */ P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
,
/* 160 */ P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
,
/* 170 */ P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, P
|G
|A
, 0,
/* 200 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 210 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 220 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 230 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 240 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 250 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 260 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 270 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 300 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 310 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 320 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 330 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 340 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 350 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 360 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 370 */ 0, 0, 0, 0, 0, 0, 0, 0,
struct dfmt
**cv
= conv_vec
;
d
->df_size
= (10 * d
->df_size
) + (*++p
- '0');
dbuf_size
= (10 * dbuf_size
) + (*++p
- '0');
printf("od: bad flag -%c\n", *p
);
* if nothing spec'd, setup default conversion.
* calculate display parameters
for (cv
= conv_vec
; d
= *cv
; cv
++)
nelm
= (dbuf_size
+ d
->df_size
- 1) / d
->df_size
;
llen
= nelm
* (d
->df_field
+ 1);
* setup df_fmt to point to uniform output fields.
for (cv
= conv_vec
; d
= *cv
; cv
++)
if (d
->df_field
) /* only if external field is known */
nelm
= (dbuf_size
+ d
->df_size
- 1) / d
->df_size
;
d
->df_fmt
= fmt
+ 12 - (field
- d
->df_field
);
if(argc
> 0 && **argv
!= '+')
if (freopen(*argv
, "r", stdin
) == NULL
)
* check for possible offset [label]
while ((n
= fread(dbuf
, 1, dbuf_size
, stdin
)) > 0)
if (same
>=0 && bcmp(dbuf
, lastdbuf
, dbuf_size
) == 0 && !showall
)
for (nelm
= 0; nelm
< dbuf_size
; nelm
++)
* Some conversions require "flushing".
for (cv
= conv_vec
; *cv
; cv
++)
put_addr(addr
, label
, '\n');
(*((*cv
)->df_put
))(0, *cv
);
fputs(icvt(a
, addr_base
, UNSIGNED
, 7), stdout
);
printf(" (%s)", icvt(l
, addr_base
, UNSIGNED
, 7));
register struct dfmt
**cv
= conv_vec
;
put_addr(addr
, label
, ' ');
i
+= (*(c
->df_put
))(dbuf
+i
, c
);
printf(d
->df_fmt
, icvt((long)*n
, d
->df_radix
, d
->df_signed
, d
->df_field
));
printf(d
->df_fmt
, icvt((long)*n
, d
->df_radix
, d
->df_signed
, d
->df_field
));
printf(d
->df_fmt
, icvt(*n
, d
->df_radix
, d
->df_signed
, d
->df_field
));
if ((((struct l
*)f
)->n
[0] & 0xff00) == 0x8000) /* Vax illegal f.p. */
sprintf(fbuf
, " %08x %08x",
((struct l
*)f
)->n
[0], ((struct l
*)f
)->n
[1]);
sprintf(fbuf
, "%21.14e", *f
);
if ((*(long *)f
& 0xff00) == 0x8000) /* Vax illegal f.p. form */
sprintf(fbuf
, " %08x", *(long *)f
);
sprintf(fbuf
, "%14.7e", *f
);
/* 000 */ "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
/* 010 */ " bs", " ht", " nl", " vt", " ff", " cr", " so", " si",
/* 020 */ "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
/* 030 */ "can", " em", "sub", "esc", " fs", " gs", " rs", " us",
register pbit
= parity((int)c
& 0377);
printf(d
->df_fmt
, underline(s
));
printf(d
->df_fmt
, underline(asc_name
[c
]));
printf(d
->df_fmt
, asc_name
[c
]);
register char *u
= ulbuf
;
printf(d
->df_fmt
, icvt((long)*b
& 0377, d
->df_radix
, d
->df_signed
, d
->df_field
));
register int c
= *cc
& 0377;
for (n
= d
->df_field
- strlen(s
); n
> 0; n
--)
return(icvt((long)c
, d
->df_radix
, d
->df_signed
, d
->df_field
));
* A string contains bytes > 037 && < 177, and ends with a null.
* The minimum length is given in the dfmt structure.
static char str_buf
[SBUFSIZE
];
static int str_mode
= S_EMPTY
;
str_addr
= addr
+ (cc
- dbuf
); /* ugly */
if ((str_label
= label
) >= 0)
str_label
+= (cc
- dbuf
); /* '' */
if (str_ptr
>= (str_buf
+ SBUFSIZE
))
register char *p
= str_buf
;
|| (!(str_mode
& S_CONT
) && (str_ptr
- str_buf
) < d
->df_size
))
if (!(str_mode
& S_CONT
))
put_addr(str_addr
, str_label
, ' ');
fputs(scvt(*p
++, d
), stdout
);
* integer to ascii conversion
* This code has been rearranged to produce optimized runtime code.
static char _digit
[] = "0123456789abcdef";
static char _icv_buf
[MAXINTLENGTH
+1];
static long _mask
= 0x7fffffff;
icvt (value
, radix
, signed, ndigits
)
register long val
= value
;
register long rad
= radix
;
register char *b
= &_icv_buf
[MAXINTLENGTH
];
register char *d
= _digit
;
goto done
; /*return(b);*/
if (signed && (sign
= (val
< 0))) /* signed conversion */
* It is necessary to do the first divide
* before the absolute value, for the case -2^31
* This is actually what is being done...
* tmp1 = (int)(val % rad);
*--b
= d
[(tmp1
* rad
) - val
];
else /* unsigned conversion */
{ /* ALL THIS IS TO SIMULATE UNSIGNED LONG MOD & DIV */
kludge
= _mask
- (rad
- 1);
* This is really what's being done...
* rem = (kludge % rad) + (val % rad);
* val = (kludge / rad) + (val / rad) + (rem / rad) + 1;
rem
= (kludge
- (tmp1
* rad
)) + (val
- (tmp2
* rad
));
*--b
= d
[rem
- (tmp1
* rad
)];
* This is really what's being done ...
*--b
= d
[val
- (tmp1
* rad
)];
tmp1
= ndigits
- (&_icv_buf
[MAXINTLENGTH
] - b
);
else if (*s
=='0' && s
[1]=='x')
a
= a
*addr_base
+ d
- '0';
else if (ishex(d
) && addr_base
==16)
a
= a
*addr_base
+ d
+ 10 - 'a';
* in case we're accessing a raw disk,
* we have to seek in multiples of a physical block.
fseek(stdin
, a
& 0xfffffe00L
, 0);
nr
= (offset
> BUFSIZ
) ? BUFSIZ
: (int)offset
;
if ((n
= fread(buf
, 1, nr
, s
)) != nr
)
fprintf(stderr
, "EOF\n");
return( (fstat(fileno(f
),&statb
)==0) &&
(statb
.st_nlink
> 0) && /*!pipe*/