summaryrefslogtreecommitdiff
path: root/src/userfunc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/userfunc.c')
-rw-r--r--src/userfunc.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/userfunc.c b/src/userfunc.c
index 032c99cff..9ac3a4426 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -5516,6 +5516,74 @@ get_user_func_name(expand_T *xp, int idx)
}
/*
+ * Make a copy of a function.
+ * Intended to be used for a function defined on a base class that has a copy
+ * on the child class.
+ * The copy has uf_refcount set to one.
+ * Returns NULL when out of memory.
+ */
+ ufunc_T *
+copy_function(ufunc_T *fp)
+{
+ // The struct may have padding, make sure we allocate at least the size of
+ // the struct.
+ size_t len = offsetof(ufunc_T, uf_name) + STRLEN(fp->uf_name) + 1;
+ ufunc_T *ufunc = alloc_clear(len < sizeof(ufunc_T) ? sizeof(ufunc_T) : len);
+ if (ufunc == NULL)
+ return NULL;
+
+ // Most things can just be copied.
+ *ufunc = *fp;
+
+ ufunc->uf_def_status = UF_TO_BE_COMPILED;
+ ufunc->uf_dfunc_idx = 0;
+ ufunc->uf_class = NULL;
+
+ ga_copy_strings(&fp->uf_args, &ufunc->uf_args);
+ ga_copy_strings(&fp->uf_def_args, &ufunc->uf_def_args);
+
+ if (ufunc->uf_arg_types != NULL)
+ {
+ // "uf_arg_types" is an allocated array, make a copy.
+ type_T **at = ALLOC_CLEAR_MULT(type_T *, ufunc->uf_args.ga_len);
+ if (at != NULL)
+ {
+ mch_memmove(at, ufunc->uf_arg_types,
+ sizeof(type_T *) * ufunc->uf_args.ga_len);
+ ufunc->uf_arg_types = at;
+ }
+ }
+
+ // TODO: how about the types themselves? they can be freed when the
+ // original function is freed:
+ // type_T **uf_arg_types;
+ // type_T *uf_ret_type;
+
+ ufunc->uf_type_list.ga_len = 0;
+ ufunc->uf_type_list.ga_data = NULL;
+
+ // TODO: partial_T *uf_partial;
+
+ if (ufunc->uf_va_name != NULL)
+ ufunc->uf_va_name = vim_strsave(ufunc->uf_va_name);
+
+ // TODO:
+ // type_T *uf_va_type;
+ // type_T *uf_func_type;
+
+ ufunc->uf_block_depth = 0;
+ ufunc->uf_block_ids = NULL;
+
+ ga_copy_strings(&fp->uf_lines, &ufunc->uf_lines);
+
+ ufunc->uf_refcount = 1;
+ ufunc->uf_name_exp = NULL;
+ STRCPY(ufunc->uf_name, fp->uf_name);
+
+ return ufunc;
+}
+
+/*
* ":delfunction {name}"
*/
void