patch 9.1.0732: xxd: cannot use -b and -i together

Problem:  xxd: cannot use -b and -i together
          (Irgendwer)
Solution: implement the missing changes
          (Andre Chang)

fixes: #15362
closes: #15661

Signed-off-by: Andre Chang <andre@augmentcode.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Andre Chang
2024-09-15 20:03:05 +02:00
committed by Christian Brabandt
parent 5e95c8f637
commit 150227258d
5 changed files with 95 additions and 50 deletions

View File

@ -63,8 +63,8 @@ Toggle autoskip: A single '*' replaces NUL-lines. Default off.
Switch to bits (binary digits) dump, rather than hex dump.
This option writes octets as eight digits "1"s and "0"s instead of a normal
hexadecimal dump. Each line is preceded by a line number in hexadecimal and
followed by an ASCII (or EBCDIC) representation. The command line switches
\-p, \-i do not work with this mode.
followed by an ASCII (or EBCDIC) representation. The command line switch
\-p does not work with this mode. Can be combined with \-i.
.TP
.IR "\-c cols " | " \-cols cols"
Format
@ -109,7 +109,8 @@ Print a summary of available commands and exit. No hex dumping is performed.
.TP
.IR \-i " | " \-include
Output in C include file style. A complete static array definition is written
(named after the input file), unless xxd reads from stdin.
(named after the input file), unless xxd reads from stdin. Can be combined
with \-b.
.TP
.IR "\-l len " | " \-len len"
Stop after writing

View File

@ -1,7 +1,5 @@
XXD(1) General Commands Manual XXD(1)
NAME
xxd - make a hex dump or do the reverse.
@ -23,9 +21,9 @@ OPTIONS
outfile is given (or a `-' character is in its place), results are sent
to standard output.
Note that a "lazy" parser is used which does not check for more than
the first option letter, unless the option is followed by a parameter.
Spaces between a single option letter and its parameter are optional.
Note that a "lazy" parser is used which does not check for more than
the first option letter, unless the option is followed by a parameter.
Spaces between a single option letter and its parameter are optional.
Parameters to options can be specified in decimal, hexadecimal or octal
notation. Thus -c8, -c 8, -c 010 and -cols 8 are all equivalent.
@ -34,19 +32,19 @@ OPTIONS
-b | -bits
Switch to bits (binary digits) dump, rather than hex dump. This
option writes octets as eight digits "1"s and "0"s instead of a
normal hexadecimal dump. Each line is preceded by a line number
in hexadecimal and followed by an ASCII (or EBCDIC) representa
tion. The command line switches -p, -i do not work with this
mode.
option writes octets as eight digits "1"s and "0"s instead of a
normal hexadecimal dump. Each line is preceded by a line number
in hexadecimal and followed by an ASCII (or EBCDIC) representa
tion. The command line switch -p does not work with this mode.
Can be combined with -i.
-c cols | -cols cols
Format <cols> octets per line. Default 16 (-i: 12, -ps: 30, -b:
6). Max 256. No maximum for -ps. With -ps, 0 results in one
Format <cols> octets per line. Default 16 (-i: 12, -ps: 30, -b:
6). Max 256. No maximum for -ps. With -ps, 0 results in one
long line of output.
-C | -capitalize
Capitalize variable names in C include file style, when using
Capitalize variable names in C include file style, when using
-i.
-d show offset in decimal instead of hex.
@ -56,46 +54,46 @@ OPTIONS
to EBCDIC. This does not change the hexadecimal representation.
The option is meaningless in combinations with -r, -p or -i.
-e Switch to little-endian hex dump. This option treats byte
-e Switch to little-endian hex dump. This option treats byte
groups as words in little-endian byte order. The default group
ing of 4 bytes may be changed using -g. This option only ap
plies to the hex dump, leaving the ASCII (or EBCDIC) representa
tion unchanged. The command line switches -r, -p, -i do not
tion unchanged. The command line switches -r, -p, -i do not
work with this mode.
-g bytes | -groupsize bytes
Separate the output of every <bytes> bytes (two hex characters
Separate the output of every <bytes> bytes (two hex characters
or eight bit digits each) by a whitespace. Specify -g 0 to sup
press grouping. <Bytes> defaults to 2 in normal mode, 4 in lit
tle-endian mode and 1 in bits mode. Grouping does not apply to
tle-endian mode and 1 in bits mode. Grouping does not apply to
PostScript or include style.
-h | -help
Print a summary of available commands and exit. No hex dumping
Print a summary of available commands and exit. No hex dumping
is performed.
-i | -include
Output in C include file style. A complete static array defini
tion is written (named after the input file), unless xxd reads
from stdin.
Output in C include file style. A complete static array defini
tion is written (named after the input file), unless xxd reads
from stdin. Can be combined with -b.
-l len | -len len
Stop after writing <len> octets.
-n name | -name name
Override the variable name output when -i is used. The array is
Override the variable name output when -i is used. The array is
named name and the length is named name_len.
-o offset
Add <offset> to the displayed file position.
-p | -ps | -postscript | -plain
Output in PostScript continuous hex dump style. Also known as
Output in PostScript continuous hex dump style. Also known as
plain hex dump style.
-r | -revert
Reverse operation: convert (or patch) hex dump into binary. If
not writing to stdout, xxd writes into its output file without
Reverse operation: convert (or patch) hex dump into binary. If
not writing to stdout, xxd writes into its output file without
truncating it. Use the combination -r -p to read plain hexadeci
mal dumps without line number information and without a particu
lar column layout. Additional whitespace and line breaks are al
@ -117,7 +115,7 @@ OPTIONS
Start at <seek> bytes abs. (or rel.) infile offset. + indicates
that the seek is relative to the current stdin file position
(meaningless when not reading from stdin). - indicates that the
seek should be that many characters from the end of the input
seek should be that many characters from the end of the input
(or if combined with +: before the current stdin file position).
Without -s option, xxd starts at the current file position.
@ -140,7 +138,7 @@ CAVEATS
input line after reading enough columns of hexadecimal data (see option
-c). This also means that changes to the printable ASCII (or EBCDIC)
columns are always ignored. Reverting a plain (or PostScript) style hex
dump with xxd -r -p does not depend on the correct number of columns.
dump with xxd -r -p does not depend on the correct number of columns.
Here, anything that looks like a pair of hex digits is interpreted.
Note the difference between
@ -148,7 +146,7 @@ CAVEATS
and
% xxd -i < file
xxd -s +seek may be different from xxd -s seek, as lseek(2) is used to
xxd -s +seek may be different from xxd -s seek, as lseek(2) is used to
"rewind" input. A '+' makes a difference if the input source is stdin,
and if stdin's file position is not at the start of the file by the
time xxd is started and given its input. The following examples may
@ -161,7 +159,7 @@ CAVEATS
Hex dump from file position 0x480 (=1024+128) onwards. The `+' sign
means "relative to the current position", thus the `128' adds to the 1k
where dd left off.
% sh -c "dd of=plain_snippet bs=1k count=1; xxd -s +128 > hex_snippet"
% sh -c "dd of=plain_snippet bs=1k count=1; xxd -s +128 > hex_snippet"
< file
Hex dump from file position 0x100 (=1024-768) onwards.
@ -179,7 +177,7 @@ EXAMPLES
Print 3 lines (hex 0x30 bytes) from the end of file.
% xxd -s -0x30 file
Note: The results of the examples below are relevant to the xxd.1 man
Note: The results of the examples below are relevant to the xxd.1 man
page as of May 2024
Print 120 bytes as a continuous hex dump with 20 octets per line.
@ -216,7 +214,7 @@ EXAMPLES
% xxd -s 0x33 -l 13 -c 13 xxd.1
00000033: 3235 7468 204d 6179 2031 3939 36 25th May 1996
Create a 65537 byte file with all bytes 0x00, except for the last one
Create a 65537 byte file with all bytes 0x00, except for the last one
which is 'A' (hex 0x41).
% echo "010000: 41" | xxd -r > file

View File

@ -269,6 +269,23 @@ func Test_xxd()
endfor
" Test 19: Print C include in binary format
let s:test += 1
call writefile(['TESTabcd09'], 'XXDfile')
%d
exe '0r! ' . s:xxd_cmd . ' -i -b XXDfile'
$d
let expected =<< trim [CODE]
unsigned char XXDfile[] = {
0b01010100, 0b01000101, 0b01010011, 0b01010100, 0b01100001, 0b01100010,
0b01100011, 0b01100100, 0b00110000, 0b00111001, 0b00001010
};
unsigned int XXDfile_len = 11;
[CODE]
call assert_equal(expected, getline(1,'$'), s:Mess(s:test))
%d
bwipe!
call delete('XXDfile')

View File

@ -704,6 +704,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
732,
/**/
731,
/**/

View File

@ -63,6 +63,7 @@
* 25.01.2024 revert the previous patch (size_t instead of unsigned int)
* 10.02.2024 fix buffer-overflow when writing color output to buffer, #14003
* 10.05.2024 fix another buffer-overflow when writing colored output to buffer, #14738
* 10.09.2024 Support -b and -i together, #15661
*
* (c) 1990-1998 by Juergen Weigert (jnweiger@gmail.com)
*
@ -143,7 +144,7 @@ extern void perror __P((char *));
# endif
#endif
char version[] = "xxd 2024-05-10 by Juergen Weigert et al.";
char version[] = "xxd 2024-09-15 by Juergen Weigert et al.";
#ifdef WIN32
char osver[] = " (Win32)";
#else
@ -220,11 +221,11 @@ char osver[] = "";
char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;
/* the different hextypes known by this program: */
#define HEX_NORMAL 0
#define HEX_POSTSCRIPT 1
#define HEX_CINCLUDE 2
#define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */
#define HEX_LITTLEENDIAN 4
#define HEX_NORMAL 0x00 /* no flags set */
#define HEX_POSTSCRIPT 0x01
#define HEX_CINCLUDE 0x02
#define HEX_BITS 0x04 /* not hex a dump, but bits: 01111001 */
#define HEX_LITTLEENDIAN 0x08
#define CONDITIONAL_CAPITALIZE(c) (capitalize ? toupper((unsigned char)(c)) : (c))
@ -255,7 +256,7 @@ exit_with_usage(void)
fprintf(stderr, " or\n %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname);
fprintf(stderr, "Options:\n");
fprintf(stderr, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
fprintf(stderr, " -b binary digit dump (incompatible with -ps,-i). Default hex.\n");
fprintf(stderr, " -b binary digit dump (incompatible with -ps). Default hex.\n");
fprintf(stderr, " -C capitalize variable names in C include file style (-i).\n");
fprintf(stderr, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n");
@ -692,11 +693,11 @@ main(int argc, char *argv[])
{
pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
else if (!STRNCMP(pp, "-e", 2)) hextype = HEX_LITTLEENDIAN;
else if (!STRNCMP(pp, "-b", 2)) hextype |= HEX_BITS;
else if (!STRNCMP(pp, "-e", 2)) hextype |= HEX_LITTLEENDIAN;
else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
else if (!STRNCMP(pp, "-p", 2)) hextype |= HEX_POSTSCRIPT;
else if (!STRNCMP(pp, "-i", 2)) hextype |= HEX_CINCLUDE;
else if (!STRNCMP(pp, "-C", 2)) capitalize = 1;
else if (!STRNCMP(pp, "-d", 2)) decimal_offset = 1;
else if (!STRNCMP(pp, "-r", 2)) revert++;
@ -856,11 +857,19 @@ main(int argc, char *argv[])
argc--;
}
if (hextype != (HEX_CINCLUDE | HEX_BITS))
{
/* Allow at most one bit to be set in hextype */
if (hextype & (hextype - 1))
error_exit(1, "only one of -b, -e, -u, -p, -i can be used");
}
if (!colsgiven || (!cols && hextype != HEX_POSTSCRIPT))
switch (hextype)
{
case HEX_POSTSCRIPT: cols = 30; break;
case HEX_CINCLUDE: cols = 12; break;
case HEX_CINCLUDE | HEX_BITS:
case HEX_BITS: cols = 6; break;
case HEX_NORMAL:
case HEX_LITTLEENDIAN:
@ -870,6 +879,7 @@ main(int argc, char *argv[])
if (octspergrp < 0)
switch (hextype)
{
case HEX_CINCLUDE | HEX_BITS:
case HEX_BITS: octspergrp = 1; break;
case HEX_NORMAL: octspergrp = 2; break;
case HEX_LITTLEENDIAN: octspergrp = 4; break;
@ -966,7 +976,7 @@ main(int argc, char *argv[])
}
}
if (hextype == HEX_CINCLUDE)
if (hextype & HEX_CINCLUDE)
{
/* A user-set variable name overrides fp == stdin */
if (varname == NULL && fp != stdin)
@ -982,11 +992,28 @@ main(int argc, char *argv[])
p = 0;
while ((length < 0 || p < length) && (c = getc_or_die(fp)) != EOF)
{
FPRINTF_OR_DIE((fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
{
if (hextype & HEX_BITS)
{
if (p == 0)
fputs_or_die(" ", fpo);
else if (p % cols == 0)
fputs_or_die(",\n ", fpo);
else
fputs_or_die(", ", fpo);
FPRINTF_OR_DIE((fpo, "0b"));
for (int j = 7; j >= 0; j--)
putc_or_die((c & (1 << j)) ? '1' : '0', fpo);
p++;
}
else
{
FPRINTF_OR_DIE((fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
(p % cols) ? ", " : (!p ? " " : ",\n "), c));
p++;
}
p++;
}
}
if (p)
fputs_or_die("\n", fpo);