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