aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2023-05-25 17:39:28 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2023-05-25 17:40:20 +0200
commite2287f99fe6f21fd6435ad04340170ad4ba5f6b3 (patch)
tree09224d93a16e18c0f4e31ada2375d7ca9cfab03e
parent64bdd7566c21cb53cb4c384ed52845106529e55f (diff)
downloadbusybox-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.c55
-rw-r--r--libbb/dump.c30
-rwxr-xr-xtestsuite/od.tests83
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.
147static const char *const add_strings[] ALIGN_PTR = { 159static 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
163static const char od_opts[] ALIGN1 = "aBbcDdeFfHhIiLlOoXxv"; 176static const char od_opts[] ALIGN1 = "aBbcDdeFfHhIiLlOoXxsv";
164 177
165static const char od_o2si[] ALIGN1 = { 178static 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
172int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 185int 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 @@
9input="$(printf '\001\002\003\nABC\xfe')" 9input="$(printf '\001\002\003\nABC\xfe')"
10 10
11le=false 11le=false
12{ printf '\0\1' | od -i | grep -q 256; } && le=true 12{ printf '\0\1' | od -s | grep -q 256; } && le=true
13readonly le 13readonly 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
15optional !DESKTOP 20optional !DESKTOP
16testing "od -a (!DESKTOP)" \ 21testing "od -a (!DESKTOP)" \
17 "od -a" \ 22 "od -a | sed 's/ *$//'" \
18"\ 23"\
190000000 soh stx etx lf A B C fe 240000000 soh stx etx lf A B C fe
200000010 250000010
21" \ 26" \
22 "" "$input" 27 "" "$input"
@@ -24,9 +29,9 @@ SKIP=
24 29
25optional !DESKTOP 30optional !DESKTOP
26testing "od -B (!DESKTOP)" \ 31testing "od -B (!DESKTOP)" \
27 "od -B" \ 32 "od -B | sed 's/ *$//'" \
28"\ 33"\
290000000 001001 005003 041101 177103 340000000 001001 005003 041101 177103
300000010 350000010
31" \ 36" \
32 "" "$input" 37 "" "$input"
@@ -35,9 +40,9 @@ SKIP=
35optional !DESKTOP 40optional !DESKTOP
36$le || SKIP=1 41$le || SKIP=1
37testing "od -o (!DESKTOP little-endian)" \ 42testing "od -o (!DESKTOP little-endian)" \
38 "od -o" \ 43 "od -o | sed 's/ *$//'" \
39"\ 44"\
400000000 001001 005003 041101 177103 450000000 001001 005003 041101 177103
410000010 460000010
42" \ 47" \
43 "" "$input" 48 "" "$input"
@@ -45,9 +50,9 @@ SKIP=
45 50
46optional !DESKTOP 51optional !DESKTOP
47testing "od -b (!DESKTOP)" \ 52testing "od -b (!DESKTOP)" \
48 "od -b" \ 53 "od -b | sed 's/ *$//'" \
49"\ 54"\
500000000 001 002 003 012 101 102 103 376 550000000 001 002 003 012 101 102 103 376
510000010 560000010
52" \ 57" \
53 "" "$input" 58 "" "$input"
@@ -55,9 +60,9 @@ SKIP=
55 60
56optional !DESKTOP 61optional !DESKTOP
57testing "od -c (!DESKTOP)" \ 62testing "od -c (!DESKTOP)" \
58 "od -c" \ 63 "od -c | sed 's/ *$//'" \
59"\ 64"\
600000000 001 002 003 \\\\n A B C 376 650000000 001 002 003 \\\\n A B C 376
610000010 660000010
62" \ 67" \
63 "" "$input" 68 "" "$input"
@@ -66,9 +71,9 @@ SKIP=
66optional !DESKTOP 71optional !DESKTOP
67$le || SKIP=1 72$le || SKIP=1
68testing "od -d (!DESKTOP little-endian)" \ 73testing "od -d (!DESKTOP little-endian)" \
69 "od -d" \ 74 "od -d | sed 's/ *$//'" \
70"\ 75"\
710000000 00513 02563 16961 65091 760000000 513 2563 16961 65091
720000010 770000010
73" \ 78" \
74 "" "$input" 79 "" "$input"
@@ -77,9 +82,9 @@ SKIP=
77optional !DESKTOP 82optional !DESKTOP
78$le || SKIP=1 83$le || SKIP=1
79testing "od -D (!DESKTOP little-endian)" \ 84testing "od -D (!DESKTOP little-endian)" \
80 "od -D" \ 85 "od -D | sed 's/ *$//'" \
81"\ 86"\
820000000 0167969281 4265820737 870000000 167969281 4265820737
830000010 880000010
84" \ 89" \
85 "" "$input" 90 "" "$input"
@@ -88,9 +93,9 @@ SKIP=
88optional !DESKTOP 93optional !DESKTOP
89$le || SKIP=1 94$le || SKIP=1
90testing "od -e (!DESKTOP little-endian)" \ 95testing "od -e (!DESKTOP little-endian)" \
91 "od -e" \ 96 "od -e | sed 's/ *$//'" \
92"\ 97"\
930000000 -1.61218556514036e+300 980000000 -1.61218556514036e+300
940000010 990000010
95" \ 100" \
96 "" "$input" 101 "" "$input"
@@ -99,9 +104,9 @@ SKIP=
99optional !DESKTOP 104optional !DESKTOP
100$le || SKIP=1 105$le || SKIP=1
101testing "od -F (!DESKTOP little-endian)" \ 106testing "od -F (!DESKTOP little-endian)" \
102 "od -F" \ 107 "od -F | sed 's/ *$//'" \
103"\ 108"\
1040000000 -1.61218556514036e+300 1090000000 -1.61218556514036e+300
1050000010 1100000010
106" \ 111" \
107 "" "$input" 112 "" "$input"
@@ -109,9 +114,9 @@ testing "od -F (!DESKTOP little-endian)" \
109optional !DESKTOP 114optional !DESKTOP
110$le || SKIP=1 115$le || SKIP=1
111testing "od -f (!DESKTOP little-endian)" \ 116testing "od -f (!DESKTOP little-endian)" \
112 "od -f" \ 117 "od -f | sed 's/ *$//'" \
113"\ 118"\
1140000000 6.3077975e-33 -6.4885867e+37 1190000000 6.3077975e-33 -6.4885867e+37
1150000010 1200000010
116" \ 121" \
117 "" "$input" 122 "" "$input"
@@ -120,9 +125,9 @@ SKIP=
120optional !DESKTOP 125optional !DESKTOP
121$le || SKIP=1 126$le || SKIP=1
122testing "od -H (!DESKTOP little-endian)" \ 127testing "od -H (!DESKTOP little-endian)" \
123 "od -H" \ 128 "od -H | sed 's/ *$//'" \
124"\ 129"\
1250000000 0a030201 fe434241 1300000000 0a030201 fe434241
1260000010 1310000010
127" \ 132" \
128 "" "$input" 133 "" "$input"
@@ -131,9 +136,9 @@ SKIP=
131optional !DESKTOP 136optional !DESKTOP
132$le || SKIP=1 137$le || SKIP=1
133testing "od -X (!DESKTOP little-endian)" \ 138testing "od -X (!DESKTOP little-endian)" \
134 "od -X" \ 139 "od -X | sed 's/ *$//'" \
135"\ 140"\
1360000000 0a030201 fe434241 1410000000 0a030201 fe434241
1370000010 1420000010
138" \ 143" \
139 "" "$input" 144 "" "$input"
@@ -142,9 +147,9 @@ SKIP=
142optional !DESKTOP 147optional !DESKTOP
143$le || SKIP=1 148$le || SKIP=1
144testing "od -h (!DESKTOP little-endian)" \ 149testing "od -h (!DESKTOP little-endian)" \
145 "od -h" \ 150 "od -h | sed 's/ *$//'" \
146"\ 151"\
1470000000 0201 0a03 4241 fe43 1520000000 0201 0a03 4241 fe43
1480000010 1530000010
149" \ 154" \
150 "" "$input" 155 "" "$input"
@@ -153,9 +158,9 @@ SKIP=
153optional !DESKTOP 158optional !DESKTOP
154$le || SKIP=1 159$le || SKIP=1
155testing "od -x (!DESKTOP little-endian)" \ 160testing "od -x (!DESKTOP little-endian)" \
156 "od -x" \ 161 "od -x | sed 's/ *$//'" \
157"\ 162"\
1580000000 0201 0a03 4241 fe43 1630000000 0201 0a03 4241 fe43
1590000010 1640000010
160" \ 165" \
161 "" "$input" 166 "" "$input"
@@ -164,9 +169,9 @@ SKIP=
164optional !DESKTOP 169optional !DESKTOP
165$le || SKIP=1 170$le || SKIP=1
166testing "od -I (!DESKTOP little-endian)" \ 171testing "od -I (!DESKTOP little-endian)" \
167 "od -I" \ 172 "od -I | sed 's/ *$//'" \
168"\ 173"\
1690000000 167969281 -29146559 1740000000 -125183517527965183
1700000010 1750000010
171" \ 176" \
172 "" "$input" 177 "" "$input"
@@ -175,9 +180,9 @@ SKIP=
175optional !DESKTOP 180optional !DESKTOP
176$le || SKIP=1 181$le || SKIP=1
177testing "od -L (!DESKTOP little-endian)" \ 182testing "od -L (!DESKTOP little-endian)" \
178 "od -L" \ 183 "od -L | sed 's/ *$//'" \
179"\ 184"\
1800000000 167969281 -29146559 1850000000 -125183517527965183
1810000010 1860000010
182" \ 187" \
183 "" "$input" 188 "" "$input"
@@ -186,9 +191,9 @@ SKIP=
186optional !DESKTOP 191optional !DESKTOP
187$le || SKIP=1 192$le || SKIP=1
188testing "od -i (!DESKTOP little-endian)" \ 193testing "od -i (!DESKTOP little-endian)" \
189 "od -i" \ 194 "od -i | sed 's/ *$//'" \
190"\ 195"\
1910000000 513 2563 16961 -445 1960000000 167969281 -29146559
1920000010 1970000010
193" \ 198" \
194 "" "$input" 199 "" "$input"
@@ -197,9 +202,9 @@ SKIP=
197optional !DESKTOP 202optional !DESKTOP
198$le || SKIP=1 203$le || SKIP=1
199testing "od -O (!DESKTOP little-endian)" \ 204testing "od -O (!DESKTOP little-endian)" \
200 "od -O" \ 205 "od -O | sed 's/ *$//'" \
201"\ 206"\
2020000000 01200601001 37620641101 2070000000 01200601001 37620641101
2030000010 2080000010
204" \ 209" \
205 "" "$input" 210 "" "$input"
@@ -208,9 +213,9 @@ SKIP=
208optional !DESKTOP 213optional !DESKTOP
209$le || SKIP=1 214$le || SKIP=1
210testing "od -l (!DESKTOP little-endian)" \ 215testing "od -l (!DESKTOP little-endian)" \
211 "od -l" \ 216 "od -l | sed 's/ *$//'" \
212"\ 217"\
2130000000 167969281 -29146559 2180000000 -125183517527965183
2140000010 2190000010
215" \ 220" \
216 "" "$input" 221 "" "$input"