Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/builtin/od.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1992-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* *
20
***********************************************************************/
21
#pragma prototyped
22
/*
23
* Glenn Fowler
24
* David Korn
25
* AT&T Research
26
*
27
* od
28
*/
29
30
static const char usage[] =
31
"[-?\n@(#)$Id: od (AT&T Research) 2012-05-31 $\n]"
32
USAGE_LICENSE
33
"[+NAME?od - dump files in octal or other formats]"
34
"[+DESCRIPTION?\bod\b dumps the contents of the input files in various "
35
"formats on the standard output. The standard input is read if \b-\b or "
36
"no files are specified. Each output line contains the file offset of "
37
"the data in the leftmost column, followed by one or more columns in the "
38
"specified format. If more than one format is specified then the "
39
"subsequent lines are listed with the offset column blank. Second and "
40
"subsequent occurrences of a repeated output line are replaced by a "
41
"single line with `*' in the first data column.]"
42
"[+?\b--format=c\b, \b--format=C\b and \b--format=O\b interpret bytes as "
43
"characters in the LC_CTYPE locale category. The three types differ only "
44
"in the C style escape sequences recognized; \b--format=C\b explicitly "
45
"allows future extensions. The backslash character is written as `\\' "
46
"and NUL is written as `\\0'. Other non-printable characters are written "
47
"as one three-digit octal number for each byte in the character. "
48
"Printable multi-byte characters are written in the area corresponding "
49
"to the first byte of the character; the two-character sequence `**' is "
50
"written in the area corresponding to each remaining byte in the "
51
"character; the remaining bytes for \b-p\b are written as ` '. If "
52
"\b--skip\b or \b--count\b position the file into the middle of a "
53
"multibyte character then the entire multibyte character is silently "
54
"treated as non-character bytes.]"
55
"[+?If the output format is specified by one of the obsolete forms (not "
56
"\b--format\b) then the last file argument is interpreted as an offset "
57
"expression if it matches the extended regular expression "
58
"\b+?[0-9]]+\\.?[bkm]]?(ll|LL)?\b . In this case the first \aoffset\a "
59
"bytes of the file are skipped. The optional \bb\b means bytes, \bk\b "
60
"means Kb, and \bm\b means Mb. \bll\b and \bLL\b are ignored for "
61
"compatibility with some systems.]"
62
"[A:address-radix?The file offset radix.]:[radix:=o]"
63
"{"
64
"[+d?decimal]"
65
"[+o?octal]"
66
"[+x?hexadecimal]"
67
"[+n?none - do not print offset]"
68
"}"
69
"[B:swap?Swap input bytes according to the bit mask \aop\a, which is the "
70
"inclusive or of:]#[op]"
71
"{"
72
"[+01?swap 8-bit bytes]"
73
"[+02?swap 16-bit words]"
74
"[+04?swap 32-bit longs]"
75
"[+0?swap for big endian testing]"
76
"}"
77
"[j:skip-bytes?Skip \bbytes\b bytes into the data before "
78
"formatting.]#[bytes]"
79
"[N:count|read-bytes?Output only \bbytes\b bytes of data.]#[bytes]"
80
"[m:map?\b--printable\b and \b--format=m\b bytes are converted from "
81
"\acodeset\a to the native codeset. The codesets are:]:[codeset]"
82
"{\fcodesets\f} [p:printable?Output the printable bytes (after \b--map\b "
83
"if specified), in the last data column. Non-printable byte values are "
84
"printed as `.'.]"
85
"[z:strings?Output NUL terminated strings of at least \alength\a "
86
"bytes.]#? [length:=3]"
87
"[t:format|type?The data item output \aformat\a and \asize\a. A decimal byte "
88
"count or size code may follow all but the \ba\b, \bc\b, \bC\b, \bm\b "
89
"and \bO\b formats.]:[format[size]]:=o2]"
90
"{\ftypes\f}"
91
"[T:test?Enable internal implementation specific tests.]:[test]"
92
"{"
93
"[+b\an\a?Allocate a fixed input buffer of size \an\a.]"
94
"[+m\an\a?Set the mapped input buffer size to \an\a.]"
95
"[+n?Turn off the \bSF_SHARE\b input buffer flag.]"
96
"}"
97
"[v:all|output-duplicates?Output all data.]"
98
"[w:per-line|width?The number of items to format per output line. "
99
"\aper-line\a must be a multiple of the least common multiple of the "
100
"sizes of the format types.]#[per-line]"
101
"[a?Equivalent to \b-ta\b.]"
102
"[b?Equivalent to \b-toC\b.]"
103
"[c?Equivalent to \b-tO\b.]"
104
"[C?Equivalent to \b-tO\b.]"
105
"[d?Equivalent to \b-tuS\b.]"
106
"[D?Equivalent to \b-tuL\b.]"
107
"[f?Equivalent to \b-tfF\b.]"
108
"[F?Equivalent to \b-tfD\b.]"
109
"[h?Equivalent to \b-txS\b.]"
110
"[i?Equivalent to \b-tdS\b.]"
111
"[l?Equivalent to \b-tdL\b.]"
112
"[o?Equivalent to \b-toS\b.]"
113
"[O?Equivalent to \b-toL\b.]"
114
"[s?Equivalent to \b-tdS\b.]"
115
"[S?Equivalent to \b-tdL\b.]"
116
"[u?Equivalent to \b-tuS\b.]"
117
"[U?Equivalent to \b-tuL\b.]"
118
"[x?Equivalent to \b-txS\b.]"
119
"[X?Equivalent to \b-txL\b.]"
120
"\n"
121
"\n[ file ... ] [ [+]offset[.|b|k|m|ll|LL] ]\n"
122
"\n"
123
"[+SEE ALSO?\bsed\b(1), \bstrings\b(1), \bswap\b(3), \bascii\b(5)]"
124
;
125
126
#include <cmd.h>
127
#include <sig.h>
128
#include <swap.h>
129
#include <ccode.h>
130
#include <ctype.h>
131
#include <iconv.h>
132
#include <vmalloc.h>
133
#include <ast_float.h>
134
135
#if _hdr_wctype
136
#include <wchar.h>
137
#include <wctype.h>
138
#else
139
#define iswprint(w) isprint(w)
140
#endif
141
142
#define NEW (1<<0)
143
#define OLD (1<<1)
144
145
#define BASE_WIDTH 7
146
#define LINE_LENGTH 78
147
148
#define WIDTHINDEX(n) (((n)>1)+((n)>2)+((n)>4)+((n)>8))
149
150
#ifdef _ast_int8_t
151
#define QUAL "ll"
152
#else
153
#define QUAL "l"
154
#endif
155
156
#if _typ_long_double
157
#define double_max long double
158
#else
159
#define double_max double
160
#endif
161
162
struct State_s; typedef struct State_s State_t;
163
struct Format_s; typedef struct Format_s Format_t;
164
165
typedef void (*Format_f)(State_t*, Format_t*, Sfio_t*, unsigned char*);
166
167
typedef union Mem_u
168
{
169
char m_char[sizeof(intmax_t) + sizeof(double_max)];
170
float m_float;
171
double m_double;
172
#if _typ_long_double
173
long double m_long_double;
174
#endif
175
} Mem_t;
176
177
typedef struct Size_s
178
{
179
char* desc;
180
int name;
181
int map;
182
int dflt;
183
const char* qual;
184
int size;
185
int prefix;
186
int digits;
187
int exponent;
188
} Size_t;
189
190
typedef struct Type_s
191
{
192
char* desc;
193
char name;
194
char mb;
195
const char* fill;
196
Format_f fun;
197
const Size_t* size;
198
char width[5];
199
} Type_t;
200
201
struct Format_s
202
{
203
struct Format_s*next;
204
const Type_t* type;
205
Format_f fun;
206
char form[16];
207
struct
208
{
209
int external;
210
int internal;
211
} size;
212
int fp;
213
int width;
214
int us;
215
int per;
216
};
217
218
struct State_s
219
{
220
int addr;
221
char base[8];
222
int block;
223
struct
224
{
225
char* base;
226
size_t size;
227
int noshare;
228
} buffer;
229
size_t count;
230
struct
231
{
232
char buf[1024];
233
char* data;
234
int mark;
235
size_t size;
236
} dup;
237
unsigned char* eob;
238
char* file;
239
Format_t* form;
240
Format_t* last;
241
unsigned char* map;
242
int mb;
243
int mbmax;
244
int mbp;
245
intmax_t offset;
246
struct
247
{
248
char* data;
249
size_t size;
250
} peek;
251
int printable;
252
int size;
253
size_t skip;
254
char* span;
255
int spansize;
256
int strings;
257
int style;
258
int swap;
259
size_t total;
260
int verbose;
261
int width;
262
Vmalloc_t* vm;
263
};
264
265
static const Size_t csize[] =
266
{
267
"char", 'C', 0, 1, 0, 1,0,0,0,
268
0
269
};
270
271
static const Size_t isize[] =
272
{
273
"char", 'C', 0, 0, 0, 1,0,0,0,
274
"short", 'S', 0, 0, 0, sizeof(short),0,0,0,
275
"int", 'I', 0, 1, 0, sizeof(int),0,0,0,
276
"long", 'L', 0, 0, "l", sizeof(long),0,0,0,
277
"long long", 'D', 0, 0,
278
#ifdef _ast_int8_t
279
"ll", sizeof(int64_t),0,0,0,
280
#else
281
0, sizeof(long),0,0,0,
282
#endif
283
0
284
};
285
286
static const Size_t fsize[] =
287
{
288
"float", 'F', 'e', 0, 0, sizeof(float),3,FLT_DIG,FLT_MAX_10_EXP,
289
"double", 'D', 'e', 1, 0, sizeof(double),3,DBL_DIG,DBL_MAX_10_EXP,
290
"long double", 'L', 'e', 0,
291
#if _typ_long_double
292
"L", sizeof(long double),3,LDBL_DIG,LDBL_MAX_10_EXP,
293
#else
294
0, sizeof(double),3,DBL_DIG,DBL_MAX_10_EXP,
295
#endif
296
0
297
};
298
299
static const Size_t asize[] =
300
{
301
"float", 'F', 'a', 0, 0, sizeof(float),5,FLT_DIG,FLT_MAX_EXP,
302
"double", 'D', 'a', 1, 0, sizeof(double),5,DBL_DIG,DBL_MAX_EXP,
303
"long double", 'L', 'a', 0,
304
#if _typ_long_double
305
"L", sizeof(long double),5,LDBL_DIG,LDBL_MAX_EXP,
306
#else
307
0, sizeof(double),5,DBL_DIG,DBL_MAX_EXP,
308
#endif
309
0
310
};
311
312
static void
313
aform(State_t* state, Format_t* fp, Sfio_t* op, unsigned char* u)
314
{
315
register int c = *u;
316
317
static const char anames[] =
318
"nulsohstxetxeotenqackbel bs ht nl vt ff cr so si"
319
"dledc1dc2dc3dc4naksynetbcan emsubesc fs gs rs us"
320
" sp ! \" # $ % & ' ( ) * + , - . /"
321
" 0 1 2 3 4 5 6 7 8 9 : ; < = > ?"
322
" @ A B C D E F G H I J K L M N O"
323
" P Q R S T U V W X Y Z [ \\ ] ^ _"
324
" ` a b c d e f g h i j k l m n o"
325
" p q r s t u v w x y z { | } ~del";
326
327
c = 3 * (c & 0177);
328
sfputc(op, anames[c]);
329
sfputc(op, anames[c+1]);
330
sfputc(op, anames[c+2]);
331
}
332
333
static void
334
bform(State_t* state, Format_t* fp, Sfio_t* op, unsigned char* u)
335
{
336
sfprintf(op, "%08..2u", *u);
337
}
338
339
static void
340
cform(State_t* state, Format_t* fp, Sfio_t* op, unsigned char* u)
341
{
342
unsigned char* v;
343
char* s;
344
wchar_t w;
345
int i;
346
int j;
347
char buf[2];
348
349
if (state->mb)
350
{
351
state->mb--;
352
sfputc(op, ' ');
353
sfputc(op, '*');
354
sfputc(op, '*');
355
return;
356
}
357
switch (*u)
358
{
359
case 0:
360
sfputc(op, ' ');
361
sfputc(op, '\\');
362
sfputc(op, '0');
363
return;
364
case '\\':
365
sfputc(op, ' ');
366
sfputc(op, ' ');
367
sfputc(op, '\\');
368
return;
369
}
370
buf[0] = *(v = u);
371
if ((w = mbnchar(u, state->eob - u)) > 0 && (i = u - v) > 1 && !iswprint(w))
372
{
373
state->mb = i - 1;
374
for (j = 3 - mbwidth(w); j > 0; j--)
375
sfputc(op, ' ');
376
while (i--)
377
sfputc(op, *v++);
378
return;
379
}
380
buf[1] = 0;
381
s = fmtesc(buf);
382
383
/*
384
* posix shalls are sometimes an impediment to progress
385
*/
386
387
if (*s != '\\')
388
{
389
sfputc(op, ' ');
390
sfputc(op, ' ');
391
sfputc(op, *s);
392
return;
393
}
394
switch (*(s + 1))
395
{
396
case 'a':
397
case 'b':
398
case 'f':
399
case 'n':
400
case 'r':
401
case 't':
402
case 'v':
403
sfputc(op, ' ');
404
sfputc(op, '\\');
405
sfputc(op, *(s + 1));
406
return;
407
case '0':
408
case '1':
409
case '2':
410
case '3':
411
case '4':
412
case '5':
413
case '6':
414
case '7':
415
sfputc(op, *++s);
416
sfputc(op, *++s);
417
sfputc(op, *++s);
418
return;
419
}
420
sfprintf(op, "%03o", *v);
421
}
422
423
static void
424
Cform(State_t* state, Format_t* fp, Sfio_t* op, unsigned char* u)
425
{
426
unsigned char* v;
427
char* s;
428
wchar_t w;
429
int i;
430
int j;
431
char buf[2];
432
433
if (state->mb)
434
{
435
state->mb--;
436
sfputc(op, ' ');
437
sfputc(op, '*');
438
sfputc(op, '*');
439
return;
440
}
441
switch (*u)
442
{
443
case 0:
444
sfputc(op, ' ');
445
sfputc(op, '\\');
446
sfputc(op, '0');
447
return;
448
case '\\':
449
sfputc(op, ' ');
450
sfputc(op, ' ');
451
sfputc(op, '\\');
452
return;
453
}
454
buf[0] = *(v = u);
455
if ((w = mbnchar(u, state->eob - u)) > 0 && (i = u - v) > 1 && !iswprint(w))
456
{
457
state->mb = i - 1;
458
for (j = 3 - mbwidth(w); j > 0; j--)
459
sfputc(op, ' ');
460
while (i--)
461
sfputc(op, *v++);
462
return;
463
}
464
buf[1] = 0;
465
s = fmtesc(buf);
466
if (*s != '\\')
467
{
468
sfputc(op, ' ');
469
sfputc(op, ' ');
470
sfputc(op, *s);
471
return;
472
}
473
if (isdigit(*(s + 1)))
474
{
475
sfputc(op, *++s);
476
sfputc(op, *++s);
477
sfputc(op, *++s);
478
return;
479
}
480
sfputc(op, ' ');
481
sfputc(op, '\\');
482
sfputc(op, *(s + 1));
483
}
484
485
static void
486
mform(State_t* state, Format_t* fp, Sfio_t* op, unsigned char* u)
487
{
488
register char* s;
489
char buf[2];
490
491
switch (buf[0] = ccmapchr(state->map, *u))
492
{
493
case 0:
494
sfputc(op, '0');
495
sfputc(op, '0');
496
return;
497
case '\\':
498
sfputc(op, ' ');
499
sfputc(op, '\\');
500
return;
501
}
502
buf[1] = 0;
503
s = fmtesc(buf);
504
if (*s != '\\')
505
{
506
sfputc(op, ' ');
507
sfputc(op, *s);
508
return;
509
}
510
if (isdigit(*(s + 1)))
511
sfprintf(op, "%02lx", strtol(s + 1, NiL, 8));
512
else
513
{
514
sfputc(op, '\\');
515
sfputc(op, *(s + 1));
516
}
517
}
518
519
static void
520
Oform(State_t* state, Format_t* fp, Sfio_t* op, unsigned char* u)
521
{
522
unsigned char* v;
523
char* s;
524
wchar_t w;
525
int i;
526
int j;
527
char buf[2];
528
529
if (state->mb)
530
{
531
state->mb--;
532
sfputc(op, ' ');
533
sfputc(op, '*');
534
sfputc(op, '*');
535
return;
536
}
537
switch (*u)
538
{
539
case 0:
540
sfputc(op, ' ');
541
sfputc(op, '\\');
542
sfputc(op, '0');
543
return;
544
case '\\':
545
sfputc(op, ' ');
546
sfputc(op, ' ');
547
sfputc(op, '\\');
548
return;
549
}
550
buf[0] = *(v = u);
551
if ((w = mbnchar(u, state->eob - u)) > 0 && (i = u - v) > 1 && !iswprint(w))
552
{
553
state->mb = i - 1;
554
for (j = 3 - mbwidth(w); j > 0; j--)
555
sfputc(op, ' ');
556
while (i--)
557
sfputc(op, *v++);
558
return;
559
}
560
buf[1] = 0;
561
s = fmtesc(buf);
562
563
/*
564
* posix shalls are sometimes an impediment to progress
565
*/
566
567
if (*s != '\\')
568
{
569
sfputc(op, ' ');
570
sfputc(op, ' ');
571
sfputc(op, *s);
572
return;
573
}
574
switch (*(s + 1))
575
{
576
case 'b':
577
case 'f':
578
case 'n':
579
case 'r':
580
case 't':
581
sfputc(op, ' ');
582
sfputc(op, '\\');
583
sfputc(op, *(s + 1));
584
return;
585
case '0':
586
case '1':
587
case '2':
588
case '3':
589
case '4':
590
case '5':
591
case '6':
592
case '7':
593
sfputc(op, *++s);
594
sfputc(op, *++s);
595
sfputc(op, *++s);
596
return;
597
}
598
sfprintf(op, "%03o", *v);
599
}
600
601
static const Type_t type[] =
602
{
603
{
604
"ISO/IEC 646:1991 named characters",
605
'a', 0, 0, aform, csize, 3, 0, 0, 0, 0
606
},
607
{
608
"hexadecimal floating point",
609
'A', 0, 0, 0, asize, 0, 0, 0, 0, 0
610
},
611
{
612
"binary character",
613
'b', 0, 0, bform, csize, 8, 0, 0, 0, 0
614
},
615
{
616
"locale character or backslash escape (\\a \\b \\f \\n \\r \\t \\v)",
617
'c', 0, 0, cform, csize, 3, 0, 0, 0, 0
618
},
619
{
620
"locale character or backslash escape (current and future escapes)",
621
'C', 0, 0, Cform, csize, 3, 0, 0, 0, 0
622
},
623
{
624
"signed decimal",
625
'd', 0, 0, 0, isize, 4, 6, 11, 21, 31
626
},
627
{
628
"floating point",
629
'f', 0, 0, 0, fsize, 0, 0, 0, 0, 0
630
},
631
{
632
"\b--map\b mapped character or hexadecimal value if not printable",
633
'm', 0, 0, mform, csize, 2, 0, 0, 0, 0
634
},
635
{
636
"octal",
637
'o', 0, "0", 0, isize, 3, 6, 11, 22, 33
638
},
639
{
640
"locale character or backslash escape (\\b \\f \\n \\r \\t)",
641
'O', 0, 0, Oform, csize, 3, 0, 0, 0, 0
642
},
643
{
644
"unsigned decimal",
645
'u', 0, 0, 0, isize, 3, 5, 10, 20, 30
646
},
647
{
648
"hexadecimal",
649
'x', 0, "0", 0, isize, 2, 4, 8, 16, 32
650
},
651
{
652
"printable bytes",
653
'z', 0, 0, 0, 0, 1, 0, 0, 0, 0
654
},
655
};
656
657
static void
658
form_int8(State_t* state, Format_t* fp, Sfio_t* op, unsigned char* u)
659
{
660
sfprintf(op, fp->form, *u);
661
}
662
663
static void
664
form_int16(State_t* state, Format_t* fp, Sfio_t* op, unsigned char* u)
665
{
666
sfprintf(op, fp->form, (int16_t)swapget(state->swap, u, fp->size.external));
667
}
668
669
static void
670
form_int32(State_t* state, Format_t* fp, Sfio_t* op, unsigned char* u)
671
{
672
sfprintf(op, fp->form, (int32_t)swapget(state->swap, u, fp->size.external));
673
}
674
675
static void
676
form_intmax(State_t* state, Format_t* fp, Sfio_t* op, unsigned char* u)
677
{
678
sfprintf(op, fp->form, (intmax_t)swapget(state->swap, u, fp->size.external));
679
}
680
681
static void
682
form_uint8(State_t* state, Format_t* fp, Sfio_t* op, unsigned char* u)
683
{
684
sfprintf(op, fp->form, *u);
685
}
686
687
static void
688
form_uint16(State_t* state, Format_t* fp, Sfio_t* op, unsigned char* u)
689
{
690
sfprintf(op, fp->form, (uint16_t)swapget(state->swap, u, fp->size.external));
691
}
692
693
static void
694
form_uint32(State_t* state, Format_t* fp, Sfio_t* op, unsigned char* u)
695
{
696
sfprintf(op, fp->form, (uint32_t)swapget(state->swap, u, fp->size.external));
697
}
698
699
static void
700
form_uintmax(State_t* state, Format_t* fp, Sfio_t* op, unsigned char* u)
701
{
702
sfprintf(op, fp->form, (uintmax_t)swapget(state->swap, u, fp->size.external));
703
}
704
705
static void
706
form_float(State_t* state, Format_t* fp, Sfio_t* op, unsigned char* u)
707
{
708
Mem_t mem;
709
710
swapmem(state->swap ^ int_swap, u, mem.m_char, fp->size.internal);
711
sfprintf(op, fp->form, mem.m_float);
712
}
713
714
static void
715
form_double(State_t* state, Format_t* fp, Sfio_t* op, unsigned char* u)
716
{
717
Mem_t mem;
718
719
swapmem(state->swap ^ int_swap, u, mem.m_char, fp->size.internal);
720
sfprintf(op, fp->form, mem.m_double);
721
}
722
723
#if _typ_long_double
724
725
static void
726
form_long_double(State_t* state, Format_t* fp, Sfio_t* op, unsigned char* u)
727
{
728
Mem_t mem;
729
730
swapmem(state->swap ^ int_swap, u, mem.m_char, fp->size.internal);
731
sfprintf(op, fp->form, mem.m_long_double);
732
}
733
734
#endif
735
736
/*
737
* add format type t to the format list
738
*/
739
740
static void
741
format(State_t* state, register char* t)
742
{
743
register int c;
744
register const Type_t* tp;
745
register const Size_t* zp;
746
register Format_t* fp;
747
const Size_t* xp;
748
uintmax_t m;
749
int prec;
750
int base;
751
int n;
752
int i;
753
char* e;
754
char* s;
755
char dig[256];
756
757
while (c = *t++)
758
{
759
if (isspace(c) || c == ',')
760
continue;
761
tp = type;
762
while (c != tp->name)
763
if (++tp >= &type[elementsof(type)])
764
{
765
error(2, "%c: invalid type name", c);
766
return;
767
}
768
if (!(zp = tp->size) && !tp->fun)
769
{
770
switch (tp->width[0])
771
{
772
case 1:
773
state->printable = 1;
774
break;
775
}
776
continue;
777
}
778
xp = 0;
779
if (isdigit(*t))
780
{
781
c = 0;
782
n = (int)strton(t, &e, NiL, 1);
783
t = e;
784
}
785
else
786
{
787
c = isupper(*t) ? *t++ : 0;
788
n = 0;
789
}
790
for (;;)
791
{
792
if (!zp->name)
793
{
794
if (c)
795
{
796
error(2, "%c: invalid size for type %c", c, tp->name);
797
return;
798
}
799
if (!(zp = xp) || zp->exponent)
800
{
801
error(2, "%d: invalid size for type %c", n, tp->name);
802
return;
803
}
804
break;
805
}
806
if (n)
807
{
808
if (n == zp->size)
809
break;
810
zp++;
811
if (n > (zp-1)->size && n < zp->size)
812
xp = zp;
813
}
814
else if (c == zp->name)
815
{
816
if (c != *t)
817
break;
818
t++;
819
zp++;
820
if (zp->name)
821
break;
822
}
823
else if (!c && !n && zp->dflt)
824
break;
825
else
826
zp++;
827
}
828
if (tp->mb && (i = mbmax()) > 1)
829
state->mbmax = i;
830
i = zp - tp->size;
831
if (!(fp = vmnewof(state->vm, 0, Format_t, 1, 0)))
832
{
833
error(ERROR_system(1), "out of space");
834
return;
835
}
836
if (state->last)
837
state->last = state->last->next = fp;
838
else
839
state->form = state->last = fp;
840
fp->type = tp;
841
fp->us = tp->name != 'd';
842
fp->size.internal = zp->size;
843
fp->size.external = n ? n : zp->size;
844
if (state->size < fp->size.external)
845
state->size = fp->size.external;
846
if (zp->exponent)
847
{
848
if (zp->map == 'a')
849
{
850
for (m = 0, i = zp->digits; i-- > 0; m = m * 10 + 9);
851
prec = sfsprintf(dig, sizeof(dig), "%I*x", sizeof(m), m);
852
}
853
else
854
prec = zp->digits;
855
base = sfsprintf(dig, sizeof(dig), "%u", zp->exponent);
856
fp->width = zp->prefix + prec + base + 2;
857
}
858
else
859
{
860
fp->width = tp->width[i = WIDTHINDEX(fp->size.internal)];
861
if (n > 1 && (n & (n - 1)))
862
{
863
c = (1 << i) - n;
864
n = (1 << i) - (1 << (i - 1));
865
fp->width -= ((fp->width - tp->width[i - 1] + n - 1) / n) * c;
866
}
867
prec = 0;
868
base = 0;
869
}
870
if (!(fp->fun = tp->fun))
871
{
872
e = fp->form;
873
*e++ = '%';
874
if (s = (char*)tp->fill)
875
while (*e = *s++)
876
e++;
877
e += sfsprintf(e, sizeof(fp->form) - (e - fp->form), "%d", fp->width);
878
if (prec)
879
e += sfsprintf(e, sizeof(fp->form) - (e - fp->form), ".%d", prec);
880
if (base)
881
e += sfsprintf(e, sizeof(fp->form) - (e - fp->form), "%s.%d", prec ? "" : ".", base);
882
if (s = (char*)zp->qual)
883
while (*e = *s++)
884
e++;
885
*e = zp->map ? zp->map : tp->name;
886
if (zp->exponent)
887
{
888
#if _typ_long_double
889
if (fp->size.internal == sizeof(long double))
890
fp->fun = form_long_double;
891
else
892
#endif
893
if (fp->size.internal == sizeof(double))
894
fp->fun = form_double;
895
else
896
fp->fun = form_float;
897
}
898
else if (fp->us)
899
switch (fp->size.internal)
900
{
901
case 1:
902
fp->fun = form_uint8;
903
break;
904
case 2:
905
fp->fun = form_uint16;
906
break;
907
case 4:
908
fp->fun = form_uint32;
909
break;
910
default:
911
fp->fun = form_uintmax;
912
break;
913
}
914
else
915
switch (fp->size.internal)
916
{
917
case 1:
918
fp->fun = form_int8;
919
break;
920
case 2:
921
fp->fun = form_int16;
922
break;
923
case 4:
924
fp->fun = form_int32;
925
break;
926
default:
927
fp->fun = form_intmax;
928
break;
929
}
930
}
931
}
932
}
933
934
static Sfio_t*
935
init(State_t* state, char*** p)
936
{
937
Sfio_t* ip;
938
intmax_t offset;
939
940
for (;;)
941
{
942
if (**p)
943
state->file = *((*p)++);
944
else if (state->file)
945
return 0;
946
if (!state->file || streq(state->file, "-"))
947
{
948
state->file = "/dev/stdin";
949
ip = sfstdin;
950
}
951
else if (!(ip = sfopen(NiL, state->file, "r")))
952
{
953
error(ERROR_system(0), "%s: cannot open", state->file);
954
error_info.errors = 1;
955
continue;
956
}
957
if (state->buffer.noshare)
958
sfset(ip, SF_SHARE, 0);
959
if (state->buffer.size)
960
sfsetbuf(ip, state->buffer.base, state->buffer.size);
961
if (state->skip)
962
{
963
if ((offset = sfseek(ip, (off_t)0, SEEK_END)) > 0)
964
{
965
if (offset <= state->skip)
966
{
967
state->skip -= offset;
968
state->offset += offset;
969
goto next;
970
}
971
if (sfseek(ip, state->skip, SEEK_SET) != state->skip)
972
{
973
error(ERROR_system(2), "%s: seek error", state->file);
974
goto next;
975
}
976
state->offset += state->skip;
977
state->skip = 0;
978
}
979
else
980
{
981
for (;;)
982
{
983
if (!(state->peek.data = sfreserve(ip, SF_UNBOUND, 0)))
984
{
985
if (sfvalue(ip))
986
error(ERROR_system(2), "%s: read error", state->file);
987
goto next;
988
}
989
state->peek.size = sfvalue(ip);
990
if (state->peek.size < state->skip)
991
state->skip -= state->peek.size;
992
else
993
{
994
state->peek.data += state->skip;
995
state->peek.size -= state->skip;
996
state->skip = 0;
997
break;
998
}
999
}
1000
}
1001
}
1002
break;
1003
next:
1004
if (ip != sfstdin)
1005
sfclose(ip);
1006
}
1007
return ip;
1008
}
1009
1010
static int
1011
block(State_t* state, Sfio_t* op, char* bp, char* ep, intmax_t base)
1012
{
1013
register Format_t* fp;
1014
register unsigned char* u;
1015
register ssize_t z;
1016
unsigned long n;
1017
1018
if (!state->verbose)
1019
{
1020
if (state->dup.size == (n = ep - bp) && !memcmp(state->dup.data, bp, n))
1021
{
1022
if (!state->dup.mark)
1023
{
1024
state->dup.mark = 1;
1025
sfprintf(op, "*\n");
1026
}
1027
return 0;
1028
}
1029
state->dup.mark = 0;
1030
}
1031
for (fp = state->form; fp; fp = fp->next)
1032
{
1033
if (*state->base)
1034
{
1035
if (fp == state->form)
1036
sfprintf(op, state->base, base);
1037
else
1038
sfprintf(op, "%-*.*s ", BASE_WIDTH, BASE_WIDTH, "");
1039
}
1040
u = (unsigned char*)bp;
1041
for (;;)
1042
{
1043
z = fp->per - fp->width;
1044
while (z-- > 0)
1045
sfputc(op, ' ');
1046
(*fp->fun)(state, fp, op, u);
1047
if ((u += fp->size.external) < (unsigned char*)ep)
1048
sfputc(op, ' ');
1049
else
1050
{
1051
if (state->printable && fp == state->form)
1052
{
1053
register int c;
1054
unsigned char* v;
1055
wchar_t w;
1056
1057
if (c = (state->block - (ep - bp)) / state->size * (state->width + 1))
1058
sfprintf(op, "%*s", c, "");
1059
sfputc(op, ' ');
1060
if (state->mbmax)
1061
for (u = (unsigned char*)bp; u < (unsigned char*)ep; u++)
1062
{
1063
if (state->mbp)
1064
{
1065
state->mbp--;
1066
sfputc(op, '.');
1067
}
1068
else if ((v = u) && (w = mbnchar(v, state->eob - u)) > 0 && (c = v - u) > 1 && !iswprint(w))
1069
{
1070
sfwrite(op, u, c);
1071
state->mbp = c - 1;
1072
}
1073
else
1074
{
1075
if ((c = ccmapchr(state->map, *u)) < 040 || c >= 0177)
1076
c = '.';
1077
sfputc(op, c);
1078
}
1079
}
1080
else
1081
for (u = (unsigned char*)bp; u < (unsigned char*)ep;)
1082
{
1083
if ((c = ccmapchr(state->map, *u++)) < 040 || c >= 0177)
1084
c = '.';
1085
sfputc(op, c);
1086
}
1087
}
1088
sfputc(op, '\n');
1089
break;
1090
}
1091
}
1092
if (sferror(op))
1093
return -1;
1094
}
1095
return 0;
1096
}
1097
1098
static int
1099
od(State_t* state, char** files)
1100
{
1101
register char* s;
1102
register char* e;
1103
register char* x;
1104
register char* span = 0;
1105
register int c;
1106
Sfio_t* ip;
1107
size_t n;
1108
size_t m;
1109
ssize_t r;
1110
1111
if (!(ip = init(state, &files)))
1112
return 0;
1113
for (;;)
1114
{
1115
if (s = state->peek.data)
1116
{
1117
state->peek.data = 0;
1118
n = state->peek.size;
1119
}
1120
else
1121
for (;;)
1122
{
1123
s = sfreserve(ip, SF_UNBOUND, 0);
1124
n = sfvalue(ip);
1125
if (s)
1126
break;
1127
if (n)
1128
error(ERROR_system(2), "%s: read error", state->file);
1129
if (ip != sfstdin)
1130
sfclose(ip);
1131
if (!(ip = init(state, &files)))
1132
{
1133
s = 0;
1134
n = 0;
1135
break;
1136
}
1137
}
1138
state->eob = (unsigned char*)s + n;
1139
if (state->count)
1140
{
1141
if (state->total >= state->count)
1142
{
1143
s = 0;
1144
n = 0;
1145
}
1146
else if ((state->total += n) > state->count)
1147
n -= state->total - state->count;
1148
}
1149
if (span)
1150
{
1151
respan:
1152
if (s)
1153
{
1154
m = state->spansize - (span - state->span);
1155
if (m > n)
1156
{
1157
memcpy(span, s, n);
1158
span += n;
1159
continue;
1160
}
1161
memcpy(span, s, m);
1162
span += m;
1163
s += m;
1164
n -= m;
1165
}
1166
if (m = (span - state->span) % state->size)
1167
{
1168
m = state->size - m;
1169
while (m--)
1170
*span++ = 0;
1171
}
1172
state->eob = (unsigned char*)span;
1173
if ((m = span - state->span) > state->block)
1174
m = state->block;
1175
if (block(state, sfstdout, state->span, state->span + m, state->offset))
1176
goto bad;
1177
state->offset += m;
1178
if (!state->verbose)
1179
memcpy(state->dup.data = state->dup.buf, state->span, state->dup.size = m);
1180
if ((r = (span - state->span) - m) > 0)
1181
{
1182
span = state->span;
1183
x = state->span + m;
1184
while (r--)
1185
*span++ = *x++;
1186
goto respan;
1187
}
1188
span = 0;
1189
if (s && !n)
1190
continue;
1191
}
1192
if (!s)
1193
break;
1194
x = s + n;
1195
if (state->strings)
1196
{
1197
state->offset += n;
1198
n = 0;
1199
for (;;)
1200
{
1201
if (s >= x || (c = *s++) == 0 || c == '\n' || !isprint(c))
1202
{
1203
if (n >= state->strings)
1204
{
1205
if (*state->base && sfprintf(sfstdout, state->base, state->offset - (x - s) - n - 1) < 0)
1206
break;
1207
if (sfprintf(sfstdout, "%.*s\n", n, s - n - 1) < 0)
1208
break;
1209
}
1210
if (s >= x)
1211
break;
1212
n = 0;
1213
}
1214
else
1215
n++;
1216
}
1217
}
1218
else
1219
{
1220
e = s + (n / state->block) * state->block;
1221
if (state->mbmax)
1222
e -= state->block + state->mbmax;
1223
if (s < e)
1224
{
1225
do
1226
{
1227
if (block(state, sfstdout, s, s + state->block, state->offset))
1228
goto bad;
1229
state->offset += state->block;
1230
state->dup.data = s;
1231
state->dup.size = state->block;
1232
} while ((s += state->block) < e);
1233
if (!state->verbose)
1234
{
1235
memcpy(state->dup.buf, state->dup.data, state->dup.size = state->block);
1236
state->dup.data = state->dup.buf;
1237
}
1238
}
1239
if (n = x - s)
1240
{
1241
memcpy(state->span, s, n);
1242
span = state->span + n;
1243
}
1244
}
1245
}
1246
return 0;
1247
bad:
1248
if (ip != sfstdin)
1249
sfclose(ip);
1250
return -1;
1251
}
1252
1253
/*
1254
* optinfo() size description
1255
*/
1256
1257
static int
1258
optsize(Sfio_t* sp, const Size_t* zp)
1259
{
1260
register int n;
1261
1262
for (n = 0; zp->name; zp++)
1263
if (zp->qual && (*zp->qual != zp->name || *(zp->qual + 1)))
1264
n += sfprintf(sp, "[%c|%s?sizeof(%s)]", zp->name, zp->qual, zp->desc);
1265
else
1266
n += sfprintf(sp, "[%c?sizeof(%s)]", zp->name, zp->desc);
1267
return n;
1268
}
1269
1270
/*
1271
* optget() info discipline function
1272
*/
1273
1274
static int
1275
optinfo(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
1276
{
1277
register iconv_list_t* ic;
1278
register int i;
1279
register int n;
1280
1281
n = 0;
1282
switch (*s)
1283
{
1284
case 'c':
1285
for (ic = iconv_list(NiL); ic; ic = iconv_list(ic))
1286
if (ic->ccode >= 0)
1287
n += sfprintf(sp, "[%c:%s?%s]", ic->match[ic->match[0] == '('], ic->name, ic->desc);
1288
break;
1289
case 't':
1290
for (i = 0; i < elementsof(type); i++)
1291
n += sfprintf(sp, "[%c?%s]", type[i].name, type[i].desc);
1292
n += sfprintf(sp, "[+----- sizes -----?]");
1293
n += optsize(sp, isize);
1294
n += optsize(sp, fsize);
1295
break;
1296
}
1297
return n;
1298
}
1299
1300
int
1301
b_od(int argc, char** argv, Shbltin_t* context)
1302
{
1303
register int n;
1304
register char* s;
1305
register Format_t* fp;
1306
char* e;
1307
int per;
1308
char buf[4];
1309
Optdisc_t optdisc;
1310
State_t state;
1311
1312
cmdinit(argc, argv, context, ERROR_CATALOG, 0);
1313
memset(&state, 0, sizeof(state));
1314
if (!(state.vm = vmopen(Vmdcheap, Vmlast, 0)))
1315
{
1316
error(ERROR_SYSTEM|2, "out of space");
1317
return 1;
1318
}
1319
optinit(&optdisc, optinfo);
1320
per = 0;
1321
state.map = ccmap(CC_ASCII, CC_ASCII);
1322
state.swap = int_swap;
1323
for (;;)
1324
{
1325
switch (optget(argv, usage))
1326
{
1327
case 'A':
1328
*state.base = *opt_info.arg;
1329
state.style |= NEW;
1330
continue;
1331
case 'B':
1332
if (opt_info.num <= 0)
1333
state.swap = -opt_info.num;
1334
else
1335
state.swap ^= opt_info.num;
1336
continue;
1337
case 'j':
1338
if (*opt_info.option == '+')
1339
{
1340
opt_info.index--;
1341
break;
1342
}
1343
state.skip = opt_info.num;
1344
state.style |= NEW;
1345
continue;
1346
case 'm':
1347
if ((n = ccmapid(opt_info.arg)) < 0)
1348
error(2, "%s: unknown character code set", opt_info.arg);
1349
else
1350
state.map = ccmap(n, CC_NATIVE);
1351
continue;
1352
case 'N':
1353
state.count = opt_info.num;
1354
state.style |= NEW;
1355
continue;
1356
case 'p':
1357
state.printable = 1;
1358
continue;
1359
case 't':
1360
format(&state, opt_info.arg);
1361
state.style |= NEW;
1362
continue;
1363
case 'T':
1364
s = opt_info.arg;
1365
switch (*s)
1366
{
1367
case 'b':
1368
case 'm':
1369
n = *s++;
1370
state.buffer.size = strton(s, &e, NiL, 1);
1371
if (n == 'b' && !(state.buffer.base = vmnewof(state.vm, 0, char, state.buffer.size, 0)))
1372
{
1373
error(ERROR_SYSTEM|2, "out of space");
1374
goto done;
1375
}
1376
if (*e)
1377
error(2, "%s: invalid characters after test", e);
1378
break;
1379
case 'n':
1380
state.buffer.noshare = 1;
1381
break;
1382
default:
1383
error(2, "%s: unknown test", s);
1384
break;
1385
}
1386
continue;
1387
case 'v':
1388
state.verbose = 1;
1389
state.style |= NEW;
1390
continue;
1391
case 'w':
1392
per = opt_info.num;
1393
continue;
1394
case 'z':
1395
state.strings = opt_info.num;
1396
continue;
1397
case 'a':
1398
case 'b':
1399
case 'c':
1400
case 'C':
1401
case 'd':
1402
case 'D':
1403
case 'f':
1404
case 'F':
1405
case 'h':
1406
case 'i':
1407
case 'l':
1408
case 'o':
1409
case 'O':
1410
case 's':
1411
case 'S':
1412
case 'u':
1413
case 'U':
1414
case 'x':
1415
case 'X':
1416
s = buf;
1417
switch (n = opt_info.option[1])
1418
{
1419
case 'b':
1420
*s++ = 'o';
1421
*s++ = 'C';
1422
break;
1423
case 'c':
1424
case 'C':
1425
*s++ = 'O';
1426
break;
1427
case 'D':
1428
n = 'U';
1429
break;
1430
case 'd':
1431
n = 'u';
1432
break;
1433
case 'h':
1434
n = 'x';
1435
break;
1436
case 'i':
1437
case 's':
1438
n = 'd';
1439
break;
1440
case 'l':
1441
case 'S':
1442
n = 'D';
1443
break;
1444
}
1445
if (s == buf)
1446
{
1447
if (isupper(n))
1448
switch (*s++ = tolower(n))
1449
{
1450
case 'f':
1451
*s++ = 'D';
1452
break;
1453
default:
1454
*s++ = 'L';
1455
break;
1456
}
1457
else
1458
switch (*s++ = n)
1459
{
1460
case 'd':
1461
case 'o':
1462
case 's':
1463
case 'u':
1464
case 'x':
1465
/* pronounce that! */
1466
*s++ = 'S';
1467
break;
1468
case 'f':
1469
*s++ = 'F';
1470
break;
1471
}
1472
}
1473
*s = 0;
1474
format(&state, buf);
1475
state.style |= OLD;
1476
continue;
1477
case ':':
1478
error(2, "%s", opt_info.arg);
1479
continue;
1480
case '?':
1481
error(ERROR_usage(2), "%s", opt_info.arg);
1482
continue;
1483
}
1484
break;
1485
}
1486
argv += opt_info.index;
1487
if (error_info.errors)
1488
error(ERROR_usage(2), "%s", optusage(NiL));
1489
switch (n = *state.base)
1490
{
1491
case 'n':
1492
*state.base = 0;
1493
break;
1494
case 0:
1495
n = 'o';
1496
/*FALLTHROUGH*/
1497
case 'o':
1498
state.addr = 8;
1499
goto base;
1500
case 'd':
1501
state.addr = 10;
1502
goto base;
1503
case 'x':
1504
state.addr = 16;
1505
/*FALLTHROUGH*/
1506
base:
1507
sfsprintf(state.base, sizeof(state.base), "%%0%d%s%c ", BASE_WIDTH, QUAL, n);
1508
break;
1509
default:
1510
error(2, "%c: invalid addr-base type", n);
1511
break;
1512
}
1513
if (!state.form)
1514
format(&state, "oS");
1515
else if (state.strings)
1516
error(2, "--strings must be the only format type");
1517
if (error_info.errors)
1518
goto done;
1519
for (fp = state.form; fp; fp = fp->next)
1520
if ((n = (state.size / fp->size.external) * (fp->width + 1) - 1) > state.width)
1521
state.width = n;
1522
for (fp = state.form; fp; fp = fp->next)
1523
fp->per = state.width * fp->size.external / state.size;
1524
n = LINE_LENGTH - state.printable;
1525
if (*state.base)
1526
n -= (BASE_WIDTH + 1);
1527
if (!(n /= (state.width + state.printable * state.size + 1)))
1528
n = 1;
1529
if (state.addr)
1530
{
1531
while (n > state.addr)
1532
state.addr *= 2;
1533
while (n < state.addr)
1534
state.addr /= 2;
1535
if (state.addr)
1536
n = state.addr;
1537
}
1538
if (per)
1539
n = per;
1540
state.block = n * state.size;
1541
state.spansize = state.block + state.mbmax;
1542
if (!(state.span = vmnewof(state.vm, 0, char, state.spansize, 0)))
1543
{
1544
error(ERROR_SYSTEM|2, "out of space");
1545
goto done;
1546
}
1547
if (!(state.style & NEW) && (s = *argv))
1548
{
1549
e = "?(+)+([0-9])?(.)?([bkm])?(ll|LL)";
1550
if (!*(argv + 1))
1551
{
1552
if (strmatch(s, e) && *s == '+')
1553
argv++;
1554
else s = 0;
1555
}
1556
else if (!*(argv + 2))
1557
{
1558
s = *(argv + 1);
1559
if (strmatch(s, e) && (state.style == OLD || *s == '+'))
1560
*(argv + 1) = 0;
1561
else s = 0;
1562
}
1563
else s = 0;
1564
if (s)
1565
{
1566
state.skip = strtol(s, &e, strchr(s, '.') ? 10 : 8);
1567
if (*e == '.')
1568
e++;
1569
switch (*e)
1570
{
1571
case 'b':
1572
state.skip *= 512;
1573
break;
1574
case 'k':
1575
state.skip *= 1024;
1576
break;
1577
case 'm':
1578
state.skip *= 1024 * 1024;
1579
break;
1580
}
1581
}
1582
}
1583
#ifdef SIGFPE
1584
signal(SIGFPE, SIG_IGN);
1585
#endif
1586
od(&state, argv);
1587
#ifdef SIGFPE
1588
signal(SIGFPE, SIG_DFL);
1589
#endif
1590
if (state.skip)
1591
{
1592
error(2, "cannot skip past available data");
1593
goto done;
1594
}
1595
if (*state.base && !state.strings)
1596
{
1597
*(state.base + strlen(state.base) - 1) = '\n';
1598
sfprintf(sfstdout, state.base, (intmax_t)state.offset);
1599
}
1600
if (sfsync(sfstdout) && !ERROR_PIPE(errno))
1601
error(ERROR_SYSTEM|2, "write error");
1602
done:
1603
vmclose(state.vm);
1604
return error_info.errors != 0;
1605
}
1606
1607