diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2023-05-25 17:39:28 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2023-05-25 17:40:20 +0200 |
commit | e2287f99fe6f21fd6435ad04340170ad4ba5f6b3 (patch) | |
tree | 09224d93a16e18c0f4e31ada2375d7ca9cfab03e | |
parent | 64bdd7566c21cb53cb4c384ed52845106529e55f (diff) | |
download | busybox-w32-e2287f99fe6f21fd6435ad04340170ad4ba5f6b3.tar.gz busybox-w32-e2287f99fe6f21fd6435ad04340170ad4ba5f6b3.tar.bz2 busybox-w32-e2287f99fe6f21fd6435ad04340170ad4ba5f6b3.zip |
od: for !DESKTOP, match output more closely to GNU coreutils 9.1, implement -s
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | coreutils/od.c | 55 | ||||
-rw-r--r-- | libbb/dump.c | 30 | ||||
-rwxr-xr-x | testsuite/od.tests | 83 |
3 files changed, 100 insertions, 68 deletions
diff --git a/coreutils/od.c b/coreutils/od.c index dcf1bd6f6..6d562ea91 100644 --- a/coreutils/od.c +++ b/coreutils/od.c | |||
@@ -22,7 +22,7 @@ | |||
22 | 22 | ||
23 | //usage:#if !ENABLE_DESKTOP | 23 | //usage:#if !ENABLE_DESKTOP |
24 | //usage:#define od_trivial_usage | 24 | //usage:#define od_trivial_usage |
25 | //usage: "[-aBbcDdeFfHhIiLlOovXx] [FILE]" | 25 | //usage: "[-aBbcDdeFfHhIiLlOoXxsv] [FILE]" |
26 | //usage:#define od_full_usage "\n\n" | 26 | //usage:#define od_full_usage "\n\n" |
27 | //usage: "Print FILE (or stdin) unambiguously, as octal bytes by default" | 27 | //usage: "Print FILE (or stdin) unambiguously, as octal bytes by default" |
28 | //usage:#endif | 28 | //usage:#endif |
@@ -144,29 +144,42 @@ odoffset(dumper_t *dumper, int argc, char ***argvp) | |||
144 | } | 144 | } |
145 | } | 145 | } |
146 | 146 | ||
147 | // A format string contains format units separated by whitespace. | ||
148 | // A format unit contains up to three items: an iteration count, a byte count, | ||
149 | // and a format. | ||
150 | // The iteration count is an optional integer (default 1) | ||
151 | // Each format is applied iteration count times. | ||
152 | // The byte count is an optional integer. It defines the number | ||
153 | // of bytes to be interpreted by each iteration of the format. | ||
154 | // If an iteration count and/or a byte count is specified, a slash must be | ||
155 | // placed after the iteration count and/or before the byte count | ||
156 | // to disambiguate them. | ||
157 | // The format is required and must be surrounded by " "s. | ||
158 | // It is a printf-style format. | ||
147 | static const char *const add_strings[] ALIGN_PTR = { | 159 | static const char *const add_strings[] ALIGN_PTR = { |
148 | "16/1 \"%3_u \" \"\\n\"", /* a */ | 160 | "16/1 \"%3_u \" \"\\n\"", /* 0: a */ |
149 | "8/2 \" %06o \" \"\\n\"", /* B, o */ | 161 | "8/2 \"%06o \" \"\\n\"", /* 1: B (undocumented in od), o */ |
150 | "16/1 \"%03o \" \"\\n\"", /* b */ | 162 | "16/1 \"%03o \" \"\\n\"", /* 2: b */ |
151 | "16/1 \"%3_c \" \"\\n\"", /* c */ | 163 | "16/1 \"%3_c \" \"\\n\"", /* 3: c */ |
152 | "8/2 \" %05u \" \"\\n\"", /* d */ | 164 | "8/2 \"%5u \" \"\\n\"", /* 4: d */ |
153 | "4/4 \" %010u \" \"\\n\"", /* D */ | 165 | "4/4 \"%10u \" \"\\n\"", /* 5: D */ |
154 | "2/8 \" %21.14e \" \"\\n\"", /* e (undocumented in od), F */ | 166 | "2/8 \"%24.14e \" \"\\n\"", /* 6: e (undocumented in od), F */ |
155 | "4/4 \" %14.7e \" \"\\n\"", /* f */ | 167 | "4/4 \"%15.7e \" \"\\n\"", /* 7: f */ |
156 | "4/4 \" %08x \" \"\\n\"", /* H, X */ | 168 | "4/4 \"%08x \" \"\\n\"", /* 8: H, X */ |
157 | "8/2 \" %04x \" \"\\n\"", /* h, x */ | 169 | "8/2 \"%04x \" \"\\n\"", /* 9: h, x */ |
158 | "4/4 \" %11d \" \"\\n\"", /* I, L, l */ | 170 | "2/8 \"%20lld \" \"\\n\"", /* 10: I, L, l */ |
159 | "8/2 \" %6d \" \"\\n\"", /* i */ | 171 | "4/4 \"%11d \" \"\\n\"", /* 11: i */ |
160 | "4/4 \" %011o \" \"\\n\"", /* O */ | 172 | "4/4 \"%011o \" \"\\n\"", /* 12: O */ |
173 | "8/2 \"%6d \" \"\\n\"", /* 13: s */ | ||
161 | }; | 174 | }; |
162 | 175 | ||
163 | static const char od_opts[] ALIGN1 = "aBbcDdeFfHhIiLlOoXxv"; | 176 | static const char od_opts[] ALIGN1 = "aBbcDdeFfHhIiLlOoXxsv"; |
164 | 177 | ||
165 | static const char od_o2si[] ALIGN1 = { | 178 | static const char od_o2si[] ALIGN1 = { |
166 | 0, 1, 2, 3, 5, | 179 | 0, 1, 2, 3, 5, /* aBbcD */ |
167 | 4, 6, 6, 7, 8, | 180 | 4, 6, 6, 7, 8, /* deFfH */ |
168 | 9, 0xa, 0xb, 0xa, 0xa, | 181 | 9, 10, 11, 10, 10, /* hIiLl */ |
169 | 0xc, 1, 8, 9, | 182 | 12, 1, 8, 9, 13 /* OoXxs */ |
170 | }; | 183 | }; |
171 | 184 | ||
172 | int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 185 | int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
@@ -184,9 +197,9 @@ int od_main(int argc, char **argv) | |||
184 | if (first) { | 197 | if (first) { |
185 | first = 0; | 198 | first = 0; |
186 | bb_dump_add(dumper, "\"%07.7_Ao\n\""); | 199 | bb_dump_add(dumper, "\"%07.7_Ao\n\""); |
187 | bb_dump_add(dumper, "\"%07.7_ao \""); | 200 | bb_dump_add(dumper, "\"%07.7_ao \""); |
188 | } else { | 201 | } else { |
189 | bb_dump_add(dumper, "\" \""); | 202 | bb_dump_add(dumper, "\" \""); |
190 | } | 203 | } |
191 | bb_dump_add(dumper, add_strings[(int)od_o2si[(p - od_opts)]]); | 204 | bb_dump_add(dumper, add_strings[(int)od_o2si[(p - od_opts)]]); |
192 | } else { /* P, p, s, w, or other unhandled */ | 205 | } else { /* P, p, s, w, or other unhandled */ |
diff --git a/libbb/dump.c b/libbb/dump.c index fcdee8343..cfb9d94f9 100644 --- a/libbb/dump.c +++ b/libbb/dump.c | |||
@@ -187,6 +187,10 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) | |||
187 | 187 | ||
188 | ++p2; | 188 | ++p2; |
189 | ++p1; | 189 | ++p1; |
190 | if (*p1 == 'l') { /* %lld etc */ | ||
191 | ++p2; | ||
192 | ++p1; | ||
193 | } | ||
190 | DO_INT_CONV: | 194 | DO_INT_CONV: |
191 | e = strchr(int_convs, *p1); /* "diouxX"? */ | 195 | e = strchr(int_convs, *p1); /* "diouxX"? */ |
192 | if (!e) | 196 | if (!e) |
@@ -194,7 +198,7 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) | |||
194 | pr->flags = F_INT; | 198 | pr->flags = F_INT; |
195 | if (e > int_convs + 1) /* not d or i? */ | 199 | if (e > int_convs + 1) /* not d or i? */ |
196 | pr->flags = F_UINT; | 200 | pr->flags = F_UINT; |
197 | byte_count_str = "\004\002\001"; | 201 | byte_count_str = "\010\004\002\001"; |
198 | goto DO_BYTE_COUNT; | 202 | goto DO_BYTE_COUNT; |
199 | } else | 203 | } else |
200 | if (strchr(int_convs, *p1)) { /* %d etc */ | 204 | if (strchr(int_convs, *p1)) { /* %d etc */ |
@@ -601,22 +605,32 @@ static NOINLINE void display(priv_dumper_t* dumper) | |||
601 | break; | 605 | break; |
602 | } | 606 | } |
603 | case F_INT: { | 607 | case F_INT: { |
604 | int ival; | 608 | union { |
605 | short sval; | 609 | uint16_t val16; |
610 | uint32_t val32; | ||
611 | uint64_t val64; | ||
612 | } u; | ||
613 | int value = *bp; | ||
606 | 614 | ||
607 | switch (pr->bcnt) { | 615 | switch (pr->bcnt) { |
608 | case 1: | 616 | case 1: |
609 | printf(pr->fmt, (int) *bp); | ||
610 | break; | 617 | break; |
611 | case 2: | 618 | case 2: |
612 | memcpy(&sval, bp, sizeof(sval)); | 619 | memcpy(&u.val16, bp, 2); |
613 | printf(pr->fmt, (int) sval); | 620 | value = u.val16; |
614 | break; | 621 | break; |
615 | case 4: | 622 | case 4: |
616 | memcpy(&ival, bp, sizeof(ival)); | 623 | memcpy(&u.val32, bp, 4); |
617 | printf(pr->fmt, ival); | 624 | value = u.val32; |
618 | break; | 625 | break; |
626 | case 8: | ||
627 | memcpy(&u.val64, bp, 8); | ||
628 | //A hack. Users _must_ use %llX formats to not truncate high bits | ||
629 | printf(pr->fmt, (long long) u.val64); | ||
630 | goto skip; | ||
619 | } | 631 | } |
632 | printf(pr->fmt, value); | ||
633 | skip: | ||
620 | break; | 634 | break; |
621 | } | 635 | } |
622 | case F_P: | 636 | case F_P: |
diff --git a/testsuite/od.tests b/testsuite/od.tests index 0b949d5f0..500e0e638 100755 --- a/testsuite/od.tests +++ b/testsuite/od.tests | |||
@@ -9,14 +9,19 @@ | |||
9 | input="$(printf '\001\002\003\nABC\xfe')" | 9 | input="$(printf '\001\002\003\nABC\xfe')" |
10 | 10 | ||
11 | le=false | 11 | le=false |
12 | { printf '\0\1' | od -i | grep -q 256; } && le=true | 12 | { printf '\0\1' | od -s | grep -q 256; } && le=true |
13 | readonly le | 13 | readonly le |
14 | 14 | ||
15 | # NB: | ||
16 | # sed 's/ *$//' truncates trailing spaces. | ||
17 | # This needs to be fixed properly (not output them). | ||
18 | # For now, the tests ignore them (does not require a match). | ||
19 | |||
15 | optional !DESKTOP | 20 | optional !DESKTOP |
16 | testing "od -a (!DESKTOP)" \ | 21 | testing "od -a (!DESKTOP)" \ |
17 | "od -a" \ | 22 | "od -a | sed 's/ *$//'" \ |
18 | "\ | 23 | "\ |
19 | 0000000 soh stx etx lf A B C fe | 24 | 0000000 soh stx etx lf A B C fe |
20 | 0000010 | 25 | 0000010 |
21 | " \ | 26 | " \ |
22 | "" "$input" | 27 | "" "$input" |
@@ -24,9 +29,9 @@ SKIP= | |||
24 | 29 | ||
25 | optional !DESKTOP | 30 | optional !DESKTOP |
26 | testing "od -B (!DESKTOP)" \ | 31 | testing "od -B (!DESKTOP)" \ |
27 | "od -B" \ | 32 | "od -B | sed 's/ *$//'" \ |
28 | "\ | 33 | "\ |
29 | 0000000 001001 005003 041101 177103 | 34 | 0000000 001001 005003 041101 177103 |
30 | 0000010 | 35 | 0000010 |
31 | " \ | 36 | " \ |
32 | "" "$input" | 37 | "" "$input" |
@@ -35,9 +40,9 @@ SKIP= | |||
35 | optional !DESKTOP | 40 | optional !DESKTOP |
36 | $le || SKIP=1 | 41 | $le || SKIP=1 |
37 | testing "od -o (!DESKTOP little-endian)" \ | 42 | testing "od -o (!DESKTOP little-endian)" \ |
38 | "od -o" \ | 43 | "od -o | sed 's/ *$//'" \ |
39 | "\ | 44 | "\ |
40 | 0000000 001001 005003 041101 177103 | 45 | 0000000 001001 005003 041101 177103 |
41 | 0000010 | 46 | 0000010 |
42 | " \ | 47 | " \ |
43 | "" "$input" | 48 | "" "$input" |
@@ -45,9 +50,9 @@ SKIP= | |||
45 | 50 | ||
46 | optional !DESKTOP | 51 | optional !DESKTOP |
47 | testing "od -b (!DESKTOP)" \ | 52 | testing "od -b (!DESKTOP)" \ |
48 | "od -b" \ | 53 | "od -b | sed 's/ *$//'" \ |
49 | "\ | 54 | "\ |
50 | 0000000 001 002 003 012 101 102 103 376 | 55 | 0000000 001 002 003 012 101 102 103 376 |
51 | 0000010 | 56 | 0000010 |
52 | " \ | 57 | " \ |
53 | "" "$input" | 58 | "" "$input" |
@@ -55,9 +60,9 @@ SKIP= | |||
55 | 60 | ||
56 | optional !DESKTOP | 61 | optional !DESKTOP |
57 | testing "od -c (!DESKTOP)" \ | 62 | testing "od -c (!DESKTOP)" \ |
58 | "od -c" \ | 63 | "od -c | sed 's/ *$//'" \ |
59 | "\ | 64 | "\ |
60 | 0000000 001 002 003 \\\\n A B C 376 | 65 | 0000000 001 002 003 \\\\n A B C 376 |
61 | 0000010 | 66 | 0000010 |
62 | " \ | 67 | " \ |
63 | "" "$input" | 68 | "" "$input" |
@@ -66,9 +71,9 @@ SKIP= | |||
66 | optional !DESKTOP | 71 | optional !DESKTOP |
67 | $le || SKIP=1 | 72 | $le || SKIP=1 |
68 | testing "od -d (!DESKTOP little-endian)" \ | 73 | testing "od -d (!DESKTOP little-endian)" \ |
69 | "od -d" \ | 74 | "od -d | sed 's/ *$//'" \ |
70 | "\ | 75 | "\ |
71 | 0000000 00513 02563 16961 65091 | 76 | 0000000 513 2563 16961 65091 |
72 | 0000010 | 77 | 0000010 |
73 | " \ | 78 | " \ |
74 | "" "$input" | 79 | "" "$input" |
@@ -77,9 +82,9 @@ SKIP= | |||
77 | optional !DESKTOP | 82 | optional !DESKTOP |
78 | $le || SKIP=1 | 83 | $le || SKIP=1 |
79 | testing "od -D (!DESKTOP little-endian)" \ | 84 | testing "od -D (!DESKTOP little-endian)" \ |
80 | "od -D" \ | 85 | "od -D | sed 's/ *$//'" \ |
81 | "\ | 86 | "\ |
82 | 0000000 0167969281 4265820737 | 87 | 0000000 167969281 4265820737 |
83 | 0000010 | 88 | 0000010 |
84 | " \ | 89 | " \ |
85 | "" "$input" | 90 | "" "$input" |
@@ -88,9 +93,9 @@ SKIP= | |||
88 | optional !DESKTOP | 93 | optional !DESKTOP |
89 | $le || SKIP=1 | 94 | $le || SKIP=1 |
90 | testing "od -e (!DESKTOP little-endian)" \ | 95 | testing "od -e (!DESKTOP little-endian)" \ |
91 | "od -e" \ | 96 | "od -e | sed 's/ *$//'" \ |
92 | "\ | 97 | "\ |
93 | 0000000 -1.61218556514036e+300 | 98 | 0000000 -1.61218556514036e+300 |
94 | 0000010 | 99 | 0000010 |
95 | " \ | 100 | " \ |
96 | "" "$input" | 101 | "" "$input" |
@@ -99,9 +104,9 @@ SKIP= | |||
99 | optional !DESKTOP | 104 | optional !DESKTOP |
100 | $le || SKIP=1 | 105 | $le || SKIP=1 |
101 | testing "od -F (!DESKTOP little-endian)" \ | 106 | testing "od -F (!DESKTOP little-endian)" \ |
102 | "od -F" \ | 107 | "od -F | sed 's/ *$//'" \ |
103 | "\ | 108 | "\ |
104 | 0000000 -1.61218556514036e+300 | 109 | 0000000 -1.61218556514036e+300 |
105 | 0000010 | 110 | 0000010 |
106 | " \ | 111 | " \ |
107 | "" "$input" | 112 | "" "$input" |
@@ -109,9 +114,9 @@ testing "od -F (!DESKTOP little-endian)" \ | |||
109 | optional !DESKTOP | 114 | optional !DESKTOP |
110 | $le || SKIP=1 | 115 | $le || SKIP=1 |
111 | testing "od -f (!DESKTOP little-endian)" \ | 116 | testing "od -f (!DESKTOP little-endian)" \ |
112 | "od -f" \ | 117 | "od -f | sed 's/ *$//'" \ |
113 | "\ | 118 | "\ |
114 | 0000000 6.3077975e-33 -6.4885867e+37 | 119 | 0000000 6.3077975e-33 -6.4885867e+37 |
115 | 0000010 | 120 | 0000010 |
116 | " \ | 121 | " \ |
117 | "" "$input" | 122 | "" "$input" |
@@ -120,9 +125,9 @@ SKIP= | |||
120 | optional !DESKTOP | 125 | optional !DESKTOP |
121 | $le || SKIP=1 | 126 | $le || SKIP=1 |
122 | testing "od -H (!DESKTOP little-endian)" \ | 127 | testing "od -H (!DESKTOP little-endian)" \ |
123 | "od -H" \ | 128 | "od -H | sed 's/ *$//'" \ |
124 | "\ | 129 | "\ |
125 | 0000000 0a030201 fe434241 | 130 | 0000000 0a030201 fe434241 |
126 | 0000010 | 131 | 0000010 |
127 | " \ | 132 | " \ |
128 | "" "$input" | 133 | "" "$input" |
@@ -131,9 +136,9 @@ SKIP= | |||
131 | optional !DESKTOP | 136 | optional !DESKTOP |
132 | $le || SKIP=1 | 137 | $le || SKIP=1 |
133 | testing "od -X (!DESKTOP little-endian)" \ | 138 | testing "od -X (!DESKTOP little-endian)" \ |
134 | "od -X" \ | 139 | "od -X | sed 's/ *$//'" \ |
135 | "\ | 140 | "\ |
136 | 0000000 0a030201 fe434241 | 141 | 0000000 0a030201 fe434241 |
137 | 0000010 | 142 | 0000010 |
138 | " \ | 143 | " \ |
139 | "" "$input" | 144 | "" "$input" |
@@ -142,9 +147,9 @@ SKIP= | |||
142 | optional !DESKTOP | 147 | optional !DESKTOP |
143 | $le || SKIP=1 | 148 | $le || SKIP=1 |
144 | testing "od -h (!DESKTOP little-endian)" \ | 149 | testing "od -h (!DESKTOP little-endian)" \ |
145 | "od -h" \ | 150 | "od -h | sed 's/ *$//'" \ |
146 | "\ | 151 | "\ |
147 | 0000000 0201 0a03 4241 fe43 | 152 | 0000000 0201 0a03 4241 fe43 |
148 | 0000010 | 153 | 0000010 |
149 | " \ | 154 | " \ |
150 | "" "$input" | 155 | "" "$input" |
@@ -153,9 +158,9 @@ SKIP= | |||
153 | optional !DESKTOP | 158 | optional !DESKTOP |
154 | $le || SKIP=1 | 159 | $le || SKIP=1 |
155 | testing "od -x (!DESKTOP little-endian)" \ | 160 | testing "od -x (!DESKTOP little-endian)" \ |
156 | "od -x" \ | 161 | "od -x | sed 's/ *$//'" \ |
157 | "\ | 162 | "\ |
158 | 0000000 0201 0a03 4241 fe43 | 163 | 0000000 0201 0a03 4241 fe43 |
159 | 0000010 | 164 | 0000010 |
160 | " \ | 165 | " \ |
161 | "" "$input" | 166 | "" "$input" |
@@ -164,9 +169,9 @@ SKIP= | |||
164 | optional !DESKTOP | 169 | optional !DESKTOP |
165 | $le || SKIP=1 | 170 | $le || SKIP=1 |
166 | testing "od -I (!DESKTOP little-endian)" \ | 171 | testing "od -I (!DESKTOP little-endian)" \ |
167 | "od -I" \ | 172 | "od -I | sed 's/ *$//'" \ |
168 | "\ | 173 | "\ |
169 | 0000000 167969281 -29146559 | 174 | 0000000 -125183517527965183 |
170 | 0000010 | 175 | 0000010 |
171 | " \ | 176 | " \ |
172 | "" "$input" | 177 | "" "$input" |
@@ -175,9 +180,9 @@ SKIP= | |||
175 | optional !DESKTOP | 180 | optional !DESKTOP |
176 | $le || SKIP=1 | 181 | $le || SKIP=1 |
177 | testing "od -L (!DESKTOP little-endian)" \ | 182 | testing "od -L (!DESKTOP little-endian)" \ |
178 | "od -L" \ | 183 | "od -L | sed 's/ *$//'" \ |
179 | "\ | 184 | "\ |
180 | 0000000 167969281 -29146559 | 185 | 0000000 -125183517527965183 |
181 | 0000010 | 186 | 0000010 |
182 | " \ | 187 | " \ |
183 | "" "$input" | 188 | "" "$input" |
@@ -186,9 +191,9 @@ SKIP= | |||
186 | optional !DESKTOP | 191 | optional !DESKTOP |
187 | $le || SKIP=1 | 192 | $le || SKIP=1 |
188 | testing "od -i (!DESKTOP little-endian)" \ | 193 | testing "od -i (!DESKTOP little-endian)" \ |
189 | "od -i" \ | 194 | "od -i | sed 's/ *$//'" \ |
190 | "\ | 195 | "\ |
191 | 0000000 513 2563 16961 -445 | 196 | 0000000 167969281 -29146559 |
192 | 0000010 | 197 | 0000010 |
193 | " \ | 198 | " \ |
194 | "" "$input" | 199 | "" "$input" |
@@ -197,9 +202,9 @@ SKIP= | |||
197 | optional !DESKTOP | 202 | optional !DESKTOP |
198 | $le || SKIP=1 | 203 | $le || SKIP=1 |
199 | testing "od -O (!DESKTOP little-endian)" \ | 204 | testing "od -O (!DESKTOP little-endian)" \ |
200 | "od -O" \ | 205 | "od -O | sed 's/ *$//'" \ |
201 | "\ | 206 | "\ |
202 | 0000000 01200601001 37620641101 | 207 | 0000000 01200601001 37620641101 |
203 | 0000010 | 208 | 0000010 |
204 | " \ | 209 | " \ |
205 | "" "$input" | 210 | "" "$input" |
@@ -208,9 +213,9 @@ SKIP= | |||
208 | optional !DESKTOP | 213 | optional !DESKTOP |
209 | $le || SKIP=1 | 214 | $le || SKIP=1 |
210 | testing "od -l (!DESKTOP little-endian)" \ | 215 | testing "od -l (!DESKTOP little-endian)" \ |
211 | "od -l" \ | 216 | "od -l | sed 's/ *$//'" \ |
212 | "\ | 217 | "\ |
213 | 0000000 167969281 -29146559 | 218 | 0000000 -125183517527965183 |
214 | 0000010 | 219 | 0000010 |
215 | " \ | 220 | " \ |
216 | "" "$input" | 221 | "" "$input" |