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