1*33080Sbostic static char *sccsid = "@(#)od.c 5.15 (Berkeley) 12/21/87";
24492Sdlw /*
34492Sdlw * od -- octal, hex, decimal, character dump of data in a file.
44492Sdlw *
511074Sdlw * usage: od [-abBcdDefFhHiIlLopPs[n]vw[n]xX] [file] [[+]offset[.][b] [label]]
64492Sdlw *
74492Sdlw * where the option flags have the following meaning:
84492Sdlw * character object radix signed?
94492Sdlw * a byte (10) (n.a.) ASCII named byte stream
104492Sdlw * b byte 8 no byte octal
114492Sdlw * c byte (8) (no) character with octal non-graphic bytes
124492Sdlw * d short 10 no
134492Sdlw * D long 10 no
144492Sdlw * e,F double (10) double precision floating pt.
154492Sdlw * f float (10) single precision floating pt.
164492Sdlw * h,x short 16 no
174492Sdlw * H,X long 16 no
184492Sdlw * i short 10 yes
194492Sdlw * I,l,L long 10 yes
204687Sdlw * o,B short 8 no (default conversion)
214492Sdlw * O long 8 no
2211074Sdlw * s[n] string (8) ASCII graphic strings
234492Sdlw *
244492Sdlw * p indicate EVEN parity on 'a' conversion
254492Sdlw * P indicate ODD parity on 'a' conversion
264492Sdlw * v show all data - don't skip like lines.
2711074Sdlw * w[n] bytes per display line
284492Sdlw *
294492Sdlw * More than one format character may be given.
304492Sdlw * If {file} is not specified, standard input is read.
314492Sdlw * If {file} is not specified, then {offset} must start with '+'.
3211074Sdlw * {Offset} may be HEX (0xnnn), OCTAL (0nn), or decimal (nnn.).
3311074Sdlw * The default is octal. The same radix will be used to display the address.
344492Sdlw */
354492Sdlw
364492Sdlw #include <stdio.h>
374492Sdlw
3811074Sdlw #define DBUF_SIZE BUFSIZ
3911074Sdlw #define BIG_DBUF 32
404687Sdlw #define NO 0
414687Sdlw #define YES 1
424687Sdlw #define EVEN -1
434687Sdlw #define ODD 1
444687Sdlw #define UNSIGNED 0
454687Sdlw #define SIGNED 1
464687Sdlw #define PADDR 1
474687Sdlw #define MIN_SLEN 3
484492Sdlw
494492Sdlw int a_put();
504492Sdlw int b_put();
514492Sdlw int c_put();
524492Sdlw int s_put();
534492Sdlw int us_put();
544492Sdlw int l_put();
554492Sdlw int f_put();
564492Sdlw int d_put();
574687Sdlw int st_put();
584492Sdlw
594492Sdlw struct dfmt {
604492Sdlw int df_field; /* external field required for object */
614492Sdlw int df_size; /* size (bytes) of object */
624492Sdlw int df_radix; /* conversion radix */
634492Sdlw int df_signed; /* signed? flag */
644687Sdlw int df_paddr; /* "put address on each line?" flag */
654492Sdlw int (*df_put)(); /* function to output object */
664687Sdlw char *df_fmt; /* output string format */
674492Sdlw } *conv_vec[32]; /* vector of conversions to be done */
684492Sdlw
694687Sdlw struct dfmt ascii = { 3, sizeof (char), 10, 0, PADDR, a_put, 0};
704687Sdlw struct dfmt byte = { 3, sizeof (char), 8, UNSIGNED, PADDR, b_put, 0};
714687Sdlw struct dfmt cchar = { 3, sizeof (char), 8, UNSIGNED, PADDR, c_put, 0};
724687Sdlw struct dfmt u_s_oct = { 6, sizeof (short), 8, UNSIGNED, PADDR, us_put, 0};
734687Sdlw struct dfmt u_s_dec = { 5, sizeof (short), 10, UNSIGNED, PADDR, us_put, 0};
744687Sdlw struct dfmt u_s_hex = { 4, sizeof (short), 16, UNSIGNED, PADDR, us_put, 0};
754687Sdlw struct dfmt u_l_oct = {11, sizeof (long), 8, UNSIGNED, PADDR, l_put, 0};
764687Sdlw struct dfmt u_l_dec = {10, sizeof (long), 10, UNSIGNED, PADDR, l_put, 0};
774687Sdlw struct dfmt u_l_hex = { 8, sizeof (long), 16, UNSIGNED, PADDR, l_put, 0};
784687Sdlw struct dfmt s_s_dec = { 6, sizeof (short), 10, SIGNED, PADDR, s_put, 0};
794687Sdlw struct dfmt s_l_dec = {11, sizeof (long), 10, SIGNED, PADDR, l_put, 0};
804687Sdlw struct dfmt flt = {14, sizeof (float), 10, SIGNED, PADDR, f_put, 0};
814687Sdlw struct dfmt dble = {21, sizeof (double), 10, SIGNED, PADDR, d_put, 0};
824687Sdlw struct dfmt string = { 0, 0, 8, 0, NO, st_put, 0};
834492Sdlw
844530Sdlw
8511074Sdlw char usage[] ="usage: od [-abcdfhilopswvx] [file] [[+]offset[.][b] [label]]";
864687Sdlw char dbuf[DBUF_SIZE];
874687Sdlw char lastdbuf[DBUF_SIZE];
8811074Sdlw int addr_base = 8; /* default address base is OCTAL */
8911074Sdlw long addr = 0L; /* current file offset */
9011074Sdlw long label = -1L; /* current label; -1 is "off" */
9111074Sdlw int dbuf_size = 16; /* file bytes / display line */
9211074Sdlw int _parity = NO; /* show parity on ascii bytes */
934492Sdlw char fmt[] = " %s"; /* 12 blanks */
944492Sdlw char *icvt();
954687Sdlw char *scvt();
964492Sdlw char *underline();
974530Sdlw long get_addr();
984492Sdlw
994530Sdlw
1004687Sdlw /*
1014687Sdlw * special form of _ctype
1024687Sdlw */
1034687Sdlw
1044687Sdlw #define A 01
1054687Sdlw #define G 02
1064687Sdlw #define D 04
1074687Sdlw #define P 010
1084687Sdlw #define X 020
1094687Sdlw #define isdigit(c) (_ctype[c] & D)
1104687Sdlw #define isascii(c) (_ctype[c] & A)
1114687Sdlw #define isgraphic(c) (_ctype[c] & G)
1124687Sdlw #define isprint(c) (_ctype[c] & P)
1134687Sdlw #define ishex(c) (_ctype[c] & (X|D))
1144687Sdlw
1154687Sdlw char _ctype[256] = {
1164687Sdlw /* 000 */ 0, 0, 0, 0, 0, 0, 0, 0,
1174687Sdlw /* 010 */ A, A, A, 0, A, A, 0, 0,
1184687Sdlw /* 020 */ 0, 0, 0, 0, 0, 0, 0, 0,
1194687Sdlw /* 030 */ 0, 0, 0, 0, 0, 0, 0, 0,
1204687Sdlw /* 040 */ P|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A,
1214687Sdlw /* 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,
1224687Sdlw /* 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,
1234687Sdlw /* 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,
1244687Sdlw /* 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,
1254687Sdlw /* 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,
1264687Sdlw /* 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,
1274687Sdlw /* 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,
1284687Sdlw /* 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,
1294687Sdlw /* 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,
1304687Sdlw /* 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,
1314687Sdlw /* 170 */ P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, 0,
1324687Sdlw /* 200 */ 0, 0, 0, 0, 0, 0, 0, 0,
1334687Sdlw /* 210 */ 0, 0, 0, 0, 0, 0, 0, 0,
1344687Sdlw /* 220 */ 0, 0, 0, 0, 0, 0, 0, 0,
1354687Sdlw /* 230 */ 0, 0, 0, 0, 0, 0, 0, 0,
1364687Sdlw /* 240 */ 0, 0, 0, 0, 0, 0, 0, 0,
1374687Sdlw /* 250 */ 0, 0, 0, 0, 0, 0, 0, 0,
1384687Sdlw /* 260 */ 0, 0, 0, 0, 0, 0, 0, 0,
1394687Sdlw /* 270 */ 0, 0, 0, 0, 0, 0, 0, 0,
1404687Sdlw /* 300 */ 0, 0, 0, 0, 0, 0, 0, 0,
1414687Sdlw /* 310 */ 0, 0, 0, 0, 0, 0, 0, 0,
1424687Sdlw /* 320 */ 0, 0, 0, 0, 0, 0, 0, 0,
1434687Sdlw /* 330 */ 0, 0, 0, 0, 0, 0, 0, 0,
1444687Sdlw /* 340 */ 0, 0, 0, 0, 0, 0, 0, 0,
1454687Sdlw /* 350 */ 0, 0, 0, 0, 0, 0, 0, 0,
1464687Sdlw /* 360 */ 0, 0, 0, 0, 0, 0, 0, 0,
1474687Sdlw /* 370 */ 0, 0, 0, 0, 0, 0, 0, 0,
1484687Sdlw };
1494687Sdlw
1504687Sdlw
main(argc,argv)1514492Sdlw main(argc, argv)
1524687Sdlw int argc;
1534687Sdlw char **argv;
1544492Sdlw {
1554492Sdlw register char *p;
1564492Sdlw register char *l;
1574492Sdlw register n, same;
1584492Sdlw struct dfmt *d;
1594492Sdlw struct dfmt **cv = conv_vec;
1604492Sdlw int showall = NO;
1614492Sdlw int field, llen, nelm;
1624492Sdlw int max_llen = 0;
1634492Sdlw
1644492Sdlw argv++;
1654530Sdlw argc--;
1664492Sdlw
1674687Sdlw if(argc > 0)
1684687Sdlw {
1694492Sdlw p = *argv;
1704687Sdlw if(*p == '-')
1714687Sdlw {
1724687Sdlw while(*++p != '\0')
1734687Sdlw {
1744687Sdlw switch(*p)
1754687Sdlw {
1764492Sdlw case 'a':
1774492Sdlw d = &ascii;
1784492Sdlw break;
1794492Sdlw case 'b':
1804492Sdlw d = &byte;
1814492Sdlw break;
1824492Sdlw case 'c':
1834492Sdlw d = &cchar;
1844492Sdlw break;
1854492Sdlw case 'd':
1864492Sdlw d = &u_s_dec;
1874492Sdlw break;
1884492Sdlw case 'D':
1894492Sdlw d = &u_l_dec;
1904492Sdlw break;
1914492Sdlw case 'e':
1924492Sdlw case 'F':
1934492Sdlw d = &dble;
1944492Sdlw break;
1954492Sdlw case 'f':
1964492Sdlw d = &flt;
1974492Sdlw break;
1984492Sdlw case 'h':
1994492Sdlw case 'x':
2004492Sdlw d = &u_s_hex;
2014492Sdlw break;
2024492Sdlw case 'H':
2034492Sdlw case 'X':
2044492Sdlw d = &u_l_hex;
2054492Sdlw break;
2064492Sdlw case 'i':
2074492Sdlw d = &s_s_dec;
2084492Sdlw break;
2094492Sdlw case 'I':
2104492Sdlw case 'l':
2114492Sdlw case 'L':
2124492Sdlw d = &s_l_dec;
2134492Sdlw break;
2144492Sdlw case 'o':
2154687Sdlw case 'B':
2164492Sdlw d = &u_s_oct;
2174492Sdlw break;
2184492Sdlw case 'O':
2194492Sdlw d = &u_l_oct;
2204492Sdlw break;
2214492Sdlw case 'p':
2224492Sdlw _parity = EVEN;
2234492Sdlw continue;
2244492Sdlw case 'P':
2254492Sdlw _parity = ODD;
2264492Sdlw continue;
2274687Sdlw case 's':
2284687Sdlw d = &string;
2294687Sdlw *(cv++) = d;
2304687Sdlw while (isdigit(p[1]))
2314687Sdlw d->df_size = (10 * d->df_size) + (*++p - '0');
2324687Sdlw if (d->df_size <= 0)
2334687Sdlw d->df_size = MIN_SLEN;
2344687Sdlw showall = YES;
2354687Sdlw continue;
23611074Sdlw case 'w':
23711074Sdlw dbuf_size = 0;
23811074Sdlw while (isdigit(p[1]))
23911074Sdlw dbuf_size = (10 * dbuf_size) + (*++p - '0');
24011074Sdlw if (dbuf_size == 0)
24111074Sdlw dbuf_size = BIG_DBUF;
24211074Sdlw continue;
2434492Sdlw case 'v':
2444492Sdlw showall = YES;
2454492Sdlw continue;
2464530Sdlw default:
2474530Sdlw printf("od: bad flag -%c\n", *p);
2484530Sdlw puts(usage);
2494530Sdlw exit(1);
2504492Sdlw }
2514492Sdlw *(cv++) = d;
2524492Sdlw }
2534492Sdlw argc--;
2544492Sdlw argv++;
2554492Sdlw }
2564492Sdlw }
2574492Sdlw
2584687Sdlw /*
2594687Sdlw * if nothing spec'd, setup default conversion.
2604687Sdlw */
2614687Sdlw if(cv == conv_vec)
2624492Sdlw *(cv++) = &u_s_oct;
26311074Sdlw
2644492Sdlw *cv = (struct dfmt *)0;
2654492Sdlw
2664687Sdlw /*
26711074Sdlw * calculate display parameters
26811074Sdlw */
26911074Sdlw for (cv = conv_vec; d = *cv; cv++)
27011074Sdlw {
27111074Sdlw nelm = (dbuf_size + d->df_size - 1) / d->df_size;
27211074Sdlw llen = nelm * (d->df_field + 1);
27311074Sdlw if (llen > max_llen)
27411074Sdlw max_llen = llen;
27511074Sdlw }
27611074Sdlw
27711074Sdlw /*
2784687Sdlw * setup df_fmt to point to uniform output fields.
2794687Sdlw */
28011074Sdlw for (cv = conv_vec; d = *cv; cv++)
2814687Sdlw {
2824687Sdlw if (d->df_field) /* only if external field is known */
2834687Sdlw {
28411074Sdlw nelm = (dbuf_size + d->df_size - 1) / d->df_size;
2854687Sdlw field = max_llen / nelm;
2864687Sdlw d->df_fmt = fmt + 12 - (field - d->df_field);
2874687Sdlw }
2884492Sdlw }
2894492Sdlw
2904687Sdlw /*
2914687Sdlw * input file specified ?
2924687Sdlw */
2934687Sdlw if(argc > 0 && **argv != '+')
2944687Sdlw {
2954687Sdlw if (freopen(*argv, "r", stdin) == NULL)
2964687Sdlw {
29712093Smckusick perror(*argv);
2984492Sdlw exit(1);
2994492Sdlw }
3004492Sdlw argv++;
3014492Sdlw argc--;
3024492Sdlw }
3034492Sdlw
3044687Sdlw /*
3054687Sdlw * check for possible offset [label]
3064687Sdlw */
3074530Sdlw if (argc > 0)
3084530Sdlw {
3094530Sdlw addr = get_addr(*argv);
3104530Sdlw offset(addr);
3114530Sdlw argv++;
3124530Sdlw argc--;
3134492Sdlw
3144530Sdlw if (argc > 0)
3154530Sdlw label = get_addr(*argv);
3164530Sdlw }
3174530Sdlw
3184687Sdlw /*
3194687Sdlw * main dump loop
3204687Sdlw */
3214492Sdlw same = -1;
32211074Sdlw while ((n = fread(dbuf, 1, dbuf_size, stdin)) > 0)
3234687Sdlw {
32416484Sralph if (same>=0 && bcmp(dbuf, lastdbuf, dbuf_size) == 0 && !showall)
3254687Sdlw {
3264687Sdlw if (same==0)
3274687Sdlw {
3284492Sdlw printf("*\n");
3294492Sdlw same = 1;
3304492Sdlw }
3314492Sdlw }
3324687Sdlw else
3334687Sdlw {
3344492Sdlw line(n);
3354492Sdlw same = 0;
3364492Sdlw p = dbuf;
3374492Sdlw l = lastdbuf;
33811074Sdlw for (nelm = 0; nelm < dbuf_size; nelm++)
3394687Sdlw {
3404492Sdlw *l++ = *p;
3414492Sdlw *p++ = '\0';
3424492Sdlw }
3434492Sdlw }
3444492Sdlw addr += n;
3454530Sdlw if (label >= 0)
3464530Sdlw label += n;
3474492Sdlw }
3484687Sdlw
3494687Sdlw /*
3504687Sdlw * Some conversions require "flushing".
3514687Sdlw */
3524687Sdlw n = 0;
3534687Sdlw for (cv = conv_vec; *cv; cv++)
3544687Sdlw {
3554687Sdlw if ((*cv)->df_paddr)
3564687Sdlw {
3574687Sdlw if (n++ == 0)
3584687Sdlw put_addr(addr, label, '\n');
3594687Sdlw }
3604687Sdlw else
3614687Sdlw (*((*cv)->df_put))(0, *cv);
3624687Sdlw }
36332739Sbostic exit(0);
3644492Sdlw }
3654492Sdlw
put_addr(a,l,c)3664687Sdlw put_addr(a, l, c)
3674687Sdlw long a;
3684687Sdlw long l;
3694530Sdlw char c;
3704530Sdlw {
3714687Sdlw fputs(icvt(a, addr_base, UNSIGNED, 7), stdout);
3724687Sdlw if (l >= 0)
3734687Sdlw printf(" (%s)", icvt(l, addr_base, UNSIGNED, 7));
3744530Sdlw putchar(c);
3754530Sdlw }
3764530Sdlw
line(n)3774492Sdlw line(n)
3784492Sdlw int n;
3794492Sdlw {
3804492Sdlw register i, first;
3814492Sdlw register struct dfmt *c;
3824492Sdlw register struct dfmt **cv = conv_vec;
3834492Sdlw
3844492Sdlw first = YES;
3854687Sdlw while (c = *cv++)
3864687Sdlw {
3874687Sdlw if (c->df_paddr)
3884687Sdlw {
3894687Sdlw if (first)
3904687Sdlw {
3914687Sdlw put_addr(addr, label, ' ');
3924687Sdlw first = NO;
3934687Sdlw }
3944687Sdlw else
3954687Sdlw {
3964687Sdlw putchar('\t');
3974687Sdlw if (label >= 0)
3984687Sdlw fputs("\t ", stdout);
3994687Sdlw }
4004530Sdlw }
4014492Sdlw i = 0;
4024492Sdlw while (i < n)
4034492Sdlw i += (*(c->df_put))(dbuf+i, c);
4044687Sdlw if (c->df_paddr)
4054687Sdlw putchar('\n');
4064492Sdlw }
4074492Sdlw }
4084492Sdlw
s_put(n,d)4094492Sdlw s_put(n, d)
4104492Sdlw short *n;
4114492Sdlw struct dfmt *d;
4124492Sdlw {
4134492Sdlw printf(d->df_fmt, icvt((long)*n, d->df_radix, d->df_signed, d->df_field));
4144492Sdlw return(d->df_size);
4154492Sdlw }
4164492Sdlw
us_put(n,d)4174492Sdlw us_put(n, d)
4184492Sdlw unsigned short *n;
4194492Sdlw struct dfmt *d;
4204492Sdlw {
4214492Sdlw printf(d->df_fmt, icvt((long)*n, d->df_radix, d->df_signed, d->df_field));
4224492Sdlw return(d->df_size);
4234492Sdlw }
4244492Sdlw
l_put(n,d)4254492Sdlw l_put(n, d)
4264492Sdlw long *n;
4274492Sdlw struct dfmt *d;
4284492Sdlw {
4294492Sdlw printf(d->df_fmt, icvt(*n, d->df_radix, d->df_signed, d->df_field));
4304492Sdlw return(d->df_size);
4314492Sdlw }
4324492Sdlw
d_put(f,d)4334492Sdlw d_put(f, d)
4344492Sdlw double *f;
4354492Sdlw struct dfmt *d;
4364492Sdlw {
4374492Sdlw char fbuf[24];
4384500Sdlw struct l { long n[2]; };
4394500Sdlw
4404500Sdlw #if vax
4414500Sdlw if ((((struct l *)f)->n[0] & 0xff00) == 0x8000) /* Vax illegal f.p. */
44232416Sbostic (void)sprintf(fbuf, " %08x %08x",
4434500Sdlw ((struct l *)f)->n[0], ((struct l *)f)->n[1]);
4444500Sdlw else
4454500Sdlw #endif
4464500Sdlw
44732416Sbostic (void)sprintf(fbuf, "%21.14e", *f);
4484492Sdlw printf(d->df_fmt, fbuf);
4494492Sdlw return(d->df_size);
4504492Sdlw }
4514492Sdlw
f_put(f,d)4524492Sdlw f_put(f, d)
4534492Sdlw float *f;
4544492Sdlw struct dfmt *d;
4554492Sdlw {
4564492Sdlw char fbuf[16];
4574500Sdlw
4584500Sdlw #if vax
4594500Sdlw if ((*(long *)f & 0xff00) == 0x8000) /* Vax illegal f.p. form */
46032416Sbostic (void)sprintf(fbuf, " %08x", *(long *)f);
4614500Sdlw else
4624500Sdlw #endif
46332416Sbostic (void)sprintf(fbuf, "%14.7e", *f);
4644492Sdlw printf(d->df_fmt, fbuf);
4654492Sdlw return(d->df_size);
4664492Sdlw }
4674492Sdlw
4684492Sdlw
4694492Sdlw char asc_name[34][4] = {
4704687Sdlw /* 000 */ "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
4714687Sdlw /* 010 */ " bs", " ht", " nl", " vt", " ff", " cr", " so", " si",
4724687Sdlw /* 020 */ "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
4734687Sdlw /* 030 */ "can", " em", "sub", "esc", " fs", " gs", " rs", " us",
4744687Sdlw /* 040 */ " sp", "del"
4754492Sdlw };
4764492Sdlw
a_put(cc,d)4774492Sdlw a_put(cc, d)
4784492Sdlw char *cc;
4794492Sdlw struct dfmt *d;
4804492Sdlw {
4814492Sdlw int c = *cc;
4824492Sdlw register char *s = " ";
4834492Sdlw register pbit = parity((int)c & 0377);
4844492Sdlw
4854492Sdlw c &= 0177;
4864687Sdlw if (isgraphic(c))
4874492Sdlw {
4884687Sdlw s[2] = c;
4894492Sdlw if (pbit == _parity)
4904503Sdlw printf(d->df_fmt, underline(s));
4914492Sdlw else
4924492Sdlw printf(d->df_fmt, s);
4934492Sdlw }
4944492Sdlw else
4954492Sdlw {
4964492Sdlw if (c == 0177)
4974492Sdlw c = ' ' + 1;
4984492Sdlw if (pbit == _parity)
4994503Sdlw printf(d->df_fmt, underline(asc_name[c]));
5004492Sdlw else
5014492Sdlw printf(d->df_fmt, asc_name[c]);
5024492Sdlw }
5034492Sdlw return(1);
5044492Sdlw }
5054492Sdlw
parity(word)5064492Sdlw parity(word)
5074492Sdlw int word;
5084492Sdlw {
5094492Sdlw register int p = 0;
5104492Sdlw register int w = word;
5114492Sdlw
5124492Sdlw if (w)
5134687Sdlw do
5144687Sdlw {
5154492Sdlw p ^= 1;
5164492Sdlw } while(w &= (~(-w)));
5174492Sdlw return (p? ODD:EVEN);
5184492Sdlw }
5194492Sdlw
5204492Sdlw char *
underline(s)5214503Sdlw underline(s)
5224492Sdlw char *s;
5234492Sdlw {
5244492Sdlw static char ulbuf[16];
5254492Sdlw register char *u = ulbuf;
5264492Sdlw
5274687Sdlw while (*s)
5284687Sdlw {
5294687Sdlw if (*s != ' ')
5304687Sdlw {
5314492Sdlw *u++ = '_';
5324492Sdlw *u++ = '\b';
5334492Sdlw }
5344492Sdlw *u++ = *s++;
5354492Sdlw }
5364492Sdlw *u = '\0';
5374492Sdlw return(ulbuf);
5384492Sdlw }
5394492Sdlw
b_put(b,d)5404492Sdlw b_put(b, d)
5414492Sdlw char *b;
5424492Sdlw struct dfmt *d;
5434492Sdlw {
5444492Sdlw printf(d->df_fmt, icvt((long)*b & 0377, d->df_radix, d->df_signed, d->df_field));
5454492Sdlw return(1);
5464492Sdlw }
5474492Sdlw
c_put(cc,d)5484492Sdlw c_put(cc, d)
5494492Sdlw char *cc;
5504492Sdlw struct dfmt *d;
5514492Sdlw {
5524687Sdlw register char *s;
5534687Sdlw register int n;
5544687Sdlw register int c = *cc & 0377;
5554492Sdlw
5564687Sdlw s = scvt(c, d);
5574687Sdlw for (n = d->df_field - strlen(s); n > 0; n--)
5584687Sdlw putchar(' ');
5594687Sdlw printf(d->df_fmt, s);
5604687Sdlw return(1);
5614687Sdlw }
5624687Sdlw
scvt(c,d)5634687Sdlw char *scvt(c, d)
5644687Sdlw int c;
5654687Sdlw struct dfmt *d;
5664687Sdlw {
5674687Sdlw static char s[2];
5684687Sdlw
5694687Sdlw switch(c)
5704687Sdlw {
5714687Sdlw case '\0':
5724687Sdlw return("\\0");
5734687Sdlw
5744687Sdlw case '\b':
5754687Sdlw return("\\b");
5764687Sdlw
5774687Sdlw case '\f':
5784687Sdlw return("\\f");
5794687Sdlw
5804687Sdlw case '\n':
5814687Sdlw return("\\n");
5824687Sdlw
5834687Sdlw case '\r':
5844687Sdlw return("\\r");
5854687Sdlw
5864687Sdlw case '\t':
5874687Sdlw return("\\t");
5884687Sdlw
5894687Sdlw default:
5904687Sdlw if (isprint(c))
5914687Sdlw {
5924687Sdlw s[0] = c;
5934687Sdlw return(s);
5944687Sdlw }
5954687Sdlw return(icvt((long)c, d->df_radix, d->df_signed, d->df_field));
5964492Sdlw }
5974687Sdlw }
5984492Sdlw
5994687Sdlw /*
6004687Sdlw * Look for strings.
6014687Sdlw * A string contains bytes > 037 && < 177, and ends with a null.
6024687Sdlw * The minimum length is given in the dfmt structure.
6034687Sdlw */
6044687Sdlw
6054687Sdlw #define CNULL '\0'
6064687Sdlw #define S_EMPTY 0
6074687Sdlw #define S_FILL 1
6084687Sdlw #define S_CONT 2
6094687Sdlw #define SBUFSIZE 1024
6104687Sdlw
6114687Sdlw static char str_buf[SBUFSIZE];
6124687Sdlw static int str_mode = S_EMPTY;
6134687Sdlw static char *str_ptr;
6144687Sdlw static long str_addr;
6154687Sdlw static long str_label;
6164687Sdlw
st_put(cc,d)6174716Sdlw st_put(cc, d)
6184716Sdlw char *cc;
6194687Sdlw struct dfmt *d;
6204687Sdlw {
6214716Sdlw register int c;
6224716Sdlw
6234716Sdlw if (cc == 0)
6244687Sdlw {
6254687Sdlw pr_sbuf(d, YES);
6264716Sdlw return(1);
6274492Sdlw }
6284716Sdlw
6294716Sdlw c = (*cc & 0377);
6304716Sdlw
6314716Sdlw if (str_mode & S_FILL)
6324687Sdlw {
6334716Sdlw if (isascii(c))
6344716Sdlw put_sbuf(c, d);
6354687Sdlw else
6364687Sdlw {
6374687Sdlw *str_ptr = CNULL;
6384716Sdlw if (c == NULL)
6394687Sdlw pr_sbuf(d, YES);
6404687Sdlw str_mode = S_EMPTY;
6414687Sdlw }
6424687Sdlw }
6434716Sdlw else if (isascii(c))
6444687Sdlw {
6454687Sdlw str_mode = S_FILL;
6464716Sdlw str_addr = addr + (cc - dbuf); /* ugly */
6474687Sdlw if ((str_label = label) >= 0)
6484716Sdlw str_label += (cc - dbuf); /* '' */
6494687Sdlw str_ptr = str_buf;
6504716Sdlw put_sbuf(c, d);
6514687Sdlw }
6524687Sdlw
6534492Sdlw return(1);
6544492Sdlw }
6554492Sdlw
put_sbuf(c,d)6564687Sdlw put_sbuf(c, d)
6574716Sdlw int c;
6584687Sdlw struct dfmt *d;
6594687Sdlw {
6604687Sdlw *str_ptr++ = c;
6614687Sdlw if (str_ptr >= (str_buf + SBUFSIZE))
6624687Sdlw {
6634687Sdlw pr_sbuf(d, NO);
6644687Sdlw str_ptr = str_buf;
6654687Sdlw str_mode |= S_CONT;
6664687Sdlw }
6674687Sdlw }
6684687Sdlw
6694687Sdlw pr_sbuf(d, end)
6704687Sdlw struct dfmt *d;
6714687Sdlw int end;
6724687Sdlw {
6734687Sdlw register char *p = str_buf;
6744687Sdlw
6754687Sdlw if (str_mode == S_EMPTY
6764687Sdlw || (!(str_mode & S_CONT) && (str_ptr - str_buf) < d->df_size))
6774687Sdlw return;
6784687Sdlw
6794687Sdlw if (!(str_mode & S_CONT))
6804687Sdlw put_addr(str_addr, str_label, ' ');
6814687Sdlw
6824687Sdlw while (p < str_ptr)
6834687Sdlw fputs(scvt(*p++, d), stdout);
6844687Sdlw
6854687Sdlw if (end)
6864687Sdlw putchar('\n');
6874687Sdlw }
6884687Sdlw
6894492Sdlw /*
6904492Sdlw * integer to ascii conversion
6914492Sdlw *
6924492Sdlw * This code has been rearranged to produce optimized runtime code.
6934492Sdlw */
6944492Sdlw
6954492Sdlw #define MAXINTLENGTH 32
6964492Sdlw static char _digit[] = "0123456789abcdef";
6974492Sdlw static char _icv_buf[MAXINTLENGTH+1];
6984492Sdlw static long _mask = 0x7fffffff;
6994492Sdlw
7004492Sdlw char *
icvt(value,radix,hassign,ndigits)701*33080Sbostic icvt (value, radix, hassign, ndigits)
7024492Sdlw long value;
7034492Sdlw int radix;
704*33080Sbostic int hassign;
7054492Sdlw int ndigits;
7064492Sdlw {
7074492Sdlw register long val = value;
7084492Sdlw register long rad = radix;
7094492Sdlw register char *b = &_icv_buf[MAXINTLENGTH];
7104492Sdlw register char *d = _digit;
7114492Sdlw register long tmp1;
7124492Sdlw register long tmp2;
7134492Sdlw long rem;
7144492Sdlw long kludge;
7154492Sdlw int sign;
7164492Sdlw
7174492Sdlw if (val == 0)
7184492Sdlw {
7194492Sdlw *--b = '0';
7204492Sdlw sign = 0;
7214492Sdlw goto done; /*return(b);*/
7224492Sdlw }
7234492Sdlw
724*33080Sbostic if (hassign && (sign = (val < 0))) /* signed conversion */
7254492Sdlw {
7264492Sdlw /*
7274492Sdlw * It is necessary to do the first divide
7284492Sdlw * before the absolute value, for the case -2^31
7294492Sdlw *
7304492Sdlw * This is actually what is being done...
7314492Sdlw * tmp1 = (int)(val % rad);
7324492Sdlw * val /= rad;
7334492Sdlw * val = -val
7344492Sdlw * *--b = d[-tmp1];
7354492Sdlw */
7364492Sdlw tmp1 = val / rad;
7374492Sdlw *--b = d[(tmp1 * rad) - val];
7384492Sdlw val = -tmp1;
7394492Sdlw }
7404492Sdlw else /* unsigned conversion */
7414492Sdlw {
7424492Sdlw sign = 0;
7434492Sdlw if (val < 0)
7444492Sdlw { /* ALL THIS IS TO SIMULATE UNSIGNED LONG MOD & DIV */
7454492Sdlw kludge = _mask - (rad - 1);
7464492Sdlw val &= _mask;
7474492Sdlw /*
7484492Sdlw * This is really what's being done...
7494492Sdlw * rem = (kludge % rad) + (val % rad);
7504492Sdlw * val = (kludge / rad) + (val / rad) + (rem / rad) + 1;
7514492Sdlw * *--b = d[rem % rad];
7524492Sdlw */
7534492Sdlw tmp1 = kludge / rad;
7544492Sdlw tmp2 = val / rad;
7554492Sdlw rem = (kludge - (tmp1 * rad)) + (val - (tmp2 * rad));
7564492Sdlw val = ++tmp1 + tmp2;
7574492Sdlw tmp1 = rem / rad;
7584492Sdlw val += tmp1;
7594492Sdlw *--b = d[rem - (tmp1 * rad)];
7604492Sdlw }
7614492Sdlw }
7624492Sdlw
7634492Sdlw while (val)
7644492Sdlw {
7654492Sdlw /*
7664492Sdlw * This is really what's being done ...
7674492Sdlw * *--b = d[val % rad];
7684492Sdlw * val /= rad;
7694492Sdlw */
7704492Sdlw tmp1 = val / rad;
7714492Sdlw *--b = d[val - (tmp1 * rad)];
7724492Sdlw val = tmp1;
7734492Sdlw }
7744492Sdlw
7754492Sdlw done:
7764492Sdlw if (sign)
7774492Sdlw *--b = '-';
7784492Sdlw
7794492Sdlw tmp1 = ndigits - (&_icv_buf[MAXINTLENGTH] - b);
780*33080Sbostic tmp2 = hassign? ' ':'0';
7814492Sdlw while (tmp1 > 0)
7824492Sdlw {
7834492Sdlw *--b = tmp2;
7844492Sdlw tmp1--;
7854492Sdlw }
7864492Sdlw
7874492Sdlw return(b);
7884492Sdlw }
7894492Sdlw
get_addr(s)7904687Sdlw long get_addr(s)
7914492Sdlw register char *s;
7924492Sdlw {
7934492Sdlw register char *p;
7944530Sdlw register long a;
7954492Sdlw register int d;
7964492Sdlw
7974492Sdlw if (*s=='+')
7984492Sdlw s++;
7994687Sdlw if (*s=='x')
8004687Sdlw {
8014492Sdlw s++;
8024492Sdlw addr_base = 16;
8034687Sdlw }
8044687Sdlw else if (*s=='0' && s[1]=='x')
8054687Sdlw {
8064492Sdlw s += 2;
8074492Sdlw addr_base = 16;
8084687Sdlw }
8094687Sdlw else if (*s == '0')
8104492Sdlw addr_base = 8;
8114492Sdlw p = s;
8124687Sdlw while(*p)
8134687Sdlw {
8144492Sdlw if (*p++=='.')
8154492Sdlw addr_base = 10;
8164492Sdlw }
8174687Sdlw for (a=0; *s; s++)
8184687Sdlw {
8194492Sdlw d = *s;
8204687Sdlw if(isdigit(d))
8214492Sdlw a = a*addr_base + d - '0';
8224687Sdlw else if (ishex(d) && addr_base==16)
8234492Sdlw a = a*addr_base + d + 10 - 'a';
8244492Sdlw else
8254492Sdlw break;
8264492Sdlw }
8274530Sdlw
8284492Sdlw if (*s == '.')
8294492Sdlw s++;
8304530Sdlw if(*s=='b')
8314492Sdlw a *= 512;
8324530Sdlw if(*s=='B')
8334530Sdlw a *= 1024;
8344530Sdlw
8354530Sdlw return(a);
8364530Sdlw }
8374530Sdlw
offset(a)8384530Sdlw offset(a)
8394530Sdlw long a;
8404530Sdlw {
8414492Sdlw if (canseek(stdin))
84211071Sdlw {
84311071Sdlw /*
84411071Sdlw * in case we're accessing a raw disk,
84511071Sdlw * we have to seek in multiples of a physical block.
84611071Sdlw */
84711071Sdlw fseek(stdin, a & 0xfffffe00L, 0);
84811071Sdlw a &= 0x1ffL;
84911071Sdlw }
85011071Sdlw dumbseek(stdin, a);
8514492Sdlw }
8524492Sdlw
dumbseek(s,offset)8534492Sdlw dumbseek(s, offset)
8544492Sdlw FILE *s;
8554492Sdlw long offset;
8564492Sdlw {
8574492Sdlw char buf[BUFSIZ];
8584492Sdlw int n;
8594492Sdlw int nr;
8604492Sdlw
8614492Sdlw while (offset > 0)
8624492Sdlw {
8634492Sdlw nr = (offset > BUFSIZ) ? BUFSIZ : (int)offset;
8644492Sdlw if ((n = fread(buf, 1, nr, s)) != nr)
8654492Sdlw {
8664492Sdlw fprintf(stderr, "EOF\n");
8674492Sdlw exit(1);
8684492Sdlw }
8694492Sdlw offset -= n;
8704492Sdlw }
8714492Sdlw }
8724492Sdlw
8734492Sdlw #include <sys/types.h>
8744492Sdlw #include <sys/stat.h>
8754492Sdlw
canseek(f)8764492Sdlw canseek(f)
8774492Sdlw FILE *f;
8784492Sdlw {
8794492Sdlw struct stat statb;
8804492Sdlw
8814492Sdlw return( (fstat(fileno(f),&statb)==0) &&
8824492Sdlw (statb.st_nlink > 0) && /*!pipe*/
8834492Sdlw (!isatty(fileno(f))) );
8844492Sdlw }
885