aboutsummaryrefslogtreecommitdiff
path: root/util-linux/hexdump_xxd.c
diff options
context:
space:
mode:
Diffstat (limited to 'util-linux/hexdump_xxd.c')
-rw-r--r--util-linux/hexdump_xxd.c63
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
66static void reverse(unsigned opt, unsigned cols, const char *filename) 72static 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
131static 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
125int xxd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 140int xxd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
126int xxd_main(int argc UNUSED_PARAM, char **argv) 141int 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}