|
|
1.1 ! root 1: /* ! 2: * Octal dump. ! 3: * The name is a bit of a joke on a ! 4: * machine that uses hexadecimal, ! 5: * but it will stay like this for now. ! 6: * Defaults to hex unless on the PDP11. ! 7: */ ! 8: ! 9: #include <stdio.h> ! 10: #include <sys/mdata.h> ! 11: ! 12: #ifndef PDP11 ! 13: #define DEFBASE 16 ! 14: #define DEFC 'x' ! 15: #else ! 16: #define DEFBASE 8 ! 17: #define DEFC 'o' ! 18: #endif ! 19: ! 20: #define WIDTH 80 ! 21: #define getbyte() getc(ifp) ! 22: #define getword() getw(ifp) ! 23: ! 24: /* Forward. */ ! 25: long getoffs(); ! 26: void mkfmt(); ! 27: int putasc(); ! 28: void usage(); ! 29: int val(); ! 30: ! 31: /* Globals. */ ! 32: int base = DEFBASE; ! 33: char buf[BUFSIZ]; ! 34: FILE *ifp; ! 35: ! 36: main(argc, argv) int argc; char *argv[]; ! 37: { ! 38: register char *p; ! 39: register c, i; ! 40: long offs; ! 41: int bump, fc, mol, nof, nol, pw; ! 42: char afmt[10], pfmt[10]; ! 43: int found; ! 44: ! 45: found = 0; ! 46: i = 1; ! 47: fc = DEFC; ! 48: if (i<argc && argv[i][0]=='-') { ! 49: p = &argv[i++][1]; ! 50: while ((c = *p++) != 0) { ! 51: switch (c) { ! 52: ! 53: case 'b': ! 54: case 'c': ! 55: case 'd': ! 56: case 'o': ! 57: case 'x': ! 58: if (found) ! 59: usage(); ! 60: fc = c; ! 61: found++; ! 62: break; ! 63: ! 64: default: ! 65: usage(); ! 66: } ! 67: } ! 68: } ! 69: setbuf(stdout, buf); ! 70: ifp = stdin; ! 71: nof = 0; ! 72: if (i < argc) { ! 73: ++nof; ! 74: if (*(p=argv[i++]) != '+') { ! 75: nof = 0; ! 76: if ((ifp=fopen(p, "rb")) == NULL) { ! 77: fprintf(stderr, "%s: cannot open.\n", p); ! 78: exit(1); ! 79: } ! 80: if (i<argc && argv[i][0]=='+') { ! 81: ++i; ! 82: ++nof; ! 83: } ! 84: } ! 85: } ! 86: if (nof && i>=argc) ! 87: usage(); ! 88: offs = 0; ! 89: if (i < argc) { ! 90: offs = getoffs(argv[i]); ! 91: fseek(ifp, offs, 0); ! 92: } ! 93: if (fc=='b' || fc=='c') { ! 94: bump = sizeof(char); ! 95: if (DEFC == 'o') ! 96: pw = (NBCHAR+2) / 3; else ! 97: pw = (NBCHAR+3) / 4; ! 98: } else { ! 99: bump = sizeof(int); ! 100: if (fc != 'x') ! 101: pw = (NBINT+2) / 3; else ! 102: pw = (NBINT+3) / 4; ! 103: } ! 104: mkfmt(pfmt, pw, fc); ! 105: if (DEFC == 'o') ! 106: mkfmt(afmt, (NBLONG+2)/3, 'O'); ! 107: else ! 108: mkfmt(afmt, (NBLONG+3)/4, 'X'); ! 109: for (mol=1; mol < (WIDTH-(NBLONG+2)/3)/(pw+1); mol<<=1) ! 110: ; ! 111: mol >>= 1; ! 112: nol = 0; ! 113: for (;;) { ! 114: c = (bump==sizeof(char)) ? getbyte() : getword(); ! 115: if (ferror(ifp) && c != EOF) /* partial read */ ! 116: clearerr(ifp); /* treated as good */ ! 117: else if (feof(ifp)) ! 118: break; ! 119: if (nol >= mol) { ! 120: putchar('\n'); ! 121: nol = 0; ! 122: } ! 123: if (nol == 0) ! 124: printf(afmt, offs); ! 125: if (fc!='c' || !putasc(c)) ! 126: printf(pfmt, c); ! 127: ++nol; ! 128: offs += bump; ! 129: } ! 130: if (nol != 0) ! 131: putchar('\n'); ! 132: exit(0); ! 133: } ! 134: ! 135: /* ! 136: * Parse the offset at p (form [0[x]]dd*[.][b]) and return its value. ! 137: * Much ado about little. ! 138: */ ! 139: long ! 140: getoffs(p) register char *p; ! 141: { ! 142: register char *ep; ! 143: int bflag; ! 144: long offs; ! 145: ! 146: ep = &p[strlen(p) - 1]; /* pointer to last char of arg */ ! 147: bflag = (*ep == 'b'); /* trailing b means blocks */ ! 148: if (bflag) ! 149: *ep-- = '\0'; ! 150: if (*ep == '.') { /* trailing . means decimal */ ! 151: *ep = '\0'; ! 152: base = 10; ! 153: } else if (*p == '0') { ! 154: if (*++p == 'x') { /* leading 0x means hex */ ! 155: ++p; ! 156: base = 16; ! 157: } else /* leading 0 means octal */ ! 158: base = 8; ! 159: } ! 160: for (offs = 0; *p != '\0'; offs = base * offs + val(*p++)) ! 161: ; ! 162: return (bflag) ? offs * BUFSIZ : offs; ! 163: } ! 164: ! 165: void ! 166: mkfmt(p, w, c) register char *p; register int w, c; ! 167: { ! 168: if (c >= 'a') ! 169: *p++ = ' '; ! 170: *p++ = '%'; ! 171: if (c != 'd') ! 172: *p++ = '0'; ! 173: if (w >= 10) { ! 174: *p++ = '1'; ! 175: w -= 10; ! 176: } ! 177: *p++ = w+'0'; ! 178: if (c=='b' || c=='c') ! 179: c = DEFC; ! 180: if (c >= 'A' && c <= 'Z') { ! 181: *p++ = 'l'; ! 182: c += 'a' - 'A'; ! 183: } ! 184: *p++ = c; ! 185: *p = 0; ! 186: } ! 187: ! 188: int ! 189: putasc(c) register int c; ! 190: { ! 191: register n; ! 192: ! 193: if (c>=' ' && c<='~') { ! 194: putchar(' '); ! 195: putchar(c); ! 196: if (DEFC == 'o') ! 197: n = (NBCHAR+2)/3 - 1; else ! 198: n = (NBCHAR+3)/4 - 1; ! 199: while (n--) ! 200: putchar(' '); ! 201: return (1); ! 202: } ! 203: switch (c) { ! 204: ! 205: case '\0': ! 206: c = '0'; ! 207: break; ! 208: ! 209: case '\b': ! 210: c = 'b'; ! 211: break; ! 212: ! 213: case '\f': ! 214: c = 'f'; ! 215: break; ! 216: ! 217: case '\n': ! 218: c = 'n'; ! 219: break; ! 220: ! 221: case '\r': ! 222: c = 'r'; ! 223: break; ! 224: ! 225: case '\t': ! 226: c = 't'; ! 227: break; ! 228: ! 229: default: ! 230: return (0); ! 231: } ! 232: putchar(' '); ! 233: putchar('\\'); ! 234: putchar(c); ! 235: if (DEFC == 'o') ! 236: n = (NBCHAR+2)/3 - 2; else ! 237: n = (NBCHAR+3)/4 - 2; ! 238: while (n--) ! 239: putchar(' '); ! 240: return (1); ! 241: } ! 242: ! 243: void ! 244: usage() ! 245: { ! 246: fprintf(stderr, "Usage: od [-bcdox] [file] [ [+] offset[.][b] ]\n"); ! 247: exit(1); ! 248: } ! 249: ! 250: /* ! 251: * Given ASCII character c, return its integer value. ! 252: * Give a usage error if the character is illegal in the given base. ! 253: * Base must be 8, 10 or 16. ! 254: */ ! 255: int ! 256: val(c) register int c; ! 257: { ! 258: if (c >= '0' && c <= '7') ! 259: return c - '0'; ! 260: else if (base == 8) ! 261: usage(); ! 262: else if (c == '8' || c == '9') ! 263: return c - '0'; ! 264: else if (base == 10) ! 265: usage(); ! 266: else if (c >= 'a' && c <= 'f') ! 267: return c + 10 - 'a'; ! 268: else if (c >= 'A' && c <= 'F') ! 269: return c + 10 - 'A'; ! 270: else ! 271: usage(); ! 272: } ! 273: ! 274: /* end of od.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.