]> granicus.if.org Git - vim/commitdiff
patch 7.4.2220 v7.4.2220
authorBram Moolenaar <Bram@vim.org>
Tue, 16 Aug 2016 19:30:54 +0000 (21:30 +0200)
committerBram Moolenaar <Bram@vim.org>
Tue, 16 Aug 2016 19:30:54 +0000 (21:30 +0200)
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)

src/message.c
src/testdir/test_expr.vim
src/version.c

index b4d7b65e6727667094ad3acca00cdd7655ddc961..513f2888da8752885f39a92bae165427936f1019 100644 (file)
@@ -3887,7 +3887,7 @@ do_browse(
 static char *e_printf = N_("E766: Insufficient arguments for printf()");
 
 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
 static double tv_float(typval_T *tvs, int *idxp);
 # endif
@@ -3916,20 +3916,28 @@ tv_nr(typval_T *tvs, int *idxp)
 
 /*
  * 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.
  */
     static char *
-tv_str(typval_T *tvs, int *idxp)
+tv_str(typval_T *tvs, int *idxp, char_u **tofree)
 {
-    int                idx = *idxp - 1;
-    char       *s = NULL;
+    int                    idx = *idxp - 1;
+    char           *s = NULL;
+    static char_u   numbuf[NUMBUFLEN];
 
     if (tvs[idx].v_type == VAR_UNKNOWN)
        EMSG(_(e_printf));
     else
     {
        ++*idxp;
-       s = (char *)get_tv_string_chk(&tvs[idx]);
+       if (tofree != NULL)
+           s = (char *)echo_string(&tvs[idx], tofree, numbuf, get_copyID());
+       else
+           s = (char *)get_tv_string_chk(&tvs[idx]);
     }
     return s;
 }
@@ -4113,6 +4121,10 @@ vim_vsnprintf(
            /* current conversion specifier character */
            char    fmt_spec = '\0';
 
+           /* buffer for 's' and 'S' specs */
+           char_u  *tofree = NULL;
+
+
            str_arg = NULL;
            p++;  /* skip '%' */
 
@@ -4276,7 +4288,7 @@ vim_vsnprintf(
                case 'S':
                    str_arg =
 # if defined(FEAT_EVAL)
-                               tvs != NULL ? tv_str(tvs, &arg_idx) :
+                               tvs != NULL ? tv_str(tvs, &arg_idx, &tofree) :
 # endif
                                    va_arg(ap, char *);
                    if (str_arg == NULL)
@@ -4367,7 +4379,8 @@ vim_vsnprintf(
                        length_modifier = '\0';
                        ptr_arg =
 # if defined(FEAT_EVAL)
-                                tvs != NULL ? (void *)tv_str(tvs, &arg_idx) :
+                                tvs != NULL ? (void *)tv_str(tvs, &arg_idx,
+                                                                       NULL) :
 # endif
                                        va_arg(ap, void *);
                        if (ptr_arg != NULL)
@@ -4877,6 +4890,7 @@ vim_vsnprintf(
                    str_l += pn;
                }
            }
+           vim_free(tofree);
        }
     }
 
index cd71c419a1f8b7242c40365ef1f8eb18df47c939..e8358540318c7abc2cb05c390de9cded30ff416a 100644 (file)
@@ -136,6 +136,33 @@ function Test_printf_64bit()
   endif
 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()
   let g:val = 'XXX'
   call assert_equal('XXX', substitute('yyy', 'y*', '\=g:val', ''))
index 505231fec68ebb5ad6c8282c727909e9c6267c4e..bb933d2bd6820275870bef509e9854089ceebc09 100644 (file)
@@ -763,6 +763,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2220,
 /**/
     2219,
 /**/