xref: /csrg-svn/old/od/od.c (revision 33080)
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