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