diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2020-10-20 18:54:36 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2020-10-20 18:57:02 +0200 |
commit | dac5b8314236338963877903cba3d7edfbfc9c58 (patch) | |
tree | 5e7ce92407b9079b4e49e728f28f8a7c6311999c /libbb | |
parent | 085f19cdffd653013b1483c08851ecc35cdd818e (diff) | |
download | busybox-dac5b8314236338963877903cba3d7edfbfc9c58.tar.gz |
xxd: fix printing of trailing spaces
function old new delta
bb_dump_dump 1497 1523 +26
xxd_main 459 466 +7
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 33/0) Total: 33 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/dump.c | 93 |
1 files changed, 71 insertions, 22 deletions
diff --git a/libbb/dump.c b/libbb/dump.c index 8029cca0e..920f003ef 100644 --- a/libbb/dump.c +++ b/libbb/dump.c @@ -13,13 +13,43 @@ #include "libbb.h" #include "dump.h" -static const char dot_flags_width_chars[] ALIGN1 = ".#-+ 0123456789"; - -static const char size_conv_str[] ALIGN1 = -"\x1\x4\x4\x4\x4\x4\x4\x8\x8\x8\x8\010cdiouxXeEfgG"; - -static const char int_convs[] ALIGN1 = "diouxX"; - +#define F_IGNORE 0x01 /* %_A */ +#define F_SETREP 0x02 /* rep count set, not default */ +#define F_ADDRESS 0x001 /* print offset */ +#define F_BPAD 0x002 /* blank pad */ +#define F_C 0x004 /* %_c */ +#define F_CHAR 0x008 /* %c */ +#define F_DBL 0x010 /* %[EefGf] */ +#define F_INT 0x020 /* %[di] */ +#define F_P 0x040 /* %_p */ +#define F_STR 0x080 /* %s */ +#define F_U 0x100 /* %_u */ +#define F_UINT 0x200 /* %[ouXx] */ +#define F_TEXT 0x400 /* no conversions */ + +typedef struct PR { + struct PR *nextpr; /* next print unit */ + unsigned flags; /* flag values */ + int bcnt; /* byte count */ + char *cchar; /* conversion character */ + char *fmt; /* printf format */ + char *nospace; /* no whitespace version */ +} PR; + +typedef struct FU { + struct FU *nextfu; /* next format unit */ + struct PR *nextpr; /* next print unit */ + unsigned flags; /* flag values */ + int reps; /* repetition count */ + int bcnt; /* byte count */ + char *fmt; /* format string */ +} FU; + +typedef struct FS { /* format strings */ + struct FS *nextfs; /* linked list of format strings */ + struct FU *nextfu; /* linked list of format units */ + int bcnt; +} FS; typedef struct priv_dumper_t { dumper_t pub; @@ -39,6 +69,13 @@ typedef struct priv_dumper_t { unsigned char *get__savp; } priv_dumper_t; +static const char dot_flags_width_chars[] ALIGN1 = ".#-+ 0123456789"; + +static const char size_conv_str[] ALIGN1 = +"\x1\x4\x4\x4\x4\x4\x4\x8\x8\x8\x8\010cdiouxXeEfgG"; + +static const char int_convs[] ALIGN1 = "diouxX"; + dumper_t* FAST_FUNC alloc_dumper(void) { priv_dumper_t *dumper = xzalloc(sizeof(*dumper)); @@ -48,7 +85,6 @@ dumper_t* FAST_FUNC alloc_dumper(void) return &dumper->pub; } - static NOINLINE int bb_dump_size(FS *fs) { FU *fu; @@ -284,7 +320,9 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) * repeat it as necessary. * * if rep count is greater than 1, no trailing whitespace - * gets output from the last iteration of the format unit. + * gets output from the last iteration of the format unit: + * 2/1 "%02x " prints "XX XX", not "XX XX " + * 2/1 "%02x\n" prints "XX\nXX", not "XX\nXX\n" */ for (fu = fs->nextfu; fu; fu = fu->nextfu) { if (!fu->nextfu @@ -453,7 +491,7 @@ static void bpad(PR *pr) for (p2 = ++p1; *p1 && strchr(" -0+#", *p1); ++p1) if (pr->nospace) pr->nospace--; - while ((*p2++ = *p1++) != 0) + while ((*p2++ = *p1++) != '\0') continue; } @@ -520,36 +558,43 @@ static void conv_u(PR *pr, unsigned char *p) static void display(priv_dumper_t* dumper) { - FS *fs; - FU *fu; - PR *pr; - int cnt; - unsigned char *bp, *savebp; - off_t saveaddress; + unsigned char *bp; unsigned char savech = '\0'; while ((bp = get(dumper)) != NULL) { + FS *fs; + unsigned char *savebp; + off_t saveaddress; + fs = dumper->pub.fshead; savebp = bp; saveaddress = dumper->address; for (; fs; fs = fs->nextfs, bp = savebp, dumper->address = saveaddress) { + FU *fu; for (fu = fs->nextfu; fu; fu = fu->nextfu) { + int cnt; if (fu->flags & F_IGNORE) { break; } for (cnt = fu->reps; cnt; --cnt) { + PR *pr; for (pr = fu->nextpr; pr; dumper->address += pr->bcnt, bp += pr->bcnt, pr = pr->nextpr) { - if (dumper->eaddress && dumper->address >= dumper->eaddress - && !(pr->flags & (F_TEXT | F_BPAD)) + if (dumper->eaddress + && dumper->address >= dumper->eaddress ) { - bpad(pr); + if (dumper->pub.eofstring) { + /* xxd support: requested to not pad incomplete blocks */ + fputs(dumper->pub.eofstring, stdout); + return; + } + if (!(pr->flags & (F_TEXT | F_BPAD))) + bpad(pr); } if (cnt == 1 && pr->nospace) { savech = *pr->nospace; *pr->nospace = '\0'; } -/* PRINT; */ switch (pr->flags) { case F_ADDRESS: printf(pr->fmt, (unsigned) dumper->address); @@ -638,7 +683,9 @@ static void display(priv_dumper_t* dumper) } } } + if (dumper->endfu) { + PR *pr; /* * if eaddress not set, error or file size was multiple * of blocksize, and no partial block ever found. @@ -695,8 +742,7 @@ void FAST_FUNC bb_dump_add(dumper_t* pub_dumper, const char *fmt) { const char *p; FS *tfs; - FU *tfu, **nextfupp; - const char *savep; + FU **nextfupp; /* start new linked list of format units */ tfs = xzalloc(sizeof(FS)); /*DBU:[dave@cray.com] start out NULL */ @@ -713,6 +759,9 @@ void FAST_FUNC bb_dump_add(dumper_t* pub_dumper, const char *fmt) /* take the format string and break it up into format units */ p = fmt; for (;;) { + FU *tfu; + const char *savep; + p = skip_whitespace(p); if (*p == '\0') { break; |