Patch 9.0.0476

5 views
Skip to first unread message

Bram Moolenaar

unread,
Sep 16, 2022, 7:11:09 AM9/16/22
to vim...@googlegroups.com

Patch 9.0.0476
Problem: Varargs does not work for replacement function of substitute().
Solution: Check the varargs flag of the function. (closes #11142)
Files: src/regexp.c, src/structs.h, src/userfunc.c,
src/testdir/test_substitute.vim


*** ../vim-9.0.0475/src/regexp.c 2022-08-26 21:33:00.662738976 +0100
--- src/regexp.c 2022-09-16 12:07:49.350014550 +0100
***************
*** 1817,1830 ****
* call_func() by vim_regsub_both().
*/
static int
! fill_submatch_list(int argc UNUSED, typval_T *argv, int argskip, int argcount)
{
listitem_T *li;
int i;
char_u *s;
typval_T *listarg = argv + argskip;

! if (argcount == argskip)
// called function doesn't take a submatches argument
return argskip;

--- 1817,1830 ----
* call_func() by vim_regsub_both().
*/
static int
! fill_submatch_list(int argc UNUSED, typval_T *argv, int argskip, ufunc_T *fp)
{
listitem_T *li;
int i;
char_u *s;
typval_T *listarg = argv + argskip;

! if (!fp->uf_varargs && fp->uf_args.ga_len <= argskip)
// called function doesn't take a submatches argument
return argskip;

*** ../vim-9.0.0475/src/structs.h 2022-09-14 00:30:47.077316538 +0100
--- src/structs.h 2022-09-16 11:49:45.861095933 +0100
***************
*** 2052,2064 ****

// Struct passed between functions dealing with function call execution.
//
! // "argv_func", when not NULL, can be used to fill in arguments only when the
// invoked function uses them. It is called like this:
! // new_argcount = argv_func(current_argcount, argv, partial_argcount,
! // called_func_argcount)
//
typedef struct {
! int (* fe_argv_func)(int, typval_T *, int, int);
linenr_T fe_firstline; // first line of range
linenr_T fe_lastline; // last line of range
int *fe_doesrange; // if not NULL: return: function handled range
--- 2052,2064 ----

// Struct passed between functions dealing with function call execution.
//
! // "fe_argv_func", when not NULL, can be used to fill in arguments only when the
// invoked function uses them. It is called like this:
! // new_argcount = fe_argv_func(current_argcount, argv, partial_argcount,
! // called_func)
//
typedef struct {
! int (* fe_argv_func)(int, typval_T *, int, ufunc_T *);
linenr_T fe_firstline; // first line of range
linenr_T fe_lastline; // last line of range
int *fe_doesrange; // if not NULL: return: function handled range
*** ../vim-9.0.0475/src/userfunc.c 2022-09-08 19:51:39.730308347 +0100
--- src/userfunc.c 2022-09-16 11:49:45.865095884 +0100
***************
*** 3644,3650 ****
if (funcexe->fe_argv_func != NULL)
// postponed filling in the arguments, do it now
argcount = funcexe->fe_argv_func(argcount, argvars,
! argv_clear, fp->uf_args.ga_len);

if (funcexe->fe_basetv != NULL)
{
--- 3644,3650 ----
if (funcexe->fe_argv_func != NULL)
// postponed filling in the arguments, do it now
argcount = funcexe->fe_argv_func(argcount, argvars,
! argv_clear, fp);

if (funcexe->fe_basetv != NULL)
{
*** ../vim-9.0.0475/src/testdir/test_substitute.vim 2022-09-13 13:45:09.802461528 +0100
--- src/testdir/test_substitute.vim 2022-09-16 12:07:15.798145387 +0100
***************
*** 439,458 ****
func SubReplacer(text, submatches)
return a:text .. a:submatches[0] .. a:text
endfunc
func SubReplacer20(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, submatches)
return a:t3 .. a:submatches[0] .. a:t11
endfunc

func Test_substitute_partial()
! call assert_equal('1foo2foo3', substitute('123', '2', function('SubReplacer', ['foo']), 'g'))

! " 19 arguments plus one is just OK
! let Replacer = function('SubReplacer20', repeat(['foo'], 19))
! call assert_equal('1foo2foo3', substitute('123', '2', Replacer, 'g'))

! " 20 arguments plus one is too many
! let Replacer = function('SubReplacer20', repeat(['foo'], 20))
! call assert_fails("call substitute('123', '2', Replacer, 'g')", 'E118:')
endfunc

func Test_substitute_float()
--- 439,462 ----
func SubReplacer(text, submatches)
return a:text .. a:submatches[0] .. a:text
endfunc
+ func SubReplacerVar(text, ...)
+ return a:text .. a:1[0] .. a:text
+ endfunc
func SubReplacer20(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, submatches)
return a:t3 .. a:submatches[0] .. a:t11
endfunc

func Test_substitute_partial()
! call assert_equal('1foo2foo3', substitute('123', '2', function('SubReplacer', ['foo']), 'g'))
! call assert_equal('1foo2foo3', substitute('123', '2', function('SubReplacerVar', ['foo']), 'g'))

! " 19 arguments plus one is just OK
! let Replacer = function('SubReplacer20', repeat(['foo'], 19))
! call assert_equal('1foo2foo3', substitute('123', '2', Replacer, 'g'))

! " 20 arguments plus one is too many
! let Replacer = function('SubReplacer20', repeat(['foo'], 20))
! call assert_fails("call substitute('123', '2', Replacer, 'g')", 'E118:')
endfunc

func Test_substitute_float()
*** ../vim-9.0.0475/src/version.c 2022-09-15 22:26:13.166294520 +0100
--- src/version.c 2022-09-16 12:09:09.205712508 +0100
***************
*** 705,706 ****
--- 705,708 ----
{ /* Add new patch number below this line */
+ /**/
+ 476,
/**/

--
From "know your smileys":
:~) A man with a tape recorder up his nose

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
Reply all
Reply to author
Forward
0 new messages