Patch 7.4.2072
Problem:    substitute() does not support a Funcref argument.
Solution:   Support a Funcref like it supports  a string starting with "\=".
Files:      src/evalfunc.c, src/regexp.c, src/eval.c, src/proto/eval.pro,
            src/proto/regexp.pro, src/testdir/test_expr.vim


*** ../vim-7.4.2071/src/evalfunc.c      2016-07-19 17:25:19.082023340 +0200
--- src/evalfunc.c      2016-07-19 17:39:59.700759367 +0200
***************
*** 11061,11074 ****
  
      char_u    *str = get_tv_string_chk(&argvars[0]);
      char_u    *pat = get_tv_string_buf_chk(&argvars[1], patbuf);
!     char_u    *sub = get_tv_string_buf_chk(&argvars[2], subbuf);
      char_u    *flg = get_tv_string_buf_chk(&argvars[3], flagsbuf);
  
      rettv->v_type = VAR_STRING;
!     if (str == NULL || pat == NULL || sub == NULL || flg == NULL)
        rettv->vval.v_string = NULL;
      else
!       rettv->vval.v_string = do_string_sub(str, pat, sub, flg);
  }
  
  /*
--- 11061,11081 ----
  
      char_u    *str = get_tv_string_chk(&argvars[0]);
      char_u    *pat = get_tv_string_buf_chk(&argvars[1], patbuf);
!     char_u    *sub = NULL;
!     typval_T  *expr = NULL;
      char_u    *flg = get_tv_string_buf_chk(&argvars[3], flagsbuf);
  
+     if (argvars[2].v_type == VAR_FUNC || argvars[2].v_type == VAR_PARTIAL)
+       expr = &argvars[2];
+     else
+       sub = get_tv_string_buf_chk(&argvars[2], subbuf);
+ 
      rettv->v_type = VAR_STRING;
!     if (str == NULL || pat == NULL || (sub == NULL && expr == NULL)
!                                                               || flg == NULL)
        rettv->vval.v_string = NULL;
      else
!       rettv->vval.v_string = do_string_sub(str, pat, sub, expr, flg);
  }
  
  /*
*** ../vim-7.4.2071/src/regexp.c        2016-04-26 21:39:08.227018806 +0200
--- src/regexp.c        2016-07-19 18:01:30.251218469 +0200
***************
*** 7169,7175 ****
  static fptr_T do_lower(int *, int);
  static fptr_T do_Lower(int *, int);
  
! static int vim_regsub_both(char_u *source, char_u *dest, int copy, int magic, 
int backslash);
  
      static fptr_T
  do_upper(int *d, int c)
--- 7169,7175 ----
  static fptr_T do_lower(int *, int);
  static fptr_T do_Lower(int *, int);
  
! static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, int 
copy, int magic, int backslash);
  
      static fptr_T
  do_upper(int *d, int c)
***************
*** 7312,7317 ****
--- 7312,7318 ----
  vim_regsub(
      regmatch_T        *rmp,
      char_u    *source,
+     typval_T  *expr,
      char_u    *dest,
      int               copy,
      int               magic,
***************
*** 7322,7328 ****
      reg_maxline = 0;
      reg_buf = curbuf;
      reg_line_lbr = TRUE;
!     return vim_regsub_both(source, dest, copy, magic, backslash);
  }
  #endif
  
--- 7323,7329 ----
      reg_maxline = 0;
      reg_buf = curbuf;
      reg_line_lbr = TRUE;
!     return vim_regsub_both(source, expr, dest, copy, magic, backslash);
  }
  #endif
  
***************
*** 7342,7353 ****
      reg_firstlnum = lnum;
      reg_maxline = curbuf->b_ml.ml_line_count - lnum;
      reg_line_lbr = FALSE;
!     return vim_regsub_both(source, dest, copy, magic, backslash);
  }
  
      static int
  vim_regsub_both(
      char_u    *source,
      char_u    *dest,
      int               copy,
      int               magic,
--- 7343,7355 ----
      reg_firstlnum = lnum;
      reg_maxline = curbuf->b_ml.ml_line_count - lnum;
      reg_line_lbr = FALSE;
!     return vim_regsub_both(source, NULL, dest, copy, magic, backslash);
  }
  
      static int
  vim_regsub_both(
      char_u    *source,
+     typval_T  *expr,
      char_u    *dest,
      int               copy,
      int               magic,
***************
*** 7364,7374 ****
      linenr_T  clnum = 0;      /* init for GCC */
      int               len = 0;        /* init for GCC */
  #ifdef FEAT_EVAL
!     static char_u *eval_result = NULL;
  #endif
  
      /* Be paranoid... */
!     if (source == NULL || dest == NULL)
      {
        EMSG(_(e_null));
        return 0;
--- 7366,7376 ----
      linenr_T  clnum = 0;      /* init for GCC */
      int               len = 0;        /* init for GCC */
  #ifdef FEAT_EVAL
!     static char_u   *eval_result = NULL;
  #endif
  
      /* Be paranoid... */
!     if ((source == NULL && expr == NULL) || dest == NULL)
      {
        EMSG(_(e_null));
        return 0;
***************
*** 7381,7391 ****
      /*
       * When the substitute part starts with "\=" evaluate it as an expression.
       */
!     if (source[0] == '\\' && source[1] == '='
  #ifdef FEAT_EVAL
            && !can_f_submatch      /* can't do this recursively */
  #endif
!           )
      {
  #ifdef FEAT_EVAL
        /* To make sure that the length doesn't change between checking the
--- 7383,7393 ----
      /*
       * When the substitute part starts with "\=" evaluate it as an expression.
       */
!     if (expr != NULL || (source[0] == '\\' && source[1] == '='
  #ifdef FEAT_EVAL
            && !can_f_submatch      /* can't do this recursively */
  #endif
!           ))
      {
  #ifdef FEAT_EVAL
        /* To make sure that the length doesn't change between checking the
***************
*** 7406,7411 ****
--- 7408,7414 ----
        {
            win_T       *save_reg_win;
            int         save_ireg_ic;
+           int         prev_can_f_submatch = can_f_submatch;
  
            vim_free(eval_result);
  
***************
*** 7422,7428 ****
            save_ireg_ic = ireg_ic;
            can_f_submatch = TRUE;
  
!           eval_result = eval_to_string(source + 2, NULL, TRUE);
            if (eval_result != NULL)
            {
                int had_backslash = FALSE;
--- 7425,7464 ----
            save_ireg_ic = ireg_ic;
            can_f_submatch = TRUE;
  
!           if (expr != NULL)
!           {
!               typval_T        argv[1];
!               int             dummy;
!               char_u          buf[NUMBUFLEN];
!               typval_T        rettv;
! 
!               rettv.v_type = VAR_STRING;
!               rettv.vval.v_string = NULL;
!               if (prev_can_f_submatch)
!               {
!                   /* can't do this recursively */
!               }
!               else if (expr->v_type == VAR_FUNC)
!               {
!                   s = expr->vval.v_string;
!                   call_func(s, (int)STRLEN(s), &rettv, 0, argv,
!                                            0L, 0L, &dummy, TRUE, NULL, NULL);
!               }
!               else if (expr->v_type == VAR_PARTIAL)
!               {
!                   partial_T   *partial = expr->vval.v_partial;
! 
!                   s = partial->pt_name;
!                   call_func(s, (int)STRLEN(s), &rettv, 0, argv,
!                                         0L, 0L, &dummy, TRUE, partial, NULL);
!               }
!               eval_result = get_tv_string_buf_chk(&rettv, buf);
!               if (eval_result != NULL)
!                   eval_result = vim_strsave(eval_result);
!           }
!           else
!               eval_result = eval_to_string(source + 2, NULL, TRUE);
! 
            if (eval_result != NULL)
            {
                int had_backslash = FALSE;
*** ../vim-7.4.2071/src/eval.c  2016-07-19 17:25:19.078023383 +0200
--- src/eval.c  2016-07-19 17:42:57.118896673 +0200
***************
*** 9769,9775 ****
                        if (sub != NULL && str != NULL)
                        {
                            *usedlen = (int)(p + 1 - src);
!                           s = do_string_sub(str, pat, sub, flags);
                            if (s != NULL)
                            {
                                *fnamep = s;
--- 9769,9775 ----
                        if (sub != NULL && str != NULL)
                        {
                            *usedlen = (int)(p + 1 - src);
!                           s = do_string_sub(str, pat, sub, NULL, flags);
                            if (s != NULL)
                            {
                                *fnamep = s;
***************
*** 9813,9818 ****
--- 9813,9819 ----
  
  /*
   * Perform a substitution on "str" with pattern "pat" and substitute "sub".
+  * When "sub" is NULL "expr" is used, must be a VAR_FUNC or VAR_PARTIAL.
   * "flags" can be "g" to do a global substitute.
   * Returns an allocated string, NULL for error.
   */
***************
*** 9821,9826 ****
--- 9822,9828 ----
      char_u    *str,
      char_u    *pat,
      char_u    *sub,
+     typval_T  *expr,
      char_u    *flags)
  {
      int               sublen;
***************
*** 9873,9879 ****
             * - The substituted text.
             * - The text after the match.
             */
!           sublen = vim_regsub(&regmatch, sub, tail, FALSE, TRUE, FALSE);
            if (ga_grow(&ga, (int)((end - tail) + sublen -
                            (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
            {
--- 9875,9881 ----
             * - The substituted text.
             * - The text after the match.
             */
!           sublen = vim_regsub(&regmatch, sub, expr, tail, FALSE, TRUE, FALSE);
            if (ga_grow(&ga, (int)((end - tail) + sublen -
                            (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
            {
***************
*** 9885,9891 ****
            i = (int)(regmatch.startp[0] - tail);
            mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
            /* add the substituted text */
!           (void)vim_regsub(&regmatch, sub, (char_u *)ga.ga_data
                                          + ga.ga_len + i, TRUE, TRUE, FALSE);
            ga.ga_len += i + sublen - 1;
            tail = regmatch.endp[0];
--- 9887,9893 ----
            i = (int)(regmatch.startp[0] - tail);
            mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
            /* add the substituted text */
!           (void)vim_regsub(&regmatch, sub, expr, (char_u *)ga.ga_data
                                          + ga.ga_len + i, TRUE, TRUE, FALSE);
            ga.ga_len += i + sublen - 1;
            tail = regmatch.endp[0];
***************
*** 9906,9912 ****
      if (p_cpo == empty_option)
        p_cpo = save_cpo;
      else
!       /* Darn, evaluating {sub} expression changed the value. */
        free_string_option(save_cpo);
  
      return ret;
--- 9908,9914 ----
      if (p_cpo == empty_option)
        p_cpo = save_cpo;
      else
!       /* Darn, evaluating {sub} expression or {expr} changed the value. */
        free_string_option(save_cpo);
  
      return ret;
*** ../vim-7.4.2071/src/proto/eval.pro  2016-07-17 22:13:26.817095253 +0200
--- src/proto/eval.pro  2016-07-19 17:45:37.957209022 +0200
***************
*** 126,131 ****
  void assert_fails(typval_T *argvars);
  void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_str, 
typval_T *exp_tv, typval_T *got_tv, assert_type_T atype);
  int modify_fname(char_u *src, int *usedlen, char_u **fnamep, char_u **bufp, 
int *fnamelen);
! char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, char_u *flags);
  void filter_map(typval_T *argvars, typval_T *rettv, int map);
  /* vim: set ft=c : */
--- 126,131 ----
  void assert_fails(typval_T *argvars);
  void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_str, 
typval_T *exp_tv, typval_T *got_tv, assert_type_T atype);
  int modify_fname(char_u *src, int *usedlen, char_u **fnamep, char_u **bufp, 
int *fnamelen);
! char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, typval_T *expr, 
char_u *flags);
  void filter_map(typval_T *argvars, typval_T *rettv, int map);
  /* vim: set ft=c : */
*** ../vim-7.4.2071/src/proto/regexp.pro        2016-01-19 13:21:55.845334290 
+0100
--- src/proto/regexp.pro        2016-07-19 18:01:53.570973761 +0200
***************
*** 7,13 ****
  reg_extmatch_T *ref_extmatch(reg_extmatch_T *em);
  void unref_extmatch(reg_extmatch_T *em);
  char_u *regtilde(char_u *source, int magic);
! int vim_regsub(regmatch_T *rmp, char_u *source, char_u *dest, int copy, int 
magic, int backslash);
  int vim_regsub_multi(regmmatch_T *rmp, linenr_T lnum, char_u *source, char_u 
*dest, int copy, int magic, int backslash);
  char_u *reg_submatch(int no);
  list_T *reg_submatch_list(int no);
--- 7,13 ----
  reg_extmatch_T *ref_extmatch(reg_extmatch_T *em);
  void unref_extmatch(reg_extmatch_T *em);
  char_u *regtilde(char_u *source, int magic);
! int vim_regsub(regmatch_T *rmp, char_u *source, typval_T *expr, char_u *dest, 
int copy, int magic, int backslash);
  int vim_regsub_multi(regmmatch_T *rmp, linenr_T lnum, char_u *source, char_u 
*dest, int copy, int magic, int backslash);
  char_u *reg_submatch(int no);
  list_T *reg_submatch_list(int no);
*** ../vim-7.4.2071/src/testdir/test_expr.vim   2016-07-12 21:11:28.711223556 
+0200
--- src/testdir/test_expr.vim   2016-07-19 19:00:18.070614811 +0200
***************
*** 135,137 ****
--- 135,155 ----
      call assert_equal("123456789012345", printf('%d', 123456789012345))
    endif
  endfunc
+ 
+ func Test_substitute_expr()
+   let g:val = 'XXX'
+   call assert_equal('XXX', substitute('yyy', 'y*', '\=g:val', ''))
+   call assert_equal('XXX', substitute('yyy', 'y*', {-> g:val}, ''))
+   call assert_equal("-\u1b \uf2-", substitute("-%1b %f2-", '%\(\x\x\)',
+                          \ '\=nr2char("0x" . submatch(1))', 'g'))
+   call assert_equal("-\u1b \uf2-", substitute("-%1b %f2-", '%\(\x\x\)',
+                          \ {-> nr2char("0x" . submatch(1))}, 'g'))
+ 
+   call assert_equal('231', substitute('123', '\(.\)\(.\)\(.\)',
+       \ {-> submatch(2) . submatch(3) . submatch(1)}, ''))
+ 
+   func Recurse()
+     return substitute('yyy', 'y*', {-> g:val}, '')
+   endfunc
+   call assert_equal('--', substitute('xxx', 'x*', {-> '-' . Recurse() . '-'}, 
''))
+ endfunc
*** ../vim-7.4.2071/src/version.c       2016-07-19 17:25:19.082023340 +0200
--- src/version.c       2016-07-19 18:11:40.232821362 +0200
***************
*** 760,761 ****
--- 760,763 ----
  {   /* Add new patch number below this line */
+ /**/
+     2072,
  /**/

-- 
A mathematician is a device for turning coffee into theorems.
                                        Paul Erdos
A computer programmer is a device for turning coffee into bugs.
                                        Bram Moolenaar

 /// 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