changeset 36149:a01518333597 v9.1.0732

patch 9.1.0732: xxd: cannot use -b and -i together Commit: https://github.com/vim/vim/commit/150227258d3f44b91cf21f527e4778f6cc38b160 Author: Andre Chang <andre@augmentcode.com> Date: Sun Sep 15 20:03:05 2024 +0200 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>
author Christian Brabandt <cb@256bit.org>
date Sun, 15 Sep 2024 20:15:02 +0200
parents 15e88eae39bd
children e0d9e1d23e79
files runtime/doc/xxd.1 runtime/doc/xxd.man src/testdir/test_xxd.vim src/version.c src/xxd/xxd.c
diffstat 5 files changed, 95 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/xxd.1
+++ b/runtime/doc/xxd.1
@@ -63,8 +63,8 @@ Toggle autoskip: A single '*' replaces N
 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 an
 .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
--- a/runtime/doc/xxd.man
+++ b/runtime/doc/xxd.man
@@ -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
 
--- a/src/testdir/test_xxd.vim
+++ b/src/testdir/test_xxd.vim
@@ -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')
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    732,
+/**/
     731,
 /**/
     730,
--- a/src/xxd/xxd.c
+++ b/src/xxd/xxd.c
@@ -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);