1: static char *sccsid = "@(#)od.c 5.12 (Berkeley) 5/14/84"; 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: } 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: offset(a) 838: long a; 839: { 840: if (canseek(stdin)) 841: { 842: /* 843: * in case we're accessing a raw disk, 844: * we have to seek in multiples of a physical block. 845: */ 846: fseek(stdin, a & 0xfffffe00L, 0); 847: a &= 0x1ffL; 848: } 849: dumbseek(stdin, a); 850: } 851: 852: dumbseek(s, offset) 853: FILE *s; 854: long offset; 855: { 856: char buf[BUFSIZ]; 857: int n; 858: int nr; 859: 860: while (offset > 0) 861: { 862: nr = (offset > BUFSIZ) ? BUFSIZ : (int)offset; 863: if ((n = fread(buf, 1, nr, s)) != nr) 864: { 865: fprintf(stderr, "EOF\n"); 866: exit(1); 867: } 868: offset -= n; 869: } 870: } 871: 872: #include <sys/types.h> 873: #include <sys/stat.h> 874: 875: canseek(f) 876: FILE *f; 877: { 878: struct stat statb; 879: 880: return( (fstat(fileno(f),&statb)==0) && 881: (statb.st_nlink > 0) && /*!pipe*/ 882: (!isatty(fileno(f))) ); 883: }