xref: /original-bsd/old/od/od.c (revision 9cf5e8d3)
1 static char *sccsid = "@(#)od.c	5.11 (Berkeley) 04/29/83";
2 /*
3  * od -- octal, hex, decimal, character dump of data in a file.
4  *
5  * usage:  od [-abBcdDefFhHiIlLopPs[n]vw[n]xX] [file] [[+]offset[.][b] [label]]
6  *
7  * where the option flags have the following meaning:
8  *   character	object	radix	signed?
9  *	a	byte	(10)	(n.a.)	ASCII named byte stream
10  *	b	byte	  8	 no	byte octal
11  *	c	byte	 (8)	(no)	character with octal non-graphic bytes
12  *	d	short	 10	 no
13  *	D	long	 10	 no
14  *	e,F	double	(10)		double precision floating pt.
15  *	f	float	(10)		single precision floating pt.
16  *	h,x	short	 16	 no
17  *	H,X	long	 16	 no
18  *	i	short	 10	yes
19  *	I,l,L	long	 10	yes
20  *	o,B	short	  8	 no	(default conversion)
21  *	O	long	  8	 no
22  *	s[n]	string	 (8)		ASCII graphic strings
23  *
24  *	p				indicate EVEN parity on 'a' conversion
25  *	P				indicate ODD parity on 'a' conversion
26  *	v				show all data - don't skip like lines.
27  *	w[n]				bytes per display line
28  *
29  * More than one format character may be given.
30  * If {file} is not specified, standard input is read.
31  * If {file} is not specified, then {offset} must start with '+'.
32  * {Offset} may be HEX (0xnnn), OCTAL (0nn), or decimal (nnn.).
33  * The default is octal. The same radix will be used to display the address.
34  */
35 
36 #include <stdio.h>
37 
38 #define DBUF_SIZE	BUFSIZ
39 #define BIG_DBUF	32
40 #define NO		0
41 #define YES		1
42 #define EVEN	       -1
43 #define ODD		1
44 #define UNSIGNED	0
45 #define SIGNED		1
46 #define PADDR		1
47 #define MIN_SLEN	3
48 
49 int	a_put();
50 int	b_put();
51 int	c_put();
52 int	s_put();
53 int	us_put();
54 int	l_put();
55 int	f_put();
56 int	d_put();
57 int	st_put();
58 
59 struct dfmt {
60 	int	df_field;	/* external field required for object */
61 	int	df_size;	/* size (bytes) of object */
62 	int	df_radix;	/* conversion radix */
63 	int	df_signed;	/* signed? flag */
64 	int	df_paddr;	/* "put address on each line?" flag */
65 	int	(*df_put)();	/* function to output object */
66 	char	*df_fmt;	/* output string format */
67 } *conv_vec[32];		/* vector of conversions to be done */
68 
69 struct dfmt	ascii	= { 3, sizeof (char),   10,        0, PADDR,  a_put, 0};
70 struct dfmt	byte	= { 3, sizeof (char),    8, UNSIGNED, PADDR,  b_put, 0};
71 struct dfmt	cchar	= { 3, sizeof (char),    8, UNSIGNED, PADDR,  c_put, 0};
72 struct dfmt	u_s_oct	= { 6, sizeof (short),   8, UNSIGNED, PADDR, us_put, 0};
73 struct dfmt	u_s_dec	= { 5, sizeof (short),  10, UNSIGNED, PADDR, us_put, 0};
74 struct dfmt	u_s_hex	= { 4, sizeof (short),  16, UNSIGNED, PADDR, us_put, 0};
75 struct dfmt	u_l_oct	= {11, sizeof (long),    8, UNSIGNED, PADDR,  l_put, 0};
76 struct dfmt	u_l_dec	= {10, sizeof (long),   10, UNSIGNED, PADDR,  l_put, 0};
77 struct dfmt	u_l_hex	= { 8, sizeof (long),   16, UNSIGNED, PADDR,  l_put, 0};
78 struct dfmt	s_s_dec	= { 6, sizeof (short),  10,   SIGNED, PADDR,  s_put, 0};
79 struct dfmt	s_l_dec	= {11, sizeof (long),   10,   SIGNED, PADDR,  l_put, 0};
80 struct dfmt	flt	= {14, sizeof (float),  10,   SIGNED, PADDR,  f_put, 0};
81 struct dfmt	dble	= {21, sizeof (double), 10,   SIGNED, PADDR,  d_put, 0};
82 struct dfmt	string	= { 0,               0,  8,        0,    NO, st_put, 0};
83 
84 
85 char	usage[]	="usage: od [-abcdfhilopswvx] [file] [[+]offset[.][b] [label]]";
86 char	dbuf[DBUF_SIZE];
87 char	lastdbuf[DBUF_SIZE];
88 int	addr_base	= 8;		/* default address base is OCTAL */
89 long	addr		= 0L;		/* current file offset */
90 long	label		= -1L;		/* current label; -1 is "off" */
91 int	dbuf_size	= 16;		/* file bytes / display line */
92 int	_parity		= NO;		/* show parity on ascii bytes */
93 char	fmt[]	= "            %s";	/* 12 blanks */
94 char	*icvt();
95 char	*scvt();
96 char	*underline();
97 long	get_addr();
98 
99 
100 /*
101  * special form of _ctype
102  */
103 
104 #define A	01
105 #define G	02
106 #define D	04
107 #define P	010
108 #define X	020
109 #define isdigit(c)	(_ctype[c] & D)
110 #define isascii(c)	(_ctype[c] & A)
111 #define isgraphic(c)	(_ctype[c] & G)
112 #define isprint(c)	(_ctype[c] & P)
113 #define ishex(c)	(_ctype[c] & (X|D))
114 
115 char	_ctype[256] = {
116 /* 000 */	0,	0,	0,	0,	0,	0,	0,	0,
117 /* 010 */	A,	A,	A,	0,	A,	A,	0,	0,
118 /* 020 */	0,	0,	0,	0,	0,	0,	0,	0,
119 /* 030 */	0,	0,	0,	0,	0,	0,	0,	0,
120 /* 040 */     P|A,  P|G|A,  P|G|A,  P|G|A,  P|G|A,  P|G|A,  P|G|A,  P|G|A,
121 /* 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,
122 /* 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,
123 /* 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,
124 /* 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,
125 /* 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,
126 /* 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,
127 /* 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,
128 /* 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,
129 /* 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,
130 /* 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,
131 /* 170 */   P|G|A,  P|G|A,  P|G|A,  P|G|A,  P|G|A,  P|G|A,  P|G|A,	0,
132 /* 200 */	0,	0,	0,	0,	0,	0,	0,	0,
133 /* 210 */	0,	0,	0,	0,	0,	0,	0,	0,
134 /* 220 */	0,	0,	0,	0,	0,	0,	0,	0,
135 /* 230 */	0,	0,	0,	0,	0,	0,	0,	0,
136 /* 240 */	0,	0,	0,	0,	0,	0,	0,	0,
137 /* 250 */	0,	0,	0,	0,	0,	0,	0,	0,
138 /* 260 */	0,	0,	0,	0,	0,	0,	0,	0,
139 /* 270 */	0,	0,	0,	0,	0,	0,	0,	0,
140 /* 300 */	0,	0,	0,	0,	0,	0,	0,	0,
141 /* 310 */	0,	0,	0,	0,	0,	0,	0,	0,
142 /* 320 */	0,	0,	0,	0,	0,	0,	0,	0,
143 /* 330 */	0,	0,	0,	0,	0,	0,	0,	0,
144 /* 340 */	0,	0,	0,	0,	0,	0,	0,	0,
145 /* 350 */	0,	0,	0,	0,	0,	0,	0,	0,
146 /* 360 */	0,	0,	0,	0,	0,	0,	0,	0,
147 /* 370 */	0,	0,	0,	0,	0,	0,	0,	0,
148 };
149 
150 
151 main(argc, argv)
152 int	argc;
153 char	**argv;
154 {
155 	register char *p;
156 	register char *l;
157 	register n, same;
158 	struct dfmt	*d;
159 	struct dfmt	**cv = conv_vec;
160 	int	showall = NO;
161 	int	field, llen, nelm;
162 	int	max_llen = 0;
163 
164 	argv++;
165 	argc--;
166 
167 	if(argc > 0)
168 	{
169 		p = *argv;
170 		if(*p == '-')
171 		{
172 			while(*++p != '\0')
173 			{
174 				switch(*p)
175 				{
176 				case 'a':
177 					d = &ascii;
178 					break;
179 				case 'b':
180 					d = &byte;
181 					break;
182 				case 'c':
183 					d = &cchar;
184 					break;
185 				case 'd':
186 					d = &u_s_dec;
187 					break;
188 				case 'D':
189 					d = &u_l_dec;
190 					break;
191 				case 'e':
192 				case 'F':
193 					d = &dble;
194 					break;
195 				case 'f':
196 					d = &flt;
197 					break;
198 				case 'h':
199 				case 'x':
200 					d = &u_s_hex;
201 					break;
202 				case 'H':
203 				case 'X':
204 					d = &u_l_hex;
205 					break;
206 				case 'i':
207 					d = &s_s_dec;
208 					break;
209 				case 'I':
210 				case 'l':
211 				case 'L':
212 					d = &s_l_dec;
213 					break;
214 				case 'o':
215 				case 'B':
216 					d = &u_s_oct;
217 					break;
218 				case 'O':
219 					d = &u_l_oct;
220 					break;
221 				case 'p':
222 					_parity = EVEN;
223 					continue;
224 				case 'P':
225 					_parity = ODD;
226 					continue;
227 				case 's':
228 					d = &string;
229 					*(cv++) = d;
230 					while (isdigit(p[1]))
231 						d->df_size = (10 * d->df_size) + (*++p - '0');
232 					if (d->df_size <= 0)
233 						d->df_size = MIN_SLEN;
234 					showall = YES;
235 					continue;
236 				case 'w':
237 					dbuf_size = 0;
238 					while (isdigit(p[1]))
239 						dbuf_size = (10 * dbuf_size) + (*++p - '0');
240 					if (dbuf_size == 0)
241 						dbuf_size = BIG_DBUF;
242 					continue;
243 				case 'v':
244 					showall = YES;
245 					continue;
246 				default:
247 					printf("od: bad flag -%c\n", *p);
248 					puts(usage);
249 					exit(1);
250 				}
251 				*(cv++) = d;
252 			}
253 			argc--;
254 			argv++;
255 		}
256 	}
257 
258 	/*
259 	 * if nothing spec'd, setup default conversion.
260 	 */
261 	if(cv == conv_vec)
262 		*(cv++) = &u_s_oct;
263 
264 	*cv = (struct dfmt *)0;
265 
266 	/*
267 	 * calculate display parameters
268 	 */
269 	for (cv = conv_vec; d = *cv; cv++)
270 	{
271 		nelm = (dbuf_size + d->df_size - 1) / d->df_size;
272 		llen = nelm * (d->df_field + 1);
273 		if (llen > max_llen)
274 			max_llen = llen;
275 	}
276 
277 	/*
278 	 * setup df_fmt to point to uniform output fields.
279 	 */
280 	for (cv = conv_vec; d = *cv; cv++)
281 	{
282 		if (d->df_field)	/* only if external field is known */
283 		{
284 			nelm = (dbuf_size + d->df_size - 1) / d->df_size;
285 			field = max_llen / nelm;
286 			d->df_fmt = fmt + 12 - (field - d->df_field);
287 		}
288 	}
289 
290 	/*
291 	 * input file specified ?
292 	 */
293 	if(argc > 0 && **argv != '+')
294 	{
295 		if (freopen(*argv, "r", stdin) == NULL)
296 		{
297 			perror(*argv);
298 			exit(1);
299 		}
300 		argv++;
301 		argc--;
302 	}
303 
304 	/*
305 	 * check for possible offset [label]
306 	 */
307 	if (argc > 0)
308 	{
309 		addr = get_addr(*argv);
310 		offset(addr);
311 		argv++;
312 		argc--;
313 
314 		if (argc > 0)
315 			label = get_addr(*argv);
316 	}
317 
318 	/*
319 	 * main dump loop
320 	 */
321 	same = -1;
322 	while ((n = fread(dbuf, 1, dbuf_size, stdin)) > 0)
323 	{
324 		if (same>=0 && bufncmp(dbuf, lastdbuf, dbuf_size) == 0 && !showall)
325 		{
326 			if (same==0)
327 			{
328 				printf("*\n");
329 				same = 1;
330 			}
331 		}
332 		else
333 		{
334 			line(n);
335 			same = 0;
336 			p = dbuf;
337 			l = lastdbuf;
338 			for (nelm = 0; nelm < dbuf_size; nelm++)
339 			{
340 				*l++ = *p;
341 				*p++ = '\0';
342 			}
343 		}
344 		addr += n;
345 		if (label >= 0)
346 			label += n;
347 	}
348 
349 	/*
350 	 * Some conversions require "flushing".
351 	 */
352 	n = 0;
353 	for (cv = conv_vec; *cv; cv++)
354 	{
355 		if ((*cv)->df_paddr)
356 		{
357 			if (n++ == 0)
358 				put_addr(addr, label, '\n');
359 		}
360 		else
361 			(*((*cv)->df_put))(0, *cv);
362 	}
363 }
364 
365 put_addr(a, l, c)
366 long	a;
367 long	l;
368 char	c;
369 {
370 	fputs(icvt(a, addr_base, UNSIGNED, 7), stdout);
371 	if (l >= 0)
372 		printf(" (%s)", icvt(l, addr_base, UNSIGNED, 7));
373 	putchar(c);
374 }
375 
376 line(n)
377 int	n;
378 {
379 	register i, first;
380 	register struct dfmt *c;
381 	register struct dfmt **cv = conv_vec;
382 
383 	first = YES;
384 	while (c = *cv++)
385 	{
386 		if (c->df_paddr)
387 		{
388 			if (first)
389 			{
390 				put_addr(addr, label, ' ');
391 				first = NO;
392 			}
393 			else
394 			{
395 				putchar('\t');
396 				if (label >= 0)
397 					fputs("\t  ", stdout);
398 			}
399 		}
400 		i = 0;
401 		while (i < n)
402 			i += (*(c->df_put))(dbuf+i, c);
403 		if (c->df_paddr)
404 			putchar('\n');
405 	}
406 }
407 
408 s_put(n, d)
409 short	*n;
410 struct dfmt	*d;
411 {
412 	printf(d->df_fmt, icvt((long)*n, d->df_radix, d->df_signed, d->df_field));
413 	return(d->df_size);
414 }
415 
416 us_put(n, d)
417 unsigned short	*n;
418 struct dfmt	*d;
419 {
420 	printf(d->df_fmt, icvt((long)*n, d->df_radix, d->df_signed, d->df_field));
421 	return(d->df_size);
422 }
423 
424 l_put(n, d)
425 long	*n;
426 struct dfmt	*d;
427 {
428 	printf(d->df_fmt, icvt(*n, d->df_radix, d->df_signed, d->df_field));
429 	return(d->df_size);
430 }
431 
432 d_put(f, d)
433 double	*f;
434 struct dfmt *d;
435 {
436 	char fbuf[24];
437 	struct l { long n[2]; };
438 
439 #if	vax
440 	if ((((struct l *)f)->n[0] & 0xff00) == 0x8000)	/* Vax illegal f.p. */
441 		sprintf(fbuf, "    %08x %08x",
442 			((struct l *)f)->n[0], ((struct l *)f)->n[1]);
443 	else
444 #endif
445 
446 		sprintf(fbuf, "%21.14e", *f);
447 	printf(d->df_fmt, fbuf);
448 	return(d->df_size);
449 }
450 
451 f_put(f, d)
452 float	*f;
453 struct dfmt *d;
454 {
455 	char fbuf[16];
456 
457 #if	vax
458 	if ((*(long *)f & 0xff00) == 0x8000)	/* Vax illegal f.p. form */
459 		sprintf(fbuf, "      %08x", *(long *)f);
460 	else
461 #endif
462 		sprintf(fbuf, "%14.7e", *f);
463 	printf(d->df_fmt, fbuf);
464 	return(d->df_size);
465 }
466 
467 
468 char	asc_name[34][4] = {
469 /* 000 */	"nul",	"soh",	"stx",	"etx",	"eot",	"enq",	"ack",	"bel",
470 /* 010 */	" bs",	" ht",	" nl",	" vt",	" ff",	" cr",	" so",	" si",
471 /* 020 */	"dle",	"dc1",	"dc2",	"dc3",	"dc4",	"nak",	"syn",	"etb",
472 /* 030 */	"can",	" em",	"sub",	"esc",	" fs",	" gs",	" rs",	" us",
473 /* 040 */	" sp",	"del"
474 };
475 
476 a_put(cc, d)
477 char	*cc;
478 struct dfmt *d;
479 {
480 	int c = *cc;
481 	register char *s = "   ";
482 	register pbit = parity((int)c & 0377);
483 
484 	c &= 0177;
485 	if (isgraphic(c))
486 	{
487 		s[2] = c;
488 		if (pbit == _parity)
489 			printf(d->df_fmt, underline(s));
490 		else
491 			printf(d->df_fmt, s);
492 	}
493 	else
494 	{
495 		if (c == 0177)
496 			c = ' ' + 1;
497 		if (pbit == _parity)
498 			printf(d->df_fmt, underline(asc_name[c]));
499 		else
500 			printf(d->df_fmt, asc_name[c]);
501 	}
502 	return(1);
503 }
504 
505 parity(word)
506 int	word;
507 {
508 	register int p = 0;
509 	register int w = word;
510 
511 	if (w)
512 		do
513 		{
514 			p ^= 1;
515 		} while(w &= (~(-w)));
516 	return (p? ODD:EVEN);
517 }
518 
519 char *
520 underline(s)
521 char	*s;
522 {
523 	static char ulbuf[16];
524 	register char *u = ulbuf;
525 
526 	while (*s)
527 	{
528 		if (*s != ' ')
529 		{
530 			*u++ = '_';
531 			*u++ = '\b';
532 		}
533 		*u++ = *s++;
534 	}
535 	*u = '\0';
536 	return(ulbuf);
537 }
538 
539 b_put(b, d)
540 char	*b;
541 struct dfmt *d;
542 {
543 	printf(d->df_fmt, icvt((long)*b & 0377, d->df_radix, d->df_signed, d->df_field));
544 	return(1);
545 }
546 
547 c_put(cc, d)
548 char	*cc;
549 struct dfmt *d;
550 {
551 	register char	*s;
552 	register int	n;
553 	register int	c = *cc & 0377;
554 
555 	s = scvt(c, d);
556 	for (n = d->df_field - strlen(s); n > 0; n--)
557 		putchar(' ');
558 	printf(d->df_fmt, s);
559 	return(1);
560 }
561 
562 char *scvt(c, d)
563 int	c;
564 struct dfmt	*d;
565 {
566 	static char s[2];
567 
568 	switch(c)
569 	{
570 		case '\0':
571 			return("\\0");
572 
573 		case '\b':
574 			return("\\b");
575 
576 		case '\f':
577 			return("\\f");
578 
579 		case '\n':
580 			return("\\n");
581 
582 		case '\r':
583 			return("\\r");
584 
585 		case '\t':
586 			return("\\t");
587 
588 		default:
589 			if (isprint(c))
590 			{
591 				s[0] = c;
592 				return(s);
593 			}
594 			return(icvt((long)c, d->df_radix, d->df_signed, d->df_field));
595 	}
596 }
597 
598 /*
599  * Look for strings.
600  * A string contains bytes > 037 && < 177, and ends with a null.
601  * The minimum length is given in the dfmt structure.
602  */
603 
604 #define CNULL		'\0'
605 #define S_EMPTY	0
606 #define S_FILL	1
607 #define	S_CONT	2
608 #define SBUFSIZE	1024
609 
610 static char	str_buf[SBUFSIZE];
611 static int	str_mode = S_EMPTY;
612 static char	*str_ptr;
613 static long	str_addr;
614 static long	str_label;
615 
616 st_put(cc, d)
617 char	*cc;
618 struct dfmt	*d;
619 {
620 	register int	c;
621 
622 	if (cc == 0)
623 	{
624 		pr_sbuf(d, YES);
625 		return(1);
626 	}
627 
628 	c = (*cc & 0377);
629 
630 	if (str_mode & S_FILL)
631 	{
632 		if (isascii(c))
633 			put_sbuf(c, d);
634 		else
635 		{
636 			*str_ptr = CNULL;
637 			if (c == NULL)
638 				pr_sbuf(d, YES);
639 			str_mode = S_EMPTY;
640 		}
641 	}
642 	else if (isascii(c))
643 	{
644 		str_mode = S_FILL;
645 		str_addr = addr + (cc - dbuf);	  /* ugly */
646 		if ((str_label = label) >= 0)
647 			str_label += (cc - dbuf); /*  ''  */
648 		str_ptr = str_buf;
649 		put_sbuf(c, d);
650 	}
651 
652 	return(1);
653 }
654 
655 put_sbuf(c, d)
656 int	c;
657 struct dfmt	*d;
658 {
659 	*str_ptr++ = c;
660 	if (str_ptr >= (str_buf + SBUFSIZE))
661 	{
662 		pr_sbuf(d, NO);
663 		str_ptr = str_buf;
664 		str_mode |= S_CONT;
665 	}
666 }
667 
668 pr_sbuf(d, end)
669 struct dfmt	*d;
670 int	end;
671 {
672 	register char	*p = str_buf;
673 
674 	if (str_mode == S_EMPTY
675 	    || (!(str_mode & S_CONT) && (str_ptr - str_buf) < d->df_size))
676 		return;
677 
678 	if (!(str_mode & S_CONT))
679 		put_addr(str_addr, str_label, ' ');
680 
681 	while (p < str_ptr)
682 		fputs(scvt(*p++, d), stdout);
683 
684 	if (end)
685 		putchar('\n');
686 }
687 
688 /*
689  * integer to ascii conversion
690  *
691  * This code has been rearranged to produce optimized runtime code.
692  */
693 
694 #define MAXINTLENGTH	32
695 static char	_digit[] = "0123456789abcdef";
696 static char	_icv_buf[MAXINTLENGTH+1];
697 static long	_mask = 0x7fffffff;
698 
699 char *
700 icvt (value, radix, signed, ndigits)
701 long	value;
702 int	radix;
703 int	signed;
704 int	ndigits;
705 {
706 	register long	val = value;
707 	register long	rad = radix;
708 	register char	*b = &_icv_buf[MAXINTLENGTH];
709 	register char	*d = _digit;
710 	register long	tmp1;
711 	register long	tmp2;
712 	long	rem;
713 	long	kludge;
714 	int	sign;
715 
716 	if (val == 0)
717 	{
718 		*--b = '0';
719 		sign = 0;
720 		goto done; /*return(b);*/
721 	}
722 
723 	if (signed && (sign = (val < 0)))	/* signed conversion */
724 	{
725 		/*
726 		 * It is necessary to do the first divide
727 		 * before the absolute value, for the case -2^31
728 		 *
729 		 * This is actually what is being done...
730 		 * tmp1 = (int)(val % rad);
731 		 * val /= rad;
732 		 * val = -val
733 		 * *--b = d[-tmp1];
734 		 */
735 		tmp1 = val / rad;
736 		*--b = d[(tmp1 * rad) - val];
737 		val = -tmp1;
738 	}
739 	else				/* unsigned conversion */
740 	{
741 		sign = 0;
742 		if (val < 0)
743 		{	/* ALL THIS IS TO SIMULATE UNSIGNED LONG MOD & DIV */
744 			kludge = _mask - (rad - 1);
745 			val &= _mask;
746 			/*
747 			 * This is really what's being done...
748 			 * rem = (kludge % rad) + (val % rad);
749 			 * val = (kludge / rad) + (val / rad) + (rem / rad) + 1;
750 			 * *--b = d[rem % rad];
751 			 */
752 			tmp1 = kludge / rad;
753 			tmp2 = val / rad;
754 			rem = (kludge - (tmp1 * rad)) + (val - (tmp2 * rad));
755 			val = ++tmp1 + tmp2;
756 			tmp1 = rem / rad;
757 			val += tmp1;
758 			*--b = d[rem - (tmp1 * rad)];
759 		}
760 	}
761 
762 	while (val)
763 	{
764 		/*
765 		 * This is really what's being done ...
766 		 * *--b = d[val % rad];
767 		 * val /= rad;
768 		 */
769 		tmp1 = val / rad;
770 		*--b = d[val - (tmp1 * rad)];
771 		val = tmp1;
772 	}
773 
774 done:
775 	if (sign)
776 		*--b = '-';
777 
778 	tmp1 = ndigits - (&_icv_buf[MAXINTLENGTH] - b);
779 	tmp2 = signed? ' ':'0';
780 	while (tmp1 > 0)
781 	{
782 		*--b = tmp2;
783 		tmp1--;
784 	}
785 
786 	return(b);
787 }
788 
789 long get_addr(s)
790 register char *s;
791 {
792 	register char *p;
793 	register long a;
794 	register int d;
795 
796 	if (*s=='+')
797 		s++;
798 	if (*s=='x')
799 	{
800 		s++;
801 		addr_base = 16;
802 	}
803 	else if (*s=='0' && s[1]=='x')
804 	{
805 		s += 2;
806 		addr_base = 16;
807 	}
808 	else if (*s == '0')
809 		addr_base = 8;
810 	p = s;
811 	while(*p)
812 	{
813 		if (*p++=='.')
814 			addr_base = 10;
815 	}
816 	for (a=0; *s; s++)
817 	{
818 		d = *s;
819 		if(isdigit(d))
820 			a = a*addr_base + d - '0';
821 		else if (ishex(d) && addr_base==16)
822 			a = a*addr_base + d + 10 - 'a';
823 		else
824 			break;
825 	}
826 
827 	if (*s == '.')
828 		s++;
829 	if(*s=='b')
830 		a *= 512;
831 	if(*s=='B')
832 		a *= 1024;
833 
834 	return(a);
835 }
836 
837 bufncmp(a, b, n)
838 char	*a;
839 char	*b;
840 int	n;
841 {
842 	while (n--)
843 		if (*a++ != *b++)
844 			return(1);
845 }
846 
847 offset(a)
848 long	a;
849 {
850 	if (canseek(stdin))
851 	{
852 		/*
853 		 * in case we're accessing a raw disk,
854 		 * we have to seek in multiples of a physical block.
855 		 */
856 		fseek(stdin, a & 0xfffffe00L, 0);
857 		a &= 0x1ffL;
858 	}
859 	dumbseek(stdin, a);
860 }
861 
862 dumbseek(s, offset)
863 FILE	*s;
864 long	offset;
865 {
866 	char	buf[BUFSIZ];
867 	int	n;
868 	int	nr;
869 
870 	while (offset > 0)
871 	{
872 		nr = (offset > BUFSIZ) ? BUFSIZ : (int)offset;
873 		if ((n = fread(buf, 1, nr, s)) != nr)
874 		{
875 			fprintf(stderr, "EOF\n");
876 			exit(1);
877 		}
878 		offset -= n;
879 	}
880 }
881 
882 #include <sys/types.h>
883 #include <sys/stat.h>
884 
885 canseek(f)
886 FILE	*f;
887 {
888 	struct stat statb;
889 
890 	return( (fstat(fileno(f),&statb)==0) &&
891 		(statb.st_nlink > 0) &&		/*!pipe*/
892 		(!isatty(fileno(f))) );
893 }
894