|
|
|
@ -171,9 +171,13 @@ one_function_arg(
|
|
|
|
|
if (!skip)
|
|
|
|
|
{
|
|
|
|
|
if (type == NULL && types_optional)
|
|
|
|
|
{
|
|
|
|
|
// lambda arguments default to "any" type
|
|
|
|
|
type = vim_strsave((char_u *)
|
|
|
|
|
(is_vararg ? "list<any>" : "any"));
|
|
|
|
|
if (is_vararg)
|
|
|
|
|
type = vim_strnsave((char_u *)"list<any>", 9);
|
|
|
|
|
else
|
|
|
|
|
type = vim_strnsave((char_u *)"any", 3);
|
|
|
|
|
}
|
|
|
|
|
((char_u **)argtypes->ga_data)[argtypes->ga_len++] = type;
|
|
|
|
|
((int8_T *)arg_objm->ga_data)[arg_objm->ga_len++] = FALSE;
|
|
|
|
|
}
|
|
|
|
@ -346,7 +350,7 @@ get_function_args(
|
|
|
|
|
if (ga_grow(default_args, 1) == FAIL)
|
|
|
|
|
goto err_ret;
|
|
|
|
|
|
|
|
|
|
char_u *expr = vim_strsave((char_u *)"v:none");
|
|
|
|
|
char_u *expr = vim_strnsave((char_u *)"v:none", 6);
|
|
|
|
|
if (expr == NULL)
|
|
|
|
|
goto err_ret;
|
|
|
|
|
((char_u **)(default_args->ga_data))
|
|
|
|
@ -373,7 +377,7 @@ get_function_args(
|
|
|
|
|
{
|
|
|
|
|
// TODO: use the actual type
|
|
|
|
|
((char_u **)argtypes->ga_data)[argtypes->ga_len++] =
|
|
|
|
|
vim_strsave((char_u *)"any");
|
|
|
|
|
vim_strnsave((char_u *)"any", 3);
|
|
|
|
|
((int8_T *)arg_objm->ga_data)[arg_objm->ga_len++] = TRUE;
|
|
|
|
|
|
|
|
|
|
// Add a line to the function body for the assignment.
|
|
|
|
@ -656,24 +660,6 @@ register_closure(ufunc_T *fp)
|
|
|
|
|
return OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
set_ufunc_name(ufunc_T *fp, char_u *name)
|
|
|
|
|
{
|
|
|
|
|
// Add a type cast to avoid a warning for an overflow, the uf_name[] array
|
|
|
|
|
// actually extends beyond the struct.
|
|
|
|
|
STRCPY((void *)fp->uf_name, name);
|
|
|
|
|
|
|
|
|
|
if (name[0] == K_SPECIAL)
|
|
|
|
|
{
|
|
|
|
|
fp->uf_name_exp = alloc(STRLEN(name) + 3);
|
|
|
|
|
if (fp->uf_name_exp != NULL)
|
|
|
|
|
{
|
|
|
|
|
STRCPY(fp->uf_name_exp, "<SNR>");
|
|
|
|
|
STRCAT(fp->uf_name_exp, fp->uf_name + 3);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If "name" starts with K_SPECIAL and "buf[bufsize]" is big enough
|
|
|
|
|
* return "buf" filled with a readable function name.
|
|
|
|
@ -699,14 +685,34 @@ make_ufunc_name_readable(char_u *name, char_u *buf, size_t bufsize)
|
|
|
|
|
/*
|
|
|
|
|
* Get a name for a lambda. Returned in static memory.
|
|
|
|
|
*/
|
|
|
|
|
static char_u lambda_name[8 + NUMBUFLEN];
|
|
|
|
|
static size_t lambda_namelen = 0;
|
|
|
|
|
|
|
|
|
|
char_u *
|
|
|
|
|
get_lambda_name(void)
|
|
|
|
|
{
|
|
|
|
|
static char_u name[30];
|
|
|
|
|
static int lambda_no = 0;
|
|
|
|
|
static int lambda_no = 0;
|
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
sprintf((char*)name, "<lambda>%d", ++lambda_no);
|
|
|
|
|
return name;
|
|
|
|
|
n = vim_snprintf((char *)lambda_name, sizeof(lambda_name), "<lambda>%d", ++lambda_no);
|
|
|
|
|
if (n < 1)
|
|
|
|
|
lambda_namelen = 0;
|
|
|
|
|
else
|
|
|
|
|
if (n >= (int)sizeof(lambda_name))
|
|
|
|
|
lambda_namelen = sizeof(lambda_name) - 1;
|
|
|
|
|
else
|
|
|
|
|
lambda_namelen = (size_t)n;
|
|
|
|
|
|
|
|
|
|
return lambda_name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Get the length of the last lambda name.
|
|
|
|
|
*/
|
|
|
|
|
size_t
|
|
|
|
|
get_lambda_name_len(void)
|
|
|
|
|
{
|
|
|
|
|
return lambda_namelen;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -714,12 +720,32 @@ get_lambda_name(void)
|
|
|
|
|
* Makes sure the size is right.
|
|
|
|
|
*/
|
|
|
|
|
static ufunc_T *
|
|
|
|
|
alloc_ufunc(char_u *name)
|
|
|
|
|
alloc_ufunc(char_u *name, size_t namelen)
|
|
|
|
|
{
|
|
|
|
|
size_t len;
|
|
|
|
|
ufunc_T *fp;
|
|
|
|
|
|
|
|
|
|
// When the name is short we need to make sure we allocate enough bytes for
|
|
|
|
|
// the whole struct, including any padding.
|
|
|
|
|
size_t len = offsetof(ufunc_T, uf_name) + STRLEN(name) + 1;
|
|
|
|
|
return alloc_clear(len < sizeof(ufunc_T) ? sizeof(ufunc_T) : len);
|
|
|
|
|
len = offsetof(ufunc_T, uf_name) + namelen + 1;
|
|
|
|
|
fp = alloc_clear(len < sizeof(ufunc_T) ? sizeof(ufunc_T) : len);
|
|
|
|
|
if (fp != NULL)
|
|
|
|
|
{
|
|
|
|
|
// Add a type cast to avoid a warning for an overflow, the uf_name[] array
|
|
|
|
|
// can actually extend beyond the struct.
|
|
|
|
|
STRCPY((void *)fp->uf_name, name);
|
|
|
|
|
fp->uf_namelen = namelen;
|
|
|
|
|
|
|
|
|
|
if (name[0] == K_SPECIAL)
|
|
|
|
|
{
|
|
|
|
|
len = namelen + 3; // including +1 for NUL
|
|
|
|
|
fp->uf_name_exp = alloc(len);
|
|
|
|
|
if (fp->uf_name_exp != NULL)
|
|
|
|
|
vim_snprintf((char *)fp->uf_name_exp, len, "<SNR>%s", fp->uf_name + 3);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return fp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if defined(FEAT_LUA) || defined(PROTO)
|
|
|
|
@ -731,9 +757,10 @@ alloc_ufunc(char_u *name)
|
|
|
|
|
register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state)
|
|
|
|
|
{
|
|
|
|
|
char_u *name = get_lambda_name();
|
|
|
|
|
size_t namelen = get_lambda_name_len();
|
|
|
|
|
ufunc_T *fp;
|
|
|
|
|
|
|
|
|
|
fp = alloc_ufunc(name);
|
|
|
|
|
fp = alloc_ufunc(name, namelen);
|
|
|
|
|
if (fp == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
@ -747,7 +774,6 @@ register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state)
|
|
|
|
|
fp->uf_cb_free = cb_free;
|
|
|
|
|
fp->uf_cb_state = state;
|
|
|
|
|
|
|
|
|
|
set_ufunc_name(fp, name);
|
|
|
|
|
hash_add(&func_hashtab, UF2HIKEY(fp), "add C function");
|
|
|
|
|
|
|
|
|
|
return name;
|
|
|
|
@ -976,6 +1002,7 @@ get_function_body(
|
|
|
|
|
int heredoc_concat_len = 0;
|
|
|
|
|
garray_T heredoc_ga;
|
|
|
|
|
char_u *heredoc_trimmed = NULL;
|
|
|
|
|
size_t heredoc_trimmedlen = 0;
|
|
|
|
|
|
|
|
|
|
ga_init2(&heredoc_ga, 1, 500);
|
|
|
|
|
|
|
|
|
@ -1059,19 +1086,20 @@ get_function_body(
|
|
|
|
|
if (heredoc_trimmed == NULL
|
|
|
|
|
|| (is_heredoc && skipwhite(theline) == theline)
|
|
|
|
|
|| STRNCMP(theline, heredoc_trimmed,
|
|
|
|
|
STRLEN(heredoc_trimmed)) == 0)
|
|
|
|
|
heredoc_trimmedlen) == 0)
|
|
|
|
|
{
|
|
|
|
|
if (heredoc_trimmed == NULL)
|
|
|
|
|
p = theline;
|
|
|
|
|
else if (is_heredoc)
|
|
|
|
|
p = skipwhite(theline) == theline
|
|
|
|
|
? theline : theline + STRLEN(heredoc_trimmed);
|
|
|
|
|
? theline : theline + heredoc_trimmedlen;
|
|
|
|
|
else
|
|
|
|
|
p = theline + STRLEN(heredoc_trimmed);
|
|
|
|
|
p = theline + heredoc_trimmedlen;
|
|
|
|
|
if (STRCMP(p, skip_until) == 0)
|
|
|
|
|
{
|
|
|
|
|
VIM_CLEAR(skip_until);
|
|
|
|
|
VIM_CLEAR(heredoc_trimmed);
|
|
|
|
|
heredoc_trimmedlen = 0;
|
|
|
|
|
getline_options = vim9_function
|
|
|
|
|
? GETLINE_CONCAT_CONTBAR : GETLINE_CONCAT_CONT;
|
|
|
|
|
is_heredoc = FALSE;
|
|
|
|
@ -1271,7 +1299,7 @@ get_function_body(
|
|
|
|
|
|| (p[2] == 's'
|
|
|
|
|
&& (!ASCII_ISALPHA(p[3])
|
|
|
|
|
|| p[3] == 'e'))))))))
|
|
|
|
|
skip_until = vim_strsave((char_u *)".");
|
|
|
|
|
skip_until = vim_strnsave((char_u *)".", 1);
|
|
|
|
|
|
|
|
|
|
// Check for ":python <<EOF", ":tcl <<EOF", etc.
|
|
|
|
|
arg = skipwhite(skiptowhite(p));
|
|
|
|
@ -1298,11 +1326,13 @@ get_function_body(
|
|
|
|
|
{
|
|
|
|
|
// Ignore leading white space.
|
|
|
|
|
p = skipwhite(p + 4);
|
|
|
|
|
heredoc_trimmed = vim_strnsave(theline,
|
|
|
|
|
skipwhite(theline) - theline);
|
|
|
|
|
heredoc_trimmedlen = skipwhite(theline) - theline;
|
|
|
|
|
heredoc_trimmed = vim_strnsave(theline, heredoc_trimmedlen);
|
|
|
|
|
if (heredoc_trimmed == NULL)
|
|
|
|
|
heredoc_trimmedlen = 0;
|
|
|
|
|
}
|
|
|
|
|
if (*p == NUL)
|
|
|
|
|
skip_until = vim_strsave((char_u *)".");
|
|
|
|
|
skip_until = vim_strnsave((char_u *)".", 1);
|
|
|
|
|
else
|
|
|
|
|
skip_until = vim_strnsave(p, skiptowhite(p) - p);
|
|
|
|
|
getline_options = GETLINE_NONE;
|
|
|
|
@ -1344,8 +1374,10 @@ get_function_body(
|
|
|
|
|
{
|
|
|
|
|
// Ignore leading white space.
|
|
|
|
|
p = skipwhite(p + 4);
|
|
|
|
|
heredoc_trimmed = vim_strnsave(theline,
|
|
|
|
|
skipwhite(theline) - theline);
|
|
|
|
|
heredoc_trimmedlen = skipwhite(theline) - theline;
|
|
|
|
|
heredoc_trimmed = vim_strnsave(theline, heredoc_trimmedlen);
|
|
|
|
|
if (heredoc_trimmed == NULL)
|
|
|
|
|
heredoc_trimmedlen = 0;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (STRNCMP(p, "eval", 4) == 0)
|
|
|
|
@ -1374,7 +1406,7 @@ get_function_body(
|
|
|
|
|
// to be used for the instruction later.
|
|
|
|
|
ga_concat(&heredoc_ga, theline);
|
|
|
|
|
ga_concat(&heredoc_ga, (char_u *)"\n");
|
|
|
|
|
p = vim_strsave((char_u *)"");
|
|
|
|
|
p = vim_strnsave((char_u *)"", 0);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
@ -1437,6 +1469,7 @@ lambda_function_body(
|
|
|
|
|
int ret = FAIL;
|
|
|
|
|
partial_T *pt;
|
|
|
|
|
char_u *name;
|
|
|
|
|
size_t namelen;
|
|
|
|
|
int lnum_save = -1;
|
|
|
|
|
linenr_T sourcing_lnum_top = SOURCING_LNUM;
|
|
|
|
|
char_u *line_arg = NULL;
|
|
|
|
@ -1498,8 +1531,12 @@ lambda_function_body(
|
|
|
|
|
// Insert NL characters at the start of each line, the string will
|
|
|
|
|
// be split again later in .get_lambda_tv().
|
|
|
|
|
if (*p == NUL || vim9_comment_start(p))
|
|
|
|
|
{
|
|
|
|
|
p = (char_u *)"";
|
|
|
|
|
plen = STRLEN(p);
|
|
|
|
|
plen = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
plen = STRLEN(p);
|
|
|
|
|
pnl = vim_strnsave((char_u *)"\n", plen + 1);
|
|
|
|
|
if (pnl != NULL)
|
|
|
|
|
mch_memmove(pnl + 1, p, plen + 1);
|
|
|
|
@ -1509,12 +1546,17 @@ lambda_function_body(
|
|
|
|
|
if (ga_grow(gap, 1) == FAIL || ga_grow(freegap, 1) == FAIL)
|
|
|
|
|
goto erret;
|
|
|
|
|
if (eap.nextcmd != NULL)
|
|
|
|
|
{
|
|
|
|
|
// more is following after the "}", which was skipped
|
|
|
|
|
last = cmdline;
|
|
|
|
|
plen = STRLEN(last);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// nothing is following the "}"
|
|
|
|
|
last = (char_u *)"}";
|
|
|
|
|
plen = STRLEN(last);
|
|
|
|
|
plen = 1;
|
|
|
|
|
}
|
|
|
|
|
pnl = vim_strnsave((char_u *)"\n", plen + 1);
|
|
|
|
|
if (pnl != NULL)
|
|
|
|
|
mch_memmove(pnl + 1, last, plen + 1);
|
|
|
|
@ -1546,10 +1588,10 @@ lambda_function_body(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
name = get_lambda_name();
|
|
|
|
|
ufunc = alloc_ufunc(name);
|
|
|
|
|
namelen = get_lambda_name_len();
|
|
|
|
|
ufunc = alloc_ufunc(name, namelen);
|
|
|
|
|
if (ufunc == NULL)
|
|
|
|
|
goto erret;
|
|
|
|
|
set_ufunc_name(ufunc, name);
|
|
|
|
|
if (hash_add(&func_hashtab, UF2HIKEY(ufunc), "add function") == FAIL)
|
|
|
|
|
goto erret;
|
|
|
|
|
ufunc->uf_flags = FC_LAMBDA;
|
|
|
|
@ -1755,8 +1797,9 @@ get_lambda_tv(
|
|
|
|
|
char_u *p;
|
|
|
|
|
char_u *line_end;
|
|
|
|
|
char_u *name = get_lambda_name();
|
|
|
|
|
size_t namelen = get_lambda_name_len();
|
|
|
|
|
|
|
|
|
|
fp = alloc_ufunc(name);
|
|
|
|
|
fp = alloc_ufunc(name, namelen);
|
|
|
|
|
if (fp == NULL)
|
|
|
|
|
goto errret;
|
|
|
|
|
fp->uf_def_status = UF_NOT_COMPILED;
|
|
|
|
@ -1804,7 +1847,6 @@ get_lambda_tv(
|
|
|
|
|
flags |= FC_NOARGS;
|
|
|
|
|
|
|
|
|
|
fp->uf_refcount = 1;
|
|
|
|
|
set_ufunc_name(fp, name);
|
|
|
|
|
fp->uf_args = newargs;
|
|
|
|
|
ga_init(&fp->uf_def_args);
|
|
|
|
|
if (types_optional)
|
|
|
|
@ -1875,10 +1917,13 @@ errret:
|
|
|
|
|
{
|
|
|
|
|
ga_clear_strings(&argtypes);
|
|
|
|
|
ga_clear(&arg_objm);
|
|
|
|
|
if (fp != NULL)
|
|
|
|
|
vim_free(fp->uf_arg_types);
|
|
|
|
|
}
|
|
|
|
|
vim_free(fp);
|
|
|
|
|
if (fp != NULL)
|
|
|
|
|
{
|
|
|
|
|
vim_free(fp->uf_arg_types);
|
|
|
|
|
vim_free(fp->uf_name_exp);
|
|
|
|
|
vim_free(fp);
|
|
|
|
|
}
|
|
|
|
|
vim_free(pt);
|
|
|
|
|
vim_free(tofree2);
|
|
|
|
|
eval_lavars_used = old_eval_lavars;
|
|
|
|
@ -2184,44 +2229,48 @@ fname_trans_sid(
|
|
|
|
|
char_u **tofree,
|
|
|
|
|
funcerror_T *error)
|
|
|
|
|
{
|
|
|
|
|
int llen;
|
|
|
|
|
char_u *script_name;
|
|
|
|
|
char_u *fname;
|
|
|
|
|
int i;
|
|
|
|
|
size_t fnamelen;
|
|
|
|
|
size_t fname_buflen;
|
|
|
|
|
|
|
|
|
|
llen = eval_fname_script(name);
|
|
|
|
|
if (llen == 0)
|
|
|
|
|
script_name = name + eval_fname_script(name);
|
|
|
|
|
if (script_name == name)
|
|
|
|
|
return name; // no prefix
|
|
|
|
|
|
|
|
|
|
fname_buf[0] = K_SPECIAL;
|
|
|
|
|
fname_buf[1] = KS_EXTRA;
|
|
|
|
|
fname_buf[2] = (int)KE_SNR;
|
|
|
|
|
i = 3;
|
|
|
|
|
if (eval_fname_sid(name)) // "<SID>" or "s:"
|
|
|
|
|
fname_buflen = 3;
|
|
|
|
|
if (!eval_fname_sid(name)) // "<SID>" or "s:"
|
|
|
|
|
fname_buf[fname_buflen] = NUL;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (current_sctx.sc_sid <= 0)
|
|
|
|
|
*error = FCERR_SCRIPT;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
sprintf((char *)fname_buf + 3, "%ld_",
|
|
|
|
|
fname_buflen += vim_snprintf((char *)fname_buf + 3,
|
|
|
|
|
FLEN_FIXED - 3,
|
|
|
|
|
"%ld_",
|
|
|
|
|
(long)current_sctx.sc_sid);
|
|
|
|
|
i = (int)STRLEN(fname_buf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (i + STRLEN(name + llen) < FLEN_FIXED)
|
|
|
|
|
fnamelen = fname_buflen + STRLEN(script_name);
|
|
|
|
|
if (fnamelen < FLEN_FIXED)
|
|
|
|
|
{
|
|
|
|
|
STRCPY(fname_buf + i, name + llen);
|
|
|
|
|
STRCPY(fname_buf + fname_buflen, script_name);
|
|
|
|
|
fname = fname_buf;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fname = alloc(i + STRLEN(name + llen) + 1);
|
|
|
|
|
fname = alloc(fnamelen + 1);
|
|
|
|
|
if (fname == NULL)
|
|
|
|
|
*error = FCERR_OTHER;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*tofree = fname;
|
|
|
|
|
mch_memmove(fname, fname_buf, (size_t)i);
|
|
|
|
|
STRCPY(fname + i, name + llen);
|
|
|
|
|
vim_snprintf((char *)fname, fnamelen + 1, "%s%s", fname_buf, script_name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return fname;
|
|
|
|
@ -2391,7 +2440,7 @@ func_is_global(ufunc_T *ufunc)
|
|
|
|
|
int
|
|
|
|
|
func_requires_g_prefix(ufunc_T *ufunc)
|
|
|
|
|
{
|
|
|
|
|
return ufunc->uf_name[0] != K_SPECIAL
|
|
|
|
|
return func_is_global(ufunc)
|
|
|
|
|
&& (ufunc->uf_flags & FC_LAMBDA) == 0
|
|
|
|
|
&& vim_strchr(ufunc->uf_name, AUTOLOAD_CHAR) == NULL
|
|
|
|
|
&& !SAFE_isdigit(ufunc->uf_name[0]);
|
|
|
|
@ -2402,16 +2451,17 @@ func_requires_g_prefix(ufunc_T *ufunc)
|
|
|
|
|
* "buf" must be able to hold the function name plus three bytes.
|
|
|
|
|
* Takes care of script-local function names.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
cat_func_name(char_u *buf, ufunc_T *fp)
|
|
|
|
|
static int
|
|
|
|
|
cat_func_name(char_u *buf, size_t bufsize, ufunc_T *fp)
|
|
|
|
|
{
|
|
|
|
|
int len;
|
|
|
|
|
|
|
|
|
|
if (!func_is_global(fp))
|
|
|
|
|
{
|
|
|
|
|
STRCPY(buf, "<SNR>");
|
|
|
|
|
STRCAT(buf, fp->uf_name + 3);
|
|
|
|
|
}
|
|
|
|
|
len = vim_snprintf((char *)buf, bufsize, "<SNR>%s", fp->uf_name + 3);
|
|
|
|
|
else
|
|
|
|
|
STRCPY(buf, fp->uf_name);
|
|
|
|
|
len = vim_snprintf((char *)buf, bufsize, "%s", fp->uf_name);
|
|
|
|
|
|
|
|
|
|
return (len >= (int)bufsize) ? (int)bufsize - 1 : len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -2773,7 +2823,7 @@ copy_lambda_to_global_func(
|
|
|
|
|
return FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fp = alloc_ufunc(global);
|
|
|
|
|
fp = alloc_ufunc(global, STRLEN(global));
|
|
|
|
|
if (fp == NULL)
|
|
|
|
|
return FAIL;
|
|
|
|
|
|
|
|
|
@ -2805,9 +2855,6 @@ copy_lambda_to_global_func(
|
|
|
|
|
|
|
|
|
|
fp->uf_refcount = 1;
|
|
|
|
|
|
|
|
|
|
fp->uf_name_exp = NULL;
|
|
|
|
|
set_ufunc_name(fp, global);
|
|
|
|
|
|
|
|
|
|
hash_add(&func_hashtab, UF2HIKEY(fp), "copy lambda");
|
|
|
|
|
|
|
|
|
|
// the referenced dfunc_T is now used one more time
|
|
|
|
@ -2943,6 +2990,7 @@ call_user_func(
|
|
|
|
|
int islambda = FALSE;
|
|
|
|
|
char_u numbuf[NUMBUFLEN];
|
|
|
|
|
char_u *name;
|
|
|
|
|
size_t namelen;
|
|
|
|
|
typval_T *tv_to_free[MAX_FUNC_ARGS];
|
|
|
|
|
int tv_to_free_len = 0;
|
|
|
|
|
#ifdef FEAT_PROFILE
|
|
|
|
@ -3099,6 +3147,8 @@ call_user_func(
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namelen = STRLEN(name);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
@ -3107,10 +3157,10 @@ call_user_func(
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// "..." argument a:1, a:2, etc.
|
|
|
|
|
sprintf((char *)numbuf, "%d", ai + 1);
|
|
|
|
|
namelen = vim_snprintf((char *)numbuf, sizeof(numbuf), "%d", ai + 1);
|
|
|
|
|
name = numbuf;
|
|
|
|
|
}
|
|
|
|
|
if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN)
|
|
|
|
|
if (fixvar_idx < FIXVAR_CNT && namelen <= VAR_SHORT_LEN)
|
|
|
|
|
{
|
|
|
|
|
v = &fc->fc_fixvar[fixvar_idx++].var;
|
|
|
|
|
v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
|
|
|
|
@ -3491,8 +3541,7 @@ delete_script_functions(int sid)
|
|
|
|
|
buf[0] = K_SPECIAL;
|
|
|
|
|
buf[1] = KS_EXTRA;
|
|
|
|
|
buf[2] = (int)KE_SNR;
|
|
|
|
|
sprintf((char *)buf + 3, "%d_", sid);
|
|
|
|
|
len = STRLEN(buf);
|
|
|
|
|
len = 3 + vim_snprintf((char *)buf + 3, sizeof(buf) - 3, "%d_", sid);
|
|
|
|
|
|
|
|
|
|
while (todo > 0)
|
|
|
|
|
{
|
|
|
|
@ -4388,7 +4437,7 @@ trans_function_name_ext(
|
|
|
|
|
{
|
|
|
|
|
if (ufunc != NULL)
|
|
|
|
|
*ufunc = lv.ll_ufunc;
|
|
|
|
|
name = vim_strsave(lv.ll_ufunc->uf_name);
|
|
|
|
|
name = vim_strnsave(lv.ll_ufunc->uf_name, lv.ll_ufunc->uf_namelen);
|
|
|
|
|
*pp = end;
|
|
|
|
|
goto theend;
|
|
|
|
|
}
|
|
|
|
@ -4485,7 +4534,7 @@ trans_function_name_ext(
|
|
|
|
|
{
|
|
|
|
|
name = vim_strsave(name);
|
|
|
|
|
*pp = end;
|
|
|
|
|
if (STRNCMP(name, "<SNR>", 5) == 0)
|
|
|
|
|
if (name != NULL && STRNCMP(name, "<SNR>", 5) == 0)
|
|
|
|
|
{
|
|
|
|
|
// Change "<SNR>" to the byte sequence.
|
|
|
|
|
name[0] = K_SPECIAL;
|
|
|
|
@ -4567,17 +4616,19 @@ trans_function_name_ext(
|
|
|
|
|
&& eval_fname_sid(lv.ll_exp_name))
|
|
|
|
|
|| eval_fname_sid(*pp))
|
|
|
|
|
{
|
|
|
|
|
size_t sid_buflen;
|
|
|
|
|
|
|
|
|
|
// It's script-local, "s:" or "<SID>"
|
|
|
|
|
if (current_sctx.sc_sid <= 0)
|
|
|
|
|
{
|
|
|
|
|
emsg(_(e_using_sid_not_in_script_context));
|
|
|
|
|
goto theend;
|
|
|
|
|
}
|
|
|
|
|
sprintf((char *)sid_buf, "%ld_", (long)current_sctx.sc_sid);
|
|
|
|
|
sid_buflen = vim_snprintf((char *)sid_buf, sizeof(sid_buf), "%ld_", (long)current_sctx.sc_sid);
|
|
|
|
|
if (vim9_local)
|
|
|
|
|
extra = 3 + (int)STRLEN(sid_buf);
|
|
|
|
|
extra = 3 + (int)sid_buflen;
|
|
|
|
|
else
|
|
|
|
|
lead += (int)STRLEN(sid_buf);
|
|
|
|
|
lead += (int)sid_buflen;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// The function name must start with an upper case letter (unless it is a
|
|
|
|
@ -4664,8 +4715,10 @@ untrans_function_name(char_u *name)
|
|
|
|
|
get_scriptlocal_funcname(char_u *funcname)
|
|
|
|
|
{
|
|
|
|
|
char sid_buf[25];
|
|
|
|
|
size_t sid_buflen;
|
|
|
|
|
int off;
|
|
|
|
|
char_u *newname;
|
|
|
|
|
size_t newnamesize;
|
|
|
|
|
char_u *p = funcname;
|
|
|
|
|
|
|
|
|
|
if (funcname == NULL)
|
|
|
|
@ -4696,13 +4749,13 @@ get_scriptlocal_funcname(char_u *funcname)
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
// Expand s: prefix into <SNR>nr_<name>
|
|
|
|
|
vim_snprintf(sid_buf, sizeof(sid_buf), "<SNR>%ld_",
|
|
|
|
|
sid_buflen = vim_snprintf(sid_buf, sizeof(sid_buf), "<SNR>%ld_",
|
|
|
|
|
(long)current_sctx.sc_sid);
|
|
|
|
|
newname = alloc(STRLEN(sid_buf) + STRLEN(p + off) + 1);
|
|
|
|
|
newnamesize = sid_buflen + STRLEN(p + off) + 1;
|
|
|
|
|
newname = alloc(newnamesize);
|
|
|
|
|
if (newname == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
STRCPY(newname, sid_buf);
|
|
|
|
|
STRCAT(newname, p + off);
|
|
|
|
|
vim_snprintf((char *)newname, newnamesize, "%s%s", sid_buf, p + off);
|
|
|
|
|
|
|
|
|
|
return newname;
|
|
|
|
|
}
|
|
|
|
@ -4811,6 +4864,7 @@ define_function(
|
|
|
|
|
int c;
|
|
|
|
|
int saved_did_emsg = FALSE;
|
|
|
|
|
char_u *name = name_arg;
|
|
|
|
|
size_t namelen = 0;
|
|
|
|
|
int is_global = FALSE;
|
|
|
|
|
char_u *p;
|
|
|
|
|
char_u *arg;
|
|
|
|
@ -5107,7 +5161,7 @@ define_function(
|
|
|
|
|
// In Vim9 script a function cannot have the same name as a
|
|
|
|
|
// variable.
|
|
|
|
|
if (vim9script && *arg == K_SPECIAL
|
|
|
|
|
&& eval_variable(name_base, (int)STRLEN(name_base), 0, NULL,
|
|
|
|
|
&& eval_variable(name_base, i, 0, NULL,
|
|
|
|
|
NULL, EVAL_VAR_NOAUTOLOAD + EVAL_VAR_IMPORT
|
|
|
|
|
+ EVAL_VAR_NO_FUNC) == OK)
|
|
|
|
|
{
|
|
|
|
@ -5252,7 +5306,7 @@ define_function(
|
|
|
|
|
*/
|
|
|
|
|
if (fudi.fd_dict != NULL)
|
|
|
|
|
{
|
|
|
|
|
char numbuf[20];
|
|
|
|
|
char numbuf[NUMBUFLEN];
|
|
|
|
|
|
|
|
|
|
fp = NULL;
|
|
|
|
|
if (fudi.fd_newkey == NULL && !eap->forceit)
|
|
|
|
@ -5273,8 +5327,8 @@ define_function(
|
|
|
|
|
// Give the function a sequential number. Can only be used with a
|
|
|
|
|
// Funcref!
|
|
|
|
|
vim_free(name);
|
|
|
|
|
sprintf(numbuf, "%d", ++func_nr);
|
|
|
|
|
name = vim_strsave((char_u *)numbuf);
|
|
|
|
|
namelen = vim_snprintf(numbuf, sizeof(numbuf), "%d", ++func_nr);
|
|
|
|
|
name = vim_strnsave((char_u *)numbuf, namelen);
|
|
|
|
|
if (name == NULL)
|
|
|
|
|
goto erret;
|
|
|
|
|
}
|
|
|
|
@ -5373,6 +5427,7 @@ define_function(
|
|
|
|
|
|
|
|
|
|
// redefine existing function, keep the expanded name
|
|
|
|
|
VIM_CLEAR(name);
|
|
|
|
|
namelen = 0;
|
|
|
|
|
fp->uf_name_exp = NULL;
|
|
|
|
|
func_clear_items(fp);
|
|
|
|
|
fp->uf_name_exp = exp_name;
|
|
|
|
@ -5421,7 +5476,9 @@ define_function(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fp = alloc_ufunc(name);
|
|
|
|
|
if (namelen == 0)
|
|
|
|
|
namelen = STRLEN(name);
|
|
|
|
|
fp = alloc_ufunc(name, namelen);
|
|
|
|
|
if (fp == NULL)
|
|
|
|
|
goto erret;
|
|
|
|
|
fp_allocated = TRUE;
|
|
|
|
@ -5448,7 +5505,7 @@ define_function(
|
|
|
|
|
// overwrite existing dict entry
|
|
|
|
|
clear_tv(&fudi.fd_di->di_tv);
|
|
|
|
|
fudi.fd_di->di_tv.v_type = VAR_FUNC;
|
|
|
|
|
fudi.fd_di->di_tv.vval.v_string = vim_strsave(name);
|
|
|
|
|
fudi.fd_di->di_tv.vval.v_string = vim_strnsave(name, namelen);
|
|
|
|
|
|
|
|
|
|
// behave like "dict" was used
|
|
|
|
|
flags |= FC_DICT;
|
|
|
|
@ -5506,7 +5563,6 @@ define_function(
|
|
|
|
|
if (fp_allocated)
|
|
|
|
|
{
|
|
|
|
|
// insert the new function in the function list
|
|
|
|
|
set_ufunc_name(fp, name);
|
|
|
|
|
if (overwrite)
|
|
|
|
|
{
|
|
|
|
|
hi = hash_find(&func_hashtab, name);
|
|
|
|
@ -5581,6 +5637,7 @@ errret_2:
|
|
|
|
|
{
|
|
|
|
|
VIM_CLEAR(fp->uf_arg_types);
|
|
|
|
|
VIM_CLEAR(fp->uf_va_name);
|
|
|
|
|
VIM_CLEAR(fp->uf_name_exp);
|
|
|
|
|
clear_func_type_list(&fp->uf_type_list, &fp->uf_func_type);
|
|
|
|
|
}
|
|
|
|
|
if (free_fp)
|
|
|
|
@ -5918,6 +5975,8 @@ get_user_func_name(expand_T *xp, int idx)
|
|
|
|
|
}
|
|
|
|
|
if (changed == func_hashtab.ht_changed && done < func_hashtab.ht_used)
|
|
|
|
|
{
|
|
|
|
|
int len;
|
|
|
|
|
|
|
|
|
|
if (done++ > 0)
|
|
|
|
|
++hi;
|
|
|
|
|
while (HASHITEM_EMPTY(hi))
|
|
|
|
@ -5929,16 +5988,19 @@ get_user_func_name(expand_T *xp, int idx)
|
|
|
|
|
|| STRNCMP(fp->uf_name, "<lambda>", 8) == 0)
|
|
|
|
|
return (char_u *)"";
|
|
|
|
|
|
|
|
|
|
if (STRLEN(fp->uf_name) + 4 >= IOSIZE)
|
|
|
|
|
if (fp->uf_namelen + 4 >= IOSIZE)
|
|
|
|
|
return fp->uf_name; // prevents overflow
|
|
|
|
|
|
|
|
|
|
cat_func_name(IObuff, fp);
|
|
|
|
|
len = cat_func_name(IObuff, IOSIZE, fp);
|
|
|
|
|
if (xp->xp_context != EXPAND_USER_FUNC
|
|
|
|
|
&& xp->xp_context != EXPAND_DISASSEMBLE)
|
|
|
|
|
{
|
|
|
|
|
STRCAT(IObuff, "(");
|
|
|
|
|
STRCPY(IObuff + len, "(");
|
|
|
|
|
if (!has_varargs(fp) && fp->uf_args.ga_len == 0)
|
|
|
|
|
STRCAT(IObuff, ")");
|
|
|
|
|
{
|
|
|
|
|
++len;
|
|
|
|
|
STRCPY(IObuff + len, ")");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return IObuff;
|
|
|
|
|
}
|
|
|
|
@ -5955,7 +6017,7 @@ get_user_func_name(expand_T *xp, int idx)
|
|
|
|
|
ufunc_T *
|
|
|
|
|
copy_function(ufunc_T *fp)
|
|
|
|
|
{
|
|
|
|
|
ufunc_T *ufunc = alloc_ufunc(fp->uf_name);
|
|
|
|
|
ufunc_T *ufunc = alloc_ufunc(fp->uf_name, fp->uf_namelen);
|
|
|
|
|
if (ufunc == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
@ -6004,8 +6066,6 @@ copy_function(ufunc_T *fp)
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
@ -6760,20 +6820,31 @@ discard_pending_return(void *rettv)
|
|
|
|
|
get_return_cmd(void *rettv)
|
|
|
|
|
{
|
|
|
|
|
char_u *s = NULL;
|
|
|
|
|
char_u *tofree = NULL;
|
|
|
|
|
char_u numbuf[NUMBUFLEN];
|
|
|
|
|
size_t slen = 0;
|
|
|
|
|
size_t IObufflen;
|
|
|
|
|
|
|
|
|
|
if (rettv != NULL)
|
|
|
|
|
{
|
|
|
|
|
char_u *tofree = NULL;
|
|
|
|
|
char_u numbuf[NUMBUFLEN];
|
|
|
|
|
|
|
|
|
|
s = echo_string((typval_T *)rettv, &tofree, numbuf, 0);
|
|
|
|
|
vim_free(tofree);
|
|
|
|
|
}
|
|
|
|
|
if (s == NULL)
|
|
|
|
|
s = (char_u *)"";
|
|
|
|
|
else
|
|
|
|
|
slen = STRLEN(s);
|
|
|
|
|
|
|
|
|
|
STRCPY(IObuff, ":return ");
|
|
|
|
|
STRNCPY(IObuff + 8, s, IOSIZE - 8);
|
|
|
|
|
if (STRLEN(s) + 8 >= IOSIZE)
|
|
|
|
|
IObufflen = 8 + slen;
|
|
|
|
|
if (slen + 8 >= IOSIZE)
|
|
|
|
|
{
|
|
|
|
|
STRCPY(IObuff + IOSIZE - 4, "...");
|
|
|
|
|
vim_free(tofree);
|
|
|
|
|
return vim_strsave(IObuff);
|
|
|
|
|
IObufflen += 3;
|
|
|
|
|
}
|
|
|
|
|
return vim_strnsave(IObuff, IObufflen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|