aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/regexp.c
diff options
context:
space:
mode:
authorMichael Ennen <mike.ennen@gmail.com>2016-12-15 13:27:32 -0700
committerMichael Ennen <mike.ennen@gmail.com>2017-02-14 17:38:17 -0700
commit7f4848aff47b7b2a85be5f83007846934ef9fd90 (patch)
tree3214b1b634132ecdb03a6a338d6c9dab174c775c /src/nvim/regexp.c
parenta0ce66371096db21f341f061df8c1b7b4d9e38fe (diff)
downloadrneovim-7f4848aff47b7b2a85be5f83007846934ef9fd90.tar.gz
rneovim-7f4848aff47b7b2a85be5f83007846934ef9fd90.tar.bz2
rneovim-7f4848aff47b7b2a85be5f83007846934ef9fd90.zip
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
Diffstat (limited to 'src/nvim/regexp.c')
-rw-r--r--src/nvim/regexp.c52
1 files changed, 31 insertions, 21 deletions
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);
}