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)
Files:      runtime/doc/eval.txt, src/message.c, src/testdir/test_expr.vim


*** ../vim-7.4.2219/runtime/doc/eval.txt        2016-08-15 22:16:21.557888355 
+0200
--- runtime/doc/eval.txt        2016-08-16 21:22:55.590093669 +0200
***************
*** 5960,5965 ****
--- 5989,5998 ----
                s       The text of the String argument is used.  If a
                        precision is specified, no more bytes than the number
                        specified are used.
+                       If the argument is not a String type, it is
+                       automatically converted to text with the same format
+                       as ":echo".
+                                                       *printf-S*
                S       The text of the String argument is used.  If a
                        precision is specified, no more display cells than the
                        number specified are used.  Without the |+multi_byte|
*** ../vim-7.4.2219/src/message.c       2016-07-30 16:40:34.780374612 +0200
--- src/message.c       2016-08-16 21:22:55.590093669 +0200
***************
*** 3887,3893 ****
  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);
  # ifdef FEAT_FLOAT
  static double tv_float(typval_T *tvs, int *idxp);
  # endif
--- 3887,3893 ----
  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, char_u **tofree);
  # ifdef FEAT_FLOAT
  static double tv_float(typval_T *tvs, int *idxp);
  # endif
***************
*** 3916,3935 ****
  
  /*
   * Get string argument from "idxp" entry in "tvs".  First entry is 1.
   * Returns NULL for an error.
   */
      static char *
! tv_str(typval_T *tvs, int *idxp)
  {
!     int               idx = *idxp - 1;
!     char      *s = NULL;
  
      if (tvs[idx].v_type == VAR_UNKNOWN)
        EMSG(_(e_printf));
      else
      {
        ++*idxp;
!       s = (char *)get_tv_string_chk(&tvs[idx]);
      }
      return s;
  }
--- 3916,3943 ----
  
  /*
   * 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, char_u **tofree)
  {
!     int                   idx = *idxp - 1;
!     char          *s = NULL;
!     static char_u   numbuf[NUMBUFLEN];
  
      if (tvs[idx].v_type == VAR_UNKNOWN)
        EMSG(_(e_printf));
      else
      {
        ++*idxp;
!       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,4118 ****
--- 4121,4130 ----
            /* current conversion specifier character */
            char    fmt_spec = '\0';
  
+           /* buffer for 's' and 'S' specs */
+           char_u  *tofree = NULL;
+ 
+ 
            str_arg = NULL;
            p++;  /* skip '%' */
  
***************
*** 4276,4282 ****
                case 'S':
                    str_arg =
  # if defined(FEAT_EVAL)
!                               tvs != NULL ? tv_str(tvs, &arg_idx) :
  # endif
                                    va_arg(ap, char *);
                    if (str_arg == NULL)
--- 4288,4294 ----
                case 'S':
                    str_arg =
  # if defined(FEAT_EVAL)
!                               tvs != NULL ? tv_str(tvs, &arg_idx, &tofree) :
  # endif
                                    va_arg(ap, char *);
                    if (str_arg == NULL)
***************
*** 4367,4373 ****
                        length_modifier = '\0';
                        ptr_arg =
  # if defined(FEAT_EVAL)
!                                tvs != NULL ? (void *)tv_str(tvs, &arg_idx) :
  # endif
                                        va_arg(ap, void *);
                        if (ptr_arg != NULL)
--- 4379,4386 ----
                        length_modifier = '\0';
                        ptr_arg =
  # if defined(FEAT_EVAL)
!                                tvs != NULL ? (void *)tv_str(tvs, &arg_idx,
!                                                                       NULL) :
  # endif
                                        va_arg(ap, void *);
                        if (ptr_arg != NULL)
***************
*** 4877,4882 ****
--- 4890,4896 ----
                    str_l += pn;
                }
            }
+           vim_free(tofree);
        }
      }
  
*** ../vim-7.4.2219/src/testdir/test_expr.vim   2016-08-05 22:51:09.597156984 
+0200
--- src/testdir/test_expr.vim   2016-08-16 21:26:27.244199354 +0200
***************
*** 136,141 ****
--- 136,168 ----
    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', ''))
*** ../vim-7.4.2219/src/version.c       2016-08-16 21:04:37.827952367 +0200
--- src/version.c       2016-08-16 21:23:31.233775243 +0200
***************
*** 765,766 ****
--- 765,768 ----
  {   /* Add new patch number below this line */
+ /**/
+     2220,
  /**/

-- 
How To Keep A Healthy Level Of Insanity:
13. Go to a poetry recital and ask why the poems don't rhyme.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui