]> granicus.if.org Git - vim/commitdiff
patch 7.4.2221 v7.4.2221
authorBram Moolenaar <Bram@vim.org>
Tue, 16 Aug 2016 19:58:41 +0000 (21:58 +0200)
committerBram Moolenaar <Bram@vim.org>
Tue, 16 Aug 2016 19:58:41 +0000 (21:58 +0200)
Problem:    printf() does not support binary format.
Solution:   Add %b and %B. (Ozaki Kiichi)

runtime/doc/eval.txt
src/message.c
src/testdir/test_expr.vim
src/version.c

index f281f4aa81672f91fb0171d05f71d26faab86c7c..32d8dad52e56d4b5a4bd70a6f18e1e31ed0fd901 100644 (file)
@@ -5884,6 +5884,7 @@ printf({fmt}, {expr1} ...)                                *printf()*
                  %04x  hex number padded with zeros to at least 4 characters
                  %X    hex number using upper case letters
                  %o    octal number
+                 %08b  binary number padded with zeros to at least 8 chars
                  %f    floating point number in the form 123.456
                  %e    floating point number in the form 1.234e3
                  %E    floating point number in the form 1.234E3
@@ -5910,6 +5911,9 @@ printf({fmt}, {expr1} ...)                                *printf()*
                              character of the output string to a zero (except
                              if a zero value is printed with an explicit
                              precision of zero).
+                             For b and B conversions, a non-zero result has
+                             the string "0b" (or "0B" for B conversions)
+                             prepended to it.
                              For x and X conversions, a non-zero result has
                              the string "0x" (or "0X" for X conversions)
                              prepended to it.
@@ -5917,8 +5921,8 @@ printf({fmt}, {expr1} ...)                                *printf()*
                    0 (zero)  Zero padding.  For all conversions the converted
                              value is padded on the left with zeros rather
                              than blanks.  If a precision is given with a
-                             numeric conversion (d, o, x, and X), the 0 flag
-                             is ignored.
+                             numeric conversion (d, b, B, o, x, and X), the 0
+                             flag is ignored.
 
                    -         A negative field width flag; the converted value
                              is to be left adjusted on the field boundary.
@@ -5966,12 +5970,13 @@ printf({fmt}, {expr1} ...)                              *printf()*
 
                The conversion specifiers and their meanings are:
 
-                               *printf-d* *printf-o* *printf-x* *printf-X*
-               doxX    The Number argument is converted to signed decimal
-                       (d), unsigned octal (o), or unsigned hexadecimal (x
-                       and X) notation.  The letters "abcdef" are used for
-                       x conversions; the letters "ABCDEF" are used for X
-                       conversions.
+                               *printf-d* *printf-b* *printf-B* *printf-o*
+                               *printf-x* *printf-X*
+               dbBoxX  The Number argument is converted to signed decimal
+                       (d), unsigned binary (b and B), unsigned octal (o), or
+                       unsigned hexadecimal (x and X) notation.  The letters
+                       "abcdef" are used for x conversions; the letters
+                       "ABCDEF" are used for X conversions.
                        The precision, if any, gives the minimum number of
                        digits that must appear; if the converted value
                        requires fewer digits, it is padded on the left with
index 513f2888da8752885f39a92bae165427936f1019..a7398f6eb0e94dd4787d7af9536a40316a723c87 100644 (file)
@@ -4091,12 +4091,14 @@ vim_vsnprintf(
            char    length_modifier = '\0';
 
            /* temporary buffer for simple numeric->string conversion */
-# ifdef FEAT_FLOAT
+# if defined(FEAT_FLOAT)
 #  define TMP_LEN 350  /* On my system 1e308 is the biggest number possible.
                         * That sounds reasonable to use as the maximum
                         * printable. */
+# elif defined(FEAT_NUM64)
+#  define TMP_LEN 66
 # else
-#  define TMP_LEN 32
+#  define TMP_LEN 34
 # endif
            char    tmp[TMP_LEN];
 
@@ -4343,9 +4345,13 @@ vim_vsnprintf(
                }
                break;
 
-           case 'd': case 'u': case 'o': case 'x': case 'X': case 'p':
+           case 'd': case 'u':
+           case 'b': case 'B':
+           case 'o':
+           case 'x': case 'X':
+           case 'p':
                {
-                   /* NOTE: the u, o, x, X and p conversion specifiers
+                   /* NOTE: the u, b, o, x, X and p conversion specifiers
                     * imply the value is unsigned;  d implies a signed
                     * value */
 
@@ -4370,6 +4376,9 @@ vim_vsnprintf(
                    uvarnumber_T ullong_arg = 0;
 # endif
 
+                   /* only defined for b convertion */
+                   uvarnumber_T bin_arg = 0;
+
                    /* pointer argument value -only defined for p
                     * conversion */
                    void *ptr_arg = NULL;
@@ -4386,6 +4395,17 @@ vim_vsnprintf(
                        if (ptr_arg != NULL)
                            arg_sign = 1;
                    }
+                   else if (fmt_spec == 'b' || fmt_spec == 'B')
+                   {
+                       bin_arg =
+# if defined(FEAT_EVAL)
+                                   tvs != NULL ?
+                                          (uvarnumber_T)tv_nr(tvs, &arg_idx) :
+# endif
+                                       va_arg(ap, uvarnumber_T);
+                       if (bin_arg != 0)
+                           arg_sign = 1;
+                   }
                    else if (fmt_spec == 'd')
                    {
                        /* signed */
@@ -4492,7 +4512,8 @@ vim_vsnprintf(
                    else if (alternate_form)
                    {
                        if (arg_sign != 0
-                                    && (fmt_spec == 'x' || fmt_spec == 'X') )
+                                    && (fmt_spec == 'b' || fmt_spec == 'B'
+                                     || fmt_spec == 'x' || fmt_spec == 'X') )
                        {
                            tmp[str_arg_l++] = '0';
                            tmp[str_arg_l++] = fmt_spec;
@@ -4508,7 +4529,7 @@ vim_vsnprintf(
                    {
                        /* When zero value is formatted with an explicit
                         * precision 0, the resulting formatted string is
-                        * empty (d, i, u, o, x, X, p).   */
+                        * empty (d, i, u, b, B, o, x, X, p).   */
                    }
                    else
                    {
@@ -4541,6 +4562,22 @@ vim_vsnprintf(
 
                        if (fmt_spec == 'p')
                            str_arg_l += sprintf(tmp + str_arg_l, f, ptr_arg);
+                       else if (fmt_spec == 'b' || fmt_spec == 'B')
+                       {
+                           char            b[8 * sizeof(uvarnumber_T)];
+                           size_t          b_l = 0;
+                           uvarnumber_T    bn = bin_arg;
+
+                           do
+                           {
+                               b[sizeof(b) - ++b_l] = '0' + (bn & 0x1);
+                               bn >>= 1;
+                           }
+                           while (bn != 0);
+
+                           memcpy(tmp + str_arg_l, b + sizeof(b) - b_l, b_l);
+                           str_arg_l += b_l;
+                       }
                        else if (fmt_spec == 'd')
                        {
                            /* signed */
index e8358540318c7abc2cb05c390de9cded30ff416a..a7ad65eef4d8c719f20b05f7ce4c1c06e5d5f191 100644 (file)
@@ -163,6 +163,23 @@ function Test_printf_spec_s()
   call assert_equal(string(function('printf', ['%s'])), printf('%s', function('printf', ['%s'])))
 endfunc
 
+function Test_printf_spec_b()
+  call assert_equal("0", printf('%b', 0))
+  call assert_equal("00001100", printf('%08b', 12))
+  call assert_equal("11111111", printf('%08b', 0xff))
+  call assert_equal("   1111011", printf('%10b', 123))
+  call assert_equal("0001111011", printf('%010b', 123))
+  call assert_equal(" 0b1111011", printf('%#10b', 123))
+  call assert_equal("0B01111011", printf('%#010B', 123))
+  call assert_equal("1001001100101100000001011010010", printf('%b', 1234567890))
+  if has('num64')
+    call assert_equal("11100000100100010000110000011011101111101111001", printf('%b', 123456789012345))
+    call assert_equal("1111111111111111111111111111111111111111111111111111111111111111", printf('%b', -1))
+  else
+    call assert_equal("11111111111111111111111111111111", printf('%b', -1))
+  endif
+endfunc
+
 func Test_substitute_expr()
   let g:val = 'XXX'
   call assert_equal('XXX', substitute('yyy', 'y*', '\=g:val', ''))
index bb933d2bd6820275870bef509e9854089ceebc09..0395201c69d343372f4e43ca948b9ec7adab7b8d 100644 (file)
@@ -763,6 +763,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2221,
 /**/
     2220,
 /**/