Mercurial > vim
diff src/userfunc.c @ 27022:eebbcc83fb75 v8.2.4040
patch 8.2.4040: keeping track of allocated lines is too complicated
Commit: https://github.com/vim/vim/commit/9f1a39a5d1cd7989ada2d1cb32f97d84360e050f
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Jan 8 15:39:39 2022 +0000
patch 8.2.4040: keeping track of allocated lines is too complicated
Problem: Keeping track of allocated lines in user functions is too
complicated.
Solution: Instead of freeing individual lines keep them all until the end.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 08 Jan 2022 16:45:02 +0100 |
parents | 268f6a3511df |
children | c9474ae175f4 |
line wrap: on
line diff
--- a/src/userfunc.c +++ b/src/userfunc.c @@ -166,13 +166,13 @@ one_function_arg( /* * Handle line continuation in function arguments or body. - * Get a next line, store it in "eap" if appropriate and use "line_to_free" to - * handle freeing the line later. + * Get a next line, store it in "eap" if appropriate and put the line in + * "lines_to_free" to free the line later. */ static char_u * get_function_line( exarg_T *eap, - char_u **line_to_free, + garray_T *lines_to_free, int indent, getline_opt_T getline_options) { @@ -184,10 +184,11 @@ get_function_line( theline = eap->getline(':', eap->cookie, indent, getline_options); if (theline != NULL) { - if (*eap->cmdlinep == *line_to_free) + if (lines_to_free->ga_len > 0 + && *eap->cmdlinep == ((char_u **)lines_to_free->ga_data) + [lines_to_free->ga_len - 1]) *eap->cmdlinep = theline; - vim_free(*line_to_free); - *line_to_free = theline; + ga_add_string(lines_to_free, theline); } return theline; @@ -210,7 +211,7 @@ get_function_args( garray_T *default_args, int skip, exarg_T *eap, - char_u **line_to_free) + garray_T *lines_to_free) { int mustend = FALSE; char_u *arg; @@ -241,7 +242,7 @@ get_function_args( && (*p == NUL || (VIM_ISWHITE(*whitep) && *p == '#'))) { // End of the line, get the next one. - char_u *theline = get_function_line(eap, line_to_free, 0, + char_u *theline = get_function_line(eap, lines_to_free, 0, GETLINE_CONCAT_CONT); if (theline == NULL) @@ -677,7 +678,7 @@ get_function_body( exarg_T *eap, garray_T *newlines, char_u *line_arg_in, - char_u **line_to_free) + garray_T *lines_to_free) { linenr_T sourcing_lnum_top = SOURCING_LNUM; linenr_T sourcing_lnum_off; @@ -744,7 +745,7 @@ get_function_body( } else { - theline = get_function_line(eap, line_to_free, indent, + theline = get_function_line(eap, lines_to_free, indent, getline_options); } if (KeyTyped) @@ -854,14 +855,20 @@ get_function_body( { // Another command follows. If the line came from "eap" // we can simply point into it, otherwise we need to - // change "eap->cmdlinep". + // change "eap->cmdlinep" to point to the last fetched + // line. eap->nextcmd = nextcmd; - if (*line_to_free != NULL - && *eap->cmdlinep != *line_to_free) + if (lines_to_free->ga_len > 0 + && *eap->cmdlinep != + ((char_u **)lines_to_free->ga_data) + [lines_to_free->ga_len - 1]) { + // *cmdlinep will be freed later, thus remove the + // line from lines_to_free. vim_free(*eap->cmdlinep); - *eap->cmdlinep = *line_to_free; - *line_to_free = NULL; + *eap->cmdlinep = ((char_u **)lines_to_free->ga_data) + [lines_to_free->ga_len - 1]; + --lines_to_free->ga_len; } } break; @@ -1118,7 +1125,6 @@ lambda_function_body( garray_T newlines; char_u *cmdline = NULL; int ret = FAIL; - char_u *line_to_free = NULL; partial_T *pt; char_u *name; int lnum_save = -1; @@ -1144,12 +1150,9 @@ lambda_function_body( } ga_init2(&newlines, (int)sizeof(char_u *), 10); - if (get_function_body(&eap, &newlines, NULL, &line_to_free) == FAIL) - { - if (cmdline != line_to_free) - vim_free(cmdline); + if (get_function_body(&eap, &newlines, NULL, + &evalarg->eval_tofree_ga) == FAIL) goto erret; - } // When inside a lambda must add the function lines to evalarg.eval_ga. evalarg->eval_break_count += newlines.ga_len; @@ -1208,8 +1211,6 @@ lambda_function_body( { ((char_u **)(tfgap->ga_data))[tfgap->ga_len++] = cmdline; evalarg->eval_using_cmdline = TRUE; - if (cmdline == line_to_free) - line_to_free = NULL; } } else @@ -1278,7 +1279,6 @@ lambda_function_body( erret: if (lnum_save >= 0) SOURCING_LNUM = lnum_save; - vim_free(line_to_free); ga_clear_strings(&newlines); if (newargs != NULL) ga_clear_strings(newargs); @@ -3957,10 +3957,11 @@ list_functions(regmatch_T *regmatch) * ":function" also supporting nested ":def". * When "name_arg" is not NULL this is a nested function, using "name_arg" for * the function name. + * "lines_to_free" is a list of strings to be freed later. * Returns a pointer to the function or NULL if no function defined. */ ufunc_T * -define_function(exarg_T *eap, char_u *name_arg, char_u **line_to_free) +define_function(exarg_T *eap, char_u *name_arg, garray_T *lines_to_free) { int j; int c; @@ -4229,7 +4230,7 @@ define_function(exarg_T *eap, char_u *na if (get_function_args(&p, ')', &newargs, eap->cmdidx == CMD_def ? &argtypes : NULL, FALSE, NULL, &varargs, &default_args, eap->skip, - eap, line_to_free) == FAIL) + eap, lines_to_free) == FAIL) goto errret_2; whitep = p; @@ -4339,7 +4340,7 @@ define_function(exarg_T *eap, char_u *na // Do not define the function when getting the body fails and when // skipping. - if (get_function_body(eap, &newlines, line_arg, line_to_free) == FAIL + if (get_function_body(eap, &newlines, line_arg, lines_to_free) == FAIL || eap->skip) goto erret; @@ -4645,10 +4646,11 @@ ret_free: void ex_function(exarg_T *eap) { - char_u *line_to_free = NULL; - - (void)define_function(eap, NULL, &line_to_free); - vim_free(line_to_free); + garray_T lines_to_free; + + ga_init2(&lines_to_free, sizeof(char_u *), 50); + (void)define_function(eap, NULL, &lines_to_free); + ga_clear_strings(&lines_to_free); } /*