forked from aniani/vim
patch 7.4.2221
Problem: printf() does not support binary format. Solution: Add %b and %B. (Ozaki Kiichi)
This commit is contained in:
@@ -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
|
||||||
|
@@ -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 */
|
||||||
|
@@ -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', ''))
|
||||||
|
@@ -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,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user