From 4d1616179745ee3883a726aaf13468e9c44dff9e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 17 Jun 2021 23:53:30 +0200 Subject: [PATCH] xxd: implement -o DISPLAYOFFSET function old new delta xxd_main 680 710 +30 xstrtoll - 30 +30 bb_dump_dump 1511 1531 +20 rewrite 941 951 +10 packed_usage 33629 33639 +10 .rodata 103250 103252 +2 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 5/0 up/down: 102/0) Total: 102 bytes Signed-off-by: Denys Vlasenko --- include/dump.h | 3 ++- libbb/dump.c | 11 ++++++----- util-linux/hexdump_xxd.c | 19 ++++++++++++++----- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/include/dump.h b/include/dump.h index 9193a6925..54f5629a7 100644 --- a/include/dump.h +++ b/include/dump.h @@ -32,8 +32,9 @@ typedef struct dumper_t { off_t dump_skip; /* bytes to skip */ int dump_length; /* max bytes to read */ smallint dump_vflag; /*enum dump_vflag_t*/ - const char *eofstring; FS *fshead; + const char *xxd_eofstring; + long long xxd_displayoff; } dumper_t; dumper_t* alloc_dumper(void) FAST_FUNC; diff --git a/libbb/dump.c b/libbb/dump.c index e83633c1d..8c2a370d0 100644 --- a/libbb/dump.c +++ b/libbb/dump.c @@ -228,7 +228,8 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) if ((p1[2] != 'd') && (p1[2] != 'o') && (p1[2] != 'x')) { goto DO_BAD_CONV_CHAR; } - *p1 = p1[2]; + *p1++ = 'l'; + *p1++ = 'l'; break; case 'c': /* %_c: chars, \ooo, \n \r \t etc */ pr->flags = F_C; @@ -558,9 +559,9 @@ static void display(priv_dumper_t* dumper) if (dumper->eaddress && dumper->address >= dumper->eaddress ) { - if (dumper->pub.eofstring) { + if (dumper->pub.xxd_eofstring) { /* xxd support: requested to not pad incomplete blocks */ - fputs_stdout(dumper->pub.eofstring); + fputs_stdout(dumper->pub.xxd_eofstring); return; } if (!(pr->flags & (F_TEXT | F_BPAD))) @@ -572,7 +573,7 @@ static void display(priv_dumper_t* dumper) } switch (pr->flags) { case F_ADDRESS: - printf(pr->fmt, (unsigned) dumper->address); + printf(pr->fmt, (unsigned long long) dumper->address + dumper->pub.xxd_displayoff); break; case F_BPAD: printf(pr->fmt, ""); @@ -674,7 +675,7 @@ static void display(priv_dumper_t* dumper) for (pr = dumper->endfu->nextpr; pr; pr = pr->nextpr) { switch (pr->flags) { case F_ADDRESS: - printf(pr->fmt, (unsigned) dumper->eaddress); + printf(pr->fmt, (unsigned long long) dumper->eaddress + dumper->pub.xxd_displayoff); break; case F_TEXT: printf(pr->fmt); diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c index 29bbc6633..817250c69 100644 --- a/util-linux/hexdump_xxd.c +++ b/util-linux/hexdump_xxd.c @@ -41,7 +41,7 @@ // -u use upper case hex letters. //usage:#define xxd_trivial_usage -//usage: "[-pr] [-g N] [-c N] [-n LEN] [-s OFS] [FILE]" +//usage: "[-pr] [-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" @@ -50,6 +50,7 @@ // 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" +//usage: "\n -o OFFSET Add OFFSET to displayed offset" //usage: "\n -r Reverse (with -p, assumes no offsets in input)" #include "libbb.h" @@ -62,6 +63,9 @@ #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) static void reverse(unsigned opt, unsigned cols, const char *filename) { @@ -127,15 +131,15 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) { char buf[80]; dumper_t *dumper; - char *opt_l, *opt_s; + char *opt_l, *opt_s, *opt_o; unsigned bytes = 2; unsigned cols = 0; unsigned opt; dumper = alloc_dumper(); - opt = getopt32(argv, "^" "l:s:aprg:+c:+" "\0" "?1" /* 1 argument max */, - &opt_l, &opt_s, &bytes, &cols + opt = getopt32(argv, "^" "l:s:aprg:+c:+o:" "\0" "?1" /* 1 argument max */, + &opt_l, &opt_s, &bytes, &cols, &opt_o ); argv += optind; @@ -158,6 +162,11 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) //BUGGY for /proc/version (unseekable?) } + if (opt & OPT_o) { + /* -o accepts negative numbers too */ + dumper->xxd_displayoff = xstrtoll(opt_o, /*base:*/ 0); + } + if (opt & OPT_p) { if (cols == 0) cols = 30; @@ -206,7 +215,7 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) bb_dump_add(dumper, buf); } else { bb_dump_add(dumper, "\"\n\""); - dumper->eofstring = "\n"; + dumper->xxd_eofstring = "\n"; } return bb_dump_dump(dumper, argv);