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>
diff --git a/util-linux/hexdump.c b/util-linux/hexdump.c
index 065b839..2174c30 100644
--- a/util-linux/hexdump.c
+++ b/util-linux/hexdump.c
@@ -15,16 +15,6 @@
//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:
-//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: bool "hd (7.8 kb)"
//config: default y
@@ -38,7 +28,7 @@
//kbuild:lib-$(CONFIG_HD) += hexdump.o
//usage:#define hexdump_trivial_usage
-//usage: "[-bcCdefnosvx" IF_FEATURE_HEXDUMP_REVERSE("R") "] [FILE]..."
+//usage: "[-bcCdefnosvx] [FILE]..."
//usage:#define hexdump_full_usage "\n\n"
//usage: "Display FILEs (or stdin) in a user specified format\n"
//usage: "\n -b 1-byte octal display"
@@ -53,9 +43,6 @@
// exactly the same help text lines in hexdump and xxd:
//usage: "\n -n LENGTH Show only first LENGTH 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:#define hd_trivial_usage
//usage: "FILE..."
@@ -94,7 +81,7 @@
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)
@@ -102,10 +89,6 @@
dumper_t *dumper = alloc_dumper();
const char *p;
int ch;
-#if ENABLE_FEATURE_HEXDUMP_REVERSE
- FILE *fp;
- smallint rdump = 0;
-#endif
if (ENABLE_HD
&& (!ENABLE_HEXDUMP || !applet_name[2])
@@ -153,11 +136,6 @@
if (ch == 'v') {
dumper->dump_vflag = ALL;
}
-#if ENABLE_FEATURE_HEXDUMP_REVERSE
- if (ch == 'R') {
- rdump = 1;
- }
-#endif
}
if (!dumper->fshead) {
@@ -167,40 +145,5 @@
argv += optind;
-#if !ENABLE_FEATURE_HEXDUMP_REVERSE
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
}
diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c
index f2d1ecb..d2f4b6e 100644
--- a/util-linux/hexdump_xxd.c
+++ b/util-linux/hexdump_xxd.c
@@ -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 -r Reverse (with -p, assumes no offsets in input)"
// TODO: implement -r (see hexdump -R)
#include "libbb.h"
@@ -57,6 +58,71 @@
/* 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 UNUSED_PARAM, char **argv)
{
@@ -69,11 +135,7 @@
dumper = alloc_dumper();
-#define OPT_l (1 << 0)
-#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 = getopt32(argv, "^" "l:s:aprg:+c:+" "\0" "?1" /* 1 argument max */,
&opt_l, &opt_s, &bytes, &cols
);
argv += optind;
@@ -107,6 +169,10 @@
bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: "
}
+ if (opt & OPT_r) {
+ reverse(opt, cols, argv[0]);
+ }
+
if (bytes < 1 || bytes >= cols) {
sprintf(buf, "%u/1 \"%%02x\"", cols); // cols * "xx"
bb_dump_add(dumper, buf);