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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 * 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 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 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 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 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