From fc46efd3f2d95920bf50832848515b14b12c0723 Mon Sep 17 00:00:00 2001 From: Michael Ennen Date: Thu, 15 Dec 2016 13:53:14 -0700 Subject: vim-patch:7.4.2072 Problem: substitute() does not support a Funcref argument. Solution: Support a Funcref like it supports a string starting with "\=". https://github.com/vim/vim/commit/72ab729c3dcdea0fba44d8e676602c847e841bcd --- src/nvim/regexp.c | 131 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 100 insertions(+), 31 deletions(-) (limited to 'src/nvim/regexp.c') diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 6613d284d7..09fafcb37e 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -6442,32 +6442,71 @@ static linenr_T submatch_firstlnum; static linenr_T submatch_maxline; static int submatch_line_lbr; -/* - * vim_regsub() - perform substitutions after a vim_regexec() or - * vim_regexec_multi() match. - * - * If "copy" is TRUE really copy into "dest". - * If "copy" is FALSE nothing is copied, this is just to find out the length - * of the result. - * - * If "backslash" is TRUE, a backslash will be removed later, need to double - * them to keep them, and insert a backslash before a CR to avoid it being - * replaced with a line break later. - * - * Note: The matched text must not change between the call of - * vim_regexec()/vim_regexec_multi() and vim_regsub()! It would make the back - * references invalid! - * - * Returns the size of the replacement, including terminating NUL. - */ -int vim_regsub(regmatch_T *rmp, char_u *source, char_u *dest, int copy, int magic, int backslash) +/// Put the submatches in "argv[0]" which is a list passed into call_func() by +/// vim_regsub_both(). +static int fill_submatch_list(int argc UNUSED, typval_T *argv, int argcount) { + listitem_T *li; + int i; + char_u *s; + + if (argcount == 0) { + // called function doesn't take an argument + return 0; + } + + // Relies on sl_list to be the first item in staticList10_T. + init_static_list((staticList10_T *)(argv->vval.v_list)); + + // There are always 10 list items in staticList10_T. + li = argv->vval.v_list->lv_first; + for (i = 0; i < 10; i++) { + s = submatch_match->startp[i]; + if (s == NULL || submatch_match->endp[i] == NULL) { + s = NULL; + } else { + s = vim_strnsave(s, (int)(submatch_match->endp[i] - s)); + } + li->li_tv.v_type = VAR_STRING; + li->li_tv.vval.v_string = s; + li = li->li_next; + } + return 1; +} + +static void clear_submatch_list(staticList10_T *sl) +{ + int i; + + for (i = 0; i < 10; i++) { + xfree(sl->sl_items[i].li_tv.vval.v_string); + } +} + +/// vim_regsub() - perform substitutions after a vim_regexec() or +/// vim_regexec_multi() match. +/// +/// If "copy" is TRUE really copy into "dest". +/// If "copy" is FALSE nothing is copied, this is just to find out the length +/// of the result. +/// +/// If "backslash" is TRUE, a backslash will be removed later, need to double +/// them to keep them, and insert a backslash before a CR to avoid it being +/// replaced with a line break later. +/// +/// Note: The matched text must not change between the call of +/// vim_regexec()/vim_regexec_multi() and vim_regsub()! It would make the back +/// references invalid! +/// +/// Returns the size of the replacement, including terminating NUL. +int vim_regsub(regmatch_T *rmp, char_u *source, typval_T *expr, char_u *dest, + int copy, int magic, int backslash) { reg_match = rmp; reg_mmatch = NULL; reg_maxline = 0; reg_buf = curbuf; - reg_line_lbr = TRUE; - return vim_regsub_both(source, dest, copy, magic, backslash); + reg_line_lbr = true; + return vim_regsub_both(source, expr, dest, copy, magic, backslash); } int vim_regsub_multi(regmmatch_T *rmp, linenr_T lnum, char_u *source, char_u *dest, int copy, int magic, int backslash) @@ -6477,11 +6516,12 @@ int vim_regsub_multi(regmmatch_T *rmp, linenr_T lnum, char_u *source, char_u *de reg_buf = curbuf; /* always works on the current buffer! */ 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); + reg_line_lbr = false; + return vim_regsub_both(source, NULL, dest, copy, magic, backslash); } -static int vim_regsub_both(char_u *source, char_u *dest, int copy, int magic, int backslash) +static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, + int copy, int magic, int backslash) { char_u *src; char_u *dst; @@ -6495,8 +6535,8 @@ static int vim_regsub_both(char_u *source, char_u *dest, int copy, int magic, in int len = 0; /* init for GCC */ static char_u *eval_result = NULL; - /* Be paranoid... */ - if (source == NULL || dest == NULL) { + // Be paranoid... + if ((source == NULL && expr == NULL) || dest == NULL) { EMSG(_(e_null)); return 0; } @@ -6508,9 +6548,9 @@ static int vim_regsub_both(char_u *source, char_u *dest, int copy, int magic, in /* * When the substitute part starts with "\=" evaluate it as an expression. */ - if (source[0] == '\\' && source[1] == '=' - && !can_f_submatch /* can't do this recursively */ - ) { + if (expr != NULL || (source[0] == '\\' && source[1] == '=' + && !can_f_submatch // can't do this recursively + )) { /* To make sure that the length doesn't change between checking the * length and copying the string, and to speed up things, the * resulting string is saved from the call with "copy" == FALSE to the @@ -6525,6 +6565,7 @@ static int vim_regsub_both(char_u *source, char_u *dest, int copy, int magic, in } else { win_T *save_reg_win; int save_ireg_ic; + bool prev_can_f_submatch = can_f_submatch; xfree(eval_result); @@ -6539,9 +6580,37 @@ static int vim_regsub_both(char_u *source, char_u *dest, int copy, int magic, in submatch_line_lbr = reg_line_lbr; save_reg_win = reg_win; save_ireg_ic = ireg_ic; - can_f_submatch = TRUE; + 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); + } - eval_result = eval_to_string(source + 2, NULL, TRUE); if (eval_result != NULL) { int had_backslash = FALSE; -- cgit From 7f4848aff47b7b2a85be5f83007846934ef9fd90 Mon Sep 17 00:00:00 2001 From: Michael Ennen Date: Thu, 15 Dec 2016 13:27:32 -0700 Subject: vim-patch:7.4.2090 Problem: Using submatch() in a lambda passed to substitute() is verbose. Solution: Use a static list and pass it as an optional argument to the function. Fix memory leak. https://github.com/vim/vim/commit/df48fb456fb6bf63d94cad9b302ff01d8ee8d311 --- src/nvim/regexp.c | 52 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 21 deletions(-) (limited to 'src/nvim/regexp.c') diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 09fafcb37e..5c6cee46a7 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -6444,7 +6444,7 @@ static int submatch_line_lbr; /// Put the submatches in "argv[0]" which is a list passed into call_func() by /// vim_regsub_both(). -static int fill_submatch_list(int argc UNUSED, typval_T *argv, int argcount) { +static int fill_submatch_list(int argc, typval_T *argv, int argcount) { listitem_T *li; int i; char_u *s; @@ -6545,16 +6545,13 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, src = source; dst = dest; - /* - * When the substitute part starts with "\=" evaluate it as an expression. - */ + // When the substitute part starts with "\=" evaluate it as an expression. if (expr != NULL || (source[0] == '\\' && source[1] == '=' - && !can_f_submatch // can't do this recursively - )) { - /* To make sure that the length doesn't change between checking the - * length and copying the string, and to speed up things, the - * resulting string is saved from the call with "copy" == FALSE to the - * call with "copy" == TRUE. */ + && !can_f_submatch)) { // can't do this recursively + // To make sure that the length doesn't change between checking the + // length and copying the string, and to speed up things, the + // resulting string is saved from the call with "copy" == FALSE to the + // call with "copy" == TRUE. if (copy) { if (eval_result != NULL) { STRCPY(dest, eval_result); @@ -6583,30 +6580,43 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, can_f_submatch = true; if (expr != NULL) { - typval_T argv[1]; + typval_T argv[2]; int dummy; char_u buf[NUMBUFLEN]; typval_T rettv; + staticList10_T matchList; 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); + } else { + argv[0].v_type = VAR_LIST; + argv[0].vval.v_list = &matchList.sl_list; + matchList.sl_list.lv_len = 0; + if (expr->v_type == VAR_FUNC) { + s = expr->vval.v_string; + call_func(s, (int)STRLEN(s), &rettv, 1, argv, + fill_submatch_list, 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, 1, argv, + fill_submatch_list, 0L, 0L, &dummy, + true, partial, NULL); + } + if (matchList.sl_list.lv_len > 0) { + // fill_submatch_list() was called. + clear_submatch_list(&matchList); + } } eval_result = get_tv_string_buf_chk(&rettv, buf); if (eval_result != NULL) { eval_result = vim_strsave(eval_result); } + clear_tv(&rettv); } else { eval_result = eval_to_string(source + 2, NULL, true); } -- cgit From 53fad45115d3ee438dfb537d99ccf3b021ebc6b7 Mon Sep 17 00:00:00 2001 From: Michael Ennen Date: Fri, 16 Dec 2016 14:51:49 -0700 Subject: vim-patch:7.4.2137 Problem: Using function() with a name will find another function when it is redefined. Solution: Add funcref(). Refer to lambda using a partial. Fix several reference counting issues. https://github.com/vim/vim/commit/437bafe4c8a83ed71ee006eda7f54b65a90f0d4c --- src/nvim/regexp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/regexp.c') diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 5c6cee46a7..269e21936c 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -6602,7 +6602,7 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, } else if (expr->v_type == VAR_PARTIAL) { partial_T *partial = expr->vval.v_partial; - s = partial->pt_name; + s = partial_name(partial); call_func(s, (int)STRLEN(s), &rettv, 1, argv, fill_submatch_list, 0L, 0L, &dummy, true, partial, NULL); -- cgit From ef8701610baa18ecf2568990eab4ecf02ca8f6c1 Mon Sep 17 00:00:00 2001 From: Michael Ennen Date: Mon, 19 Dec 2016 20:09:07 -0700 Subject: Allow lambdas to be used with jobs, timers and dictwatchers. --- src/nvim/regexp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/regexp.c') diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 269e21936c..1cd334abcd 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -6444,7 +6444,8 @@ static int submatch_line_lbr; /// Put the submatches in "argv[0]" which is a list passed into call_func() by /// vim_regsub_both(). -static int fill_submatch_list(int argc, typval_T *argv, int argcount) { +static int fill_submatch_list(int argc, typval_T *argv, int argcount) +{ listitem_T *li; int i; char_u *s; -- cgit