4540c2a |
Jamozed |
2020-07-06 23:15:03 |
0
|
// od.c, version 0.8.1 |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
1
|
// OMKOV coreutils implementation of POSIX od |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
2
|
// Copyright (C) 2020, Jakob Wakeling |
e2140ec |
Jamozed |
2022-03-06 15:27:45 |
3
|
// MIT Licence |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
4
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
5
|
/* |
4540c2a |
Jamozed |
2020-07-06 23:15:03 |
6
|
TODO Improve error handling |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
7
|
TODO Implement [[+]offset[.][b]] operand as required by POSIX. |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
8
|
TODO Fix segfault when using standard input. |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
9
|
*/ |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
10
|
|
b181413 |
Jamozed |
2022-02-05 22:32:00 |
11
|
#include "util/error.h" |
b181413 |
Jamozed |
2022-02-05 22:32:00 |
12
|
#include "util/optget.h" |
4540c2a |
Jamozed |
2020-07-06 23:15:03 |
13
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
14
|
#include <errno.h> |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
15
|
#include <limits.h> |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
16
|
#include <stdbool.h> |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
17
|
#include <stdint.h> |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
18
|
#include <stdio.h> |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
19
|
#include <stdlib.h> |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
20
|
#include <string.h> |
4540c2a |
Jamozed |
2020-07-06 23:15:03 |
21
|
|
4540c2a |
Jamozed |
2020-07-06 23:15:03 |
22
|
#define VERSION "0.8.1" |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
23
|
|
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
24
|
static struct lop lops[] = { |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
25
|
{ "help", ARG_NUL, 256 }, |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
26
|
{ "version", ARG_NUL, 257 }, |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
27
|
{ NULL, 0, 0 } |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
28
|
}; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
29
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
30
|
typedef struct { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
31
|
union { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
32
|
uint8_t i8[16]; uint16_t i16[8]; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
33
|
uint32_t i32[4]; uint64_t i64[2]; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
34
|
float f32[4]; double f64[2]; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
35
|
}; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
36
|
long count; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
37
|
} block_t; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
38
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
39
|
typedef struct { int type, bytes, pads, padm; char *form; } type_t; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
40
|
typedef struct { int *data; size_t cap, len; } list_t; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
41
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
42
|
enum { ta = 19, tb = 4, tc = 20, td = 9, tl = 21, to = 5, ts = 1, tx = 13 }; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
43
|
static type_t types[] = { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
44
|
{ 'd', 1, 4, 80, "%4d" }, { 'd', 2, 6, 56, "%6d" }, |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
45
|
{ 'd', 4, 11, 48, "%11d" }, { 'd', 8, 21, 44, "%21ld" }, |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
46
|
{ 'o', 1, 3, 64, "%03hho" }, { 'o', 2, 6, 56, "%06ho" }, |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
47
|
{ 'o', 4, 11, 48, "%011o" }, { 'o', 8, 22, 46, "%022lo" }, |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
48
|
{ 'u', 1, 3, 64, "%3hhu" }, { 'u', 2, 5, 48, "%5hu" }, |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
49
|
{ 'u', 4, 10, 44, "%10u" }, { 'u', 8, 20, 42, "%20lu" }, |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
50
|
{ 'x', 1, 2, 48, "%2hhx" }, { 'x', 2, 4, 40, "%4hx" }, |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
51
|
{ 'x', 4, 8, 36, "%8x" }, { 'x', 8, 16, 34, "%16lx" }, |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
52
|
{ 'f', 4, 15, 64, "%15.7e" }, { 'f', 8, 22, 46, "%22.14e" }, |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
53
|
{ 0 , 0, 0, 0, NULL }, { 'a', 1, 3, 64, "" }, |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
54
|
{ 'c', 1, 3, 64, "" }, { 'l', 1, 3, 64, "" } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
55
|
}; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
56
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
57
|
static const char *const aTABL[] = { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
58
|
"nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
59
|
" bs", " ht", " nl", " vt", " ff", " cr", " so", " si", |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
60
|
"dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb", |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
61
|
"can", " em", "sub", "esc", " fs", " gs", " rs", " us", |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
62
|
" sp" |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
63
|
}; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
64
|
static const char *const cTABL[] = { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
65
|
" \\0", "001", "002", "003", "004", "005", "006", " \\a", |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
66
|
" \\b", " \\t", " \\n", " \\v", " \\f", " \\r", "016", "017", |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
67
|
"020", "021", "022", "023", "024", "025", "026", "027", |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
68
|
"030", "031", "032", "033", "034", "035", "036", "037" |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
69
|
}; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
70
|
static const char *const lTABL[] = { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
71
|
" \\0", "001", "002", "003", "004", "005", "006", "007", |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
72
|
" \\b", " \\t", " \\n", "013", " \\f", " \\r", "016", "017", |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
73
|
"020", "021", "022", "023", "024", "025", "026", "027", |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
74
|
"030", "031", "032", "033", "034", "035", "036", "037", |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
75
|
}; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
76
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
77
|
static char Aform[] = "%08jo"; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
78
|
static bool vflag; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
79
|
static bool Nflag; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
80
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
81
|
static uintmax_t start, limit, offset, total; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
82
|
static list_t tlist; static int mpad = 0; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
83
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
84
|
static char **files; static FILE *file; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
85
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
86
|
static inline uintmax_t bparse(char *str); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
87
|
static inline int tparse(char *str); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
88
|
static inline int skip(uintmax_t offset); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
89
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
90
|
static inline void aprint_generic(uintmax_t addr, char c); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
91
|
static inline void aprint_none(uintmax_t addr, char c); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
92
|
static void (*aprint)(uintmax_t, char) = aprint_generic; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
93
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
94
|
static inline int bread(block_t *blk); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
95
|
static inline void bprint(block_t *blk, int ti); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
96
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
97
|
static inline FILE *fnext(void); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
98
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
99
|
static inline list_t linit(void); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
100
|
static inline void lpush(list_t *list, int i); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
101
|
|
be8a914 |
Jamozed |
2020-10-26 12:22:47 |
102
|
static void hlp(void); |
be8a914 |
Jamozed |
2020-10-26 12:22:47 |
103
|
static void ver(void); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
104
|
|
4540c2a |
Jamozed |
2020-07-06 23:15:03 |
105
|
int main(int ac, char *av[]) { A0 = av[0]; |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
106
|
struct opt opt = OPTGET_INIT; opt.lops = lops; int ret = 0; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
107
|
opt.str = "A:bcdj:N:ost:vx"; tlist = linit(); |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
108
|
for (int o; (o = optget(&opt, av, 1)) != -1;) switch (o) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
109
|
case 'A': switch(opt.arg[0]) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
110
|
case 'd': { aprint = aprint_generic; Aform[4] = 'u'; continue; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
111
|
case 'o': { aprint = aprint_generic; Aform[4] = 'o'; continue; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
112
|
case 'x': { aprint = aprint_generic; Aform[4] = 'x'; continue; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
113
|
case 'n': { aprint = aprint_none; continue; } |
4540c2a |
Jamozed |
2020-07-06 23:15:03 |
114
|
default: { warn("%c: invalid address base", opt.arg[0]); ret = 1; |
4540c2a |
Jamozed |
2020-07-06 23:15:03 |
115
|
goto end; }} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
116
|
case 'b': { lpush(&tlist, tb); break; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
117
|
case 'c': { lpush(&tlist, tl); break; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
118
|
case 'd': { lpush(&tlist, td); break; } |
be8a914 |
Jamozed |
2020-10-26 12:22:47 |
119
|
case 'j': { |
be8a914 |
Jamozed |
2020-10-26 12:22:47 |
120
|
errno = 0; start = bparse(opt.arg); if (errno) { |
be8a914 |
Jamozed |
2020-10-26 12:22:47 |
121
|
warn("%s: invalid skip value", opt.arg); ret = 1; goto end; } |
be8a914 |
Jamozed |
2020-10-26 12:22:47 |
122
|
break; |
be8a914 |
Jamozed |
2020-10-26 12:22:47 |
123
|
} |
be8a914 |
Jamozed |
2020-10-26 12:22:47 |
124
|
case 'N': { |
be8a914 |
Jamozed |
2020-10-26 12:22:47 |
125
|
errno = 0; limit = bparse(opt.arg); if (errno) { |
4540c2a |
Jamozed |
2020-07-06 23:15:03 |
126
|
warn("%s: invalid limit value", opt.arg); ret = 1; goto end; } |
be8a914 |
Jamozed |
2020-10-26 12:22:47 |
127
|
Nflag = true; break; |
be8a914 |
Jamozed |
2020-10-26 12:22:47 |
128
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
129
|
case 'o': { lpush(&tlist, to); break; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
130
|
case 's': { lpush(&tlist, ts); break; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
131
|
case 't': { if (tparse(opt.arg)) { goto end; } break; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
132
|
case 'v': { vflag = true; break; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
133
|
case 'x': { lpush(&tlist, tx); break; } |
be8a914 |
Jamozed |
2020-10-26 12:22:47 |
134
|
case 256: { hlp(); return 0; } |
be8a914 |
Jamozed |
2020-10-26 12:22:47 |
135
|
case 257: { ver(); return 0; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
136
|
default: { ret = 1; goto end; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
137
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
138
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
139
|
if (!tlist.len) { lpush(&tlist, to); } |
4540c2a |
Jamozed |
2020-07-06 23:15:03 |
140
|
if (opt.ind == ac) { file = stdin; } |
4540c2a |
Jamozed |
2020-07-06 23:15:03 |
141
|
else { files = av + opt.ind; file = fnext(); } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
142
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
143
|
for (size_t i = 0; i < tlist.len; ++i) { int t = tlist.data[i]; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
144
|
if (types[t].padm > mpad) { mpad = types[t].padm; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
145
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
146
|
for (size_t i = 0; i < tlist.len; ++i) { int t = tlist.data[i]; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
147
|
if (types[t].padm < mpad) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
148
|
int d = mpad - types[t].padm; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
149
|
int e = d / (16 / types[t].bytes); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
150
|
types[t].pads = e; types[t].padm = mpad; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
151
|
} else { types[t].pads = 0; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
152
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
153
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
154
|
block_t b0, b1; int c; bool btok = false, bskp = false; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
155
|
if (skip(start) == EOF) { |
4540c2a |
Jamozed |
2020-07-06 23:15:03 |
156
|
warn("cannot skip past end of input"); ret = 1; goto end; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
157
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
158
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
159
|
while ((c = bread(btok ? &b0 : &b1)) > 0) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
160
|
if (!vflag && b0.i64[0] == b1.i64[0] && b0.i64[1] == b1.i64[1]) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
161
|
if (!bskp) { fputs("*\n", stdout); bskp = true; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
162
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
163
|
else { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
164
|
(*aprint)(offset - (uintmax_t)c, ' '); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
165
|
bprint(btok ? &b0 : &b1, tlist.data[0]); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
166
|
for (size_t i = 1; i < tlist.len; ++i) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
167
|
fputs(" ", stdout); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
168
|
bprint(btok ? &b0 : &b1, tlist.data[i]); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
169
|
} bskp = false; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
170
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
171
|
if (c < 16) { break; } btok = !btok; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
172
|
} (*aprint)(offset, '\n'); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
173
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
174
|
end: |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
175
|
free(tlist.data); return ret; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
176
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
177
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
178
|
static inline uintmax_t bparse(char *str) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
179
|
register uintmax_t n = 0, d; register int b = 10; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
180
|
if (*str == '0') { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
181
|
if (*++str == 'x' || *str == 'X') { b = 16; ++str; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
182
|
else { b = 8; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
183
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
184
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
185
|
if (b == 16) for (;; ++str) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
186
|
if (*str >= '0' && *str <= '9') { d = (uintmax_t)*str - '0'; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
187
|
else if (*str >= 'A' && *str <= 'F') { d = (uintmax_t)*str - 'K'; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
188
|
else if (*str >= 'a' && *str <= 'f') { d = (uintmax_t)*str - 'k'; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
189
|
else { break; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
190
|
if (n > (UINTMAX_MAX - d) / 16) { errno = ERANGE; return 0; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
191
|
n = n * 16 + d; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
192
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
193
|
else for (; *str >= '0' && *str < b + '0'; ++str) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
194
|
d = (uintmax_t)*str - '0'; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
195
|
if (n > (UINTMAX_MAX - d) / (uintmax_t)b) { errno = ERANGE; return 0; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
196
|
n = n * (uintmax_t)b + d; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
197
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
198
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
199
|
switch (*str) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
200
|
case 'b': { d = 512; goto mul; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
201
|
case 'k': { d = 1024; goto mul; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
202
|
case 'm': { d = 1048576; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
203
|
mul: if (n > UINTMAX_MAX / d) { errno = ERANGE; return 0; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
204
|
n *= d; ++str; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
205
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
206
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
207
|
if (*str) { errno = EINVAL; return 0; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
208
|
return n; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
209
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
210
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
211
|
static inline int atow(char **str) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
212
|
register int n = 0, d; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
213
|
for (; **str >= '0' && **str <= '9'; ++*str) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
214
|
d = (int)**str - '0'; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
215
|
if (n > (INT_MAX - d) / 10) { return -1; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
216
|
n = n * 10 + d; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
217
|
} return n; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
218
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
219
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
220
|
static inline int tparse(char *str) { register int c; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
221
|
for (char *s = str; *s; ++s) { register int b = 0; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
222
|
if (*s == 'a') { lpush(&tlist, ta); continue; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
223
|
else if (*s == 'c') { lpush(&tlist, tc); continue; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
224
|
else if (*s == 'd' || *s == 'o' || *s == 'u' || *s == 'x') { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
225
|
char *p = s + 1; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
226
|
if (*p == 'C') { b = sizeof(char); ++p; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
227
|
else if (*p == 'S') { b = sizeof(short); ++p; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
228
|
else if (*p == 'I') { b = sizeof(int); ++p; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
229
|
else if (*p == 'L') { b = sizeof(long); ++p; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
230
|
else if ((b = atow(&p)) == -1) { goto fail; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
231
|
ssize_t m = p - (s + 1); if (!m) { b = sizeof(int); } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
232
|
if (!(b == 1 || b == 2 || b == 4 || b == 8)) { |
4540c2a |
Jamozed |
2020-07-06 23:15:03 |
233
|
error(1, "no %d-byte integer type", b); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
234
|
} else { c = *s; s += m; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
235
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
236
|
else if (*s == 'f') { char *p = s + 1; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
237
|
if (*p == 'F') { b = sizeof(float); ++p; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
238
|
else if (*p == 'D') { b = sizeof(double); ++p; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
239
|
else if (*p == 'L') { b = sizeof(/*long*/ double); ++p; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
240
|
else if ((b = atow(&p)) == -1) { goto fail; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
241
|
ssize_t m = p - (s + 1); if (!m) { b = sizeof(double); } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
242
|
if (!(b == 4 || b == 8 /*|| b == 16*/)) { |
4540c2a |
Jamozed |
2020-07-06 23:15:03 |
243
|
error(1, "no %d-byte float type", b); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
244
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
245
|
else { c = 'f'; s += m; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
246
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
247
|
else { |
4540c2a |
Jamozed |
2020-07-06 23:15:03 |
248
|
fail: error(1, "%s: invalid type string", str); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
249
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
250
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
251
|
for (int i = 0; types[i].type; ++i) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
252
|
if (types[i].type == c && types[i].bytes == b) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
253
|
lpush(&tlist, i); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
254
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
255
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
256
|
} return 0; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
257
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
258
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
259
|
static inline int skip(uintmax_t n) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
260
|
for (; n; --n) if (fgetc(file) == EOF && fnext() == NULL) { return EOF; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
261
|
offset = start; return 0; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
262
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
263
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
264
|
static inline void aprint_generic(uintmax_t addr, char c) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
265
|
printf(Aform, addr); fputc(c, stdout); return; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
266
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
267
|
static inline void aprint_none(uintmax_t addr, char c) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
268
|
(void)(addr); (void)(c); return; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
269
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
270
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
271
|
static inline int bread(block_t *blk) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
272
|
int i = 0; int c; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
273
|
while (i < 16 && (!Nflag || total < limit)) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
274
|
if (file == NULL || (c = fgetc(file)) == EOF) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
275
|
if ((file = fnext()) == NULL) { break; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
276
|
else { continue; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
277
|
} blk->i8[i++] = (uint8_t)c; ++total; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
278
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
279
|
offset += (uintmax_t)i; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
280
|
blk->count = i; return i; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
281
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
282
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
283
|
static inline void bprint(block_t *blk, int ti) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
284
|
type_t t = types[ti]; bool spc = false; long count = blk->count / t.bytes; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
285
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
286
|
for (int i = 0; i < count; ++i) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
287
|
if (spc) { fputc(' ', stdout); } else { spc = true; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
288
|
for (int j = 0; j < t.pads; ++j) { fputc(' ', stdout); } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
289
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
290
|
switch (t.type) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
291
|
case 'a': { register uint8_t c = blk->i8[i] & 127; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
292
|
if (c <= 32) { fputs(aTABL[c], stdout); } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
293
|
else if (c == 127) { fputs("del", stdout); } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
294
|
else { printf("%3c", c); } break; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
295
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
296
|
case 'c': case 'l': { register uint8_t c = blk->i8[i]; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
297
|
if (c < 32) { fputs(t.type == 'c' ? cTABL[c] : lTABL[c], stdout); } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
298
|
else if (c >= 127) { printf("%3o", c); } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
299
|
else { printf("%3c", c); } break; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
300
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
301
|
default: { char *form = types[ti].form; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
302
|
if (t.type == 'f') { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
303
|
if (t.bytes == 4) { printf(form, (double)blk->f32[i]); } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
304
|
else if (t.bytes == 8) { printf(form, blk->f64[i]); } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
305
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
306
|
else { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
307
|
if (t.bytes == 1) { printf(form, blk->i8[i]); } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
308
|
else if (t.bytes == 2) { printf(form, blk->i16[i]); } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
309
|
else if (t.bytes == 4) { printf(form, blk->i32[i]); } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
310
|
else if (t.bytes == 8) { printf(form, blk->i64[i]); } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
311
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
312
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
313
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
314
|
} fputc('\n', stdout); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
315
|
return; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
316
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
317
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
318
|
static inline FILE *fnext(void) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
319
|
if (file && file != stdin) { fclose(file); } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
320
|
if (*files) { FILE *f; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
321
|
if (files[0][0] == '-' && files[0][1] == '\0') { f = stdin; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
322
|
else if (!(f = fopen(*files, "r"))) { |
4540c2a |
Jamozed |
2020-07-06 23:15:03 |
323
|
warn("%s: %s\n", *files, strerror(errno)); return NULL; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
324
|
} ++files; return f; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
325
|
} else { return NULL; } |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
326
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
327
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
328
|
static inline list_t linit(void) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
329
|
list_t list; list.cap = 32; list.len = 0; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
330
|
list.data = (int *)malloc(sizeof(int) * list.cap); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
331
|
return list; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
332
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
333
|
|
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
334
|
static inline void lpush(list_t *list, int i) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
335
|
if (list->len >= list->cap) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
336
|
list->data = (int *)realloc(list->data, list->cap *= 2); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
337
|
} list->data[list->len++] = i; return; |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
338
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
339
|
|
be8a914 |
Jamozed |
2020-10-26 12:22:47 |
340
|
static void hlp(void) { |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
341
|
puts("od - dump files in various formats\n"); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
342
|
puts("usage: od [-bcdosvx] [-A base] [-j skip] [-N count] [-t type] \ |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
343
|
[file...]\n"); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
344
|
puts("options:"); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
345
|
puts(" -A base Offset address base ('d', 'o', 'x', or 'n')"); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
346
|
puts(" -b Interpret bytes in octal (-t01)"); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
347
|
puts(" -c Interpret bytes as characters"); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
348
|
puts(" -d Interpret words in unsigned decimal (-tu2)"); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
349
|
puts(" -j skip Number of bytes to skip from the beginning of input"); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
350
|
puts(" -N count Number of bytes to process in total"); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
351
|
puts(" -o Interpret words in octal (-to2)"); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
352
|
puts(" -s Interpret words in signed decimal (-td2)"); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
353
|
puts(" -t type Interpret data according to specified types"); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
354
|
puts(" -v Write all input data"); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
355
|
puts(" -x Interpret words in hexadecimal (-tx2)"); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
356
|
puts(" --help Display help information"); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
357
|
puts(" --version Display version information"); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
358
|
} |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
359
|
|
be8a914 |
Jamozed |
2020-10-26 12:22:47 |
360
|
static void ver(void) { |
4540c2a |
Jamozed |
2020-07-06 23:15:03 |
361
|
puts("OMKOV coreutils od, version " VERSION); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
362
|
puts("Copyright (C) 2020, Jakob Wakeling"); |
e2140ec |
Jamozed |
2022-03-06 15:27:45 |
363
|
puts("MIT Licence (https://opensource.org/licenses/MIT)"); |
c1461fb |
Jamozed |
2020-06-27 14:35:08 |
364
|
} |
|
|
|
365
|
|