mirror of
https://github.com/vim/vim.git
synced 2025-09-27 04:14:06 -04:00
patch 7.4.2220
Problem: printf() gives an error when the argument for %s is not a string. (Ozaki Kiichi) Solution: Behave like invoking string() on the argument. (Ken Takata)
This commit is contained in:
@@ -3887,7 +3887,7 @@ do_browse(
|
|||||||
static char *e_printf = N_("E766: Insufficient arguments for printf()");
|
static char *e_printf = N_("E766: Insufficient arguments for printf()");
|
||||||
|
|
||||||
static varnumber_T tv_nr(typval_T *tvs, int *idxp);
|
static varnumber_T tv_nr(typval_T *tvs, int *idxp);
|
||||||
static char *tv_str(typval_T *tvs, int *idxp);
|
static char *tv_str(typval_T *tvs, int *idxp, char_u **tofree);
|
||||||
# ifdef FEAT_FLOAT
|
# ifdef FEAT_FLOAT
|
||||||
static double tv_float(typval_T *tvs, int *idxp);
|
static double tv_float(typval_T *tvs, int *idxp);
|
||||||
# endif
|
# endif
|
||||||
@@ -3916,19 +3916,27 @@ tv_nr(typval_T *tvs, int *idxp)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Get string argument from "idxp" entry in "tvs". First entry is 1.
|
* Get string argument from "idxp" entry in "tvs". First entry is 1.
|
||||||
|
* If "tofree" is NULL get_tv_string_chk() is used. Some types (e.g. List)
|
||||||
|
* are not converted to a string.
|
||||||
|
* If "tofree" is not NULL echo_string() is used. All types are converted to
|
||||||
|
* a string with the same format as ":echo". The caller must free "*tofree".
|
||||||
* Returns NULL for an error.
|
* Returns NULL for an error.
|
||||||
*/
|
*/
|
||||||
static char *
|
static char *
|
||||||
tv_str(typval_T *tvs, int *idxp)
|
tv_str(typval_T *tvs, int *idxp, char_u **tofree)
|
||||||
{
|
{
|
||||||
int idx = *idxp - 1;
|
int idx = *idxp - 1;
|
||||||
char *s = NULL;
|
char *s = NULL;
|
||||||
|
static char_u numbuf[NUMBUFLEN];
|
||||||
|
|
||||||
if (tvs[idx].v_type == VAR_UNKNOWN)
|
if (tvs[idx].v_type == VAR_UNKNOWN)
|
||||||
EMSG(_(e_printf));
|
EMSG(_(e_printf));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
++*idxp;
|
++*idxp;
|
||||||
|
if (tofree != NULL)
|
||||||
|
s = (char *)echo_string(&tvs[idx], tofree, numbuf, get_copyID());
|
||||||
|
else
|
||||||
s = (char *)get_tv_string_chk(&tvs[idx]);
|
s = (char *)get_tv_string_chk(&tvs[idx]);
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
@@ -4113,6 +4121,10 @@ vim_vsnprintf(
|
|||||||
/* current conversion specifier character */
|
/* current conversion specifier character */
|
||||||
char fmt_spec = '\0';
|
char fmt_spec = '\0';
|
||||||
|
|
||||||
|
/* buffer for 's' and 'S' specs */
|
||||||
|
char_u *tofree = NULL;
|
||||||
|
|
||||||
|
|
||||||
str_arg = NULL;
|
str_arg = NULL;
|
||||||
p++; /* skip '%' */
|
p++; /* skip '%' */
|
||||||
|
|
||||||
@@ -4276,7 +4288,7 @@ vim_vsnprintf(
|
|||||||
case 'S':
|
case 'S':
|
||||||
str_arg =
|
str_arg =
|
||||||
# if defined(FEAT_EVAL)
|
# if defined(FEAT_EVAL)
|
||||||
tvs != NULL ? tv_str(tvs, &arg_idx) :
|
tvs != NULL ? tv_str(tvs, &arg_idx, &tofree) :
|
||||||
# endif
|
# endif
|
||||||
va_arg(ap, char *);
|
va_arg(ap, char *);
|
||||||
if (str_arg == NULL)
|
if (str_arg == NULL)
|
||||||
@@ -4367,7 +4379,8 @@ vim_vsnprintf(
|
|||||||
length_modifier = '\0';
|
length_modifier = '\0';
|
||||||
ptr_arg =
|
ptr_arg =
|
||||||
# if defined(FEAT_EVAL)
|
# if defined(FEAT_EVAL)
|
||||||
tvs != NULL ? (void *)tv_str(tvs, &arg_idx) :
|
tvs != NULL ? (void *)tv_str(tvs, &arg_idx,
|
||||||
|
NULL) :
|
||||||
# endif
|
# endif
|
||||||
va_arg(ap, void *);
|
va_arg(ap, void *);
|
||||||
if (ptr_arg != NULL)
|
if (ptr_arg != NULL)
|
||||||
@@ -4877,6 +4890,7 @@ vim_vsnprintf(
|
|||||||
str_l += pn;
|
str_l += pn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
vim_free(tofree);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -136,6 +136,33 @@ function Test_printf_64bit()
|
|||||||
endif
|
endif
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
function Test_printf_spec_s()
|
||||||
|
" number
|
||||||
|
call assert_equal("1234567890", printf('%s', 1234567890))
|
||||||
|
|
||||||
|
" string
|
||||||
|
call assert_equal("abcdefgi", printf('%s', "abcdefgi"))
|
||||||
|
|
||||||
|
" float
|
||||||
|
if has('float')
|
||||||
|
call assert_equal("1.23", printf('%s', 1.23))
|
||||||
|
endif
|
||||||
|
|
||||||
|
" list
|
||||||
|
let value = [1, 'two', ['three', 4]]
|
||||||
|
call assert_equal(string(value), printf('%s', value))
|
||||||
|
|
||||||
|
" dict
|
||||||
|
let value = {'key1' : 'value1', 'key2' : ['list', 'value'], 'key3' : {'dict' : 'value'}}
|
||||||
|
call assert_equal(string(value), printf('%s', value))
|
||||||
|
|
||||||
|
" funcref
|
||||||
|
call assert_equal('printf', printf('%s', function('printf')))
|
||||||
|
|
||||||
|
" partial
|
||||||
|
call assert_equal(string(function('printf', ['%s'])), printf('%s', function('printf', ['%s'])))
|
||||||
|
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 */
|
||||||
|
/**/
|
||||||
|
2220,
|
||||||
/**/
|
/**/
|
||||||
2219,
|
2219,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user