xref: /csrg-svn/old/od/od.c (revision 4687)
1*4687Sdlw static char *sccsid = "@(#)od.c	5.5 (Berkeley) 10/31/81";
24492Sdlw /*
34492Sdlw  * od -- octal, hex, decimal, character dump of data in a file.
44492Sdlw  *
5*4687Sdlw  * usage:  od [-abBcdDefFhHiIlLopPsvxX] [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
20*4687Sdlw  *	o,B	short	  8	 no	(default conversion)
214492Sdlw  *	O	long	  8	 no
22*4687Sdlw  *	s	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.
274492Sdlw  *
284492Sdlw  * More than one format character may be given.
294492Sdlw  * If {file} is not specified, standard input is read.
304492Sdlw  * If {file} is not specified, then {offset} must start with '+'.
314492Sdlw  * {Offset} may be HEX (0xnnn), OCTAL (0nn), or decimal (nnn.); the default
324492Sdlw  * is the same as the address radix, which will be the same as the first
334492Sdlw  * object radix.
344492Sdlw  */
354492Sdlw 
364492Sdlw #include <stdio.h>
374492Sdlw 
38*4687Sdlw #define DBUF_SIZE      16
39*4687Sdlw #define NO		0
40*4687Sdlw #define YES		1
41*4687Sdlw #define EVEN	       -1
42*4687Sdlw #define ODD		1
43*4687Sdlw #define UNSIGNED	0
44*4687Sdlw #define SIGNED		1
45*4687Sdlw #define PADDR		1
46*4687Sdlw #define MIN_SLEN	3
474492Sdlw 
484492Sdlw int	a_put();
494492Sdlw int	b_put();
504492Sdlw int	c_put();
514492Sdlw int	s_put();
524492Sdlw int	us_put();
534492Sdlw int	l_put();
544492Sdlw int	f_put();
554492Sdlw int	d_put();
56*4687Sdlw int	st_put();
574492Sdlw 
584492Sdlw struct dfmt {
594492Sdlw 	int	df_field;	/* external field required for object */
604492Sdlw 	int	df_size;	/* size (bytes) of object */
614492Sdlw 	int	df_radix;	/* conversion radix */
624492Sdlw 	int	df_signed;	/* signed? flag */
63*4687Sdlw 	int	df_paddr;	/* "put address on each line?" flag */
644492Sdlw 	int	(*df_put)();	/* function to output object */
65*4687Sdlw 	char	*df_fmt;	/* output string format */
664492Sdlw } *conv_vec[32];		/* vector of conversions to be done */
674492Sdlw 
68*4687Sdlw struct dfmt	ascii	= { 3, sizeof (char),   10,        0, PADDR,  a_put, 0};
69*4687Sdlw struct dfmt	byte	= { 3, sizeof (char),    8, UNSIGNED, PADDR,  b_put, 0};
70*4687Sdlw struct dfmt	cchar	= { 3, sizeof (char),    8, UNSIGNED, PADDR,  c_put, 0};
71*4687Sdlw struct dfmt	u_s_oct	= { 6, sizeof (short),   8, UNSIGNED, PADDR, us_put, 0};
72*4687Sdlw struct dfmt	u_s_dec	= { 5, sizeof (short),  10, UNSIGNED, PADDR, us_put, 0};
73*4687Sdlw struct dfmt	u_s_hex	= { 4, sizeof (short),  16, UNSIGNED, PADDR, us_put, 0};
74*4687Sdlw struct dfmt	u_l_oct	= {11, sizeof (long),    8, UNSIGNED, PADDR,  l_put, 0};
75*4687Sdlw struct dfmt	u_l_dec	= {10, sizeof (long),   10, UNSIGNED, PADDR,  l_put, 0};
76*4687Sdlw struct dfmt	u_l_hex	= { 8, sizeof (long),   16, UNSIGNED, PADDR,  l_put, 0};
77*4687Sdlw struct dfmt	s_s_dec	= { 6, sizeof (short),  10,   SIGNED, PADDR,  s_put, 0};
78*4687Sdlw struct dfmt	s_l_dec	= {11, sizeof (long),   10,   SIGNED, PADDR,  l_put, 0};
79*4687Sdlw struct dfmt	flt	= {14, sizeof (float),  10,   SIGNED, PADDR,  f_put, 0};
80*4687Sdlw struct dfmt	dble	= {21, sizeof (double), 10,   SIGNED, PADDR,  d_put, 0};
81*4687Sdlw struct dfmt	string	= { 0,               0,  8,        0,    NO, st_put, 0};
824492Sdlw 
834530Sdlw 
84*4687Sdlw char	usage[]	= "usage: od [-abcdfhilopsvx] [file] [[+]offset[.][b] [label]]";
85*4687Sdlw char	dbuf[DBUF_SIZE];
86*4687Sdlw char	lastdbuf[DBUF_SIZE];
874492Sdlw int	addr_base;
884492Sdlw long	addr;
894530Sdlw long	label = -1L;
904492Sdlw int	_parity = NO;
914492Sdlw char	fmt[]	= "            %s";	/* 12 blanks */
924492Sdlw char	*icvt();
93*4687Sdlw char	*scvt();
944492Sdlw char	*underline();
954530Sdlw long	get_addr();
964492Sdlw 
974530Sdlw 
98*4687Sdlw /*
99*4687Sdlw  * special form of _ctype
100*4687Sdlw  */
101*4687Sdlw 
102*4687Sdlw #define A	01
103*4687Sdlw #define G	02
104*4687Sdlw #define D	04
105*4687Sdlw #define P	010
106*4687Sdlw #define X	020
107*4687Sdlw #define isdigit(c)	(_ctype[c] & D)
108*4687Sdlw #define isascii(c)	(_ctype[c] & A)
109*4687Sdlw #define isgraphic(c)	(_ctype[c] & G)
110*4687Sdlw #define isprint(c)	(_ctype[c] & P)
111*4687Sdlw #define ishex(c)	(_ctype[c] & (X|D))
112*4687Sdlw 
113*4687Sdlw char	_ctype[256] = {
114*4687Sdlw /* 000 */	0,	0,	0,	0,	0,	0,	0,	0,
115*4687Sdlw /* 010 */	A,	A,	A,	0,	A,	A,	0,	0,
116*4687Sdlw /* 020 */	0,	0,	0,	0,	0,	0,	0,	0,
117*4687Sdlw /* 030 */	0,	0,	0,	0,	0,	0,	0,	0,
118*4687Sdlw /* 040 */     P|A,  P|G|A,  P|G|A,  P|G|A,  P|G|A,  P|G|A,  P|G|A,  P|G|A,
119*4687Sdlw /* 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,
120*4687Sdlw /* 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,
121*4687Sdlw /* 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,
122*4687Sdlw /* 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,
123*4687Sdlw /* 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,
124*4687Sdlw /* 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,
125*4687Sdlw /* 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,
126*4687Sdlw /* 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,
127*4687Sdlw /* 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,
128*4687Sdlw /* 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,
129*4687Sdlw /* 170 */   P|G|A,  P|G|A,  P|G|A,  P|G|A,  P|G|A,  P|G|A,  P|G|A,	0,
130*4687Sdlw /* 200 */	0,	0,	0,	0,	0,	0,	0,	0,
131*4687Sdlw /* 210 */	0,	0,	0,	0,	0,	0,	0,	0,
132*4687Sdlw /* 220 */	0,	0,	0,	0,	0,	0,	0,	0,
133*4687Sdlw /* 230 */	0,	0,	0,	0,	0,	0,	0,	0,
134*4687Sdlw /* 240 */	0,	0,	0,	0,	0,	0,	0,	0,
135*4687Sdlw /* 250 */	0,	0,	0,	0,	0,	0,	0,	0,
136*4687Sdlw /* 260 */	0,	0,	0,	0,	0,	0,	0,	0,
137*4687Sdlw /* 270 */	0,	0,	0,	0,	0,	0,	0,	0,
138*4687Sdlw /* 300 */	0,	0,	0,	0,	0,	0,	0,	0,
139*4687Sdlw /* 310 */	0,	0,	0,	0,	0,	0,	0,	0,
140*4687Sdlw /* 320 */	0,	0,	0,	0,	0,	0,	0,	0,
141*4687Sdlw /* 330 */	0,	0,	0,	0,	0,	0,	0,	0,
142*4687Sdlw /* 340 */	0,	0,	0,	0,	0,	0,	0,	0,
143*4687Sdlw /* 350 */	0,	0,	0,	0,	0,	0,	0,	0,
144*4687Sdlw /* 360 */	0,	0,	0,	0,	0,	0,	0,	0,
145*4687Sdlw /* 370 */	0,	0,	0,	0,	0,	0,	0,	0,
146*4687Sdlw };
147*4687Sdlw 
148*4687Sdlw 
1494492Sdlw main(argc, argv)
150*4687Sdlw int	argc;
151*4687Sdlw char	**argv;
1524492Sdlw {
1534492Sdlw 	register char *p;
1544492Sdlw 	register char *l;
1554492Sdlw 	register n, same;
1564492Sdlw 	struct dfmt	*d;
1574492Sdlw 	struct dfmt	**cv = conv_vec;
1584492Sdlw 	int	showall = NO;
1594492Sdlw 	int	field, llen, nelm;
1604492Sdlw 	int	max_llen = 0;
1614492Sdlw 
1624492Sdlw 	argv++;
1634530Sdlw 	argc--;
1644492Sdlw 	max_llen = max_nelm = 0;
1654492Sdlw 
166*4687Sdlw 	if(argc > 0)
167*4687Sdlw 	{
1684492Sdlw 		p = *argv;
169*4687Sdlw 		if(*p == '-')
170*4687Sdlw 		{
171*4687Sdlw 			while(*++p != '\0')
172*4687Sdlw 			{
173*4687Sdlw 				switch(*p)
174*4687Sdlw 				{
1754492Sdlw 				case 'a':
1764492Sdlw 					d = &ascii;
1774492Sdlw 					break;
1784492Sdlw 				case 'b':
1794492Sdlw 					d = &byte;
1804492Sdlw 					break;
1814492Sdlw 				case 'c':
1824492Sdlw 					d = &cchar;
1834492Sdlw 					break;
1844492Sdlw 				case 'd':
1854492Sdlw 					d = &u_s_dec;
1864492Sdlw 					break;
1874492Sdlw 				case 'D':
1884492Sdlw 					d = &u_l_dec;
1894492Sdlw 					break;
1904492Sdlw 				case 'e':
1914492Sdlw 				case 'F':
1924492Sdlw 					d = &dble;
1934492Sdlw 					break;
1944492Sdlw 				case 'f':
1954492Sdlw 					d = &flt;
1964492Sdlw 					break;
1974492Sdlw 				case 'h':
1984492Sdlw 				case 'x':
1994492Sdlw 					d = &u_s_hex;
2004492Sdlw 					break;
2014492Sdlw 				case 'H':
2024492Sdlw 				case 'X':
2034492Sdlw 					d = &u_l_hex;
2044492Sdlw 					break;
2054492Sdlw 				case 'i':
2064492Sdlw 					d = &s_s_dec;
2074492Sdlw 					break;
2084492Sdlw 				case 'I':
2094492Sdlw 				case 'l':
2104492Sdlw 				case 'L':
2114492Sdlw 					d = &s_l_dec;
2124492Sdlw 					break;
2134492Sdlw 				case 'o':
214*4687Sdlw 				case 'B':
2154492Sdlw 					d = &u_s_oct;
2164492Sdlw 					break;
2174492Sdlw 				case 'O':
2184492Sdlw 					d = &u_l_oct;
2194492Sdlw 					break;
2204492Sdlw 				case 'p':
2214492Sdlw 					_parity = EVEN;
2224492Sdlw 					continue;
2234492Sdlw 				case 'P':
2244492Sdlw 					_parity = ODD;
2254492Sdlw 					continue;
226*4687Sdlw 				case 's':
227*4687Sdlw 					d = &string;
228*4687Sdlw 					*(cv++) = d;
229*4687Sdlw 					if (addr_base == 0)
230*4687Sdlw 						addr_base = d->df_radix;
231*4687Sdlw 					while (isdigit(p[1]))
232*4687Sdlw 						d->df_size = (10 * d->df_size) + (*++p - '0');
233*4687Sdlw 					if (d->df_size <= 0)
234*4687Sdlw 						d->df_size = MIN_SLEN;
235*4687Sdlw 					showall = YES;
236*4687Sdlw 					continue;
2374492Sdlw 				case 'v':
2384492Sdlw 					showall = YES;
2394492Sdlw 					continue;
2404530Sdlw 				default:
2414530Sdlw 					printf("od: bad flag -%c\n", *p);
2424530Sdlw 					puts(usage);
2434530Sdlw 					exit(1);
2444492Sdlw 				}
245*4687Sdlw 				nelm = DBUF_SIZE / d->df_size;
2464492Sdlw 				llen = (d->df_field + 1) * nelm;
2474492Sdlw 				if (llen > max_llen)
2484492Sdlw 					max_llen = llen;
2494492Sdlw 				if (nelm > max_nelm)
2504492Sdlw 					max_nelm = nelm;
2514492Sdlw 				/*
2524492Sdlw 				 * nelm will always be a power of 2.
2534492Sdlw 				 * line length must always be multiple
2544492Sdlw 				 * of max_nelm.
2554492Sdlw 				 */
2564492Sdlw 				nelm = max_nelm - 1;
2574492Sdlw 				max_llen = (max_llen + nelm) & (~nelm);
2584492Sdlw 				if (addr_base == 0)
2594492Sdlw 					addr_base = d->df_radix;
2604492Sdlw 				*(cv++) = d;
2614492Sdlw 			}
2624492Sdlw 			argc--;
2634492Sdlw 			argv++;
2644492Sdlw 		}
2654492Sdlw 	}
2664492Sdlw 
267*4687Sdlw 	/*
268*4687Sdlw 	 * if nothing spec'd, setup default conversion.
269*4687Sdlw 	 */
270*4687Sdlw 	if(cv == conv_vec)
271*4687Sdlw 	{
2724492Sdlw 		addr_base = 8;
2734492Sdlw 		*(cv++) = &u_s_oct;
274*4687Sdlw 		max_nelm = DBUF_SIZE / u_s_oct.df_size;
2754530Sdlw 		max_llen = max_nelm * (u_s_oct.df_field + 1);
2764492Sdlw 	}
2774492Sdlw 	*cv = (struct dfmt *)0;
2784492Sdlw 
279*4687Sdlw 	/*
280*4687Sdlw 	 * setup df_fmt to point to uniform output fields.
281*4687Sdlw 	 */
2824492Sdlw 	cv = conv_vec;
283*4687Sdlw 	while (d = *cv++)
284*4687Sdlw 	{
285*4687Sdlw 		if (d->df_field)	/* only if external field is known */
286*4687Sdlw 		{
287*4687Sdlw 			nelm = DBUF_SIZE / d->df_size;
288*4687Sdlw 			field = max_llen / nelm;
289*4687Sdlw 			d->df_fmt = fmt + 12 - (field - d->df_field);
290*4687Sdlw 		}
2914492Sdlw 	}
2924492Sdlw 
293*4687Sdlw 	/*
294*4687Sdlw 	 * input file specified ?
295*4687Sdlw 	 */
296*4687Sdlw 	if(argc > 0 && **argv != '+')
297*4687Sdlw 	{
298*4687Sdlw 		if (freopen(*argv, "r", stdin) == NULL)
299*4687Sdlw 		{
3004492Sdlw 			printf("od: cannot open %s\n", *argv);
3014492Sdlw 			exit(1);
3024492Sdlw 		}
3034492Sdlw 		argv++;
3044492Sdlw 		argc--;
3054492Sdlw 	}
3064492Sdlw 
307*4687Sdlw 	/*
308*4687Sdlw 	 * check for possible offset [label]
309*4687Sdlw 	 */
3104530Sdlw 	if (argc > 0)
3114530Sdlw 	{
3124530Sdlw 		addr = get_addr(*argv);
3134530Sdlw 		offset(addr);
3144530Sdlw 		argv++;
3154530Sdlw 		argc--;
3164492Sdlw 
3174530Sdlw 		if (argc > 0)
3184530Sdlw 			label = get_addr(*argv);
3194530Sdlw 	}
3204530Sdlw 
321*4687Sdlw 	/*
322*4687Sdlw 	 * main dump loop
323*4687Sdlw 	 */
3244492Sdlw 	same = -1;
325*4687Sdlw 	while ((n = fread(dbuf, 1, DBUF_SIZE, stdin)) > 0)
326*4687Sdlw 	{
327*4687Sdlw 		if (same>=0 && strncmp(dbuf, lastdbuf, DBUF_SIZE) == 0 && !showall)
328*4687Sdlw 		{
329*4687Sdlw 			if (same==0)
330*4687Sdlw 			{
3314492Sdlw 				printf("*\n");
3324492Sdlw 				same = 1;
3334492Sdlw 			}
3344492Sdlw 		}
335*4687Sdlw 		else
336*4687Sdlw 		{
3374492Sdlw 			line(n);
3384492Sdlw 			same = 0;
3394492Sdlw 			p = dbuf;
3404492Sdlw 			l = lastdbuf;
341*4687Sdlw 			for (nelm = 0; nelm < DBUF_SIZE; nelm++)
342*4687Sdlw 			{
3434492Sdlw 				*l++ = *p;
3444492Sdlw 				*p++ = '\0';
3454492Sdlw 			}
3464492Sdlw 		}
3474492Sdlw 		addr += n;
3484530Sdlw 		if (label >= 0)
3494530Sdlw 			label += n;
3504492Sdlw 	}
351*4687Sdlw 
352*4687Sdlw 	/*
353*4687Sdlw 	 * Some conversions require "flushing".
354*4687Sdlw 	 */
355*4687Sdlw 	n = 0;
356*4687Sdlw 	for (cv = conv_vec; *cv; cv++)
357*4687Sdlw 	{
358*4687Sdlw 		if ((*cv)->df_paddr)
359*4687Sdlw 		{
360*4687Sdlw 			if (n++ == 0)
361*4687Sdlw 				put_addr(addr, label, '\n');
362*4687Sdlw 		}
363*4687Sdlw 		else
364*4687Sdlw 			(*((*cv)->df_put))(0, *cv);
365*4687Sdlw 	}
3664492Sdlw }
3674492Sdlw 
368*4687Sdlw put_addr(a, l, c)
369*4687Sdlw long	a;
370*4687Sdlw long	l;
3714530Sdlw char	c;
3724530Sdlw {
373*4687Sdlw 	fputs(icvt(a, addr_base, UNSIGNED, 7), stdout);
374*4687Sdlw 	if (l >= 0)
375*4687Sdlw 		printf(" (%s)", icvt(l, addr_base, UNSIGNED, 7));
3764530Sdlw 	putchar(c);
3774530Sdlw }
3784530Sdlw 
3794492Sdlw line(n)
3804492Sdlw int	n;
3814492Sdlw {
3824492Sdlw 	register i, first;
3834492Sdlw 	register struct dfmt *c;
3844492Sdlw 	register struct dfmt **cv = conv_vec;
3854492Sdlw 
3864492Sdlw 	first = YES;
387*4687Sdlw 	while (c = *cv++)
388*4687Sdlw 	{
389*4687Sdlw 		if (c->df_paddr)
390*4687Sdlw 		{
391*4687Sdlw 			if (first)
392*4687Sdlw 			{
393*4687Sdlw 				put_addr(addr, label, ' ');
394*4687Sdlw 				first = NO;
395*4687Sdlw 			}
396*4687Sdlw 			else
397*4687Sdlw 			{
398*4687Sdlw 				putchar('\t');
399*4687Sdlw 				if (label >= 0)
400*4687Sdlw 					fputs("\t  ", stdout);
401*4687Sdlw 			}
4024530Sdlw 		}
4034492Sdlw 		i = 0;
4044492Sdlw 		while (i < n)
4054492Sdlw 			i += (*(c->df_put))(dbuf+i, c);
406*4687Sdlw 		if (c->df_paddr)
407*4687Sdlw 			putchar('\n');
4084492Sdlw 	}
4094492Sdlw }
4104492Sdlw 
4114492Sdlw s_put(n, d)
4124492Sdlw short	*n;
4134492Sdlw struct dfmt	*d;
4144492Sdlw {
4154492Sdlw 	printf(d->df_fmt, icvt((long)*n, d->df_radix, d->df_signed, d->df_field));
4164492Sdlw 	return(d->df_size);
4174492Sdlw }
4184492Sdlw 
4194492Sdlw us_put(n, d)
4204492Sdlw unsigned short	*n;
4214492Sdlw struct dfmt	*d;
4224492Sdlw {
4234492Sdlw 	printf(d->df_fmt, icvt((long)*n, d->df_radix, d->df_signed, d->df_field));
4244492Sdlw 	return(d->df_size);
4254492Sdlw }
4264492Sdlw 
4274492Sdlw l_put(n, d)
4284492Sdlw long	*n;
4294492Sdlw struct dfmt	*d;
4304492Sdlw {
4314492Sdlw 	printf(d->df_fmt, icvt(*n, d->df_radix, d->df_signed, d->df_field));
4324492Sdlw 	return(d->df_size);
4334492Sdlw }
4344492Sdlw 
4354492Sdlw d_put(f, d)
4364492Sdlw double	*f;
4374492Sdlw struct dfmt *d;
4384492Sdlw {
4394492Sdlw 	char fbuf[24];
4404500Sdlw 	struct l { long n[2]; };
4414500Sdlw 
4424500Sdlw #if	vax
4434500Sdlw 	if ((((struct l *)f)->n[0] & 0xff00) == 0x8000)	/* Vax illegal f.p. */
4444500Sdlw 		sprintf(fbuf, "    %08x %08x",
4454500Sdlw 			((struct l *)f)->n[0], ((struct l *)f)->n[1]);
4464500Sdlw 	else
4474500Sdlw #endif
4484500Sdlw 
4494500Sdlw 		sprintf(fbuf, "%21.14e", *f);
4504492Sdlw 	printf(d->df_fmt, fbuf);
4514492Sdlw 	return(d->df_size);
4524492Sdlw }
4534492Sdlw 
4544492Sdlw f_put(f, d)
4554492Sdlw float	*f;
4564492Sdlw struct dfmt *d;
4574492Sdlw {
4584492Sdlw 	char fbuf[16];
4594500Sdlw 
4604500Sdlw #if	vax
4614500Sdlw 	if ((*(long *)f & 0xff00) == 0x8000)	/* Vax illegal f.p. form */
4624500Sdlw 		sprintf(fbuf, "      %08x", *(long *)f);
4634500Sdlw 	else
4644500Sdlw #endif
4654500Sdlw 		sprintf(fbuf, "%14.7e", *f);
4664492Sdlw 	printf(d->df_fmt, fbuf);
4674492Sdlw 	return(d->df_size);
4684492Sdlw }
4694492Sdlw 
4704492Sdlw 
4714492Sdlw char	asc_name[34][4] = {
472*4687Sdlw /* 000 */	"nul",	"soh",	"stx",	"etx",	"eot",	"enq",	"ack",	"bel",
473*4687Sdlw /* 010 */	" bs",	" ht",	" nl",	" vt",	" ff",	" cr",	" so",	" si",
474*4687Sdlw /* 020 */	"dle",	"dc1",	"dc2",	"dc3",	"dc4",	"nak",	"syn",	"etb",
475*4687Sdlw /* 030 */	"can",	" em",	"sub",	"esc",	" fs",	" gs",	" rs",	" us",
476*4687Sdlw /* 040 */	" sp",	"del"
4774492Sdlw };
4784492Sdlw 
4794492Sdlw a_put(cc, d)
4804492Sdlw char	*cc;
4814492Sdlw struct dfmt *d;
4824492Sdlw {
4834492Sdlw 	int c = *cc;
4844492Sdlw 	register char *s = "   ";
4854492Sdlw 	register pbit = parity((int)c & 0377);
4864492Sdlw 
4874492Sdlw 	c &= 0177;
488*4687Sdlw 	if (isgraphic(c))
4894492Sdlw 	{
490*4687Sdlw 		s[2] = c;
4914492Sdlw 		if (pbit == _parity)
4924503Sdlw 			printf(d->df_fmt, underline(s));
4934492Sdlw 		else
4944492Sdlw 			printf(d->df_fmt, s);
4954492Sdlw 	}
4964492Sdlw 	else
4974492Sdlw 	{
4984492Sdlw 		if (c == 0177)
4994492Sdlw 			c = ' ' + 1;
5004492Sdlw 		if (pbit == _parity)
5014503Sdlw 			printf(d->df_fmt, underline(asc_name[c]));
5024492Sdlw 		else
5034492Sdlw 			printf(d->df_fmt, asc_name[c]);
5044492Sdlw 	}
5054492Sdlw 	return(1);
5064492Sdlw }
5074492Sdlw 
5084492Sdlw parity(word)
5094492Sdlw int	word;
5104492Sdlw {
5114492Sdlw 	register int p = 0;
5124492Sdlw 	register int w = word;
5134492Sdlw 
5144492Sdlw 	if (w)
515*4687Sdlw 		do
516*4687Sdlw 		{
5174492Sdlw 			p ^= 1;
5184492Sdlw 		} while(w &= (~(-w)));
5194492Sdlw 	return (p? ODD:EVEN);
5204492Sdlw }
5214492Sdlw 
5224492Sdlw char *
5234503Sdlw underline(s)
5244492Sdlw char	*s;
5254492Sdlw {
5264492Sdlw 	static char ulbuf[16];
5274492Sdlw 	register char *u = ulbuf;
5284492Sdlw 
529*4687Sdlw 	while (*s)
530*4687Sdlw 	{
531*4687Sdlw 		if (*s != ' ')
532*4687Sdlw 		{
5334492Sdlw 			*u++ = '_';
5344492Sdlw 			*u++ = '\b';
5354492Sdlw 		}
5364492Sdlw 		*u++ = *s++;
5374492Sdlw 	}
5384492Sdlw 	*u = '\0';
5394492Sdlw 	return(ulbuf);
5404492Sdlw }
5414492Sdlw 
5424492Sdlw b_put(b, d)
5434492Sdlw char	*b;
5444492Sdlw struct dfmt *d;
5454492Sdlw {
5464492Sdlw 	printf(d->df_fmt, icvt((long)*b & 0377, d->df_radix, d->df_signed, d->df_field));
5474492Sdlw 	return(1);
5484492Sdlw }
5494492Sdlw 
5504492Sdlw c_put(cc, d)
5514492Sdlw char	*cc;
5524492Sdlw struct dfmt *d;
5534492Sdlw {
554*4687Sdlw 	register char	*s;
555*4687Sdlw 	register int	n;
556*4687Sdlw 	register int	c = *cc & 0377;
5574492Sdlw 
558*4687Sdlw 	s = scvt(c, d);
559*4687Sdlw 	for (n = d->df_field - strlen(s); n > 0; n--)
560*4687Sdlw 		putchar(' ');
561*4687Sdlw 	printf(d->df_fmt, s);
562*4687Sdlw 	return(1);
563*4687Sdlw }
564*4687Sdlw 
565*4687Sdlw char *scvt(c, d)
566*4687Sdlw int	c;
567*4687Sdlw struct dfmt	*d;
568*4687Sdlw {
569*4687Sdlw 	static char s[2];
570*4687Sdlw 
571*4687Sdlw 	switch(c)
572*4687Sdlw 	{
573*4687Sdlw 		case '\0':
574*4687Sdlw 			return("\\0");
575*4687Sdlw 
576*4687Sdlw 		case '\b':
577*4687Sdlw 			return("\\b");
578*4687Sdlw 
579*4687Sdlw 		case '\f':
580*4687Sdlw 			return("\\f");
581*4687Sdlw 
582*4687Sdlw 		case '\n':
583*4687Sdlw 			return("\\n");
584*4687Sdlw 
585*4687Sdlw 		case '\r':
586*4687Sdlw 			return("\\r");
587*4687Sdlw 
588*4687Sdlw 		case '\t':
589*4687Sdlw 			return("\\t");
590*4687Sdlw 
591*4687Sdlw 		default:
592*4687Sdlw 			if (isprint(c))
593*4687Sdlw 			{
594*4687Sdlw 				s[0] = c;
595*4687Sdlw 				return(s);
596*4687Sdlw 			}
597*4687Sdlw 			return(icvt((long)c, d->df_radix, d->df_signed, d->df_field));
5984492Sdlw 	}
599*4687Sdlw }
6004492Sdlw 
601*4687Sdlw /*
602*4687Sdlw  * Look for strings.
603*4687Sdlw  * A string contains bytes > 037 && < 177, and ends with a null.
604*4687Sdlw  * The minimum length is given in the dfmt structure.
605*4687Sdlw  */
606*4687Sdlw 
607*4687Sdlw #define CNULL		'\0'
608*4687Sdlw #define S_EMPTY	0
609*4687Sdlw #define S_FILL	1
610*4687Sdlw #define	S_CONT	2
611*4687Sdlw #define SBUFSIZE	1024
612*4687Sdlw 
613*4687Sdlw static char	str_buf[SBUFSIZE];
614*4687Sdlw static int	str_mode = S_EMPTY;
615*4687Sdlw static char	*str_ptr;
616*4687Sdlw static long	str_addr;
617*4687Sdlw static long	str_label;
618*4687Sdlw 
619*4687Sdlw st_put(c, d)
620*4687Sdlw register char	*c;
621*4687Sdlw struct dfmt	*d;
622*4687Sdlw {
623*4687Sdlw 	if (c == 0)
624*4687Sdlw 	{
625*4687Sdlw 		pr_sbuf(d, YES);
6264492Sdlw 	}
627*4687Sdlw 	else if (str_mode & S_FILL)
628*4687Sdlw 	{
629*4687Sdlw 		if (isascii(*c))
630*4687Sdlw 			put_sbuf(*c, d);
631*4687Sdlw 		else
632*4687Sdlw 		{
633*4687Sdlw 			*str_ptr = CNULL;
634*4687Sdlw 			if (*c == CNULL)
635*4687Sdlw 				pr_sbuf(d, YES);
636*4687Sdlw 			str_mode = S_EMPTY;
637*4687Sdlw 		}
638*4687Sdlw 	}
639*4687Sdlw 	else if (isascii(*c))
640*4687Sdlw 	{
641*4687Sdlw 		str_mode = S_FILL;
642*4687Sdlw 		str_addr = addr + (c - dbuf);	/* ugly */
643*4687Sdlw 		if ((str_label = label) >= 0)
644*4687Sdlw 			str_label += (c - dbuf);/*  ''  */
645*4687Sdlw 		str_ptr = str_buf;
646*4687Sdlw 		put_sbuf(*c, d);
647*4687Sdlw 	}
648*4687Sdlw 
6494492Sdlw 	return(1);
6504492Sdlw }
6514492Sdlw 
652*4687Sdlw put_sbuf(c, d)
653*4687Sdlw char	c;
654*4687Sdlw struct dfmt	*d;
655*4687Sdlw {
656*4687Sdlw 	*str_ptr++ = c;
657*4687Sdlw 	if (str_ptr >= (str_buf + SBUFSIZE))
658*4687Sdlw 	{
659*4687Sdlw 		pr_sbuf(d, NO);
660*4687Sdlw 		str_ptr = str_buf;
661*4687Sdlw 		str_mode |= S_CONT;
662*4687Sdlw 	}
663*4687Sdlw }
664*4687Sdlw 
665*4687Sdlw pr_sbuf(d, end)
666*4687Sdlw struct dfmt	*d;
667*4687Sdlw int	end;
668*4687Sdlw {
669*4687Sdlw 	register char	*p = str_buf;
670*4687Sdlw 
671*4687Sdlw 	if (str_mode == S_EMPTY
672*4687Sdlw 	    || (!(str_mode & S_CONT) && (str_ptr - str_buf) < d->df_size))
673*4687Sdlw 		return;
674*4687Sdlw 
675*4687Sdlw 	if (!(str_mode & S_CONT))
676*4687Sdlw 		put_addr(str_addr, str_label, ' ');
677*4687Sdlw 
678*4687Sdlw 	while (p < str_ptr)
679*4687Sdlw 		fputs(scvt(*p++, d), stdout);
680*4687Sdlw 
681*4687Sdlw 	if (end)
682*4687Sdlw 		putchar('\n');
683*4687Sdlw }
684*4687Sdlw 
6854492Sdlw /*
6864492Sdlw  * integer to ascii conversion
6874492Sdlw  *
6884492Sdlw  * This code has been rearranged to produce optimized runtime code.
6894492Sdlw  */
6904492Sdlw 
6914492Sdlw #define MAXINTLENGTH	32
6924492Sdlw static char	_digit[] = "0123456789abcdef";
6934492Sdlw static char	_icv_buf[MAXINTLENGTH+1];
6944492Sdlw static long	_mask = 0x7fffffff;
6954492Sdlw 
6964492Sdlw char *
6974492Sdlw icvt (value, radix, signed, ndigits)
6984492Sdlw long	value;
6994492Sdlw int	radix;
7004492Sdlw int	signed;
7014492Sdlw int	ndigits;
7024492Sdlw {
7034492Sdlw 	register long	val = value;
7044492Sdlw 	register long	rad = radix;
7054492Sdlw 	register char	*b = &_icv_buf[MAXINTLENGTH];
7064492Sdlw 	register char	*d = _digit;
7074492Sdlw 	register long	tmp1;
7084492Sdlw 	register long	tmp2;
7094492Sdlw 	long	rem;
7104492Sdlw 	long	kludge;
7114492Sdlw 	int	sign;
7124492Sdlw 
7134492Sdlw 	if (val == 0)
7144492Sdlw 	{
7154492Sdlw 		*--b = '0';
7164492Sdlw 		sign = 0;
7174492Sdlw 		goto done; /*return(b);*/
7184492Sdlw 	}
7194492Sdlw 
7204492Sdlw 	if (signed && (sign = (val < 0)))	/* signed conversion */
7214492Sdlw 	{
7224492Sdlw 		/*
7234492Sdlw 		 * It is necessary to do the first divide
7244492Sdlw 		 * before the absolute value, for the case -2^31
7254492Sdlw 		 *
7264492Sdlw 		 * This is actually what is being done...
7274492Sdlw 		 * tmp1 = (int)(val % rad);
7284492Sdlw 		 * val /= rad;
7294492Sdlw 		 * val = -val
7304492Sdlw 		 * *--b = d[-tmp1];
7314492Sdlw 		 */
7324492Sdlw 		tmp1 = val / rad;
7334492Sdlw 		*--b = d[(tmp1 * rad) - val];
7344492Sdlw 		val = -tmp1;
7354492Sdlw 	}
7364492Sdlw 	else				/* unsigned conversion */
7374492Sdlw 	{
7384492Sdlw 		sign = 0;
7394492Sdlw 		if (val < 0)
7404492Sdlw 		{	/* ALL THIS IS TO SIMULATE UNSIGNED LONG MOD & DIV */
7414492Sdlw 			kludge = _mask - (rad - 1);
7424492Sdlw 			val &= _mask;
7434492Sdlw 			/*
7444492Sdlw 			 * This is really what's being done...
7454492Sdlw 			 * rem = (kludge % rad) + (val % rad);
7464492Sdlw 			 * val = (kludge / rad) + (val / rad) + (rem / rad) + 1;
7474492Sdlw 			 * *--b = d[rem % rad];
7484492Sdlw 			 */
7494492Sdlw 			tmp1 = kludge / rad;
7504492Sdlw 			tmp2 = val / rad;
7514492Sdlw 			rem = (kludge - (tmp1 * rad)) + (val - (tmp2 * rad));
7524492Sdlw 			val = ++tmp1 + tmp2;
7534492Sdlw 			tmp1 = rem / rad;
7544492Sdlw 			val += tmp1;
7554492Sdlw 			*--b = d[rem - (tmp1 * rad)];
7564492Sdlw 		}
7574492Sdlw 	}
7584492Sdlw 
7594492Sdlw 	while (val)
7604492Sdlw 	{
7614492Sdlw 		/*
7624492Sdlw 		 * This is really what's being done ...
7634492Sdlw 		 * *--b = d[val % rad];
7644492Sdlw 		 * val /= rad;
7654492Sdlw 		 */
7664492Sdlw 		tmp1 = val / rad;
7674492Sdlw 		*--b = d[val - (tmp1 * rad)];
7684492Sdlw 		val = tmp1;
7694492Sdlw 	}
7704492Sdlw 
7714492Sdlw done:
7724492Sdlw 	if (sign)
7734492Sdlw 		*--b = '-';
7744492Sdlw 
7754492Sdlw 	tmp1 = ndigits - (&_icv_buf[MAXINTLENGTH] - b);
7764492Sdlw 	tmp2 = signed? ' ':'0';
7774492Sdlw 	while (tmp1 > 0)
7784492Sdlw 	{
7794492Sdlw 		*--b = tmp2;
7804492Sdlw 		tmp1--;
7814492Sdlw 	}
7824492Sdlw 
7834492Sdlw 	return(b);
7844492Sdlw }
7854492Sdlw 
786*4687Sdlw long get_addr(s)
7874492Sdlw register char *s;
7884492Sdlw {
7894492Sdlw 	register char *p;
7904530Sdlw 	register long a;
7914492Sdlw 	register int d;
7924492Sdlw 
7934492Sdlw 	if (*s=='+')
7944492Sdlw 		s++;
795*4687Sdlw 	if (*s=='x')
796*4687Sdlw 	{
7974492Sdlw 		s++;
7984492Sdlw 		addr_base = 16;
799*4687Sdlw 	}
800*4687Sdlw 	else if (*s=='0' && s[1]=='x')
801*4687Sdlw 	{
8024492Sdlw 		s += 2;
8034492Sdlw 		addr_base = 16;
804*4687Sdlw 	}
805*4687Sdlw 	else if (*s == '0')
8064492Sdlw 		addr_base = 8;
8074492Sdlw 	p = s;
808*4687Sdlw 	while(*p)
809*4687Sdlw 	{
8104492Sdlw 		if (*p++=='.')
8114492Sdlw 			addr_base = 10;
8124492Sdlw 	}
813*4687Sdlw 	for (a=0; *s; s++)
814*4687Sdlw 	{
8154492Sdlw 		d = *s;
816*4687Sdlw 		if(isdigit(d))
8174492Sdlw 			a = a*addr_base + d - '0';
818*4687Sdlw 		else if (ishex(d) && addr_base==16)
8194492Sdlw 			a = a*addr_base + d + 10 - 'a';
8204492Sdlw 		else
8214492Sdlw 			break;
8224492Sdlw 	}
8234530Sdlw 
8244492Sdlw 	if (*s == '.')
8254492Sdlw 		s++;
8264530Sdlw 	if(*s=='b')
8274492Sdlw 		a *= 512;
8284530Sdlw 	if(*s=='B')
8294530Sdlw 		a *= 1024;
8304530Sdlw 
8314530Sdlw 	return(a);
8324530Sdlw }
8334530Sdlw 
8344530Sdlw offset(a)
8354530Sdlw long	a;
8364530Sdlw {
8374492Sdlw 	if (canseek(stdin))
8384492Sdlw 		fseek(stdin, a, 0);
8394492Sdlw 	else
8404492Sdlw 		dumbseek(stdin, a);
8414492Sdlw }
8424492Sdlw 
8434492Sdlw dumbseek(s, offset)
8444492Sdlw FILE	*s;
8454492Sdlw long	offset;
8464492Sdlw {
8474492Sdlw 	char	buf[BUFSIZ];
8484492Sdlw 	int	n;
8494492Sdlw 	int	nr;
8504492Sdlw 
8514492Sdlw 	while (offset > 0)
8524492Sdlw 	{
8534492Sdlw 		nr = (offset > BUFSIZ) ? BUFSIZ : (int)offset;
8544492Sdlw 		if ((n = fread(buf, 1, nr, s)) != nr)
8554492Sdlw 		{
8564492Sdlw 			fprintf(stderr, "EOF\n");
8574492Sdlw 			exit(1);
8584492Sdlw 		}
8594492Sdlw 		offset -= n;
8604492Sdlw 	}
8614492Sdlw }
8624492Sdlw 
8634492Sdlw #include <sys/types.h>
8644492Sdlw #include <sys/stat.h>
8654492Sdlw 
8664492Sdlw canseek(f)
8674492Sdlw FILE	*f;
8684492Sdlw {
8694492Sdlw 	struct stat statb;
8704492Sdlw 
8714492Sdlw 	return( (fstat(fileno(f),&statb)==0) &&
8724492Sdlw 		(statb.st_nlink > 0) &&		/*!pipe*/
8734492Sdlw 		(!isatty(fileno(f))) );
8744492Sdlw }
875