1 static char *sccsid = "@(#)od.c 5.15 (Berkeley) 12/21/87";
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
main(argc,argv)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 && bcmp(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 exit(0);
364 }
365
put_addr(a,l,c)366 put_addr(a, l, c)
367 long a;
368 long l;
369 char c;
370 {
371 fputs(icvt(a, addr_base, UNSIGNED, 7), stdout);
372 if (l >= 0)
373 printf(" (%s)", icvt(l, addr_base, UNSIGNED, 7));
374 putchar(c);
375 }
376
line(n)377 line(n)
378 int n;
379 {
380 register i, first;
381 register struct dfmt *c;
382 register struct dfmt **cv = conv_vec;
383
384 first = YES;
385 while (c = *cv++)
386 {
387 if (c->df_paddr)
388 {
389 if (first)
390 {
391 put_addr(addr, label, ' ');
392 first = NO;
393 }
394 else
395 {
396 putchar('\t');
397 if (label >= 0)
398 fputs("\t ", stdout);
399 }
400 }
401 i = 0;
402 while (i < n)
403 i += (*(c->df_put))(dbuf+i, c);
404 if (c->df_paddr)
405 putchar('\n');
406 }
407 }
408
s_put(n,d)409 s_put(n, d)
410 short *n;
411 struct dfmt *d;
412 {
413 printf(d->df_fmt, icvt((long)*n, d->df_radix, d->df_signed, d->df_field));
414 return(d->df_size);
415 }
416
us_put(n,d)417 us_put(n, d)
418 unsigned short *n;
419 struct dfmt *d;
420 {
421 printf(d->df_fmt, icvt((long)*n, d->df_radix, d->df_signed, d->df_field));
422 return(d->df_size);
423 }
424
l_put(n,d)425 l_put(n, d)
426 long *n;
427 struct dfmt *d;
428 {
429 printf(d->df_fmt, icvt(*n, d->df_radix, d->df_signed, d->df_field));
430 return(d->df_size);
431 }
432
d_put(f,d)433 d_put(f, d)
434 double *f;
435 struct dfmt *d;
436 {
437 char fbuf[24];
438 struct l { long n[2]; };
439
440 #if vax
441 if ((((struct l *)f)->n[0] & 0xff00) == 0x8000) /* Vax illegal f.p. */
442 (void)sprintf(fbuf, " %08x %08x",
443 ((struct l *)f)->n[0], ((struct l *)f)->n[1]);
444 else
445 #endif
446
447 (void)sprintf(fbuf, "%21.14e", *f);
448 printf(d->df_fmt, fbuf);
449 return(d->df_size);
450 }
451
f_put(f,d)452 f_put(f, d)
453 float *f;
454 struct dfmt *d;
455 {
456 char fbuf[16];
457
458 #if vax
459 if ((*(long *)f & 0xff00) == 0x8000) /* Vax illegal f.p. form */
460 (void)sprintf(fbuf, " %08x", *(long *)f);
461 else
462 #endif
463 (void)sprintf(fbuf, "%14.7e", *f);
464 printf(d->df_fmt, fbuf);
465 return(d->df_size);
466 }
467
468
469 char asc_name[34][4] = {
470 /* 000 */ "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
471 /* 010 */ " bs", " ht", " nl", " vt", " ff", " cr", " so", " si",
472 /* 020 */ "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
473 /* 030 */ "can", " em", "sub", "esc", " fs", " gs", " rs", " us",
474 /* 040 */ " sp", "del"
475 };
476
a_put(cc,d)477 a_put(cc, d)
478 char *cc;
479 struct dfmt *d;
480 {
481 int c = *cc;
482 register char *s = " ";
483 register pbit = parity((int)c & 0377);
484
485 c &= 0177;
486 if (isgraphic(c))
487 {
488 s[2] = c;
489 if (pbit == _parity)
490 printf(d->df_fmt, underline(s));
491 else
492 printf(d->df_fmt, s);
493 }
494 else
495 {
496 if (c == 0177)
497 c = ' ' + 1;
498 if (pbit == _parity)
499 printf(d->df_fmt, underline(asc_name[c]));
500 else
501 printf(d->df_fmt, asc_name[c]);
502 }
503 return(1);
504 }
505
parity(word)506 parity(word)
507 int word;
508 {
509 register int p = 0;
510 register int w = word;
511
512 if (w)
513 do
514 {
515 p ^= 1;
516 } while(w &= (~(-w)));
517 return (p? ODD:EVEN);
518 }
519
520 char *
underline(s)521 underline(s)
522 char *s;
523 {
524 static char ulbuf[16];
525 register char *u = ulbuf;
526
527 while (*s)
528 {
529 if (*s != ' ')
530 {
531 *u++ = '_';
532 *u++ = '\b';
533 }
534 *u++ = *s++;
535 }
536 *u = '\0';
537 return(ulbuf);
538 }
539
b_put(b,d)540 b_put(b, d)
541 char *b;
542 struct dfmt *d;
543 {
544 printf(d->df_fmt, icvt((long)*b & 0377, d->df_radix, d->df_signed, d->df_field));
545 return(1);
546 }
547
c_put(cc,d)548 c_put(cc, d)
549 char *cc;
550 struct dfmt *d;
551 {
552 register char *s;
553 register int n;
554 register int c = *cc & 0377;
555
556 s = scvt(c, d);
557 for (n = d->df_field - strlen(s); n > 0; n--)
558 putchar(' ');
559 printf(d->df_fmt, s);
560 return(1);
561 }
562
scvt(c,d)563 char *scvt(c, d)
564 int c;
565 struct dfmt *d;
566 {
567 static char s[2];
568
569 switch(c)
570 {
571 case '\0':
572 return("\\0");
573
574 case '\b':
575 return("\\b");
576
577 case '\f':
578 return("\\f");
579
580 case '\n':
581 return("\\n");
582
583 case '\r':
584 return("\\r");
585
586 case '\t':
587 return("\\t");
588
589 default:
590 if (isprint(c))
591 {
592 s[0] = c;
593 return(s);
594 }
595 return(icvt((long)c, d->df_radix, d->df_signed, d->df_field));
596 }
597 }
598
599 /*
600 * Look for strings.
601 * A string contains bytes > 037 && < 177, and ends with a null.
602 * The minimum length is given in the dfmt structure.
603 */
604
605 #define CNULL '\0'
606 #define S_EMPTY 0
607 #define S_FILL 1
608 #define S_CONT 2
609 #define SBUFSIZE 1024
610
611 static char str_buf[SBUFSIZE];
612 static int str_mode = S_EMPTY;
613 static char *str_ptr;
614 static long str_addr;
615 static long str_label;
616
st_put(cc,d)617 st_put(cc, d)
618 char *cc;
619 struct dfmt *d;
620 {
621 register int c;
622
623 if (cc == 0)
624 {
625 pr_sbuf(d, YES);
626 return(1);
627 }
628
629 c = (*cc & 0377);
630
631 if (str_mode & S_FILL)
632 {
633 if (isascii(c))
634 put_sbuf(c, d);
635 else
636 {
637 *str_ptr = CNULL;
638 if (c == NULL)
639 pr_sbuf(d, YES);
640 str_mode = S_EMPTY;
641 }
642 }
643 else if (isascii(c))
644 {
645 str_mode = S_FILL;
646 str_addr = addr + (cc - dbuf); /* ugly */
647 if ((str_label = label) >= 0)
648 str_label += (cc - dbuf); /* '' */
649 str_ptr = str_buf;
650 put_sbuf(c, d);
651 }
652
653 return(1);
654 }
655
put_sbuf(c,d)656 put_sbuf(c, d)
657 int c;
658 struct dfmt *d;
659 {
660 *str_ptr++ = c;
661 if (str_ptr >= (str_buf + SBUFSIZE))
662 {
663 pr_sbuf(d, NO);
664 str_ptr = str_buf;
665 str_mode |= S_CONT;
666 }
667 }
668
669 pr_sbuf(d, end)
670 struct dfmt *d;
671 int end;
672 {
673 register char *p = str_buf;
674
675 if (str_mode == S_EMPTY
676 || (!(str_mode & S_CONT) && (str_ptr - str_buf) < d->df_size))
677 return;
678
679 if (!(str_mode & S_CONT))
680 put_addr(str_addr, str_label, ' ');
681
682 while (p < str_ptr)
683 fputs(scvt(*p++, d), stdout);
684
685 if (end)
686 putchar('\n');
687 }
688
689 /*
690 * integer to ascii conversion
691 *
692 * This code has been rearranged to produce optimized runtime code.
693 */
694
695 #define MAXINTLENGTH 32
696 static char _digit[] = "0123456789abcdef";
697 static char _icv_buf[MAXINTLENGTH+1];
698 static long _mask = 0x7fffffff;
699
700 char *
icvt(value,radix,hassign,ndigits)701 icvt (value, radix, hassign, ndigits)
702 long value;
703 int radix;
704 int hassign;
705 int ndigits;
706 {
707 register long val = value;
708 register long rad = radix;
709 register char *b = &_icv_buf[MAXINTLENGTH];
710 register char *d = _digit;
711 register long tmp1;
712 register long tmp2;
713 long rem;
714 long kludge;
715 int sign;
716
717 if (val == 0)
718 {
719 *--b = '0';
720 sign = 0;
721 goto done; /*return(b);*/
722 }
723
724 if (hassign && (sign = (val < 0))) /* signed conversion */
725 {
726 /*
727 * It is necessary to do the first divide
728 * before the absolute value, for the case -2^31
729 *
730 * This is actually what is being done...
731 * tmp1 = (int)(val % rad);
732 * val /= rad;
733 * val = -val
734 * *--b = d[-tmp1];
735 */
736 tmp1 = val / rad;
737 *--b = d[(tmp1 * rad) - val];
738 val = -tmp1;
739 }
740 else /* unsigned conversion */
741 {
742 sign = 0;
743 if (val < 0)
744 { /* ALL THIS IS TO SIMULATE UNSIGNED LONG MOD & DIV */
745 kludge = _mask - (rad - 1);
746 val &= _mask;
747 /*
748 * This is really what's being done...
749 * rem = (kludge % rad) + (val % rad);
750 * val = (kludge / rad) + (val / rad) + (rem / rad) + 1;
751 * *--b = d[rem % rad];
752 */
753 tmp1 = kludge / rad;
754 tmp2 = val / rad;
755 rem = (kludge - (tmp1 * rad)) + (val - (tmp2 * rad));
756 val = ++tmp1 + tmp2;
757 tmp1 = rem / rad;
758 val += tmp1;
759 *--b = d[rem - (tmp1 * rad)];
760 }
761 }
762
763 while (val)
764 {
765 /*
766 * This is really what's being done ...
767 * *--b = d[val % rad];
768 * val /= rad;
769 */
770 tmp1 = val / rad;
771 *--b = d[val - (tmp1 * rad)];
772 val = tmp1;
773 }
774
775 done:
776 if (sign)
777 *--b = '-';
778
779 tmp1 = ndigits - (&_icv_buf[MAXINTLENGTH] - b);
780 tmp2 = hassign? ' ':'0';
781 while (tmp1 > 0)
782 {
783 *--b = tmp2;
784 tmp1--;
785 }
786
787 return(b);
788 }
789
get_addr(s)790 long get_addr(s)
791 register char *s;
792 {
793 register char *p;
794 register long a;
795 register int d;
796
797 if (*s=='+')
798 s++;
799 if (*s=='x')
800 {
801 s++;
802 addr_base = 16;
803 }
804 else if (*s=='0' && s[1]=='x')
805 {
806 s += 2;
807 addr_base = 16;
808 }
809 else if (*s == '0')
810 addr_base = 8;
811 p = s;
812 while(*p)
813 {
814 if (*p++=='.')
815 addr_base = 10;
816 }
817 for (a=0; *s; s++)
818 {
819 d = *s;
820 if(isdigit(d))
821 a = a*addr_base + d - '0';
822 else if (ishex(d) && addr_base==16)
823 a = a*addr_base + d + 10 - 'a';
824 else
825 break;
826 }
827
828 if (*s == '.')
829 s++;
830 if(*s=='b')
831 a *= 512;
832 if(*s=='B')
833 a *= 1024;
834
835 return(a);
836 }
837
offset(a)838 offset(a)
839 long a;
840 {
841 if (canseek(stdin))
842 {
843 /*
844 * in case we're accessing a raw disk,
845 * we have to seek in multiples of a physical block.
846 */
847 fseek(stdin, a & 0xfffffe00L, 0);
848 a &= 0x1ffL;
849 }
850 dumbseek(stdin, a);
851 }
852
dumbseek(s,offset)853 dumbseek(s, offset)
854 FILE *s;
855 long offset;
856 {
857 char buf[BUFSIZ];
858 int n;
859 int nr;
860
861 while (offset > 0)
862 {
863 nr = (offset > BUFSIZ) ? BUFSIZ : (int)offset;
864 if ((n = fread(buf, 1, nr, s)) != nr)
865 {
866 fprintf(stderr, "EOF\n");
867 exit(1);
868 }
869 offset -= n;
870 }
871 }
872
873 #include <sys/types.h>
874 #include <sys/stat.h>
875
canseek(f)876 canseek(f)
877 FILE *f;
878 {
879 struct stat statb;
880
881 return( (fstat(fileno(f),&statb)==0) &&
882 (statb.st_nlink > 0) && /*!pipe*/
883 (!isatty(fileno(f))) );
884 }
885