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