diff options
Diffstat (limited to 'util-linux/hexdump_xxd.c')
-rw-r--r-- | util-linux/hexdump_xxd.c | 63 |
1 files changed, 51 insertions, 12 deletions
diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c index 29bbc6633..fe78f6242 100644 --- a/util-linux/hexdump_xxd.c +++ b/util-linux/hexdump_xxd.c | |||
@@ -41,15 +41,17 @@ | |||
41 | // -u use upper case hex letters. | 41 | // -u use upper case hex letters. |
42 | 42 | ||
43 | //usage:#define xxd_trivial_usage | 43 | //usage:#define xxd_trivial_usage |
44 | //usage: "[-pr] [-g N] [-c N] [-n LEN] [-s OFS] [FILE]" | 44 | //usage: "[-pri] [-g N] [-c N] [-n LEN] [-s OFS] [-o OFS] [FILE]" |
45 | //usage:#define xxd_full_usage "\n\n" | 45 | //usage:#define xxd_full_usage "\n\n" |
46 | //usage: "Hex dump FILE (or stdin)\n" | 46 | //usage: "Hex dump FILE (or stdin)\n" |
47 | //usage: "\n -g N Bytes per group" | 47 | //usage: "\n -g N Bytes per group" |
48 | //usage: "\n -c N Bytes per line" | 48 | //usage: "\n -c N Bytes per line" |
49 | //usage: "\n -p Show only hex bytes, assumes -c30" | 49 | //usage: "\n -p Show only hex bytes, assumes -c30" |
50 | //usage: "\n -i C include file style" | ||
50 | // exactly the same help text lines in hexdump and xxd: | 51 | // exactly the same help text lines in hexdump and xxd: |
51 | //usage: "\n -l LENGTH Show only first LENGTH bytes" | 52 | //usage: "\n -l LENGTH Show only first LENGTH bytes" |
52 | //usage: "\n -s OFFSET Skip OFFSET bytes" | 53 | //usage: "\n -s OFFSET Skip OFFSET bytes" |
54 | //usage: "\n -o OFFSET Add OFFSET to displayed offset" | ||
53 | //usage: "\n -r Reverse (with -p, assumes no offsets in input)" | 55 | //usage: "\n -r Reverse (with -p, assumes no offsets in input)" |
54 | 56 | ||
55 | #include "libbb.h" | 57 | #include "libbb.h" |
@@ -61,7 +63,11 @@ | |||
61 | #define OPT_s (1 << 1) | 63 | #define OPT_s (1 << 1) |
62 | #define OPT_a (1 << 2) | 64 | #define OPT_a (1 << 2) |
63 | #define OPT_p (1 << 3) | 65 | #define OPT_p (1 << 3) |
64 | #define OPT_r (1 << 4) | 66 | #define OPT_i (1 << 4) |
67 | #define OPT_r (1 << 5) | ||
68 | #define OPT_g (1 << 6) | ||
69 | #define OPT_c (1 << 7) | ||
70 | #define OPT_o (1 << 8) | ||
65 | 71 | ||
66 | static void reverse(unsigned opt, unsigned cols, const char *filename) | 72 | static void reverse(unsigned opt, unsigned cols, const char *filename) |
67 | { | 73 | { |
@@ -122,20 +128,30 @@ static void reverse(unsigned opt, unsigned cols, const char *filename) | |||
122 | fflush_stdout_and_exit(EXIT_SUCCESS); | 128 | fflush_stdout_and_exit(EXIT_SUCCESS); |
123 | } | 129 | } |
124 | 130 | ||
131 | static void print_C_style(const char *p, const char *hdr) | ||
132 | { | ||
133 | printf(hdr, isdigit(p[0]) ? "__" : ""); | ||
134 | while (*p) { | ||
135 | bb_putchar(isalnum(*p) ? *p : '_'); | ||
136 | p++; | ||
137 | } | ||
138 | } | ||
139 | |||
125 | int xxd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 140 | int xxd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
126 | int xxd_main(int argc UNUSED_PARAM, char **argv) | 141 | int xxd_main(int argc UNUSED_PARAM, char **argv) |
127 | { | 142 | { |
128 | char buf[80]; | 143 | char buf[80]; |
129 | dumper_t *dumper; | 144 | dumper_t *dumper; |
130 | char *opt_l, *opt_s; | 145 | char *opt_l, *opt_s, *opt_o; |
131 | unsigned bytes = 2; | 146 | unsigned bytes = 2; |
132 | unsigned cols = 0; | 147 | unsigned cols = 0; |
133 | unsigned opt; | 148 | unsigned opt; |
149 | int r; | ||
134 | 150 | ||
135 | dumper = alloc_dumper(); | 151 | dumper = alloc_dumper(); |
136 | 152 | ||
137 | opt = getopt32(argv, "^" "l:s:aprg:+c:+" "\0" "?1" /* 1 argument max */, | 153 | opt = getopt32(argv, "^" "l:s:apirg:+c:+o:" "\0" "?1" /* 1 argument max */, |
138 | &opt_l, &opt_s, &bytes, &cols | 154 | &opt_l, &opt_s, &bytes, &cols, &opt_o |
139 | ); | 155 | ); |
140 | argv += optind; | 156 | argv += optind; |
141 | 157 | ||
@@ -158,14 +174,24 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) | |||
158 | //BUGGY for /proc/version (unseekable?) | 174 | //BUGGY for /proc/version (unseekable?) |
159 | } | 175 | } |
160 | 176 | ||
177 | if (opt & OPT_o) { | ||
178 | /* -o accepts negative numbers too */ | ||
179 | dumper->xxd_displayoff = xstrtoll(opt_o, /*base:*/ 0); | ||
180 | } | ||
181 | |||
161 | if (opt & OPT_p) { | 182 | if (opt & OPT_p) { |
162 | if (cols == 0) | 183 | if (cols == 0) |
163 | cols = 30; | 184 | cols = 30; |
164 | bytes = cols; /* -p ignores -gN */ | 185 | bytes = cols; /* -p ignores -gN */ |
165 | } else { | 186 | } else { |
166 | if (cols == 0) | 187 | if (cols == 0) |
167 | cols = 16; | 188 | cols = (opt & OPT_i) ? 12 : 16; |
168 | bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: " | 189 | if (opt & OPT_i) { |
190 | bytes = 1; // -i ignores -gN | ||
191 | // output is " 0xXX, 0xXX, 0xXX...", add leading space | ||
192 | bb_dump_add(dumper, "\" \""); | ||
193 | } else | ||
194 | bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: " | ||
169 | } | 195 | } |
170 | 196 | ||
171 | if (opt & OPT_r) { | 197 | if (opt & OPT_r) { |
@@ -173,11 +199,15 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) | |||
173 | } | 199 | } |
174 | 200 | ||
175 | if (bytes < 1 || bytes >= cols) { | 201 | if (bytes < 1 || bytes >= cols) { |
176 | sprintf(buf, "%u/1 \"%%02x\"", cols); // cols * "xx" | 202 | sprintf(buf, "%u/1 \"%%02x\"", cols); // cols * "XX" |
177 | bb_dump_add(dumper, buf); | 203 | bb_dump_add(dumper, buf); |
178 | } | 204 | } |
179 | else if (bytes == 1) { | 205 | else if (bytes == 1) { |
180 | sprintf(buf, "%u/1 \"%%02x \"", cols); // cols * "xx " | 206 | if (opt & OPT_i) |
207 | sprintf(buf, "%u/1 \" 0x%%02x,\"", cols); // cols * " 0xXX," | ||
208 | //TODO: compat: omit the last comma after the very last byte | ||
209 | else | ||
210 | sprintf(buf, "%u/1 \"%%02x \"", cols); // cols * "XX " | ||
181 | bb_dump_add(dumper, buf); | 211 | bb_dump_add(dumper, buf); |
182 | } | 212 | } |
183 | else { | 213 | else { |
@@ -201,13 +231,22 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) | |||
201 | free(bigbuf); | 231 | free(bigbuf); |
202 | } | 232 | } |
203 | 233 | ||
204 | if (!(opt & OPT_p)) { | 234 | if (!(opt & (OPT_p|OPT_i))) { |
205 | sprintf(buf, "\" \"%u/1 \"%%_p\"\"\n\"", cols); // " ASCII\n" | 235 | sprintf(buf, "\" \"%u/1 \"%%_p\"\"\n\"", cols); // " ASCII\n" |
206 | bb_dump_add(dumper, buf); | 236 | bb_dump_add(dumper, buf); |
207 | } else { | 237 | } else { |
208 | bb_dump_add(dumper, "\"\n\""); | 238 | bb_dump_add(dumper, "\"\n\""); |
209 | dumper->eofstring = "\n"; | 239 | dumper->xxd_eofstring = "\n"; |
210 | } | 240 | } |
211 | 241 | ||
212 | return bb_dump_dump(dumper, argv); | 242 | if ((opt & OPT_i) && argv[0]) { |
243 | print_C_style(argv[0], "unsigned char %s"); | ||
244 | printf("[] = {\n"); | ||
245 | } | ||
246 | r = bb_dump_dump(dumper, argv); | ||
247 | if (r == 0 && (opt & OPT_i) && argv[0]) { | ||
248 | print_C_style(argv[0], "};\nunsigned int %s"); | ||
249 | printf("_len = %"OFF_FMT"u;\n", dumper->address); | ||
250 | } | ||
251 | return r; | ||
213 | } | 252 | } |