compat: move hexdump -R functionality to xxd -r
function old new delta xxd_main 466 680 +214 packed_usage 33474 33483 +9 hexdump_opts 17 16 -1 hexdump_main 565 401 -164 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/2 up/down: 223/-165) Total: 58 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
e16f7eb596
commit
32e1f69ae0
@ -15,16 +15,6 @@
|
|||||||
//config: The hexdump utility is used to display binary data in a readable
|
//config: The hexdump utility is used to display binary data in a readable
|
||||||
//config: way that is comparable to the output from most hex editors.
|
//config: way that is comparable to the output from most hex editors.
|
||||||
//config:
|
//config:
|
||||||
//config:config FEATURE_HEXDUMP_REVERSE
|
|
||||||
//config: bool "Support -R, reverse of 'hexdump -Cv'"
|
|
||||||
//config: default y
|
|
||||||
//config: depends on HEXDUMP
|
|
||||||
//config: help
|
|
||||||
//config: The hexdump utility is used to display binary data in an ascii
|
|
||||||
//config: readable way. This option creates binary data from an ascii input.
|
|
||||||
//config: NB: this option is non-standard. It's unwise to use it in scripts
|
|
||||||
//config: aimed to be portable.
|
|
||||||
//config:
|
|
||||||
//config:config HD
|
//config:config HD
|
||||||
//config: bool "hd (7.8 kb)"
|
//config: bool "hd (7.8 kb)"
|
||||||
//config: default y
|
//config: default y
|
||||||
@ -38,7 +28,7 @@
|
|||||||
//kbuild:lib-$(CONFIG_HD) += hexdump.o
|
//kbuild:lib-$(CONFIG_HD) += hexdump.o
|
||||||
|
|
||||||
//usage:#define hexdump_trivial_usage
|
//usage:#define hexdump_trivial_usage
|
||||||
//usage: "[-bcCdefnosvx" IF_FEATURE_HEXDUMP_REVERSE("R") "] [FILE]..."
|
//usage: "[-bcCdefnosvx] [FILE]..."
|
||||||
//usage:#define hexdump_full_usage "\n\n"
|
//usage:#define hexdump_full_usage "\n\n"
|
||||||
//usage: "Display FILEs (or stdin) in a user specified format\n"
|
//usage: "Display FILEs (or stdin) in a user specified format\n"
|
||||||
//usage: "\n -b 1-byte octal display"
|
//usage: "\n -b 1-byte octal display"
|
||||||
@ -53,9 +43,6 @@
|
|||||||
// exactly the same help text lines in hexdump and xxd:
|
// exactly the same help text lines in hexdump and xxd:
|
||||||
//usage: "\n -n LENGTH Show only first LENGTH bytes"
|
//usage: "\n -n LENGTH Show only first LENGTH bytes"
|
||||||
//usage: "\n -s OFFSET Skip OFFSET bytes"
|
//usage: "\n -s OFFSET Skip OFFSET bytes"
|
||||||
//usage: IF_FEATURE_HEXDUMP_REVERSE(
|
|
||||||
//usage: "\n -R Reverse of 'hexdump -Cv'")
|
|
||||||
// TODO: NONCOMPAT!!! move -R to xxd -r
|
|
||||||
//usage:
|
//usage:
|
||||||
//usage:#define hd_trivial_usage
|
//usage:#define hd_trivial_usage
|
||||||
//usage: "FILE..."
|
//usage: "FILE..."
|
||||||
@ -94,7 +81,7 @@ static const char *const add_strings[] = {
|
|||||||
|
|
||||||
static const char add_first[] ALIGN1 = "\"%07.7_Ax\n\"";
|
static const char add_first[] ALIGN1 = "\"%07.7_Ax\n\"";
|
||||||
|
|
||||||
static const char hexdump_opts[] ALIGN1 = "bcdoxCe:f:n:s:v" IF_FEATURE_HEXDUMP_REVERSE("R");
|
static const char hexdump_opts[] ALIGN1 = "bcdoxCe:f:n:s:v";
|
||||||
|
|
||||||
int hexdump_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
int hexdump_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||||
int hexdump_main(int argc, char **argv)
|
int hexdump_main(int argc, char **argv)
|
||||||
@ -102,10 +89,6 @@ int hexdump_main(int argc, char **argv)
|
|||||||
dumper_t *dumper = alloc_dumper();
|
dumper_t *dumper = alloc_dumper();
|
||||||
const char *p;
|
const char *p;
|
||||||
int ch;
|
int ch;
|
||||||
#if ENABLE_FEATURE_HEXDUMP_REVERSE
|
|
||||||
FILE *fp;
|
|
||||||
smallint rdump = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ENABLE_HD
|
if (ENABLE_HD
|
||||||
&& (!ENABLE_HEXDUMP || !applet_name[2])
|
&& (!ENABLE_HEXDUMP || !applet_name[2])
|
||||||
@ -153,11 +136,6 @@ int hexdump_main(int argc, char **argv)
|
|||||||
if (ch == 'v') {
|
if (ch == 'v') {
|
||||||
dumper->dump_vflag = ALL;
|
dumper->dump_vflag = ALL;
|
||||||
}
|
}
|
||||||
#if ENABLE_FEATURE_HEXDUMP_REVERSE
|
|
||||||
if (ch == 'R') {
|
|
||||||
rdump = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dumper->fshead) {
|
if (!dumper->fshead) {
|
||||||
@ -167,40 +145,5 @@ int hexdump_main(int argc, char **argv)
|
|||||||
|
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
#if !ENABLE_FEATURE_HEXDUMP_REVERSE
|
|
||||||
return bb_dump_dump(dumper, argv);
|
return bb_dump_dump(dumper, argv);
|
||||||
#else
|
|
||||||
if (!rdump) {
|
|
||||||
return bb_dump_dump(dumper, argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -R: reverse of 'hexdump -Cv' */
|
|
||||||
fp = stdin;
|
|
||||||
if (!*argv) {
|
|
||||||
argv--;
|
|
||||||
goto jump_in;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
char *buf;
|
|
||||||
fp = xfopen_for_read(*argv);
|
|
||||||
jump_in:
|
|
||||||
while ((buf = xmalloc_fgetline(fp)) != NULL) {
|
|
||||||
p = buf;
|
|
||||||
while (1) {
|
|
||||||
/* skip address or previous byte */
|
|
||||||
while (isxdigit(*p)) p++;
|
|
||||||
while (*p == ' ') p++;
|
|
||||||
/* '|' char will break the line */
|
|
||||||
if (!isxdigit(*p) || sscanf(p, "%x ", &ch) != 1)
|
|
||||||
break;
|
|
||||||
putchar(ch);
|
|
||||||
}
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
} while (*++argv);
|
|
||||||
|
|
||||||
fflush_stdout_and_exit(EXIT_SUCCESS);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
@ -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 -r Reverse (with -p, assumes no offsets in input)"
|
||||||
// TODO: implement -r (see hexdump -R)
|
// TODO: implement -r (see hexdump -R)
|
||||||
|
|
||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
@ -57,6 +58,71 @@
|
|||||||
|
|
||||||
/* This is a NOEXEC applet. Be very careful! */
|
/* This is a NOEXEC applet. Be very careful! */
|
||||||
|
|
||||||
|
#define OPT_l (1 << 0)
|
||||||
|
#define OPT_s (1 << 1)
|
||||||
|
#define OPT_a (1 << 2)
|
||||||
|
#define OPT_p (1 << 3)
|
||||||
|
#define OPT_r (1 << 4)
|
||||||
|
|
||||||
|
static void reverse(unsigned opt, unsigned cols, const char *filename)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
fp = filename ? xfopen_for_read(filename) : stdin;
|
||||||
|
|
||||||
|
while ((buf = xmalloc_fgetline(fp)) != NULL) {
|
||||||
|
char *p = buf;
|
||||||
|
unsigned cnt = cols;
|
||||||
|
|
||||||
|
if (!(opt & OPT_p)) {
|
||||||
|
/* skip address */
|
||||||
|
while (isxdigit(*p)) p++;
|
||||||
|
/* NB: for xxd -r, first hex portion is address even without colon */
|
||||||
|
/* If it's there, skip it: */
|
||||||
|
if (*p == ':') p++;
|
||||||
|
|
||||||
|
//TODO: seek (or zero-pad if unseekable) to the address position
|
||||||
|
//NOTE: -s SEEK value should be added to the address before seeking
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process hex bytes optionally separated by whitespace */
|
||||||
|
do {
|
||||||
|
uint8_t val, c;
|
||||||
|
|
||||||
|
p = skip_whitespace(p);
|
||||||
|
|
||||||
|
c = *p++;
|
||||||
|
if (isdigit(c))
|
||||||
|
val = c - '0';
|
||||||
|
else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
|
||||||
|
val = (c|0x20) - ('a' - 10);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
val <<= 4;
|
||||||
|
|
||||||
|
/* Works the same with xxd V1.10:
|
||||||
|
* echo "31 09 32 0a" | xxd -r -p
|
||||||
|
* echo "31 0 9 32 0a" | xxd -r -p
|
||||||
|
* thus allow whitespace even within the byte:
|
||||||
|
*/
|
||||||
|
p = skip_whitespace(p);
|
||||||
|
|
||||||
|
c = *p++;
|
||||||
|
if (isdigit(c))
|
||||||
|
val |= c - '0';
|
||||||
|
else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
|
||||||
|
val |= (c|0x20) - ('a' - 10);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
putchar(val);
|
||||||
|
} while (!(opt & OPT_p) || --cnt != 0);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
//fclose(fp);
|
||||||
|
fflush_stdout_and_exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
int xxd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
int xxd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||||
int xxd_main(int argc UNUSED_PARAM, char **argv)
|
int xxd_main(int argc UNUSED_PARAM, char **argv)
|
||||||
{
|
{
|
||||||
@ -69,11 +135,7 @@ int xxd_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
|
|
||||||
dumper = alloc_dumper();
|
dumper = alloc_dumper();
|
||||||
|
|
||||||
#define OPT_l (1 << 0)
|
opt = getopt32(argv, "^" "l:s:aprg:+c:+" "\0" "?1" /* 1 argument max */,
|
||||||
#define OPT_s (1 << 1)
|
|
||||||
#define OPT_a (1 << 2)
|
|
||||||
#define OPT_p (1 << 3)
|
|
||||||
opt = getopt32(argv, "^" "l:s:apg:+c:+" "\0" "?1" /* 1 argument max */,
|
|
||||||
&opt_l, &opt_s, &bytes, &cols
|
&opt_l, &opt_s, &bytes, &cols
|
||||||
);
|
);
|
||||||
argv += optind;
|
argv += optind;
|
||||||
@ -107,6 +169,10 @@ int xxd_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: "
|
bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: "
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opt & OPT_r) {
|
||||||
|
reverse(opt, cols, argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
if (bytes < 1 || bytes >= cols) {
|
if (bytes < 1 || bytes >= cols) {
|
||||||
sprintf(buf, "%u/1 \"%%02x\"", cols); // cols * "xx"
|
sprintf(buf, "%u/1 \"%%02x\"", cols); // cols * "xx"
|
||||||
bb_dump_add(dumper, buf);
|
bb_dump_add(dumper, buf);
|
||||||
|
Loading…
Reference in New Issue
Block a user