Commit | Line | Data |
---|---|---|
3dbf8875 | 1 | static char *sccsid = "@(#)od.c 5.8 (Berkeley) %G%"; |
3718e103 DW |
2 | /* |
3 | * od -- octal, hex, decimal, character dump of data in a file. | |
4 | * | |
0e88daf2 | 5 | * usage: od [-abBcdDefFhHiIlLopPsvxX] [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 |
0e88daf2 | 22 | * s 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. | |
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 | ||
0e88daf2 DW |
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 | |
3718e103 DW |
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(); | |
0e88daf2 | 56 | int st_put(); |
3718e103 DW |
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 */ | |
0e88daf2 | 63 | int df_paddr; /* "put address on each line?" flag */ |
3718e103 | 64 | int (*df_put)(); /* function to output object */ |
0e88daf2 | 65 | char *df_fmt; /* output string format */ |
3718e103 DW |
66 | } *conv_vec[32]; /* vector of conversions to be done */ |
67 | ||
0e88daf2 DW |
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]; | |
7f1bc61f | 87 | int addr_base = 8; /* default address base is OCTAL */ |
3718e103 | 88 | long addr; |
1fd5a2d4 | 89 | long label = -1L; |
3718e103 DW |
90 | int _parity = NO; |
91 | char fmt[] = " %s"; /* 12 blanks */ | |
92 | char *icvt(); | |
0e88daf2 | 93 | char *scvt(); |
3718e103 | 94 | char *underline(); |
1fd5a2d4 DW |
95 | long get_addr(); |
96 | ||
3718e103 | 97 | |
0e88daf2 DW |
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 | ||
3718e103 | 149 | main(argc, argv) |
0e88daf2 DW |
150 | int argc; |
151 | char **argv; | |
3718e103 DW |
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++; | |
1fd5a2d4 | 163 | argc--; |
3718e103 DW |
164 | max_llen = max_nelm = 0; |
165 | ||
0e88daf2 DW |
166 | if(argc > 0) |
167 | { | |
3718e103 | 168 | p = *argv; |
0e88daf2 DW |
169 | if(*p == '-') |
170 | { | |
171 | while(*++p != '\0') | |
172 | { | |
173 | switch(*p) | |
174 | { | |
3718e103 DW |
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': | |
0e88daf2 | 214 | case 'B': |
3718e103 DW |
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; | |
0e88daf2 DW |
226 | case 's': |
227 | d = &string; | |
228 | *(cv++) = d; | |
0e88daf2 DW |
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; | |
3718e103 DW |
235 | case 'v': |
236 | showall = YES; | |
237 | continue; | |
1fd5a2d4 DW |
238 | default: |
239 | printf("od: bad flag -%c\n", *p); | |
240 | puts(usage); | |
241 | exit(1); | |
3718e103 | 242 | } |
0e88daf2 | 243 | nelm = DBUF_SIZE / d->df_size; |
3718e103 DW |
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); | |
3718e103 DW |
256 | *(cv++) = d; |
257 | } | |
258 | argc--; | |
259 | argv++; | |
260 | } | |
261 | } | |
262 | ||
0e88daf2 DW |
263 | /* |
264 | * if nothing spec'd, setup default conversion. | |
265 | */ | |
266 | if(cv == conv_vec) | |
267 | { | |
3718e103 | 268 | *(cv++) = &u_s_oct; |
0e88daf2 | 269 | max_nelm = DBUF_SIZE / u_s_oct.df_size; |
1fd5a2d4 | 270 | max_llen = max_nelm * (u_s_oct.df_field + 1); |
3718e103 DW |
271 | } |
272 | *cv = (struct dfmt *)0; | |
273 | ||
0e88daf2 DW |
274 | /* |
275 | * setup df_fmt to point to uniform output fields. | |
276 | */ | |
3718e103 | 277 | cv = conv_vec; |
0e88daf2 DW |
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 | } | |
3718e103 DW |
286 | } |
287 | ||
0e88daf2 DW |
288 | /* |
289 | * input file specified ? | |
290 | */ | |
291 | if(argc > 0 && **argv != '+') | |
292 | { | |
293 | if (freopen(*argv, "r", stdin) == NULL) | |
294 | { | |
3718e103 DW |
295 | printf("od: cannot open %s\n", *argv); |
296 | exit(1); | |
297 | } | |
298 | argv++; | |
299 | argc--; | |
300 | } | |
301 | ||
0e88daf2 DW |
302 | /* |
303 | * check for possible offset [label] | |
304 | */ | |
1fd5a2d4 DW |
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 | } | |
3718e103 | 315 | |
0e88daf2 DW |
316 | /* |
317 | * main dump loop | |
318 | */ | |
3718e103 | 319 | same = -1; |
0e88daf2 DW |
320 | while ((n = fread(dbuf, 1, DBUF_SIZE, stdin)) > 0) |
321 | { | |
7f1bc61f | 322 | if (same>=0 && bufncmp(dbuf, lastdbuf, DBUF_SIZE) == 0 && !showall) |
0e88daf2 DW |
323 | { |
324 | if (same==0) | |
325 | { | |
3718e103 DW |
326 | printf("*\n"); |
327 | same = 1; | |
328 | } | |
329 | } | |
0e88daf2 DW |
330 | else |
331 | { | |
3718e103 DW |
332 | line(n); |
333 | same = 0; | |
334 | p = dbuf; | |
335 | l = lastdbuf; | |
0e88daf2 DW |
336 | for (nelm = 0; nelm < DBUF_SIZE; nelm++) |
337 | { | |
3718e103 DW |
338 | *l++ = *p; |
339 | *p++ = '\0'; | |
340 | } | |
341 | } | |
342 | addr += n; | |
1fd5a2d4 DW |
343 | if (label >= 0) |
344 | label += n; | |
3718e103 | 345 | } |
0e88daf2 DW |
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 | } | |
1fd5a2d4 DW |
361 | } |
362 | ||
0e88daf2 DW |
363 | put_addr(a, l, c) |
364 | long a; | |
365 | long l; | |
1fd5a2d4 DW |
366 | char c; |
367 | { | |
0e88daf2 DW |
368 | fputs(icvt(a, addr_base, UNSIGNED, 7), stdout); |
369 | if (l >= 0) | |
370 | printf(" (%s)", icvt(l, addr_base, UNSIGNED, 7)); | |
1fd5a2d4 | 371 | putchar(c); |
3718e103 DW |
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; | |
0e88daf2 DW |
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 | } | |
1fd5a2d4 | 397 | } |
3718e103 DW |
398 | i = 0; |
399 | while (i < n) | |
400 | i += (*(c->df_put))(dbuf+i, c); | |
0e88daf2 DW |
401 | if (c->df_paddr) |
402 | putchar('\n'); | |
3718e103 DW |
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]; | |
d13b8628 DW |
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); | |
3718e103 DW |
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]; | |
d13b8628 DW |
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); | |
3718e103 DW |
461 | printf(d->df_fmt, fbuf); |
462 | return(d->df_size); | |
463 | } | |
464 | ||
465 | ||
466 | char asc_name[34][4] = { | |
0e88daf2 DW |
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" | |
3718e103 DW |
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; | |
0e88daf2 | 483 | if (isgraphic(c)) |
3718e103 | 484 | { |
0e88daf2 | 485 | s[2] = c; |
3718e103 | 486 | if (pbit == _parity) |
d2b19b28 | 487 | printf(d->df_fmt, underline(s)); |
3718e103 DW |
488 | else |
489 | printf(d->df_fmt, s); | |
490 | } | |
491 | else | |
492 | { | |
493 | if (c == 0177) | |
494 | c = ' ' + 1; | |
495 | if (pbit == _parity) | |
d2b19b28 | 496 | printf(d->df_fmt, underline(asc_name[c])); |
3718e103 DW |
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) | |
0e88daf2 DW |
510 | do |
511 | { | |
3718e103 DW |
512 | p ^= 1; |
513 | } while(w &= (~(-w))); | |
514 | return (p? ODD:EVEN); | |
515 | } | |
516 | ||
517 | char * | |
d2b19b28 | 518 | underline(s) |
3718e103 | 519 | char *s; |
3718e103 DW |
520 | { |
521 | static char ulbuf[16]; | |
522 | register char *u = ulbuf; | |
523 | ||
0e88daf2 DW |
524 | while (*s) |
525 | { | |
526 | if (*s != ' ') | |
527 | { | |
3718e103 DW |
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 | { | |
0e88daf2 DW |
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"); | |
3718e103 | 573 | |
0e88daf2 DW |
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)); | |
3718e103 | 593 | } |
0e88daf2 | 594 | } |
3718e103 | 595 | |
0e88daf2 DW |
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 | ||
67e162d0 DW |
614 | st_put(cc, d) |
615 | char *cc; | |
0e88daf2 DW |
616 | struct dfmt *d; |
617 | { | |
67e162d0 DW |
618 | register int c; |
619 | ||
620 | if (cc == 0) | |
0e88daf2 DW |
621 | { |
622 | pr_sbuf(d, YES); | |
67e162d0 | 623 | return(1); |
3718e103 | 624 | } |
67e162d0 DW |
625 | |
626 | c = (*cc & 0377); | |
627 | ||
628 | if (str_mode & S_FILL) | |
0e88daf2 | 629 | { |
67e162d0 DW |
630 | if (isascii(c)) |
631 | put_sbuf(c, d); | |
0e88daf2 DW |
632 | else |
633 | { | |
634 | *str_ptr = CNULL; | |
67e162d0 | 635 | if (c == NULL) |
0e88daf2 DW |
636 | pr_sbuf(d, YES); |
637 | str_mode = S_EMPTY; | |
638 | } | |
639 | } | |
67e162d0 | 640 | else if (isascii(c)) |
0e88daf2 DW |
641 | { |
642 | str_mode = S_FILL; | |
67e162d0 | 643 | str_addr = addr + (cc - dbuf); /* ugly */ |
0e88daf2 | 644 | if ((str_label = label) >= 0) |
67e162d0 | 645 | str_label += (cc - dbuf); /* '' */ |
0e88daf2 | 646 | str_ptr = str_buf; |
67e162d0 | 647 | put_sbuf(c, d); |
0e88daf2 DW |
648 | } |
649 | ||
3718e103 DW |
650 | return(1); |
651 | } | |
652 | ||
0e88daf2 | 653 | put_sbuf(c, d) |
67e162d0 | 654 | int c; |
0e88daf2 DW |
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 | ||
3718e103 DW |
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 | ||
0e88daf2 | 787 | long get_addr(s) |
3718e103 DW |
788 | register char *s; |
789 | { | |
790 | register char *p; | |
1fd5a2d4 | 791 | register long a; |
3718e103 DW |
792 | register int d; |
793 | ||
794 | if (*s=='+') | |
795 | s++; | |
0e88daf2 DW |
796 | if (*s=='x') |
797 | { | |
3718e103 DW |
798 | s++; |
799 | addr_base = 16; | |
0e88daf2 DW |
800 | } |
801 | else if (*s=='0' && s[1]=='x') | |
802 | { | |
3718e103 DW |
803 | s += 2; |
804 | addr_base = 16; | |
0e88daf2 DW |
805 | } |
806 | else if (*s == '0') | |
3718e103 DW |
807 | addr_base = 8; |
808 | p = s; | |
0e88daf2 DW |
809 | while(*p) |
810 | { | |
3718e103 DW |
811 | if (*p++=='.') |
812 | addr_base = 10; | |
813 | } | |
0e88daf2 DW |
814 | for (a=0; *s; s++) |
815 | { | |
3718e103 | 816 | d = *s; |
0e88daf2 | 817 | if(isdigit(d)) |
3718e103 | 818 | a = a*addr_base + d - '0'; |
0e88daf2 | 819 | else if (ishex(d) && addr_base==16) |
3718e103 DW |
820 | a = a*addr_base + d + 10 - 'a'; |
821 | else | |
822 | break; | |
823 | } | |
1fd5a2d4 | 824 | |
3718e103 DW |
825 | if (*s == '.') |
826 | s++; | |
1fd5a2d4 | 827 | if(*s=='b') |
3718e103 | 828 | a *= 512; |
1fd5a2d4 DW |
829 | if(*s=='B') |
830 | a *= 1024; | |
831 | ||
832 | return(a); | |
833 | } | |
834 | ||
7f1bc61f DW |
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 | ||
1fd5a2d4 DW |
845 | offset(a) |
846 | long a; | |
847 | { | |
3718e103 DW |
848 | if (canseek(stdin)) |
849 | fseek(stdin, a, 0); | |
850 | else | |
851 | dumbseek(stdin, a); | |
3718e103 DW |
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 | } |