From 2c436679fbb5fa38b0e7a505022a2075fab87d84 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 18 Jun 2021 00:59:17 +0200 Subject: [PATCH] xxd: implement -i "C style output" function old new delta xxd_main 710 888 +178 .rodata 103252 103331 +79 print_C_style - 78 +78 packed_usage 33639 33652 +13 next 276 278 +2 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 4/0 up/down: 350/0) Total: 350 bytes Signed-off-by: Denys Vlasenko --- include/dump.h | 1 + libbb/dump.c | 29 ++++++++++++------------ util-linux/hexdump_xxd.c | 49 +++++++++++++++++++++++++++++++--------- 3 files changed, 53 insertions(+), 26 deletions(-) diff --git a/include/dump.h b/include/dump.h index 54f5629a7..10fc5d900 100644 --- a/include/dump.h +++ b/include/dump.h @@ -34,6 +34,7 @@ typedef struct dumper_t { smallint dump_vflag; /*enum dump_vflag_t*/ FS *fshead; const char *xxd_eofstring; + off_t address; /* address/offset in stream */ long long xxd_displayoff; } dumper_t; diff --git a/libbb/dump.c b/libbb/dump.c index 9c16f1f94..f8bb6fd03 100644 --- a/libbb/dump.c +++ b/libbb/dump.c @@ -34,7 +34,6 @@ typedef struct priv_dumper_t { FU *endfu; off_t savaddress; /* saved address/offset in stream */ off_t eaddress; /* end address */ - off_t address; /* address/offset in stream */ int blocksize; smallint exitval; /* final exit value */ @@ -335,14 +334,14 @@ static void do_skip(priv_dumper_t *dumper, const char *fname) ) { /* If st_size is valid and pub.dump_skip >= st_size */ dumper->pub.dump_skip -= sbuf.st_size; - dumper->address += sbuf.st_size; + dumper->pub.address += sbuf.st_size; return; } if (fseeko(stdin, dumper->pub.dump_skip, SEEK_SET)) { bb_simple_perror_msg_and_die(fname); } - dumper->address += dumper->pub.dump_skip; - dumper->savaddress = dumper->address; + dumper->pub.address += dumper->pub.dump_skip; + dumper->savaddress = dumper->pub.address; dumper->pub.dump_skip = 0; } @@ -381,7 +380,7 @@ static unsigned char *get(priv_dumper_t *dumper) int blocksize = dumper->blocksize; if (!dumper->get__curp) { - dumper->address = (off_t)0; /*DBU:[dave@cray.com] initialize,initialize..*/ + dumper->pub.address = (off_t)0; /*DBU:[dave@cray.com] initialize,initialize..*/ dumper->get__curp = xmalloc(blocksize); dumper->get__savp = xzalloc(blocksize); /* need to be initialized */ } else { @@ -389,7 +388,7 @@ static unsigned char *get(priv_dumper_t *dumper) dumper->get__curp = dumper->get__savp; dumper->get__savp = tmp; dumper->savaddress += blocksize; - dumper->address = dumper->savaddress; + dumper->pub.address = dumper->savaddress; } need = blocksize; nread = 0; @@ -412,7 +411,7 @@ static unsigned char *get(priv_dumper_t *dumper) } } memset(dumper->get__curp + nread, 0, need); - dumper->eaddress = dumper->address + nread; + dumper->eaddress = dumper->pub.address + nread; return dumper->get__curp; } n = fread(dumper->get__curp + nread, sizeof(unsigned char), @@ -444,7 +443,7 @@ static unsigned char *get(priv_dumper_t *dumper) } dumper->pub.dump_vflag = DUP; dumper->savaddress += blocksize; - dumper->address = dumper->savaddress; + dumper->pub.address = dumper->savaddress; need = blocksize; nread = 0; } else { @@ -545,8 +544,8 @@ static void display(priv_dumper_t* dumper) fs = dumper->pub.fshead; savebp = bp; - saveaddress = dumper->address; - for (; fs; fs = fs->nextfs, bp = savebp, dumper->address = saveaddress) { + saveaddress = dumper->pub.address; + for (; fs; fs = fs->nextfs, bp = savebp, dumper->pub.address = saveaddress) { FU *fu; for (fu = fs->nextfu; fu; fu = fu->nextfu) { int cnt; @@ -555,10 +554,10 @@ static void display(priv_dumper_t* dumper) } for (cnt = fu->reps; cnt; --cnt) { PR *pr; - for (pr = fu->nextpr; pr; dumper->address += pr->bcnt, + for (pr = fu->nextpr; pr; dumper->pub.address += pr->bcnt, bp += pr->bcnt, pr = pr->nextpr) { if (dumper->eaddress - && dumper->address >= dumper->eaddress + && dumper->pub.address >= dumper->eaddress ) { if (dumper->pub.xxd_eofstring) { /* xxd support: requested to not pad incomplete blocks */ @@ -574,7 +573,7 @@ static void display(priv_dumper_t* dumper) } switch (pr->flags) { case F_ADDRESS: - printf(pr->fmt, (unsigned long long) dumper->address + dumper->pub.xxd_displayoff); + printf(pr->fmt, (unsigned long long) dumper->pub.address + dumper->pub.xxd_displayoff); break; case F_BPAD: printf(pr->fmt, ""); @@ -668,10 +667,10 @@ static void display(priv_dumper_t* dumper) * of blocksize, and no partial block ever found. */ if (!dumper->eaddress) { - if (!dumper->address) { + if (!dumper->pub.address) { return; } - dumper->eaddress = dumper->address; + dumper->eaddress = dumper->pub.address; } for (pr = dumper->endfu->nextpr; pr; pr = pr->nextpr) { switch (pr->flags) { diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c index 817250c69..aa215569f 100644 --- a/util-linux/hexdump_xxd.c +++ b/util-linux/hexdump_xxd.c @@ -41,12 +41,13 @@ // -u use upper case hex letters. //usage:#define xxd_trivial_usage -//usage: "[-pr] [-g N] [-c N] [-n LEN] [-s OFS] [-o OFS] [FILE]" +//usage: "[-pri] [-g N] [-c N] [-n LEN] [-s OFS] [-o OFS] [FILE]" //usage:#define xxd_full_usage "\n\n" //usage: "Hex dump FILE (or stdin)\n" //usage: "\n -g N Bytes per group" //usage: "\n -c N Bytes per line" //usage: "\n -p Show only hex bytes, assumes -c30" +//usage: "\n -i C include file style" // exactly the same help text lines in hexdump and xxd: //usage: "\n -l LENGTH Show only first LENGTH bytes" //usage: "\n -s OFFSET Skip OFFSET bytes" @@ -62,10 +63,11 @@ #define OPT_s (1 << 1) #define OPT_a (1 << 2) #define OPT_p (1 << 3) -#define OPT_r (1 << 4) -#define OPT_g (1 << 5) -#define OPT_c (1 << 6) -#define OPT_o (1 << 7) +#define OPT_i (1 << 4) +#define OPT_r (1 << 5) +#define OPT_g (1 << 6) +#define OPT_c (1 << 7) +#define OPT_o (1 << 8) static void reverse(unsigned opt, unsigned cols, const char *filename) { @@ -126,6 +128,15 @@ static void reverse(unsigned opt, unsigned cols, const char *filename) fflush_stdout_and_exit(EXIT_SUCCESS); } +static void print_C_style(const char *p, const char *hdr) +{ + printf(hdr, isdigit(p[0]) ? "__" : ""); + while (*p) { + bb_putchar(isalnum(*p) ? *p : '_'); + p++; + } +} + int xxd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int xxd_main(int argc UNUSED_PARAM, char **argv) { @@ -135,10 +146,11 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) unsigned bytes = 2; unsigned cols = 0; unsigned opt; + int r; dumper = alloc_dumper(); - opt = getopt32(argv, "^" "l:s:aprg:+c:+o:" "\0" "?1" /* 1 argument max */, + opt = getopt32(argv, "^" "l:s:apirg:+c:+o:" "\0" "?1" /* 1 argument max */, &opt_l, &opt_s, &bytes, &cols, &opt_o ); argv += optind; @@ -173,8 +185,11 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) bytes = cols; /* -p ignores -gN */ } else { if (cols == 0) - cols = 16; - bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: " + cols = (opt & OPT_i) ? 12 : 16; + if (opt & OPT_i) + bytes = 1; /* -i ignores -gN */ + else + bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: " } if (opt & OPT_r) { @@ -186,7 +201,10 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) bb_dump_add(dumper, buf); } else if (bytes == 1) { - sprintf(buf, "%u/1 \"%%02x \"", cols); // cols * "xx " + if (opt & OPT_i) + sprintf(buf, "%u/1 \" 0x%%02x,\"", cols); // cols * " 0xxx," + else + sprintf(buf, "%u/1 \"%%02x \"", cols); // cols * "xx " bb_dump_add(dumper, buf); } else { @@ -210,7 +228,7 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) free(bigbuf); } - if (!(opt & OPT_p)) { + if (!(opt & (OPT_p|OPT_i))) { sprintf(buf, "\" \"%u/1 \"%%_p\"\"\n\"", cols); // " ASCII\n" bb_dump_add(dumper, buf); } else { @@ -218,5 +236,14 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) dumper->xxd_eofstring = "\n"; } - return bb_dump_dump(dumper, argv); + if ((opt & OPT_i) && argv[0]) { + print_C_style(argv[0], "unsigned char %s"); + printf("[] = {\n"); + } + r = bb_dump_dump(dumper, argv); + if (r == 0 && (opt & OPT_i) && argv[0]) { + print_C_style(argv[0], "};\nunsigned int %s"); + printf("_len = %"OFF_FMT"u;\n", dumper->address); + } + return r; }