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 <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2021-06-17 23:53:30 +02:00
parent a0f8076d19
commit 4d16161797
3 changed files with 22 additions and 11 deletions

View File

@ -32,8 +32,9 @@ typedef struct dumper_t {
off_t dump_skip; /* bytes to skip */ off_t dump_skip; /* bytes to skip */
int dump_length; /* max bytes to read */ int dump_length; /* max bytes to read */
smallint dump_vflag; /*enum dump_vflag_t*/ smallint dump_vflag; /*enum dump_vflag_t*/
const char *eofstring;
FS *fshead; FS *fshead;
const char *xxd_eofstring;
long long xxd_displayoff;
} dumper_t; } dumper_t;
dumper_t* alloc_dumper(void) FAST_FUNC; dumper_t* alloc_dumper(void) FAST_FUNC;

View File

@ -228,7 +228,8 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
if ((p1[2] != 'd') && (p1[2] != 'o') && (p1[2] != 'x')) { if ((p1[2] != 'd') && (p1[2] != 'o') && (p1[2] != 'x')) {
goto DO_BAD_CONV_CHAR; goto DO_BAD_CONV_CHAR;
} }
*p1 = p1[2]; *p1++ = 'l';
*p1++ = 'l';
break; break;
case 'c': /* %_c: chars, \ooo, \n \r \t etc */ case 'c': /* %_c: chars, \ooo, \n \r \t etc */
pr->flags = F_C; pr->flags = F_C;
@ -558,9 +559,9 @@ static void display(priv_dumper_t* dumper)
if (dumper->eaddress if (dumper->eaddress
&& dumper->address >= dumper->eaddress && dumper->address >= dumper->eaddress
) { ) {
if (dumper->pub.eofstring) { if (dumper->pub.xxd_eofstring) {
/* xxd support: requested to not pad incomplete blocks */ /* xxd support: requested to not pad incomplete blocks */
fputs_stdout(dumper->pub.eofstring); fputs_stdout(dumper->pub.xxd_eofstring);
return; return;
} }
if (!(pr->flags & (F_TEXT | F_BPAD))) if (!(pr->flags & (F_TEXT | F_BPAD)))
@ -572,7 +573,7 @@ static void display(priv_dumper_t* dumper)
} }
switch (pr->flags) { switch (pr->flags) {
case F_ADDRESS: case F_ADDRESS:
printf(pr->fmt, (unsigned) dumper->address); printf(pr->fmt, (unsigned long long) dumper->address + dumper->pub.xxd_displayoff);
break; break;
case F_BPAD: case F_BPAD:
printf(pr->fmt, ""); printf(pr->fmt, "");
@ -674,7 +675,7 @@ static void display(priv_dumper_t* dumper)
for (pr = dumper->endfu->nextpr; pr; pr = pr->nextpr) { for (pr = dumper->endfu->nextpr; pr; pr = pr->nextpr) {
switch (pr->flags) { switch (pr->flags) {
case F_ADDRESS: case F_ADDRESS:
printf(pr->fmt, (unsigned) dumper->eaddress); printf(pr->fmt, (unsigned long long) dumper->eaddress + dumper->pub.xxd_displayoff);
break; break;
case F_TEXT: case F_TEXT:
printf(pr->fmt); printf(pr->fmt);

View File

@ -41,7 +41,7 @@
// -u use upper case hex letters. // -u use upper case hex letters.
//usage:#define xxd_trivial_usage //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:#define xxd_full_usage "\n\n"
//usage: "Hex dump FILE (or stdin)\n" //usage: "Hex dump FILE (or stdin)\n"
//usage: "\n -g N Bytes per group" //usage: "\n -g N Bytes per group"
@ -50,6 +50,7 @@
// exactly the same help text lines in hexdump and xxd: // exactly the same help text lines in hexdump and xxd:
//usage: "\n -l LENGTH Show only first LENGTH bytes" //usage: "\n -l LENGTH Show only first LENGTH bytes"
//usage: "\n -s OFFSET Skip OFFSET 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)" //usage: "\n -r Reverse (with -p, assumes no offsets in input)"
#include "libbb.h" #include "libbb.h"
@ -62,6 +63,9 @@
#define OPT_a (1 << 2) #define OPT_a (1 << 2)
#define OPT_p (1 << 3) #define OPT_p (1 << 3)
#define OPT_r (1 << 4) #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) 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]; char buf[80];
dumper_t *dumper; dumper_t *dumper;
char *opt_l, *opt_s; char *opt_l, *opt_s, *opt_o;
unsigned bytes = 2; unsigned bytes = 2;
unsigned cols = 0; unsigned cols = 0;
unsigned opt; unsigned opt;
dumper = alloc_dumper(); dumper = alloc_dumper();
opt = getopt32(argv, "^" "l:s:aprg:+c:+" "\0" "?1" /* 1 argument max */, opt = getopt32(argv, "^" "l:s:aprg:+c:+o:" "\0" "?1" /* 1 argument max */,
&opt_l, &opt_s, &bytes, &cols &opt_l, &opt_s, &bytes, &cols, &opt_o
); );
argv += optind; argv += optind;
@ -158,6 +162,11 @@ int xxd_main(int argc UNUSED_PARAM, char **argv)
//BUGGY for /proc/version (unseekable?) //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 (opt & OPT_p) {
if (cols == 0) if (cols == 0)
cols = 30; cols = 30;
@ -206,7 +215,7 @@ int xxd_main(int argc UNUSED_PARAM, char **argv)
bb_dump_add(dumper, buf); bb_dump_add(dumper, buf);
} else { } else {
bb_dump_add(dumper, "\"\n\""); bb_dump_add(dumper, "\"\n\"");
dumper->eofstring = "\n"; dumper->xxd_eofstring = "\n";
} }
return bb_dump_dump(dumper, argv); return bb_dump_dump(dumper, argv);