summaryrefslogtreecommitdiff
path: root/src/userfunc.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-09-04 15:40:36 +0100
committerBram Moolenaar <Bram@vim.org>2022-09-04 15:40:36 +0100
commit806a273f3c84ecd475913d901890bb1929be9a0a (patch)
tree7970b531379736fd2497f3a1acea0c400028db81 /src/userfunc.c
parentc1eb131c9eb38e00e08109f50e3e5337c072b71e (diff)
downloadvim-git-806a273f3c84ecd475913d901890bb1929be9a0a.tar.gz
patch 9.0.0379: cleaning up after writefile() is a hasslev9.0.0379
Problem: Cleaning up after writefile() is a hassle. Solution: Add the 'D' flag to defer deleting the written file. Very useful in tests.
Diffstat (limited to 'src/userfunc.c')
-rw-r--r--src/userfunc.c60
1 files changed, 43 insertions, 17 deletions
diff --git a/src/userfunc.c b/src/userfunc.c
index a22703101..9ac681f20 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -1728,6 +1728,7 @@ emsg_funcname(char *ermsg, char_u *name)
/*
* Get function arguments at "*arg" and advance it.
* Return them in "*argvars[MAX_FUNC_ARGS + 1]" and the count in "argcount".
+ * On failure FAIL is returned but the "argvars[argcount]" are still set.
*/
static int
get_func_arguments(
@@ -5570,9 +5571,6 @@ ex_defer_inner(char_u *name, char_u **arg, evalarg_T *evalarg)
{
typval_T argvars[MAX_FUNC_ARGS + 1]; // vars for arguments
int argcount = 0; // number of arguments found
- defer_T *dr;
- int ret = FAIL;
- char_u *saved_name;
if (current_funccal == NULL)
{
@@ -5580,23 +5578,51 @@ ex_defer_inner(char_u *name, char_u **arg, evalarg_T *evalarg)
return FAIL;
}
if (get_func_arguments(arg, evalarg, FALSE, argvars, &argcount) == FAIL)
- goto theend;
- saved_name = vim_strsave(name);
- if (saved_name == NULL)
- goto theend;
+ {
+ while (--argcount >= 0)
+ clear_tv(&argvars[argcount]);
+ return FAIL;
+ }
+ return add_defer(name, argcount, argvars);
+}
- if (current_funccal->fc_defer.ga_itemsize == 0)
- ga_init2(&current_funccal->fc_defer, sizeof(defer_T), 10);
- if (ga_grow(&current_funccal->fc_defer, 1) == FAIL)
+/*
+ * Add a deferred call for "name" with arguments "argvars[argcount]".
+ * Consumes "argvars[]".
+ * Caller must check that in_def_function() returns TRUE or current_funccal is
+ * not NULL.
+ * Returns OK or FAIL.
+ */
+ int
+add_defer(char_u *name, int argcount_arg, typval_T *argvars)
+{
+ char_u *saved_name = vim_strsave(name);
+ int argcount = argcount_arg;
+ defer_T *dr;
+ int ret = FAIL;
+
+ if (saved_name == NULL)
goto theend;
- dr = ((defer_T *)current_funccal->fc_defer.ga_data)
- + current_funccal->fc_defer.ga_len++;
- dr->dr_name = saved_name;
- dr->dr_argcount = argcount;
- while (argcount > 0)
+ if (in_def_function())
+ {
+ if (add_defer_function(saved_name, argcount, argvars) == OK)
+ argcount = 0;
+ }
+ else
{
- --argcount;
- dr->dr_argvars[argcount] = argvars[argcount];
+ if (current_funccal->fc_defer.ga_itemsize == 0)
+ ga_init2(&current_funccal->fc_defer, sizeof(defer_T), 10);
+ if (ga_grow(&current_funccal->fc_defer, 1) == FAIL)
+ goto theend;
+ dr = ((defer_T *)current_funccal->fc_defer.ga_data)
+ + current_funccal->fc_defer.ga_len++;
+ dr->dr_name = saved_name;
+ dr->dr_argcount = argcount;
+ while (argcount > 0)
+ {
+ --argcount;
+ dr->dr_argvars[argcount] = argvars[argcount];
+ }
}
ret = OK;