0
0
mirror of https://github.com/vim/vim.git synced 2025-10-05 05:34:07 -04:00

patch 7.4.2221

Problem:    printf() does not support binary format.
Solution:   Add %b and %B. (Ozaki Kiichi)
This commit is contained in:
Bram Moolenaar
2016-08-16 21:58:41 +02:00
parent e5a8f35b42
commit 91984b9034
4 changed files with 75 additions and 14 deletions

View File

@@ -5884,6 +5884,7 @@ printf({fmt}, {expr1} ...) *printf()*
%04x hex number padded with zeros to at least 4 characters %04x hex number padded with zeros to at least 4 characters
%X hex number using upper case letters %X hex number using upper case letters
%o octal number %o octal number
%08b binary number padded with zeros to at least 8 chars
%f floating point number in the form 123.456 %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
%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 character of the output string to a zero (except
if a zero value is printed with an explicit if a zero value is printed with an explicit
precision of zero). 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 For x and X conversions, a non-zero result has
the string "0x" (or "0X" for X conversions) the string "0x" (or "0X" for X conversions)
prepended to it. prepended to it.
@@ -5917,8 +5921,8 @@ printf({fmt}, {expr1} ...) *printf()*
0 (zero) Zero padding. For all conversions the converted 0 (zero) Zero padding. For all conversions the converted
value is padded on the left with zeros rather value is padded on the left with zeros rather
than blanks. If a precision is given with a than blanks. If a precision is given with a
numeric conversion (d, o, x, and X), the 0 flag numeric conversion (d, b, B, o, x, and X), the 0
is ignored. flag is ignored.
- A negative field width flag; the converted value - A negative field width flag; the converted value
is to be left adjusted on the field boundary. is to be left adjusted on the field boundary.
@@ -5966,12 +5970,13 @@ printf({fmt}, {expr1} ...) *printf()*
The conversion specifiers and their meanings are: The conversion specifiers and their meanings are:
*printf-d* *printf-o* *printf-x* *printf-X* *printf-d* *printf-b* *printf-B* *printf-o*
doxX The Number argument is converted to signed decimal *printf-x* *printf-X*
(d), unsigned octal (o), or unsigned hexadecimal (x dbBoxX The Number argument is converted to signed decimal
and X) notation. The letters "abcdef" are used for (d), unsigned binary (b and B), unsigned octal (o), or
x conversions; the letters "ABCDEF" are used for X unsigned hexadecimal (x and X) notation. The letters
conversions. "abcdef" are used for x conversions; the letters
"ABCDEF" are used for X conversions.
The precision, if any, gives the minimum number of The precision, if any, gives the minimum number of
digits that must appear; if the converted value digits that must appear; if the converted value
requires fewer digits, it is padded on the left with requires fewer digits, it is padded on the left with

View File

@@ -4091,12 +4091,14 @@ vim_vsnprintf(
char length_modifier = '\0'; char length_modifier = '\0';
/* temporary buffer for simple numeric->string conversion */ /* 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. # define TMP_LEN 350 /* On my system 1e308 is the biggest number possible.
* That sounds reasonable to use as the maximum * That sounds reasonable to use as the maximum
* printable. */ * printable. */
# elif defined(FEAT_NUM64)
# define TMP_LEN 66
# else # else
# define TMP_LEN 32 # define TMP_LEN 34
# endif # endif
char tmp[TMP_LEN]; char tmp[TMP_LEN];
@@ -4343,9 +4345,13 @@ vim_vsnprintf(
} }
break; 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 * imply the value is unsigned; d implies a signed
* value */ * value */
@@ -4370,6 +4376,9 @@ vim_vsnprintf(
uvarnumber_T ullong_arg = 0; uvarnumber_T ullong_arg = 0;
# endif # endif
/* only defined for b convertion */
uvarnumber_T bin_arg = 0;
/* pointer argument value -only defined for p /* pointer argument value -only defined for p
* conversion */ * conversion */
void *ptr_arg = NULL; void *ptr_arg = NULL;
@@ -4386,6 +4395,17 @@ vim_vsnprintf(
if (ptr_arg != NULL) if (ptr_arg != NULL)
arg_sign = 1; 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') else if (fmt_spec == 'd')
{ {
/* signed */ /* signed */
@@ -4492,7 +4512,8 @@ vim_vsnprintf(
else if (alternate_form) else if (alternate_form)
{ {
if (arg_sign != 0 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++] = '0';
tmp[str_arg_l++] = fmt_spec; tmp[str_arg_l++] = fmt_spec;
@@ -4508,7 +4529,7 @@ vim_vsnprintf(
{ {
/* When zero value is formatted with an explicit /* When zero value is formatted with an explicit
* precision 0, the resulting formatted string is * 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 else
{ {
@@ -4541,6 +4562,22 @@ vim_vsnprintf(
if (fmt_spec == 'p') if (fmt_spec == 'p')
str_arg_l += sprintf(tmp + str_arg_l, f, ptr_arg); 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') else if (fmt_spec == 'd')
{ {
/* signed */ /* signed */

View File

@@ -163,6 +163,23 @@ function Test_printf_spec_s()
call assert_equal(string(function('printf', ['%s'])), printf('%s', function('printf', ['%s']))) call assert_equal(string(function('printf', ['%s'])), printf('%s', function('printf', ['%s'])))
endfunc 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() func Test_substitute_expr()
let g:val = 'XXX' let g:val = 'XXX'
call assert_equal('XXX', substitute('yyy', 'y*', '\=g:val', '')) call assert_equal('XXX', substitute('yyy', 'y*', '\=g:val', ''))

View File

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