diff options
Diffstat (limited to 'src/userfunc.c')
-rw-r--r-- | src/userfunc.c | 68 |
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 |