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:
		@@ -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 *const add_strings[] = {
 | 
			
		||||
 | 
			
		||||
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 @@ int hexdump_main(int argc, char **argv)
 | 
			
		||||
	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 @@ int hexdump_main(int argc, char **argv)
 | 
			
		||||
		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 @@ int hexdump_main(int argc, char **argv)
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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 @@ int xxd_main(int argc UNUSED_PARAM, char **argv)
 | 
			
		||||
 | 
			
		||||
	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 @@ int xxd_main(int argc UNUSED_PARAM, char **argv)
 | 
			
		||||
		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);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user