Commit | Line | Data |
---|---|---|
78d90aa3 | 1 | static char *sccsid = "@(#)od.c 5.11 (Berkeley) %G%"; |
3718e103 DW |
2 | /* |
3 | * od -- octal, hex, decimal, character dump of data in a file. | |
4 | * | |
bca5f88e | 5 | * usage: od [-abBcdDefFhHiIlLopPs[n]vw[n]xX] [file] [[+]offset[.][b] [label]] |
3718e103 DW |
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 | |
0e88daf2 | 20 | * o,B short 8 no (default conversion) |
3718e103 | 21 | * O long 8 no |
bca5f88e | 22 | * s[n] string (8) ASCII graphic strings |
3718e103 DW |
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. | |
bca5f88e | 27 | * w[n] bytes per display line |
3718e103 DW |
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 '+'. | |
bca5f88e DW |
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. | |
3718e103 DW |
34 | */ |
35 | ||
36 | #include <stdio.h> | |
37 | ||
bca5f88e DW |
38 | #define DBUF_SIZE BUFSIZ |
39 | #define BIG_DBUF 32 | |
0e88daf2 DW |
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 | |
3718e103 DW |
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(); | |
0e88daf2 | 57 | int st_put(); |
3718e103 DW |
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 */ | |
0e88daf2 | 64 | int df_paddr; /* "put address on each line?" flag */ |
3718e103 | 65 | int (*df_put)(); /* function to output object */ |
0e88daf2 | 66 | char *df_fmt; /* output string format */ |
3718e103 DW |
67 | } *conv_vec[32]; /* vector of conversions to be done */ |
68 | ||
0e88daf2 DW |
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 | ||
bca5f88e | 85 | char usage[] ="usage: od [-abcdfhilopswvx] [file] [[+]offset[.][b] [label]]"; |
0e88daf2 DW |
86 | char dbuf[DBUF_SIZE]; |
87 | char lastdbuf[DBUF_SIZE]; | |
bca5f88e DW |
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 */ | |
3718e103 DW |
93 | char fmt[] = " %s"; /* 12 blanks */ |
94 | char *icvt(); | |
0e88daf2 | 95 | char *scvt(); |
3718e103 | 96 | char *underline(); |
1fd5a2d4 DW |
97 | long get_addr(); |
98 | ||
3718e103 | 99 | |
0e88daf2 DW |
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 | ||
3718e103 | 151 | main(argc, argv) |
0e88daf2 DW |
152 | int argc; |
153 | char **argv; | |
3718e103 DW |
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++; | |
1fd5a2d4 | 165 | argc--; |
3718e103 | 166 | |
0e88daf2 DW |
167 | if(argc > 0) |
168 | { | |
3718e103 | 169 | p = *argv; |
0e88daf2 DW |
170 | if(*p == '-') |
171 | { | |
172 | while(*++p != '\0') | |
173 | { | |
174 | switch(*p) | |
175 | { | |
3718e103 DW |
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': | |
0e88daf2 | 215 | case 'B': |
3718e103 DW |
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; | |
0e88daf2 DW |
227 | case 's': |
228 | d = &string; | |
229 | *(cv++) = d; | |
0e88daf2 DW |
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; | |
bca5f88e DW |
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; | |
3718e103 DW |
243 | case 'v': |
244 | showall = YES; | |
245 | continue; | |
1fd5a2d4 DW |
246 | default: |
247 | printf("od: bad flag -%c\n", *p); | |
248 | puts(usage); | |
249 | exit(1); | |
3718e103 | 250 | } |
3718e103 DW |
251 | *(cv++) = d; |
252 | } | |
253 | argc--; | |
254 | argv++; | |
255 | } | |
256 | } | |
257 | ||
0e88daf2 DW |
258 | /* |
259 | * if nothing spec'd, setup default conversion. | |
260 | */ | |
261 | if(cv == conv_vec) | |
3718e103 | 262 | *(cv++) = &u_s_oct; |
bca5f88e | 263 | |
3718e103 DW |
264 | *cv = (struct dfmt *)0; |
265 | ||
bca5f88e DW |
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 | ||
0e88daf2 DW |
277 | /* |
278 | * setup df_fmt to point to uniform output fields. | |
279 | */ | |
bca5f88e | 280 | for (cv = conv_vec; d = *cv; cv++) |
0e88daf2 DW |
281 | { |
282 | if (d->df_field) /* only if external field is known */ | |
283 | { | |
bca5f88e | 284 | nelm = (dbuf_size + d->df_size - 1) / d->df_size; |
0e88daf2 DW |
285 | field = max_llen / nelm; |
286 | d->df_fmt = fmt + 12 - (field - d->df_field); | |
287 | } | |
3718e103 DW |
288 | } |
289 | ||
0e88daf2 DW |
290 | /* |
291 | * input file specified ? | |
292 | */ | |
293 | if(argc > 0 && **argv != '+') | |
294 | { | |
295 | if (freopen(*argv, "r", stdin) == NULL) | |
296 | { | |
78d90aa3 | 297 | perror(*argv); |
3718e103 DW |
298 | exit(1); |
299 | } | |
300 | argv++; | |
301 | argc--; | |
302 | } | |
303 | ||
0e88daf2 DW |
304 | /* |
305 | * check for possible offset [label] | |
306 | */ | |
1fd5a2d4 DW |
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 | } | |
3718e103 | 317 | |
0e88daf2 DW |
318 | /* |
319 | * main dump loop | |
320 | */ | |
3718e103 | 321 | same = -1; |
bca5f88e | 322 | while ((n = fread(dbuf, 1, dbuf_size, stdin)) > 0) |
0e88daf2 | 323 | { |
bca5f88e | 324 | if (same>=0 && bufncmp(dbuf, lastdbuf, dbuf_size) == 0 && !showall) |
0e88daf2 DW |
325 | { |
326 | if (same==0) | |
327 | { | |
3718e103 DW |
328 | printf("*\n"); |
329 | same = 1; | |
330 | } | |
331 | } | |
0e88daf2 DW |
332 | else |
333 | { | |
3718e103 DW |
334 | line(n); |
335 | same = 0; | |
336 | p = dbuf; | |
337 | l = lastdbuf; | |
bca5f88e | 338 | for (nelm = 0; nelm < dbuf_size; nelm++) |
0e88daf2 | 339 | { |
3718e103 DW |
340 | *l++ = *p; |
341 | *p++ = '\0'; | |
342 | } | |
343 | } | |
344 | addr += n; | |
1fd5a2d4 DW |
345 | if (label >= 0) |
346 | label += n; | |
3718e103 | 347 | } |
0e88daf2 DW |
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 | } | |
1fd5a2d4 DW |
363 | } |
364 | ||
0e88daf2 DW |
365 | put_addr(a, l, c) |
366 | long a; | |
367 | long l; | |
1fd5a2d4 DW |
368 | char c; |
369 | { | |
0e88daf2 DW |
370 | fputs(icvt(a, addr_base, UNSIGNED, 7), stdout); |
371 | if (l >= 0) | |
372 | printf(" (%s)", icvt(l, addr_base, UNSIGNED, 7)); | |
1fd5a2d4 | 373 | putchar(c); |
3718e103 DW |
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; | |
0e88daf2 DW |
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 | } | |
1fd5a2d4 | 399 | } |
3718e103 DW |
400 | i = 0; |
401 | while (i < n) | |
402 | i += (*(c->df_put))(dbuf+i, c); | |
0e88daf2 DW |
403 | if (c->df_paddr) |
404 | putchar('\n'); | |
3718e103 DW |
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]; | |
d13b8628 DW |
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); | |
3718e103 DW |
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]; | |
d13b8628 DW |
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); | |
3718e103 DW |
463 | printf(d->df_fmt, fbuf); |
464 | return(d->df_size); | |
465 | } | |
466 | ||
467 | ||
468 | char asc_name[34][4] = { | |
0e88daf2 DW |
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" | |
3718e103 DW |
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; | |
0e88daf2 | 485 | if (isgraphic(c)) |
3718e103 | 486 | { |
0e88daf2 | 487 | s[2] = c; |
3718e103 | 488 | if (pbit == _parity) |
d2b19b28 | 489 | printf(d->df_fmt, underline(s)); |
3718e103 DW |
490 | else |
491 | printf(d->df_fmt, s); | |
492 | } | |
493 | else | |
494 | { | |
495 | if (c == 0177) | |
496 | c = ' ' + 1; | |
497 | if (pbit == _parity) | |
d2b19b28 | 498 | printf(d->df_fmt, underline(asc_name[c])); |
3718e103 DW |
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) | |
0e88daf2 DW |
512 | do |
513 | { | |
3718e103 DW |
514 | p ^= 1; |
515 | } while(w &= (~(-w))); | |
516 | return (p? ODD:EVEN); | |
517 | } | |
518 | ||
519 | char * | |
d2b19b28 | 520 | underline(s) |
3718e103 | 521 | char *s; |
3718e103 DW |
522 | { |
523 | static char ulbuf[16]; | |
524 | register char *u = ulbuf; | |
525 | ||
0e88daf2 DW |
526 | while (*s) |
527 | { | |
528 | if (*s != ' ') | |
529 | { | |
3718e103 DW |
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 | { | |
0e88daf2 DW |
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"); | |
3718e103 | 575 | |
0e88daf2 DW |
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)); | |
3718e103 | 595 | } |
0e88daf2 | 596 | } |
3718e103 | 597 | |
0e88daf2 DW |
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 | ||
67e162d0 DW |
616 | st_put(cc, d) |
617 | char *cc; | |
0e88daf2 DW |
618 | struct dfmt *d; |
619 | { | |
67e162d0 DW |
620 | register int c; |
621 | ||
622 | if (cc == 0) | |
0e88daf2 DW |
623 | { |
624 | pr_sbuf(d, YES); | |
67e162d0 | 625 | return(1); |
3718e103 | 626 | } |
67e162d0 DW |
627 | |
628 | c = (*cc & 0377); | |
629 | ||
630 | if (str_mode & S_FILL) | |
0e88daf2 | 631 | { |
67e162d0 DW |
632 | if (isascii(c)) |
633 | put_sbuf(c, d); | |
0e88daf2 DW |
634 | else |
635 | { | |
636 | *str_ptr = CNULL; | |
67e162d0 | 637 | if (c == NULL) |
0e88daf2 DW |
638 | pr_sbuf(d, YES); |
639 | str_mode = S_EMPTY; | |
640 | } | |
641 | } | |
67e162d0 | 642 | else if (isascii(c)) |
0e88daf2 DW |
643 | { |
644 | str_mode = S_FILL; | |
67e162d0 | 645 | str_addr = addr + (cc - dbuf); /* ugly */ |
0e88daf2 | 646 | if ((str_label = label) >= 0) |
67e162d0 | 647 | str_label += (cc - dbuf); /* '' */ |
0e88daf2 | 648 | str_ptr = str_buf; |
67e162d0 | 649 | put_sbuf(c, d); |
0e88daf2 DW |
650 | } |
651 | ||
3718e103 DW |
652 | return(1); |
653 | } | |
654 | ||
0e88daf2 | 655 | put_sbuf(c, d) |
67e162d0 | 656 | int c; |
0e88daf2 DW |
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 | ||
3718e103 DW |
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 | ||
0e88daf2 | 789 | long get_addr(s) |
3718e103 DW |
790 | register char *s; |
791 | { | |
792 | register char *p; | |
1fd5a2d4 | 793 | register long a; |
3718e103 DW |
794 | register int d; |
795 | ||
796 | if (*s=='+') | |
797 | s++; | |
0e88daf2 DW |
798 | if (*s=='x') |
799 | { | |
3718e103 DW |
800 | s++; |
801 | addr_base = 16; | |
0e88daf2 DW |
802 | } |
803 | else if (*s=='0' && s[1]=='x') | |
804 | { | |
3718e103 DW |
805 | s += 2; |
806 | addr_base = 16; | |
0e88daf2 DW |
807 | } |
808 | else if (*s == '0') | |
3718e103 DW |
809 | addr_base = 8; |
810 | p = s; | |
0e88daf2 DW |
811 | while(*p) |
812 | { | |
3718e103 DW |
813 | if (*p++=='.') |
814 | addr_base = 10; | |
815 | } | |
0e88daf2 DW |
816 | for (a=0; *s; s++) |
817 | { | |
3718e103 | 818 | d = *s; |
0e88daf2 | 819 | if(isdigit(d)) |
3718e103 | 820 | a = a*addr_base + d - '0'; |
0e88daf2 | 821 | else if (ishex(d) && addr_base==16) |
3718e103 DW |
822 | a = a*addr_base + d + 10 - 'a'; |
823 | else | |
824 | break; | |
825 | } | |
1fd5a2d4 | 826 | |
3718e103 DW |
827 | if (*s == '.') |
828 | s++; | |
1fd5a2d4 | 829 | if(*s=='b') |
3718e103 | 830 | a *= 512; |
1fd5a2d4 DW |
831 | if(*s=='B') |
832 | a *= 1024; | |
833 | ||
834 | return(a); | |
835 | } | |
836 | ||
7f1bc61f DW |
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 | ||
1fd5a2d4 DW |
847 | offset(a) |
848 | long a; | |
849 | { | |
3718e103 | 850 | if (canseek(stdin)) |
1c2b767a DW |
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); | |
3718e103 DW |
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 | } |