xref: /vim-8.2.3635/src/userfunc.c (revision d604d78e)
1edf3f97aSBram Moolenaar /* vi:set ts=8 sts=4 sw=4 noet:
2a9b579f3SBram Moolenaar  *
3a9b579f3SBram Moolenaar  * VIM - Vi IMproved	by Bram Moolenaar
4a9b579f3SBram Moolenaar  *
5a9b579f3SBram Moolenaar  * Do ":help uganda"  in Vim to read copying and usage conditions.
6a9b579f3SBram Moolenaar  * Do ":help credits" in Vim to see a list of people who contributed.
7a9b579f3SBram Moolenaar  * See README.txt for an overview of the Vim source code.
8a9b579f3SBram Moolenaar  */
9a9b579f3SBram Moolenaar 
10a9b579f3SBram Moolenaar /*
1114c01f83SBram Moolenaar  * userfunc.c: User defined function support
12a9b579f3SBram Moolenaar  */
13a9b579f3SBram Moolenaar 
14a9b579f3SBram Moolenaar #include "vim.h"
15a9b579f3SBram Moolenaar 
16a9b579f3SBram Moolenaar #if defined(FEAT_EVAL) || defined(PROTO)
17a9b579f3SBram Moolenaar /*
18a9b579f3SBram Moolenaar  * All user-defined functions are found in this hashtable.
19a9b579f3SBram Moolenaar  */
20a9b579f3SBram Moolenaar static hashtab_T	func_hashtab;
21a9b579f3SBram Moolenaar 
22e38eab22SBram Moolenaar // Used by get_func_tv()
23a9b579f3SBram Moolenaar static garray_T funcargs = GA_EMPTY;
24a9b579f3SBram Moolenaar 
25209b8e3eSBram Moolenaar // pointer to funccal for currently active function
26209b8e3eSBram Moolenaar static funccall_T *current_funccal = NULL;
27a9b579f3SBram Moolenaar 
28209b8e3eSBram Moolenaar // Pointer to list of previously used funccal, still around because some
29209b8e3eSBram Moolenaar // item in it is still being used.
30209b8e3eSBram Moolenaar static funccall_T *previous_funccal = NULL;
31a9b579f3SBram Moolenaar 
32a9b579f3SBram Moolenaar static char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it");
33a9b579f3SBram Moolenaar static char *e_funcdict = N_("E717: Dictionary entry already exists");
34a9b579f3SBram Moolenaar static char *e_funcref = N_("E718: Funcref required");
35a9b579f3SBram Moolenaar static char *e_nofunc = N_("E130: Unknown function: %s");
36a9b579f3SBram Moolenaar 
37bc7ce675SBram Moolenaar static void funccal_unref(funccall_T *fc, ufunc_T *fp, int force);
3879efa2e3SBram Moolenaar static void func_clear(ufunc_T *fp, int force);
3979efa2e3SBram Moolenaar static int func_free(ufunc_T *fp, int force);
40a9b579f3SBram Moolenaar 
41a9b579f3SBram Moolenaar     void
func_init()42a9b579f3SBram Moolenaar func_init()
43a9b579f3SBram Moolenaar {
44a9b579f3SBram Moolenaar     hash_init(&func_hashtab);
45a9b579f3SBram Moolenaar }
46a9b579f3SBram Moolenaar 
474f0383bcSBram Moolenaar /*
48660a10adSBram Moolenaar  * Return the function hash table
49660a10adSBram Moolenaar  */
50660a10adSBram Moolenaar     hashtab_T *
func_tbl_get(void)51660a10adSBram Moolenaar func_tbl_get(void)
52660a10adSBram Moolenaar {
53660a10adSBram Moolenaar     return &func_hashtab;
54660a10adSBram Moolenaar }
55660a10adSBram Moolenaar 
56660a10adSBram Moolenaar /*
576e949784SBram Moolenaar  * Get one function argument.
5851e7e78dSBram Moolenaar  * If "argtypes" is not NULL also get the type: "arg: type" (:def function).
59b4d16cb1SBram Moolenaar  * If "types_optional" is TRUE a missing type is OK, use "any".
60057e84afSBram Moolenaar  * If "evalarg" is not NULL use it to check for an already declared name.
618a7d6542SBram Moolenaar  * Return a pointer to after the type.
628a7d6542SBram Moolenaar  * When something is wrong return "arg".
638a7d6542SBram Moolenaar  */
648a7d6542SBram Moolenaar     static char_u *
one_function_arg(char_u * arg,garray_T * newargs,garray_T * argtypes,int types_optional,evalarg_T * evalarg,int is_vararg,int skip)65b4d16cb1SBram Moolenaar one_function_arg(
66b4d16cb1SBram Moolenaar 	char_u	    *arg,
67b4d16cb1SBram Moolenaar 	garray_T    *newargs,
68b4d16cb1SBram Moolenaar 	garray_T    *argtypes,
69b4d16cb1SBram Moolenaar 	int	    types_optional,
70057e84afSBram Moolenaar 	evalarg_T   *evalarg,
712a38908bSBram Moolenaar 	int	    is_vararg,
72b4d16cb1SBram Moolenaar 	int	    skip)
738a7d6542SBram Moolenaar {
748a7d6542SBram Moolenaar     char_u	*p = arg;
756e949784SBram Moolenaar     char_u	*arg_copy = NULL;
7651e7e78dSBram Moolenaar     int		is_underscore = FALSE;
778a7d6542SBram Moolenaar 
788a7d6542SBram Moolenaar     while (ASCII_ISALNUM(*p) || *p == '_')
798a7d6542SBram Moolenaar 	++p;
808a7d6542SBram Moolenaar     if (arg == p || isdigit(*arg)
81b816dae1SBram Moolenaar 	    || (argtypes == NULL
82b816dae1SBram Moolenaar 		&& ((p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0)
83b816dae1SBram Moolenaar 		    || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0))))
848a7d6542SBram Moolenaar     {
858a7d6542SBram Moolenaar 	if (!skip)
868a7d6542SBram Moolenaar 	    semsg(_("E125: Illegal argument: %s"), arg);
878a7d6542SBram Moolenaar 	return arg;
888a7d6542SBram Moolenaar     }
89b4893b84SBram Moolenaar 
90057e84afSBram Moolenaar     // Vim9 script: cannot use script var name for argument. In function: also
91057e84afSBram Moolenaar     // check local vars and arguments.
92057e84afSBram Moolenaar     if (!skip && argtypes != NULL && check_defined(arg, p - arg,
93057e84afSBram Moolenaar 		    evalarg == NULL ? NULL : evalarg->eval_cctx, TRUE) == FAIL)
94b4893b84SBram Moolenaar 	return arg;
95b4893b84SBram Moolenaar 
968a7d6542SBram Moolenaar     if (newargs != NULL && ga_grow(newargs, 1) == FAIL)
978a7d6542SBram Moolenaar 	return arg;
988a7d6542SBram Moolenaar     if (newargs != NULL)
998a7d6542SBram Moolenaar     {
1008a7d6542SBram Moolenaar 	int	c;
1018a7d6542SBram Moolenaar 	int	i;
1028a7d6542SBram Moolenaar 
1038a7d6542SBram Moolenaar 	c = *p;
1048a7d6542SBram Moolenaar 	*p = NUL;
1058a7d6542SBram Moolenaar 	arg_copy = vim_strsave(arg);
1068a7d6542SBram Moolenaar 	if (arg_copy == NULL)
1078a7d6542SBram Moolenaar 	{
1088a7d6542SBram Moolenaar 	    *p = c;
1098a7d6542SBram Moolenaar 	    return arg;
1108a7d6542SBram Moolenaar 	}
11151e7e78dSBram Moolenaar 	is_underscore = arg_copy[0] == '_' && arg_copy[1] == NUL;
11287795939SBram Moolenaar 	if (argtypes == NULL || !is_underscore)
1138a7d6542SBram Moolenaar 	    // Check for duplicate argument name.
1148a7d6542SBram Moolenaar 	    for (i = 0; i < newargs->ga_len; ++i)
1158a7d6542SBram Moolenaar 		if (STRCMP(((char_u **)(newargs->ga_data))[i], arg_copy) == 0)
1168a7d6542SBram Moolenaar 		{
1178a7d6542SBram Moolenaar 		    semsg(_("E853: Duplicate argument name: %s"), arg_copy);
1188a7d6542SBram Moolenaar 		    vim_free(arg_copy);
1198a7d6542SBram Moolenaar 		    return arg;
1208a7d6542SBram Moolenaar 		}
1218a7d6542SBram Moolenaar 	((char_u **)(newargs->ga_data))[newargs->ga_len] = arg_copy;
1228a7d6542SBram Moolenaar 	newargs->ga_len++;
1238a7d6542SBram Moolenaar 
1248a7d6542SBram Moolenaar 	*p = c;
1258a7d6542SBram Moolenaar     }
1268a7d6542SBram Moolenaar 
1278a7d6542SBram Moolenaar     // get any type from "arg: type"
128b4d16cb1SBram Moolenaar     if (argtypes != NULL && (skip || ga_grow(argtypes, 1) == OK))
1298a7d6542SBram Moolenaar     {
1308a7d6542SBram Moolenaar 	char_u *type = NULL;
1318a7d6542SBram Moolenaar 
1326e949784SBram Moolenaar 	if (VIM_ISWHITE(*p) && *skipwhite(p) == ':')
1336e949784SBram Moolenaar 	{
134451c2e35SBram Moolenaar 	    semsg(_(e_no_white_space_allowed_before_colon_str),
1356e949784SBram Moolenaar 					    arg_copy == NULL ? arg : arg_copy);
1366e949784SBram Moolenaar 	    p = skipwhite(p);
1376e949784SBram Moolenaar 	}
1388a7d6542SBram Moolenaar 	if (*p == ':')
1398a7d6542SBram Moolenaar 	{
140f93c7feaSBram Moolenaar 	    ++p;
141b4d16cb1SBram Moolenaar 	    if (!skip && !VIM_ISWHITE(*p))
142f93c7feaSBram Moolenaar 	    {
143c3fc75dbSBram Moolenaar 		semsg(_(e_white_space_required_after_str_str), ":", p - 1);
144f93c7feaSBram Moolenaar 		return arg;
145f93c7feaSBram Moolenaar 	    }
146f93c7feaSBram Moolenaar 	    type = skipwhite(p);
1474fc224caSBram Moolenaar 	    p = skip_type(type, TRUE);
148b4d16cb1SBram Moolenaar 	    if (!skip)
1498a7d6542SBram Moolenaar 		type = vim_strnsave(type, p - type);
1508a7d6542SBram Moolenaar 	}
15151e7e78dSBram Moolenaar 	else if (*skipwhite(p) != '=' && !types_optional && !is_underscore)
1526e949784SBram Moolenaar 	{
153451c2e35SBram Moolenaar 	    semsg(_(e_missing_argument_type_for_str),
1546e949784SBram Moolenaar 					    arg_copy == NULL ? arg : arg_copy);
1556e949784SBram Moolenaar 	    return arg;
1566e949784SBram Moolenaar 	}
157b4d16cb1SBram Moolenaar 	if (!skip)
158b4d16cb1SBram Moolenaar 	{
159b4d16cb1SBram Moolenaar 	    if (type == NULL && types_optional)
160b4d16cb1SBram Moolenaar 		// lambda arguments default to "any" type
1612a38908bSBram Moolenaar 		type = vim_strsave((char_u *)
1622a38908bSBram Moolenaar 					    (is_vararg ? "list<any>" : "any"));
1638a7d6542SBram Moolenaar 	    ((char_u **)argtypes->ga_data)[argtypes->ga_len++] = type;
1648a7d6542SBram Moolenaar 	}
165b4d16cb1SBram Moolenaar     }
1668a7d6542SBram Moolenaar 
1678a7d6542SBram Moolenaar     return p;
1688a7d6542SBram Moolenaar }
1698a7d6542SBram Moolenaar 
1708a7d6542SBram Moolenaar /*
1714f0383bcSBram Moolenaar  * Get function arguments.
172cef1270dSBram Moolenaar  * "argp" should point to just after the "(", possibly to white space.
17365c44152SBram Moolenaar  * "argp" is advanced just after "endchar".
1744f0383bcSBram Moolenaar  */
175cef1270dSBram Moolenaar     static int
get_function_args(char_u ** argp,char_u endchar,garray_T * newargs,garray_T * argtypes,int types_optional,evalarg_T * evalarg,int * varargs,garray_T * default_args,int skip,exarg_T * eap,char_u ** line_to_free)176a9b579f3SBram Moolenaar get_function_args(
177a9b579f3SBram Moolenaar     char_u	**argp,
178a9b579f3SBram Moolenaar     char_u	endchar,
179a9b579f3SBram Moolenaar     garray_T	*newargs,
1808a7d6542SBram Moolenaar     garray_T	*argtypes,	// NULL unless using :def
181b4d16cb1SBram Moolenaar     int		types_optional,	// types optional if "argtypes" is not NULL
182057e84afSBram Moolenaar     evalarg_T	*evalarg,	// context or NULL
183a9b579f3SBram Moolenaar     int		*varargs,
18442ae78cfSBram Moolenaar     garray_T	*default_args,
1855e774c75SBram Moolenaar     int		skip,
1865e774c75SBram Moolenaar     exarg_T	*eap,
1875e774c75SBram Moolenaar     char_u	**line_to_free)
188a9b579f3SBram Moolenaar {
189a9b579f3SBram Moolenaar     int		mustend = FALSE;
190cef1270dSBram Moolenaar     char_u	*arg;
191cef1270dSBram Moolenaar     char_u	*p;
192a9b579f3SBram Moolenaar     int		c;
19342ae78cfSBram Moolenaar     int		any_default = FALSE;
19442ae78cfSBram Moolenaar     char_u	*expr;
195cef1270dSBram Moolenaar     char_u	*whitep = *argp;
196a9b579f3SBram Moolenaar 
197a9b579f3SBram Moolenaar     if (newargs != NULL)
198a9b579f3SBram Moolenaar 	ga_init2(newargs, (int)sizeof(char_u *), 3);
1998a7d6542SBram Moolenaar     if (argtypes != NULL)
2008a7d6542SBram Moolenaar 	ga_init2(argtypes, (int)sizeof(char_u *), 3);
201e3ffaa6bSBram Moolenaar     if (!skip && default_args != NULL)
20242ae78cfSBram Moolenaar 	ga_init2(default_args, (int)sizeof(char_u *), 3);
203a9b579f3SBram Moolenaar 
204a9b579f3SBram Moolenaar     if (varargs != NULL)
205a9b579f3SBram Moolenaar 	*varargs = FALSE;
206a9b579f3SBram Moolenaar 
207a9b579f3SBram Moolenaar     /*
208a9b579f3SBram Moolenaar      * Isolate the arguments: "arg1, arg2, ...)"
209a9b579f3SBram Moolenaar      */
210cef1270dSBram Moolenaar     arg = skipwhite(*argp);
211cef1270dSBram Moolenaar     p = arg;
212a9b579f3SBram Moolenaar     while (*p != endchar)
213a9b579f3SBram Moolenaar     {
2142c330432SBram Moolenaar 	while (eap != NULL && eap->getline != NULL
2152c330432SBram Moolenaar 			 && (*p == NUL || (VIM_ISWHITE(*whitep) && *p == '#')))
2165e774c75SBram Moolenaar 	{
2175e774c75SBram Moolenaar 	    char_u *theline;
2185e774c75SBram Moolenaar 
2195e774c75SBram Moolenaar 	    // End of the line, get the next one.
2205e774c75SBram Moolenaar 	    theline = eap->getline(':', eap->cookie, 0, TRUE);
2215e774c75SBram Moolenaar 	    if (theline == NULL)
2225e774c75SBram Moolenaar 		break;
2235e774c75SBram Moolenaar 	    vim_free(*line_to_free);
2245e774c75SBram Moolenaar 	    *line_to_free = theline;
2252c330432SBram Moolenaar 	    whitep = (char_u *)" ";
2265e774c75SBram Moolenaar 	    p = skipwhite(theline);
2275e774c75SBram Moolenaar 	}
2285e774c75SBram Moolenaar 
2295e774c75SBram Moolenaar 	if (mustend && *p != endchar)
2305e774c75SBram Moolenaar 	{
2315e774c75SBram Moolenaar 	    if (!skip)
2325e774c75SBram Moolenaar 		semsg(_(e_invarg2), *argp);
233b4d16cb1SBram Moolenaar 	    goto err_ret;
2345e774c75SBram Moolenaar 	}
2355e774c75SBram Moolenaar 	if (*p == endchar)
2365e774c75SBram Moolenaar 	    break;
2375e774c75SBram Moolenaar 
238a9b579f3SBram Moolenaar 	if (p[0] == '.' && p[1] == '.' && p[2] == '.')
239a9b579f3SBram Moolenaar 	{
240a9b579f3SBram Moolenaar 	    if (varargs != NULL)
241a9b579f3SBram Moolenaar 		*varargs = TRUE;
242a9b579f3SBram Moolenaar 	    p += 3;
243a9b579f3SBram Moolenaar 	    mustend = TRUE;
2448a7d6542SBram Moolenaar 
2458a7d6542SBram Moolenaar 	    if (argtypes != NULL)
2468a7d6542SBram Moolenaar 	    {
2478a7d6542SBram Moolenaar 		// ...name: list<type>
24828022727SBram Moolenaar 		if (!eval_isnamec1(*p))
2498a7d6542SBram Moolenaar 		{
250b4d16cb1SBram Moolenaar 		    if (!skip)
251451c2e35SBram Moolenaar 			emsg(_(e_missing_name_after_dots));
252b4d16cb1SBram Moolenaar 		    goto err_ret;
2538a7d6542SBram Moolenaar 		}
2548a7d6542SBram Moolenaar 
2558a7d6542SBram Moolenaar 		arg = p;
256b4d16cb1SBram Moolenaar 		p = one_function_arg(p, newargs, argtypes, types_optional,
2572a38908bSBram Moolenaar 							  evalarg, TRUE, skip);
2588a7d6542SBram Moolenaar 		if (p == arg)
2598a7d6542SBram Moolenaar 		    break;
2604f53b79bSBram Moolenaar 		if (*skipwhite(p) == '=')
2614f53b79bSBram Moolenaar 		{
2624f53b79bSBram Moolenaar 		    emsg(_(e_cannot_use_default_for_variable_arguments));
2634f53b79bSBram Moolenaar 		    break;
2644f53b79bSBram Moolenaar 		}
2658a7d6542SBram Moolenaar 	    }
266a9b579f3SBram Moolenaar 	}
267a9b579f3SBram Moolenaar 	else
268a9b579f3SBram Moolenaar 	{
269015cf103SBram Moolenaar 	    char_u *np;
270015cf103SBram Moolenaar 
271a9b579f3SBram Moolenaar 	    arg = p;
272057e84afSBram Moolenaar 	    p = one_function_arg(p, newargs, argtypes, types_optional,
2732a38908bSBram Moolenaar 							 evalarg, FALSE, skip);
2748a7d6542SBram Moolenaar 	    if (p == arg)
275a9b579f3SBram Moolenaar 		break;
276a9b579f3SBram Moolenaar 
277015cf103SBram Moolenaar 	    // Recognize " = expr" but not " == expr".  A lambda can have
27898f9a5f4SBram Moolenaar 	    // "(a = expr" but "(a == expr" and "(a =~ expr" are not a lambda.
279015cf103SBram Moolenaar 	    np = skipwhite(p);
28098f9a5f4SBram Moolenaar 	    if (*np == '=' && np[1] != '=' && np[1] != '~'
28198f9a5f4SBram Moolenaar 						       && default_args != NULL)
28242ae78cfSBram Moolenaar 	    {
28342ae78cfSBram Moolenaar 		typval_T	rettv;
28442ae78cfSBram Moolenaar 
285170fcfcfSBram Moolenaar 		// find the end of the expression (doesn't evaluate it)
28642ae78cfSBram Moolenaar 		any_default = TRUE;
28742ae78cfSBram Moolenaar 		p = skipwhite(p) + 1;
2882c330432SBram Moolenaar 		whitep = p;
28942ae78cfSBram Moolenaar 		p = skipwhite(p);
29042ae78cfSBram Moolenaar 		expr = p;
2915409f5d8SBram Moolenaar 		if (eval1(&p, &rettv, NULL) != FAIL)
29242ae78cfSBram Moolenaar 		{
293e3ffaa6bSBram Moolenaar 		    if (!skip)
294e3ffaa6bSBram Moolenaar 		    {
29542ae78cfSBram Moolenaar 			if (ga_grow(default_args, 1) == FAIL)
29642ae78cfSBram Moolenaar 			    goto err_ret;
29742ae78cfSBram Moolenaar 
29842ae78cfSBram Moolenaar 			// trim trailing whitespace
29942ae78cfSBram Moolenaar 			while (p > expr && VIM_ISWHITE(p[-1]))
30042ae78cfSBram Moolenaar 			    p--;
30142ae78cfSBram Moolenaar 			c = *p;
30242ae78cfSBram Moolenaar 			*p = NUL;
30342ae78cfSBram Moolenaar 			expr = vim_strsave(expr);
30442ae78cfSBram Moolenaar 			if (expr == NULL)
30542ae78cfSBram Moolenaar 			{
30642ae78cfSBram Moolenaar 			    *p = c;
30742ae78cfSBram Moolenaar 			    goto err_ret;
30842ae78cfSBram Moolenaar 			}
30942ae78cfSBram Moolenaar 			((char_u **)(default_args->ga_data))
31042ae78cfSBram Moolenaar 						 [default_args->ga_len] = expr;
31142ae78cfSBram Moolenaar 			default_args->ga_len++;
31242ae78cfSBram Moolenaar 			*p = c;
31342ae78cfSBram Moolenaar 		    }
314e3ffaa6bSBram Moolenaar 		}
31542ae78cfSBram Moolenaar 		else
31642ae78cfSBram Moolenaar 		    mustend = TRUE;
31742ae78cfSBram Moolenaar 	    }
31842ae78cfSBram Moolenaar 	    else if (any_default)
31942ae78cfSBram Moolenaar 	    {
32042ae78cfSBram Moolenaar 		emsg(_("E989: Non-default argument follows default argument"));
321914e7eaaSBram Moolenaar 		goto err_ret;
32242ae78cfSBram Moolenaar 	    }
32386cdb8a4SBram Moolenaar 
32486cdb8a4SBram Moolenaar 	    if (VIM_ISWHITE(*p) && *skipwhite(p) == ',')
32586cdb8a4SBram Moolenaar 	    {
32686cdb8a4SBram Moolenaar 		// Be tolerant when skipping
32786cdb8a4SBram Moolenaar 		if (!skip)
32886cdb8a4SBram Moolenaar 		{
32986cdb8a4SBram Moolenaar 		    semsg(_(e_no_white_space_allowed_before_str_str), ",", p);
33086cdb8a4SBram Moolenaar 		    goto err_ret;
33186cdb8a4SBram Moolenaar 		}
33286cdb8a4SBram Moolenaar 		p = skipwhite(p);
33386cdb8a4SBram Moolenaar 	    }
334a9b579f3SBram Moolenaar 	    if (*p == ',')
335914e7eaaSBram Moolenaar 	    {
336a9b579f3SBram Moolenaar 		++p;
337914e7eaaSBram Moolenaar 		// Don't give this error when skipping, it makes the "->" not
338914e7eaaSBram Moolenaar 		// found in "{k,v -> x}" and give a confusing error.
339608d78fbSBram Moolenaar 		// Allow missing space after comma in legacy functions.
340608d78fbSBram Moolenaar 		if (!skip && argtypes != NULL
341914e7eaaSBram Moolenaar 				      && !IS_WHITE_OR_NUL(*p) && *p != endchar)
342914e7eaaSBram Moolenaar 		{
343c3fc75dbSBram Moolenaar 		    semsg(_(e_white_space_required_after_str_str), ",", p - 1);
344914e7eaaSBram Moolenaar 		    goto err_ret;
345914e7eaaSBram Moolenaar 		}
346914e7eaaSBram Moolenaar 	    }
347a9b579f3SBram Moolenaar 	    else
348a9b579f3SBram Moolenaar 		mustend = TRUE;
349a9b579f3SBram Moolenaar 	}
3502c330432SBram Moolenaar 	whitep = p;
351a9b579f3SBram Moolenaar 	p = skipwhite(p);
352a9b579f3SBram Moolenaar     }
3535e774c75SBram Moolenaar 
3544f0383bcSBram Moolenaar     if (*p != endchar)
3554f0383bcSBram Moolenaar 	goto err_ret;
356e38eab22SBram Moolenaar     ++p;	// skip "endchar"
357a9b579f3SBram Moolenaar 
358a9b579f3SBram Moolenaar     *argp = p;
359a9b579f3SBram Moolenaar     return OK;
360a9b579f3SBram Moolenaar 
361a9b579f3SBram Moolenaar err_ret:
362a9b579f3SBram Moolenaar     if (newargs != NULL)
363a9b579f3SBram Moolenaar 	ga_clear_strings(newargs);
364e3ffaa6bSBram Moolenaar     if (!skip && default_args != NULL)
36542ae78cfSBram Moolenaar 	ga_clear_strings(default_args);
366a9b579f3SBram Moolenaar     return FAIL;
367a9b579f3SBram Moolenaar }
368a9b579f3SBram Moolenaar 
369a9b579f3SBram Moolenaar /*
370b4d16cb1SBram Moolenaar  * Parse the argument types, filling "fp->uf_arg_types".
371b4d16cb1SBram Moolenaar  * Return OK or FAIL.
372b4d16cb1SBram Moolenaar  */
373b4d16cb1SBram Moolenaar     static int
parse_argument_types(ufunc_T * fp,garray_T * argtypes,int varargs)374b4d16cb1SBram Moolenaar parse_argument_types(ufunc_T *fp, garray_T *argtypes, int varargs)
375b4d16cb1SBram Moolenaar {
3762a38908bSBram Moolenaar     int len = 0;
3772a38908bSBram Moolenaar 
378b4d16cb1SBram Moolenaar     ga_init2(&fp->uf_type_list, sizeof(type_T *), 10);
379b4d16cb1SBram Moolenaar     if (argtypes->ga_len > 0)
380b4d16cb1SBram Moolenaar     {
381b4d16cb1SBram Moolenaar 	// When "varargs" is set the last name/type goes into uf_va_name
382b4d16cb1SBram Moolenaar 	// and uf_va_type.
3832a38908bSBram Moolenaar 	len = argtypes->ga_len - (varargs ? 1 : 0);
384b4d16cb1SBram Moolenaar 
385b4d16cb1SBram Moolenaar 	if (len > 0)
386b4d16cb1SBram Moolenaar 	    fp->uf_arg_types = ALLOC_CLEAR_MULT(type_T *, len);
387b4d16cb1SBram Moolenaar 	if (fp->uf_arg_types != NULL)
388b4d16cb1SBram Moolenaar 	{
389b4d16cb1SBram Moolenaar 	    int	i;
390b4d16cb1SBram Moolenaar 	    type_T	*type;
391b4d16cb1SBram Moolenaar 
392b4d16cb1SBram Moolenaar 	    for (i = 0; i < len; ++ i)
393b4d16cb1SBram Moolenaar 	    {
394b4d16cb1SBram Moolenaar 		char_u *p = ((char_u **)argtypes->ga_data)[i];
395b4d16cb1SBram Moolenaar 
396b4d16cb1SBram Moolenaar 		if (p == NULL)
397b4d16cb1SBram Moolenaar 		    // will get the type from the default value
398b4d16cb1SBram Moolenaar 		    type = &t_unknown;
399b4d16cb1SBram Moolenaar 		else
4009e68c325SBram Moolenaar 		    type = parse_type(&p, &fp->uf_type_list, TRUE);
401b4d16cb1SBram Moolenaar 		if (type == NULL)
402b4d16cb1SBram Moolenaar 		    return FAIL;
403b4d16cb1SBram Moolenaar 		fp->uf_arg_types[i] = type;
404b4d16cb1SBram Moolenaar 	    }
405b4d16cb1SBram Moolenaar 	}
4062a38908bSBram Moolenaar     }
4072a38908bSBram Moolenaar 
408b4d16cb1SBram Moolenaar     if (varargs)
409b4d16cb1SBram Moolenaar     {
410b4d16cb1SBram Moolenaar 	char_u *p;
411b4d16cb1SBram Moolenaar 
412b4d16cb1SBram Moolenaar 	// Move the last argument "...name: type" to uf_va_name and
413b4d16cb1SBram Moolenaar 	// uf_va_type.
414b4d16cb1SBram Moolenaar 	fp->uf_va_name = ((char_u **)fp->uf_args.ga_data)
415b4d16cb1SBram Moolenaar 					      [fp->uf_args.ga_len - 1];
416b4d16cb1SBram Moolenaar 	--fp->uf_args.ga_len;
417b4d16cb1SBram Moolenaar 	p = ((char_u **)argtypes->ga_data)[len];
418b4d16cb1SBram Moolenaar 	if (p == NULL)
4192a38908bSBram Moolenaar 	    // TODO: get type from default value
4202a38908bSBram Moolenaar 	    fp->uf_va_type = &t_list_any;
421b4d16cb1SBram Moolenaar 	else
4222a38908bSBram Moolenaar 	{
4239e68c325SBram Moolenaar 	    fp->uf_va_type = parse_type(&p, &fp->uf_type_list, TRUE);
4242a38908bSBram Moolenaar 	    if (fp->uf_va_type != NULL && fp->uf_va_type->tt_type != VAR_LIST)
4252a38908bSBram Moolenaar 	    {
4262a38908bSBram Moolenaar 		semsg(_(e_variable_arguments_type_must_be_list_str),
4272a38908bSBram Moolenaar 					  ((char_u **)argtypes->ga_data)[len]);
428b4d16cb1SBram Moolenaar 		return FAIL;
429b4d16cb1SBram Moolenaar 	    }
430b4d16cb1SBram Moolenaar 	}
4312a38908bSBram Moolenaar 	if (fp->uf_va_type == NULL)
4322a38908bSBram Moolenaar 	    return FAIL;
4332a38908bSBram Moolenaar     }
4342a38908bSBram Moolenaar 
435b4d16cb1SBram Moolenaar     return OK;
436b4d16cb1SBram Moolenaar }
437b4d16cb1SBram Moolenaar 
4387a6eaa06SBram Moolenaar     static int
parse_return_type(ufunc_T * fp,char_u * ret_type)4397a6eaa06SBram Moolenaar parse_return_type(ufunc_T *fp, char_u *ret_type)
4407a6eaa06SBram Moolenaar {
4417a6eaa06SBram Moolenaar     if (ret_type == NULL)
4427a6eaa06SBram Moolenaar 	fp->uf_ret_type = &t_void;
4437a6eaa06SBram Moolenaar     else
4447a6eaa06SBram Moolenaar     {
4457a6eaa06SBram Moolenaar 	char_u *p = ret_type;
4467a6eaa06SBram Moolenaar 
4477a6eaa06SBram Moolenaar 	fp->uf_ret_type = parse_type(&p, &fp->uf_type_list, TRUE);
4487a6eaa06SBram Moolenaar 	if (fp->uf_ret_type == NULL)
4497a6eaa06SBram Moolenaar 	{
4507a6eaa06SBram Moolenaar 	    fp->uf_ret_type = &t_void;
4517a6eaa06SBram Moolenaar 	    return FAIL;
4527a6eaa06SBram Moolenaar 	}
4537a6eaa06SBram Moolenaar     }
4547a6eaa06SBram Moolenaar     return OK;
4557a6eaa06SBram Moolenaar }
4567a6eaa06SBram Moolenaar 
457b4d16cb1SBram Moolenaar /*
45858016448SBram Moolenaar  * Register function "fp" as using "current_funccal" as its scope.
45958016448SBram Moolenaar  */
46058016448SBram Moolenaar     static int
register_closure(ufunc_T * fp)46158016448SBram Moolenaar register_closure(ufunc_T *fp)
46258016448SBram Moolenaar {
4638dd3a43dSBram Moolenaar     if (fp->uf_scoped == current_funccal)
464e38eab22SBram Moolenaar 	// no change
4658dd3a43dSBram Moolenaar 	return OK;
466bc7ce675SBram Moolenaar     funccal_unref(fp->uf_scoped, fp, FALSE);
46758016448SBram Moolenaar     fp->uf_scoped = current_funccal;
46858016448SBram Moolenaar     current_funccal->fc_refcount++;
4698dd3a43dSBram Moolenaar 
47058016448SBram Moolenaar     if (ga_grow(&current_funccal->fc_funcs, 1) == FAIL)
47158016448SBram Moolenaar 	return FAIL;
47258016448SBram Moolenaar     ((ufunc_T **)current_funccal->fc_funcs.ga_data)
47358016448SBram Moolenaar 	[current_funccal->fc_funcs.ga_len++] = fp;
47458016448SBram Moolenaar     return OK;
47558016448SBram Moolenaar }
47658016448SBram Moolenaar 
4771a47ae32SBram Moolenaar     static void
set_ufunc_name(ufunc_T * fp,char_u * name)4781a47ae32SBram Moolenaar set_ufunc_name(ufunc_T *fp, char_u *name)
4791a47ae32SBram Moolenaar {
4807b6903f0SBram Moolenaar     // Add a type cast to avoid a warning for an overflow, the uf_name[] array
4817b6903f0SBram Moolenaar     // actually extends beyond the struct.
4827b6903f0SBram Moolenaar     STRCPY((void *)fp->uf_name, name);
4831a47ae32SBram Moolenaar 
4841a47ae32SBram Moolenaar     if (name[0] == K_SPECIAL)
4851a47ae32SBram Moolenaar     {
4861a47ae32SBram Moolenaar 	fp->uf_name_exp = alloc(STRLEN(name) + 3);
4871a47ae32SBram Moolenaar 	if (fp->uf_name_exp != NULL)
4881a47ae32SBram Moolenaar 	{
4891a47ae32SBram Moolenaar 	    STRCPY(fp->uf_name_exp, "<SNR>");
4901a47ae32SBram Moolenaar 	    STRCAT(fp->uf_name_exp, fp->uf_name + 3);
4911a47ae32SBram Moolenaar 	}
4921a47ae32SBram Moolenaar     }
4931a47ae32SBram Moolenaar }
4941a47ae32SBram Moolenaar 
49558016448SBram Moolenaar /*
49604b12697SBram Moolenaar  * Get a name for a lambda.  Returned in static memory.
49704b12697SBram Moolenaar  */
49804b12697SBram Moolenaar     char_u *
get_lambda_name(void)49904b12697SBram Moolenaar get_lambda_name(void)
50004b12697SBram Moolenaar {
50104b12697SBram Moolenaar     static char_u   name[30];
50204b12697SBram Moolenaar     static int	    lambda_no = 0;
50304b12697SBram Moolenaar 
50404b12697SBram Moolenaar     sprintf((char*)name, "<lambda>%d", ++lambda_no);
50504b12697SBram Moolenaar     return name;
50604b12697SBram Moolenaar }
50704b12697SBram Moolenaar 
508801ab069SBram Moolenaar #if defined(FEAT_LUA) || defined(PROTO)
509801ab069SBram Moolenaar /*
510801ab069SBram Moolenaar  * Registers a native C callback which can be called from Vim script.
511801ab069SBram Moolenaar  * Returns the name of the Vim script function.
512801ab069SBram Moolenaar  */
513801ab069SBram Moolenaar     char_u *
register_cfunc(cfunc_T cb,cfunc_free_T cb_free,void * state)514801ab069SBram Moolenaar register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state)
515801ab069SBram Moolenaar {
516801ab069SBram Moolenaar     char_u	*name = get_lambda_name();
5177d2ac92eSBram Moolenaar     ufunc_T	*fp;
518801ab069SBram Moolenaar 
519801ab069SBram Moolenaar     fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1);
520801ab069SBram Moolenaar     if (fp == NULL)
5217d2ac92eSBram Moolenaar 	return NULL;
522801ab069SBram Moolenaar 
52338ddf333SBram Moolenaar     fp->uf_def_status = UF_NOT_COMPILED;
524801ab069SBram Moolenaar     fp->uf_refcount = 1;
525801ab069SBram Moolenaar     fp->uf_varargs = TRUE;
526801ab069SBram Moolenaar     fp->uf_flags = FC_CFUNC;
527801ab069SBram Moolenaar     fp->uf_calls = 0;
528801ab069SBram Moolenaar     fp->uf_script_ctx = current_sctx;
529801ab069SBram Moolenaar     fp->uf_cb = cb;
530801ab069SBram Moolenaar     fp->uf_cb_free = cb_free;
531801ab069SBram Moolenaar     fp->uf_cb_state = state;
532801ab069SBram Moolenaar 
533801ab069SBram Moolenaar     set_ufunc_name(fp, name);
534801ab069SBram Moolenaar     hash_add(&func_hashtab, UF2HIKEY(fp));
535801ab069SBram Moolenaar 
536801ab069SBram Moolenaar     return name;
537801ab069SBram Moolenaar }
538801ab069SBram Moolenaar #endif
539801ab069SBram Moolenaar 
54004b12697SBram Moolenaar /*
54165c44152SBram Moolenaar  * Skip over "->" or "=>" after the arguments of a lambda.
5429e68c325SBram Moolenaar  * If ": type" is found make "ret_type" point to "type".
543c754b4ccSBram Moolenaar  * If "white_error" is not NULL check for correct use of white space and set
544c754b4ccSBram Moolenaar  * "white_error" to TRUE if there is an error.
54565c44152SBram Moolenaar  * Return NULL if no valid arrow found.
54665c44152SBram Moolenaar  */
54765c44152SBram Moolenaar     static char_u *
skip_arrow(char_u * start,int equal_arrow,char_u ** ret_type,int * white_error)548c754b4ccSBram Moolenaar skip_arrow(
549c754b4ccSBram Moolenaar 	char_u	*start,
550c754b4ccSBram Moolenaar 	int	equal_arrow,
551c754b4ccSBram Moolenaar 	char_u	**ret_type,
552c754b4ccSBram Moolenaar 	int	*white_error)
55365c44152SBram Moolenaar {
55465c44152SBram Moolenaar     char_u  *s = start;
555c754b4ccSBram Moolenaar     char_u  *bef = start - 2; // "start" points to > of ->
55665c44152SBram Moolenaar 
55765c44152SBram Moolenaar     if (equal_arrow)
55865c44152SBram Moolenaar     {
55965c44152SBram Moolenaar 	if (*s == ':')
5609e68c325SBram Moolenaar 	{
561c754b4ccSBram Moolenaar 	    if (white_error != NULL && !VIM_ISWHITE(s[1]))
562c754b4ccSBram Moolenaar 	    {
563c754b4ccSBram Moolenaar 		*white_error = TRUE;
564c3fc75dbSBram Moolenaar 		semsg(_(e_white_space_required_after_str_str), ":", s);
565c754b4ccSBram Moolenaar 		return NULL;
566c754b4ccSBram Moolenaar 	    }
5679e68c325SBram Moolenaar 	    s = skipwhite(s + 1);
5689e68c325SBram Moolenaar 	    *ret_type = s;
5699e68c325SBram Moolenaar 	    s = skip_type(s, TRUE);
5700346b799SBram Moolenaar 	    if (s == *ret_type)
5710346b799SBram Moolenaar 	    {
5720346b799SBram Moolenaar 		emsg(_(e_missing_return_type));
5730346b799SBram Moolenaar 		return NULL;
5740346b799SBram Moolenaar 	    }
5759e68c325SBram Moolenaar 	}
576c754b4ccSBram Moolenaar 	bef = s;
57765c44152SBram Moolenaar 	s = skipwhite(s);
57865c44152SBram Moolenaar 	if (*s != '=')
57965c44152SBram Moolenaar 	    return NULL;
58065c44152SBram Moolenaar 	++s;
58165c44152SBram Moolenaar     }
58265c44152SBram Moolenaar     if (*s != '>')
58365c44152SBram Moolenaar 	return NULL;
584c754b4ccSBram Moolenaar     if (white_error != NULL && ((!VIM_ISWHITE(*bef) && *bef != '{')
585c754b4ccSBram Moolenaar 		|| !IS_WHITE_OR_NUL(s[1])))
586c754b4ccSBram Moolenaar     {
587c754b4ccSBram Moolenaar 	*white_error = TRUE;
588e7a73e07SBram Moolenaar 	semsg(_(e_white_space_required_before_and_after_str_at_str),
589e7a73e07SBram Moolenaar 					       equal_arrow ? "=>" : "->", bef);
590c754b4ccSBram Moolenaar 	return NULL;
591c754b4ccSBram Moolenaar     }
59265c44152SBram Moolenaar     return skipwhite(s + 1);
59365c44152SBram Moolenaar }
59465c44152SBram Moolenaar 
59565c44152SBram Moolenaar /*
5967a6eaa06SBram Moolenaar  * Check if "*cmd" points to a function command and if so advance "*cmd" and
5977a6eaa06SBram Moolenaar  * return TRUE.
5987a6eaa06SBram Moolenaar  * Otherwise return FALSE;
5997a6eaa06SBram Moolenaar  * Do not consider "function(" to be a command.
6007a6eaa06SBram Moolenaar  */
6017a6eaa06SBram Moolenaar     static int
is_function_cmd(char_u ** cmd)6027a6eaa06SBram Moolenaar is_function_cmd(char_u **cmd)
6037a6eaa06SBram Moolenaar {
6047a6eaa06SBram Moolenaar     char_u *p = *cmd;
6057a6eaa06SBram Moolenaar 
6067a6eaa06SBram Moolenaar     if (checkforcmd(&p, "function", 2))
6077a6eaa06SBram Moolenaar     {
6087a6eaa06SBram Moolenaar 	if (*p == '(')
6097a6eaa06SBram Moolenaar 	    return FALSE;
6107a6eaa06SBram Moolenaar 	*cmd = p;
6117a6eaa06SBram Moolenaar 	return TRUE;
6127a6eaa06SBram Moolenaar     }
6137a6eaa06SBram Moolenaar     return FALSE;
6147a6eaa06SBram Moolenaar }
6157a6eaa06SBram Moolenaar 
6167a6eaa06SBram Moolenaar /*
6172eb6fc3bSBram Moolenaar  * Called when defining a function: The context may be needed for script
6182eb6fc3bSBram Moolenaar  * variables declared in a block that is visible now but not when the function
6192eb6fc3bSBram Moolenaar  * is compiled or called later.
6202eb6fc3bSBram Moolenaar  */
6212eb6fc3bSBram Moolenaar     static void
function_using_block_scopes(ufunc_T * fp,cstack_T * cstack)6222eb6fc3bSBram Moolenaar function_using_block_scopes(ufunc_T *fp, cstack_T *cstack)
6232eb6fc3bSBram Moolenaar {
6242eb6fc3bSBram Moolenaar     if (cstack != NULL && cstack->cs_idx >= 0)
6252eb6fc3bSBram Moolenaar     {
6262eb6fc3bSBram Moolenaar 	int	    count = cstack->cs_idx + 1;
6272eb6fc3bSBram Moolenaar 	int	    i;
6282eb6fc3bSBram Moolenaar 
6292eb6fc3bSBram Moolenaar 	fp->uf_block_ids = ALLOC_MULT(int, count);
6302eb6fc3bSBram Moolenaar 	if (fp->uf_block_ids != NULL)
6312eb6fc3bSBram Moolenaar 	{
6322eb6fc3bSBram Moolenaar 	    mch_memmove(fp->uf_block_ids, cstack->cs_block_id,
6332eb6fc3bSBram Moolenaar 							  sizeof(int) * count);
6342eb6fc3bSBram Moolenaar 	    fp->uf_block_depth = count;
6352eb6fc3bSBram Moolenaar 	}
6362eb6fc3bSBram Moolenaar 
6372eb6fc3bSBram Moolenaar 	// Set flag in each block to indicate a function was defined.  This
6382eb6fc3bSBram Moolenaar 	// is used to keep the variable when leaving the block, see
6392eb6fc3bSBram Moolenaar 	// hide_script_var().
6402eb6fc3bSBram Moolenaar 	for (i = 0; i <= cstack->cs_idx; ++i)
6412eb6fc3bSBram Moolenaar 	    cstack->cs_flags[i] |= CSF_FUNC_DEF;
6422eb6fc3bSBram Moolenaar     }
6432eb6fc3bSBram Moolenaar }
6442eb6fc3bSBram Moolenaar 
6452eb6fc3bSBram Moolenaar /*
6467a6eaa06SBram Moolenaar  * Read the body of a function, put every line in "newlines".
647074f84c0SBram Moolenaar  * This stops at "}", "endfunction" or "enddef".
6487a6eaa06SBram Moolenaar  * "newlines" must already have been initialized.
6497a6eaa06SBram Moolenaar  * "eap->cmdidx" is CMD_function, CMD_def or CMD_block;
6507a6eaa06SBram Moolenaar  */
6517a6eaa06SBram Moolenaar     static int
get_function_body(exarg_T * eap,garray_T * newlines,char_u * line_arg_in,char_u ** line_to_free)6527a6eaa06SBram Moolenaar get_function_body(
6537a6eaa06SBram Moolenaar 	exarg_T	    *eap,
6547a6eaa06SBram Moolenaar 	garray_T    *newlines,
6557a6eaa06SBram Moolenaar 	char_u	    *line_arg_in,
6567a6eaa06SBram Moolenaar 	char_u	    **line_to_free)
6577a6eaa06SBram Moolenaar {
6587a6eaa06SBram Moolenaar     linenr_T	sourcing_lnum_top = SOURCING_LNUM;
6597a6eaa06SBram Moolenaar     linenr_T	sourcing_lnum_off;
6607a6eaa06SBram Moolenaar     int		saved_wait_return = need_wait_return;
6617a6eaa06SBram Moolenaar     char_u	*line_arg = line_arg_in;
6627a6eaa06SBram Moolenaar     int		vim9_function = eap->cmdidx == CMD_def
6637a6eaa06SBram Moolenaar 						   || eap->cmdidx == CMD_block;
6647a6eaa06SBram Moolenaar #define MAX_FUNC_NESTING 50
6657a6eaa06SBram Moolenaar     char	nesting_def[MAX_FUNC_NESTING];
6665245beb3SBram Moolenaar     char	nesting_inline[MAX_FUNC_NESTING];
6677a6eaa06SBram Moolenaar     int		nesting = 0;
6687a6eaa06SBram Moolenaar     getline_opt_T getline_options;
6697a6eaa06SBram Moolenaar     int		indent = 2;
6707a6eaa06SBram Moolenaar     char_u	*skip_until = NULL;
6717a6eaa06SBram Moolenaar     int		ret = FAIL;
6727a6eaa06SBram Moolenaar     int		is_heredoc = FALSE;
6732067733bSBram Moolenaar     int		heredoc_concat_len = 0;
6742067733bSBram Moolenaar     garray_T	heredoc_ga;
6757a6eaa06SBram Moolenaar     char_u	*heredoc_trimmed = NULL;
6767a6eaa06SBram Moolenaar 
6772067733bSBram Moolenaar     ga_init2(&heredoc_ga, 1, 500);
6782067733bSBram Moolenaar 
6797a6eaa06SBram Moolenaar     // Detect having skipped over comment lines to find the return
6807a6eaa06SBram Moolenaar     // type.  Add NULL lines to keep the line count correct.
6817a6eaa06SBram Moolenaar     sourcing_lnum_off = get_sourced_lnum(eap->getline, eap->cookie);
6827a6eaa06SBram Moolenaar     if (SOURCING_LNUM < sourcing_lnum_off)
6837a6eaa06SBram Moolenaar     {
6847a6eaa06SBram Moolenaar 	sourcing_lnum_off -= SOURCING_LNUM;
6857a6eaa06SBram Moolenaar 	if (ga_grow(newlines, sourcing_lnum_off) == FAIL)
6867a6eaa06SBram Moolenaar 	    goto theend;
6877a6eaa06SBram Moolenaar 	while (sourcing_lnum_off-- > 0)
6887a6eaa06SBram Moolenaar 	    ((char_u **)(newlines->ga_data))[newlines->ga_len++] = NULL;
6897a6eaa06SBram Moolenaar     }
6907a6eaa06SBram Moolenaar 
6915245beb3SBram Moolenaar     nesting_def[0] = vim9_function;
6925245beb3SBram Moolenaar     nesting_inline[0] = eap->cmdidx == CMD_block;
6937a6eaa06SBram Moolenaar     getline_options = vim9_function
6947a6eaa06SBram Moolenaar 				? GETLINE_CONCAT_CONTBAR : GETLINE_CONCAT_CONT;
6957a6eaa06SBram Moolenaar     for (;;)
6967a6eaa06SBram Moolenaar     {
6977a6eaa06SBram Moolenaar 	char_u	*theline;
6987a6eaa06SBram Moolenaar 	char_u	*p;
6997a6eaa06SBram Moolenaar 	char_u	*arg;
7007a6eaa06SBram Moolenaar 
7017a6eaa06SBram Moolenaar 	if (KeyTyped)
7027a6eaa06SBram Moolenaar 	{
7037a6eaa06SBram Moolenaar 	    msg_scroll = TRUE;
7047a6eaa06SBram Moolenaar 	    saved_wait_return = FALSE;
7057a6eaa06SBram Moolenaar 	}
7067a6eaa06SBram Moolenaar 	need_wait_return = FALSE;
7077a6eaa06SBram Moolenaar 
7087a6eaa06SBram Moolenaar 	if (line_arg != NULL)
7097a6eaa06SBram Moolenaar 	{
7107a6eaa06SBram Moolenaar 	    // Use eap->arg, split up in parts by line breaks.
7117a6eaa06SBram Moolenaar 	    theline = line_arg;
7127a6eaa06SBram Moolenaar 	    p = vim_strchr(theline, '\n');
7137a6eaa06SBram Moolenaar 	    if (p == NULL)
7147a6eaa06SBram Moolenaar 		line_arg += STRLEN(line_arg);
7157a6eaa06SBram Moolenaar 	    else
7167a6eaa06SBram Moolenaar 	    {
7177a6eaa06SBram Moolenaar 		*p = NUL;
7187a6eaa06SBram Moolenaar 		line_arg = p + 1;
7197a6eaa06SBram Moolenaar 	    }
7207a6eaa06SBram Moolenaar 	}
7217a6eaa06SBram Moolenaar 	else
7227a6eaa06SBram Moolenaar 	{
7237a6eaa06SBram Moolenaar 	    vim_free(*line_to_free);
7247a6eaa06SBram Moolenaar 	    if (eap->getline == NULL)
7257a6eaa06SBram Moolenaar 		theline = getcmdline(':', 0L, indent, getline_options);
7267a6eaa06SBram Moolenaar 	    else
7277a6eaa06SBram Moolenaar 		theline = eap->getline(':', eap->cookie, indent,
7287a6eaa06SBram Moolenaar 							      getline_options);
7297a6eaa06SBram Moolenaar 	    *line_to_free = theline;
7307a6eaa06SBram Moolenaar 	}
7317a6eaa06SBram Moolenaar 	if (KeyTyped)
7327a6eaa06SBram Moolenaar 	    lines_left = Rows - 1;
7337a6eaa06SBram Moolenaar 	if (theline == NULL)
7347a6eaa06SBram Moolenaar 	{
7357a6eaa06SBram Moolenaar 	    // Use the start of the function for the line number.
7367a6eaa06SBram Moolenaar 	    SOURCING_LNUM = sourcing_lnum_top;
7377a6eaa06SBram Moolenaar 	    if (skip_until != NULL)
7387a6eaa06SBram Moolenaar 		semsg(_(e_missing_heredoc_end_marker_str), skip_until);
7395245beb3SBram Moolenaar 	    else if (nesting_inline[nesting])
7405245beb3SBram Moolenaar 		emsg(_(e_missing_end_block));
7417a6eaa06SBram Moolenaar 	    else if (eap->cmdidx == CMD_def)
7427a6eaa06SBram Moolenaar 		emsg(_(e_missing_enddef));
7437a6eaa06SBram Moolenaar 	    else
7447a6eaa06SBram Moolenaar 		emsg(_("E126: Missing :endfunction"));
7457a6eaa06SBram Moolenaar 	    goto theend;
7467a6eaa06SBram Moolenaar 	}
7477a6eaa06SBram Moolenaar 
7487a6eaa06SBram Moolenaar 	// Detect line continuation: SOURCING_LNUM increased more than one.
7497a6eaa06SBram Moolenaar 	sourcing_lnum_off = get_sourced_lnum(eap->getline, eap->cookie);
7507a6eaa06SBram Moolenaar 	if (SOURCING_LNUM < sourcing_lnum_off)
7517a6eaa06SBram Moolenaar 	    sourcing_lnum_off -= SOURCING_LNUM;
7527a6eaa06SBram Moolenaar 	else
7537a6eaa06SBram Moolenaar 	    sourcing_lnum_off = 0;
7547a6eaa06SBram Moolenaar 
7557a6eaa06SBram Moolenaar 	if (skip_until != NULL)
7567a6eaa06SBram Moolenaar 	{
7577a6eaa06SBram Moolenaar 	    // Don't check for ":endfunc"/":enddef" between
7587a6eaa06SBram Moolenaar 	    // * ":append" and "."
7597a6eaa06SBram Moolenaar 	    // * ":python <<EOF" and "EOF"
7607a6eaa06SBram Moolenaar 	    // * ":let {var-name} =<< [trim] {marker}" and "{marker}"
7617a6eaa06SBram Moolenaar 	    if (heredoc_trimmed == NULL
7627a6eaa06SBram Moolenaar 		    || (is_heredoc && skipwhite(theline) == theline)
7637a6eaa06SBram Moolenaar 		    || STRNCMP(theline, heredoc_trimmed,
7647a6eaa06SBram Moolenaar 						 STRLEN(heredoc_trimmed)) == 0)
7657a6eaa06SBram Moolenaar 	    {
7667a6eaa06SBram Moolenaar 		if (heredoc_trimmed == NULL)
7677a6eaa06SBram Moolenaar 		    p = theline;
7687a6eaa06SBram Moolenaar 		else if (is_heredoc)
7697a6eaa06SBram Moolenaar 		    p = skipwhite(theline) == theline
7707a6eaa06SBram Moolenaar 				 ? theline : theline + STRLEN(heredoc_trimmed);
7717a6eaa06SBram Moolenaar 		else
7727a6eaa06SBram Moolenaar 		    p = theline + STRLEN(heredoc_trimmed);
7737a6eaa06SBram Moolenaar 		if (STRCMP(p, skip_until) == 0)
7747a6eaa06SBram Moolenaar 		{
7757a6eaa06SBram Moolenaar 		    VIM_CLEAR(skip_until);
7767a6eaa06SBram Moolenaar 		    VIM_CLEAR(heredoc_trimmed);
7777a6eaa06SBram Moolenaar 		    getline_options = vim9_function
7787a6eaa06SBram Moolenaar 				? GETLINE_CONCAT_CONTBAR : GETLINE_CONCAT_CONT;
7797a6eaa06SBram Moolenaar 		    is_heredoc = FALSE;
7802067733bSBram Moolenaar 
7812067733bSBram Moolenaar 		    if (heredoc_concat_len > 0)
7822067733bSBram Moolenaar 		    {
7832067733bSBram Moolenaar 			// Replace the starting line with all the concatenated
7842067733bSBram Moolenaar 			// lines.
7852067733bSBram Moolenaar 			ga_concat(&heredoc_ga, theline);
7862067733bSBram Moolenaar 			vim_free(((char_u **)(newlines->ga_data))[
7872067733bSBram Moolenaar 						      heredoc_concat_len - 1]);
7882067733bSBram Moolenaar 			((char_u **)(newlines->ga_data))[
7892067733bSBram Moolenaar 				  heredoc_concat_len - 1] = heredoc_ga.ga_data;
7902067733bSBram Moolenaar 			ga_init(&heredoc_ga);
7912067733bSBram Moolenaar 			heredoc_concat_len = 0;
7922067733bSBram Moolenaar 			theline += STRLEN(theline);  // skip the "EOF"
7932067733bSBram Moolenaar 		    }
7947a6eaa06SBram Moolenaar 		}
7957a6eaa06SBram Moolenaar 	    }
7967a6eaa06SBram Moolenaar 	}
7977a6eaa06SBram Moolenaar 	else
7987a6eaa06SBram Moolenaar 	{
7997a6eaa06SBram Moolenaar 	    int	    c;
8005245beb3SBram Moolenaar 	    char_u  *end;
8017a6eaa06SBram Moolenaar 
8027a6eaa06SBram Moolenaar 	    // skip ':' and blanks
8037a6eaa06SBram Moolenaar 	    for (p = theline; VIM_ISWHITE(*p) || *p == ':'; ++p)
8047a6eaa06SBram Moolenaar 		;
8057a6eaa06SBram Moolenaar 
8067a6eaa06SBram Moolenaar 	    // Check for "endfunction", "enddef" or "}".
8077a6eaa06SBram Moolenaar 	    // When a ":" follows it must be a dict key; "enddef: value,"
8085245beb3SBram Moolenaar 	    if (nesting_inline[nesting]
8097a6eaa06SBram Moolenaar 		    ? *p == '}'
8107a6eaa06SBram Moolenaar 		    : (checkforcmd(&p, nesting_def[nesting]
8117a6eaa06SBram Moolenaar 						? "enddef" : "endfunction", 4)
8127a6eaa06SBram Moolenaar 			&& *p != ':'))
8137a6eaa06SBram Moolenaar 	    {
8147a6eaa06SBram Moolenaar 		if (nesting-- == 0)
8157a6eaa06SBram Moolenaar 		{
8167a6eaa06SBram Moolenaar 		    char_u *nextcmd = NULL;
8177a6eaa06SBram Moolenaar 
8187a6eaa06SBram Moolenaar 		    if (*p == '|' || *p == '}')
8197a6eaa06SBram Moolenaar 			nextcmd = p + 1;
8207a6eaa06SBram Moolenaar 		    else if (line_arg != NULL && *skipwhite(line_arg) != NUL)
8217a6eaa06SBram Moolenaar 			nextcmd = line_arg;
8227a6eaa06SBram Moolenaar 		    else if (*p != NUL && *p != (vim9_function ? '#' : '"')
82349f1e9ecSBram Moolenaar 					   && (vim9_function || p_verbose > 0))
82449f1e9ecSBram Moolenaar 		    {
8254bba16d2SBram Moolenaar 			SOURCING_LNUM = sourcing_lnum_top
8264bba16d2SBram Moolenaar 							+ newlines->ga_len + 1;
82749f1e9ecSBram Moolenaar 			if (eap->cmdidx == CMD_def)
82849f1e9ecSBram Moolenaar 			    semsg(_(e_text_found_after_enddef_str), p);
82949f1e9ecSBram Moolenaar 			else
83049f1e9ecSBram Moolenaar 			    give_warning2((char_u *)
83149f1e9ecSBram Moolenaar 				   _("W22: Text found after :endfunction: %s"),
8327a6eaa06SBram Moolenaar 				   p, TRUE);
83349f1e9ecSBram Moolenaar 		    }
83449f1e9ecSBram Moolenaar 		    if (nextcmd != NULL && *skipwhite(nextcmd) != NUL)
8357a6eaa06SBram Moolenaar 		    {
8367a6eaa06SBram Moolenaar 			// Another command follows. If the line came from "eap"
8377a6eaa06SBram Moolenaar 			// we can simply point into it, otherwise we need to
8387a6eaa06SBram Moolenaar 			// change "eap->cmdlinep".
8397a6eaa06SBram Moolenaar 			eap->nextcmd = nextcmd;
8407a6eaa06SBram Moolenaar 			if (*line_to_free != NULL)
8417a6eaa06SBram Moolenaar 			{
8427a6eaa06SBram Moolenaar 			    vim_free(*eap->cmdlinep);
8437a6eaa06SBram Moolenaar 			    *eap->cmdlinep = *line_to_free;
8447a6eaa06SBram Moolenaar 			    *line_to_free = NULL;
8457a6eaa06SBram Moolenaar 			}
8467a6eaa06SBram Moolenaar 		    }
8477a6eaa06SBram Moolenaar 		    break;
8487a6eaa06SBram Moolenaar 		}
8497a6eaa06SBram Moolenaar 	    }
8507a6eaa06SBram Moolenaar 
8517a6eaa06SBram Moolenaar 	    // Check for mismatched "endfunc" or "enddef".
8527a6eaa06SBram Moolenaar 	    // We don't check for "def" inside "func" thus we also can't check
8537a6eaa06SBram Moolenaar 	    // for "enddef".
8547a6eaa06SBram Moolenaar 	    // We continue to find the end of the function, although we might
8557a6eaa06SBram Moolenaar 	    // not find it.
8567a6eaa06SBram Moolenaar 	    else if (nesting_def[nesting])
8577a6eaa06SBram Moolenaar 	    {
8587a6eaa06SBram Moolenaar 		if (checkforcmd(&p, "endfunction", 4) && *p != ':')
8597a6eaa06SBram Moolenaar 		    emsg(_(e_mismatched_endfunction));
8607a6eaa06SBram Moolenaar 	    }
8617a6eaa06SBram Moolenaar 	    else if (eap->cmdidx == CMD_def && checkforcmd(&p, "enddef", 4))
8627a6eaa06SBram Moolenaar 		emsg(_(e_mismatched_enddef));
8637a6eaa06SBram Moolenaar 
8647a6eaa06SBram Moolenaar 	    // Increase indent inside "if", "while", "for" and "try", decrease
8657a6eaa06SBram Moolenaar 	    // at "end".
8667a6eaa06SBram Moolenaar 	    if (indent > 2 && (*p == '}' || STRNCMP(p, "end", 3) == 0))
8677a6eaa06SBram Moolenaar 		indent -= 2;
8687a6eaa06SBram Moolenaar 	    else if (STRNCMP(p, "if", 2) == 0
8697a6eaa06SBram Moolenaar 		    || STRNCMP(p, "wh", 2) == 0
8707a6eaa06SBram Moolenaar 		    || STRNCMP(p, "for", 3) == 0
8717a6eaa06SBram Moolenaar 		    || STRNCMP(p, "try", 3) == 0)
8727a6eaa06SBram Moolenaar 		indent += 2;
8737a6eaa06SBram Moolenaar 
8747a6eaa06SBram Moolenaar 	    // Check for defining a function inside this function.
8757a6eaa06SBram Moolenaar 	    // Only recognize "def" inside "def", not inside "function",
8767a6eaa06SBram Moolenaar 	    // For backwards compatibility, see Test_function_python().
8777a6eaa06SBram Moolenaar 	    c = *p;
8787a6eaa06SBram Moolenaar 	    if (is_function_cmd(&p)
8797a6eaa06SBram Moolenaar 		    || (eap->cmdidx == CMD_def && checkforcmd(&p, "def", 3)))
8807a6eaa06SBram Moolenaar 	    {
8817a6eaa06SBram Moolenaar 		if (*p == '!')
8827a6eaa06SBram Moolenaar 		    p = skipwhite(p + 1);
8837a6eaa06SBram Moolenaar 		p += eval_fname_script(p);
8847a6eaa06SBram Moolenaar 		vim_free(trans_function_name(&p, NULL, TRUE, 0, NULL,
8857a6eaa06SBram Moolenaar 								  NULL, NULL));
8867a6eaa06SBram Moolenaar 		if (*skipwhite(p) == '(')
8877a6eaa06SBram Moolenaar 		{
8887a6eaa06SBram Moolenaar 		    if (nesting == MAX_FUNC_NESTING - 1)
8897a6eaa06SBram Moolenaar 			emsg(_(e_function_nesting_too_deep));
8907a6eaa06SBram Moolenaar 		    else
8917a6eaa06SBram Moolenaar 		    {
8927a6eaa06SBram Moolenaar 			++nesting;
8937a6eaa06SBram Moolenaar 			nesting_def[nesting] = (c == 'd');
8945245beb3SBram Moolenaar 			nesting_inline[nesting] = FALSE;
8955245beb3SBram Moolenaar 			indent += 2;
8965245beb3SBram Moolenaar 		    }
8975245beb3SBram Moolenaar 		}
8985245beb3SBram Moolenaar 	    }
8995245beb3SBram Moolenaar 
900ac2cd2b0SBram Moolenaar 	    if (nesting_def[nesting] ? *p != '#' : *p != '"')
901ac2cd2b0SBram Moolenaar 	    {
902ac2cd2b0SBram Moolenaar 		// Not a comment line: check for nested inline function.
9035245beb3SBram Moolenaar 		end = p + STRLEN(p) - 1;
9045245beb3SBram Moolenaar 		while (end > p && VIM_ISWHITE(*end))
9055245beb3SBram Moolenaar 		    --end;
90613212573SBram Moolenaar 		if (end > p + 1 && *end == '{' && VIM_ISWHITE(end[-1]))
9075245beb3SBram Moolenaar 		{
908e4db17fbSBram Moolenaar 		    int	    is_block;
909e4db17fbSBram Moolenaar 
910e4db17fbSBram Moolenaar 		    // check for trailing "=> {": start of an inline function
9115245beb3SBram Moolenaar 		    --end;
9125245beb3SBram Moolenaar 		    while (end > p && VIM_ISWHITE(*end))
9135245beb3SBram Moolenaar 			--end;
914e4db17fbSBram Moolenaar 		    is_block = end > p + 2 && end[-1] == '=' && end[0] == '>';
915e4db17fbSBram Moolenaar 		    if (!is_block)
9165245beb3SBram Moolenaar 		    {
917e4db17fbSBram Moolenaar 			char_u *s = p;
918e4db17fbSBram Moolenaar 
919e4db17fbSBram Moolenaar 			// check for line starting with "au" for :autocmd or
920e4db17fbSBram Moolenaar 			// "com" for :command, these can use a {} block
921e4db17fbSBram Moolenaar 			is_block = checkforcmd_noparen(&s, "autocmd", 2)
922e4db17fbSBram Moolenaar 				      || checkforcmd_noparen(&s, "command", 3);
923e4db17fbSBram Moolenaar 		    }
924e4db17fbSBram Moolenaar 
925e4db17fbSBram Moolenaar 		    if (is_block)
926e4db17fbSBram Moolenaar 		    {
9275245beb3SBram Moolenaar 			if (nesting == MAX_FUNC_NESTING - 1)
9285245beb3SBram Moolenaar 			    emsg(_(e_function_nesting_too_deep));
9295245beb3SBram Moolenaar 			else
9305245beb3SBram Moolenaar 			{
9315245beb3SBram Moolenaar 			    ++nesting;
9325245beb3SBram Moolenaar 			    nesting_def[nesting] = TRUE;
9335245beb3SBram Moolenaar 			    nesting_inline[nesting] = TRUE;
9347a6eaa06SBram Moolenaar 			    indent += 2;
9357a6eaa06SBram Moolenaar 			}
9367a6eaa06SBram Moolenaar 		    }
9377a6eaa06SBram Moolenaar 		}
938ac2cd2b0SBram Moolenaar 	    }
9397a6eaa06SBram Moolenaar 
9407a6eaa06SBram Moolenaar 	    // Check for ":append", ":change", ":insert".  Not for :def.
9417a6eaa06SBram Moolenaar 	    p = skip_range(p, FALSE, NULL);
9427a6eaa06SBram Moolenaar 	    if (!vim9_function
9437a6eaa06SBram Moolenaar 		&& ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
9447a6eaa06SBram Moolenaar 		    || (p[0] == 'c'
9457a6eaa06SBram Moolenaar 			&& (!ASCII_ISALPHA(p[1]) || (p[1] == 'h'
9467a6eaa06SBram Moolenaar 				&& (!ASCII_ISALPHA(p[2]) || (p[2] == 'a'
9477a6eaa06SBram Moolenaar 					&& (STRNCMP(&p[3], "nge", 3) != 0
9487a6eaa06SBram Moolenaar 					    || !ASCII_ISALPHA(p[6])))))))
9497a6eaa06SBram Moolenaar 		    || (p[0] == 'i'
9507a6eaa06SBram Moolenaar 			&& (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
9517a6eaa06SBram Moolenaar 				&& (!ASCII_ISALPHA(p[2])
9527a6eaa06SBram Moolenaar 				    || (p[2] == 's'
9537a6eaa06SBram Moolenaar 					&& (!ASCII_ISALPHA(p[3])
9547a6eaa06SBram Moolenaar 						|| p[3] == 'e'))))))))
9557a6eaa06SBram Moolenaar 		skip_until = vim_strsave((char_u *)".");
9567a6eaa06SBram Moolenaar 
9577a6eaa06SBram Moolenaar 	    // Check for ":python <<EOF", ":tcl <<EOF", etc.
9587a6eaa06SBram Moolenaar 	    arg = skipwhite(skiptowhite(p));
9597a6eaa06SBram Moolenaar 	    if (arg[0] == '<' && arg[1] =='<'
9607a6eaa06SBram Moolenaar 		    && ((p[0] == 'p' && p[1] == 'y'
9617a6eaa06SBram Moolenaar 				    && (!ASCII_ISALNUM(p[2]) || p[2] == 't'
9627a6eaa06SBram Moolenaar 					|| ((p[2] == '3' || p[2] == 'x')
9637a6eaa06SBram Moolenaar 						   && !ASCII_ISALPHA(p[3]))))
9647a6eaa06SBram Moolenaar 			|| (p[0] == 'p' && p[1] == 'e'
9657a6eaa06SBram Moolenaar 				    && (!ASCII_ISALPHA(p[2]) || p[2] == 'r'))
9667a6eaa06SBram Moolenaar 			|| (p[0] == 't' && p[1] == 'c'
9677a6eaa06SBram Moolenaar 				    && (!ASCII_ISALPHA(p[2]) || p[2] == 'l'))
9687a6eaa06SBram Moolenaar 			|| (p[0] == 'l' && p[1] == 'u' && p[2] == 'a'
9697a6eaa06SBram Moolenaar 				    && !ASCII_ISALPHA(p[3]))
9707a6eaa06SBram Moolenaar 			|| (p[0] == 'r' && p[1] == 'u' && p[2] == 'b'
9717a6eaa06SBram Moolenaar 				    && (!ASCII_ISALPHA(p[3]) || p[3] == 'y'))
9727a6eaa06SBram Moolenaar 			|| (p[0] == 'm' && p[1] == 'z'
9737a6eaa06SBram Moolenaar 				    && (!ASCII_ISALPHA(p[2]) || p[2] == 's'))
9747a6eaa06SBram Moolenaar 			))
9757a6eaa06SBram Moolenaar 	    {
9767a6eaa06SBram Moolenaar 		// ":python <<" continues until a dot, like ":append"
9777a6eaa06SBram Moolenaar 		p = skipwhite(arg + 2);
9787a6eaa06SBram Moolenaar 		if (STRNCMP(p, "trim", 4) == 0)
9797a6eaa06SBram Moolenaar 		{
9807a6eaa06SBram Moolenaar 		    // Ignore leading white space.
9817a6eaa06SBram Moolenaar 		    p = skipwhite(p + 4);
9827a6eaa06SBram Moolenaar 		    heredoc_trimmed = vim_strnsave(theline,
9837a6eaa06SBram Moolenaar 						 skipwhite(theline) - theline);
9847a6eaa06SBram Moolenaar 		}
9857a6eaa06SBram Moolenaar 		if (*p == NUL)
9867a6eaa06SBram Moolenaar 		    skip_until = vim_strsave((char_u *)".");
9877a6eaa06SBram Moolenaar 		else
9887a6eaa06SBram Moolenaar 		    skip_until = vim_strnsave(p, skiptowhite(p) - p);
9897a6eaa06SBram Moolenaar 		getline_options = GETLINE_NONE;
9907a6eaa06SBram Moolenaar 		is_heredoc = TRUE;
9912067733bSBram Moolenaar 		if (eap->cmdidx == CMD_def)
9922067733bSBram Moolenaar 		    heredoc_concat_len = newlines->ga_len + 1;
9937a6eaa06SBram Moolenaar 	    }
9947a6eaa06SBram Moolenaar 
9957a6eaa06SBram Moolenaar 	    // Check for ":cmd v =<< [trim] EOF"
9967a6eaa06SBram Moolenaar 	    //       and ":cmd [a, b] =<< [trim] EOF"
9977a6eaa06SBram Moolenaar 	    //       and "lines =<< [trim] EOF" for Vim9
9987a6eaa06SBram Moolenaar 	    // Where "cmd" can be "let", "var", "final" or "const".
9997a6eaa06SBram Moolenaar 	    arg = skipwhite(skiptowhite(p));
10007a6eaa06SBram Moolenaar 	    if (*arg == '[')
10017a6eaa06SBram Moolenaar 		arg = vim_strchr(arg, ']');
10027a6eaa06SBram Moolenaar 	    if (arg != NULL)
10037a6eaa06SBram Moolenaar 	    {
10047a6eaa06SBram Moolenaar 		int found = (eap->cmdidx == CMD_def && arg[0] == '='
10057a6eaa06SBram Moolenaar 					     && arg[1] == '<' && arg[2] =='<');
10067a6eaa06SBram Moolenaar 
10077a6eaa06SBram Moolenaar 		if (!found)
10087a6eaa06SBram Moolenaar 		    // skip over the argument after "cmd"
10097a6eaa06SBram Moolenaar 		    arg = skipwhite(skiptowhite(arg));
10107a6eaa06SBram Moolenaar 		if (found || (arg[0] == '=' && arg[1] == '<' && arg[2] =='<'
10117a6eaa06SBram Moolenaar 			&& (checkforcmd(&p, "let", 2)
10127a6eaa06SBram Moolenaar 			    || checkforcmd(&p, "var", 3)
10137a6eaa06SBram Moolenaar 			    || checkforcmd(&p, "final", 5)
10147a6eaa06SBram Moolenaar 			    || checkforcmd(&p, "const", 5))))
10157a6eaa06SBram Moolenaar 		{
10167a6eaa06SBram Moolenaar 		    p = skipwhite(arg + 3);
10177a6eaa06SBram Moolenaar 		    if (STRNCMP(p, "trim", 4) == 0)
10187a6eaa06SBram Moolenaar 		    {
10197a6eaa06SBram Moolenaar 			// Ignore leading white space.
10207a6eaa06SBram Moolenaar 			p = skipwhite(p + 4);
10217a6eaa06SBram Moolenaar 			heredoc_trimmed = vim_strnsave(theline,
10227a6eaa06SBram Moolenaar 						 skipwhite(theline) - theline);
10237a6eaa06SBram Moolenaar 		    }
10247a6eaa06SBram Moolenaar 		    skip_until = vim_strnsave(p, skiptowhite(p) - p);
10257a6eaa06SBram Moolenaar 		    getline_options = GETLINE_NONE;
10267a6eaa06SBram Moolenaar 		    is_heredoc = TRUE;
10277a6eaa06SBram Moolenaar 		}
10287a6eaa06SBram Moolenaar 	    }
10297a6eaa06SBram Moolenaar 	}
10307a6eaa06SBram Moolenaar 
10317a6eaa06SBram Moolenaar 	// Add the line to the function.
10327a6eaa06SBram Moolenaar 	if (ga_grow(newlines, 1 + sourcing_lnum_off) == FAIL)
10337a6eaa06SBram Moolenaar 	    goto theend;
10347a6eaa06SBram Moolenaar 
10352067733bSBram Moolenaar 	if (heredoc_concat_len > 0)
10362067733bSBram Moolenaar 	{
10372067733bSBram Moolenaar 	    // For a :def function "python << EOF" concatenats all the lines,
10382067733bSBram Moolenaar 	    // to be used for the instruction later.
10392067733bSBram Moolenaar 	    ga_concat(&heredoc_ga, theline);
10402067733bSBram Moolenaar 	    ga_concat(&heredoc_ga, (char_u *)"\n");
10412067733bSBram Moolenaar 	    p = vim_strsave((char_u *)"");
10422067733bSBram Moolenaar 	}
10432067733bSBram Moolenaar 	else
10442067733bSBram Moolenaar 	{
10457a6eaa06SBram Moolenaar 	    // Copy the line to newly allocated memory.  get_one_sourceline()
10462067733bSBram Moolenaar 	    // allocates 250 bytes per line, this saves 80% on average.  The
10472067733bSBram Moolenaar 	    // cost is an extra alloc/free.
10487a6eaa06SBram Moolenaar 	    p = vim_strsave(theline);
10492067733bSBram Moolenaar 	}
10507a6eaa06SBram Moolenaar 	if (p == NULL)
10517a6eaa06SBram Moolenaar 	    goto theend;
10527a6eaa06SBram Moolenaar 	((char_u **)(newlines->ga_data))[newlines->ga_len++] = p;
10537a6eaa06SBram Moolenaar 
10547a6eaa06SBram Moolenaar 	// Add NULL lines for continuation lines, so that the line count is
10557a6eaa06SBram Moolenaar 	// equal to the index in the growarray.
10567a6eaa06SBram Moolenaar 	while (sourcing_lnum_off-- > 0)
10577a6eaa06SBram Moolenaar 	    ((char_u **)(newlines->ga_data))[newlines->ga_len++] = NULL;
10587a6eaa06SBram Moolenaar 
10597a6eaa06SBram Moolenaar 	// Check for end of eap->arg.
10607a6eaa06SBram Moolenaar 	if (line_arg != NULL && *line_arg == NUL)
10617a6eaa06SBram Moolenaar 	    line_arg = NULL;
10627a6eaa06SBram Moolenaar     }
10637a6eaa06SBram Moolenaar 
1064074f84c0SBram Moolenaar     // Return OK when no error was detected.
1065074f84c0SBram Moolenaar     if (!did_emsg)
10667a6eaa06SBram Moolenaar 	ret = OK;
10677a6eaa06SBram Moolenaar 
10687a6eaa06SBram Moolenaar theend:
10697a6eaa06SBram Moolenaar     vim_free(skip_until);
10707a6eaa06SBram Moolenaar     vim_free(heredoc_trimmed);
10712067733bSBram Moolenaar     vim_free(heredoc_ga.ga_data);
10727a6eaa06SBram Moolenaar     need_wait_return |= saved_wait_return;
10737a6eaa06SBram Moolenaar     return ret;
10747a6eaa06SBram Moolenaar }
10757a6eaa06SBram Moolenaar 
10767a6eaa06SBram Moolenaar /*
10777a6eaa06SBram Moolenaar  * Handle the body of a lambda.  *arg points to the "{", process statements
10787a6eaa06SBram Moolenaar  * until the matching "}".
1079074f84c0SBram Moolenaar  * When not evaluating "newargs" is NULL.
10807a6eaa06SBram Moolenaar  * When successful "rettv" is set to a funcref.
10817a6eaa06SBram Moolenaar  */
10827a6eaa06SBram Moolenaar     static int
lambda_function_body(char_u ** arg,typval_T * rettv,evalarg_T * evalarg,garray_T * newargs,garray_T * argtypes,int varargs,garray_T * default_args,char_u * ret_type)10837a6eaa06SBram Moolenaar lambda_function_body(
10847a6eaa06SBram Moolenaar 	char_u	    **arg,
10857a6eaa06SBram Moolenaar 	typval_T    *rettv,
10867a6eaa06SBram Moolenaar 	evalarg_T   *evalarg,
10877a6eaa06SBram Moolenaar 	garray_T    *newargs,
10887a6eaa06SBram Moolenaar 	garray_T    *argtypes,
10897a6eaa06SBram Moolenaar 	int	    varargs,
10907a6eaa06SBram Moolenaar 	garray_T    *default_args,
10917a6eaa06SBram Moolenaar 	char_u	    *ret_type)
10927a6eaa06SBram Moolenaar {
1093fed9e830SBram Moolenaar     int		evaluate = (evalarg->eval_flags & EVAL_EVALUATE);
1094074f84c0SBram Moolenaar     garray_T	*gap = &evalarg->eval_ga;
1095ecb66450SBram Moolenaar     garray_T	*freegap = &evalarg->eval_freega;
109679efa2e3SBram Moolenaar     ufunc_T	*ufunc = NULL;
10977a6eaa06SBram Moolenaar     exarg_T	eap;
10987a6eaa06SBram Moolenaar     garray_T	newlines;
10997a6eaa06SBram Moolenaar     char_u	*cmdline = NULL;
11007a6eaa06SBram Moolenaar     int		ret = FAIL;
11017a6eaa06SBram Moolenaar     char_u	*line_to_free = NULL;
11027a6eaa06SBram Moolenaar     partial_T	*pt;
11037a6eaa06SBram Moolenaar     char_u	*name;
11047a6eaa06SBram Moolenaar     int		lnum_save = -1;
11057a6eaa06SBram Moolenaar     linenr_T	sourcing_lnum_top = SOURCING_LNUM;
11067a6eaa06SBram Moolenaar 
1107e98f60a5SBram Moolenaar     if (!ends_excmd2(*arg, skipwhite(*arg + 1)))
1108e98f60a5SBram Moolenaar     {
1109e98f60a5SBram Moolenaar 	semsg(_(e_trailing_arg), *arg + 1);
1110e98f60a5SBram Moolenaar 	return FAIL;
1111e98f60a5SBram Moolenaar     }
1112e98f60a5SBram Moolenaar 
11137a6eaa06SBram Moolenaar     CLEAR_FIELD(eap);
11147a6eaa06SBram Moolenaar     eap.cmdidx = CMD_block;
11157a6eaa06SBram Moolenaar     eap.forceit = FALSE;
11167a6eaa06SBram Moolenaar     eap.cmdlinep = &cmdline;
11177a6eaa06SBram Moolenaar     eap.skip = !evaluate;
11187a6eaa06SBram Moolenaar     if (evalarg->eval_cctx != NULL)
11197a6eaa06SBram Moolenaar 	fill_exarg_from_cctx(&eap, evalarg->eval_cctx);
11207a6eaa06SBram Moolenaar     else
11217a6eaa06SBram Moolenaar     {
11227a6eaa06SBram Moolenaar 	eap.getline = evalarg->eval_getline;
11237a6eaa06SBram Moolenaar 	eap.cookie = evalarg->eval_cookie;
11247a6eaa06SBram Moolenaar     }
11257a6eaa06SBram Moolenaar 
11267a6eaa06SBram Moolenaar     ga_init2(&newlines, (int)sizeof(char_u *), 10);
11277a6eaa06SBram Moolenaar     if (get_function_body(&eap, &newlines, NULL, &line_to_free) == FAIL)
112867da21a1SBram Moolenaar     {
112967da21a1SBram Moolenaar 	vim_free(cmdline);
11307a6eaa06SBram Moolenaar 	goto erret;
113167da21a1SBram Moolenaar     }
1132074f84c0SBram Moolenaar 
1133074f84c0SBram Moolenaar     // When inside a lambda must add the function lines to evalarg.eval_ga.
1134074f84c0SBram Moolenaar     evalarg->eval_break_count += newlines.ga_len;
1135074f84c0SBram Moolenaar     if (gap->ga_itemsize > 0)
1136074f84c0SBram Moolenaar     {
1137074f84c0SBram Moolenaar 	int	idx;
1138074f84c0SBram Moolenaar 	char_u	*last;
1139074f84c0SBram Moolenaar 	size_t  plen;
1140074f84c0SBram Moolenaar 	char_u  *pnl;
1141074f84c0SBram Moolenaar 
1142074f84c0SBram Moolenaar 	for (idx = 0; idx < newlines.ga_len; ++idx)
1143074f84c0SBram Moolenaar 	{
1144074f84c0SBram Moolenaar 	    char_u  *p = skipwhite(((char_u **)newlines.ga_data)[idx]);
1145074f84c0SBram Moolenaar 
1146ecb66450SBram Moolenaar 	    if (ga_grow(gap, 1) == FAIL || ga_grow(freegap, 1) == FAIL)
1147074f84c0SBram Moolenaar 		goto erret;
1148074f84c0SBram Moolenaar 
1149074f84c0SBram Moolenaar 	    // Going to concatenate the lines after parsing.  For an empty or
1150074f84c0SBram Moolenaar 	    // comment line use an empty string.
1151074f84c0SBram Moolenaar 	    // Insert NL characters at the start of each line, the string will
1152074f84c0SBram Moolenaar 	    // be split again later in .get_lambda_tv().
1153074f84c0SBram Moolenaar 	    if (*p == NUL || vim9_comment_start(p))
1154074f84c0SBram Moolenaar 		p = (char_u *)"";
1155074f84c0SBram Moolenaar 	    plen = STRLEN(p);
1156074f84c0SBram Moolenaar 	    pnl = vim_strnsave((char_u *)"\n", plen + 1);
1157074f84c0SBram Moolenaar 	    if (pnl != NULL)
1158074f84c0SBram Moolenaar 		mch_memmove(pnl + 1, p, plen + 1);
1159ecb66450SBram Moolenaar 	    ((char_u **)gap->ga_data)[gap->ga_len++] = pnl;
1160ecb66450SBram Moolenaar 	    ((char_u **)freegap->ga_data)[freegap->ga_len++] = pnl;
1161074f84c0SBram Moolenaar 	}
1162ecb66450SBram Moolenaar 	if (ga_grow(gap, 1) == FAIL || ga_grow(freegap, 1) == FAIL)
1163074f84c0SBram Moolenaar 	    goto erret;
1164074f84c0SBram Moolenaar 	if (cmdline != NULL)
1165074f84c0SBram Moolenaar 	    // more is following after the "}", which was skipped
1166074f84c0SBram Moolenaar 	    last = cmdline;
1167074f84c0SBram Moolenaar 	else
1168074f84c0SBram Moolenaar 	    // nothing is following the "}"
1169074f84c0SBram Moolenaar 	    last = (char_u *)"}";
1170074f84c0SBram Moolenaar 	plen = STRLEN(last);
1171074f84c0SBram Moolenaar 	pnl = vim_strnsave((char_u *)"\n", plen + 1);
1172074f84c0SBram Moolenaar 	if (pnl != NULL)
1173074f84c0SBram Moolenaar 	    mch_memmove(pnl + 1, last, plen + 1);
1174ecb66450SBram Moolenaar 	((char_u **)gap->ga_data)[gap->ga_len++] = pnl;
1175ecb66450SBram Moolenaar 	((char_u **)freegap->ga_data)[freegap->ga_len++] = pnl;
1176074f84c0SBram Moolenaar     }
1177074f84c0SBram Moolenaar 
11787a6eaa06SBram Moolenaar     if (cmdline != NULL)
11797a6eaa06SBram Moolenaar     {
1180844fb64aSBram Moolenaar 	garray_T *tfgap = &evalarg->eval_tofree_ga;
1181844fb64aSBram Moolenaar 
11827a6eaa06SBram Moolenaar 	// Something comes after the "}".
11837a6eaa06SBram Moolenaar 	*arg = eap.nextcmd;
118467da21a1SBram Moolenaar 
118567da21a1SBram Moolenaar 	// "arg" points into cmdline, need to keep the line and free it later.
1186844fb64aSBram Moolenaar 	if (ga_grow(tfgap, 1) == OK)
1187844fb64aSBram Moolenaar 	{
1188844fb64aSBram Moolenaar 	    ((char_u **)(tfgap->ga_data))[tfgap->ga_len++] = cmdline;
1189844fb64aSBram Moolenaar 	    evalarg->eval_using_cmdline = TRUE;
1190844fb64aSBram Moolenaar 	}
11917a6eaa06SBram Moolenaar     }
11927a6eaa06SBram Moolenaar     else
11937a6eaa06SBram Moolenaar 	*arg = (char_u *)"";
11947a6eaa06SBram Moolenaar 
1195074f84c0SBram Moolenaar     if (!evaluate)
1196074f84c0SBram Moolenaar     {
1197074f84c0SBram Moolenaar 	ret = OK;
1198074f84c0SBram Moolenaar 	goto erret;
1199074f84c0SBram Moolenaar     }
1200074f84c0SBram Moolenaar 
12017a6eaa06SBram Moolenaar     name = get_lambda_name();
12027a6eaa06SBram Moolenaar     ufunc = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1);
12037a6eaa06SBram Moolenaar     if (ufunc == NULL)
12047a6eaa06SBram Moolenaar 	goto erret;
12057a6eaa06SBram Moolenaar     set_ufunc_name(ufunc, name);
12067a6eaa06SBram Moolenaar     if (hash_add(&func_hashtab, UF2HIKEY(ufunc)) == FAIL)
12077a6eaa06SBram Moolenaar 	goto erret;
12087a6eaa06SBram Moolenaar     ufunc->uf_refcount = 1;
12097a6eaa06SBram Moolenaar     ufunc->uf_args = *newargs;
12107a6eaa06SBram Moolenaar     newargs->ga_data = NULL;
12117a6eaa06SBram Moolenaar     ufunc->uf_def_args = *default_args;
12127a6eaa06SBram Moolenaar     default_args->ga_data = NULL;
12137a6eaa06SBram Moolenaar     ufunc->uf_func_type = &t_func_any;
12147a6eaa06SBram Moolenaar 
12157a6eaa06SBram Moolenaar     // error messages are for the first function line
12167a6eaa06SBram Moolenaar     lnum_save = SOURCING_LNUM;
12177a6eaa06SBram Moolenaar     SOURCING_LNUM = sourcing_lnum_top;
12187a6eaa06SBram Moolenaar 
12197a6eaa06SBram Moolenaar     // parse argument types
12207a6eaa06SBram Moolenaar     if (parse_argument_types(ufunc, argtypes, varargs) == FAIL)
12217a6eaa06SBram Moolenaar     {
12227a6eaa06SBram Moolenaar 	SOURCING_LNUM = lnum_save;
12237a6eaa06SBram Moolenaar 	goto erret;
12247a6eaa06SBram Moolenaar     }
12257a6eaa06SBram Moolenaar 
12267a6eaa06SBram Moolenaar     // parse the return type, if any
12277a6eaa06SBram Moolenaar     if (parse_return_type(ufunc, ret_type) == FAIL)
12287a6eaa06SBram Moolenaar 	goto erret;
12297a6eaa06SBram Moolenaar 
12307a6eaa06SBram Moolenaar     pt = ALLOC_CLEAR_ONE(partial_T);
12317a6eaa06SBram Moolenaar     if (pt == NULL)
12327a6eaa06SBram Moolenaar 	goto erret;
12337a6eaa06SBram Moolenaar     pt->pt_func = ufunc;
12347a6eaa06SBram Moolenaar     pt->pt_refcount = 1;
12357a6eaa06SBram Moolenaar 
12367a6eaa06SBram Moolenaar     ufunc->uf_lines = newlines;
12377a6eaa06SBram Moolenaar     newlines.ga_data = NULL;
12387a6eaa06SBram Moolenaar     if (sandbox)
12397a6eaa06SBram Moolenaar 	ufunc->uf_flags |= FC_SANDBOX;
12407a6eaa06SBram Moolenaar     if (!ASCII_ISUPPER(*ufunc->uf_name))
12417a6eaa06SBram Moolenaar 	ufunc->uf_flags |= FC_VIM9;
12427a6eaa06SBram Moolenaar     ufunc->uf_script_ctx = current_sctx;
12437a6eaa06SBram Moolenaar     ufunc->uf_script_ctx_version = current_sctx.sc_version;
12447a6eaa06SBram Moolenaar     ufunc->uf_script_ctx.sc_lnum += sourcing_lnum_top;
12457a6eaa06SBram Moolenaar     set_function_type(ufunc);
12467a6eaa06SBram Moolenaar 
12472eb6fc3bSBram Moolenaar     function_using_block_scopes(ufunc, evalarg->eval_cstack);
12482eb6fc3bSBram Moolenaar 
12497a6eaa06SBram Moolenaar     rettv->vval.v_partial = pt;
12507a6eaa06SBram Moolenaar     rettv->v_type = VAR_PARTIAL;
125179efa2e3SBram Moolenaar     ufunc = NULL;
12527a6eaa06SBram Moolenaar     ret = OK;
12537a6eaa06SBram Moolenaar 
12547a6eaa06SBram Moolenaar erret:
12557a6eaa06SBram Moolenaar     if (lnum_save >= 0)
12567a6eaa06SBram Moolenaar 	SOURCING_LNUM = lnum_save;
12577a6eaa06SBram Moolenaar     vim_free(line_to_free);
12587a6eaa06SBram Moolenaar     ga_clear_strings(&newlines);
1259074f84c0SBram Moolenaar     if (newargs != NULL)
12607a6eaa06SBram Moolenaar 	ga_clear_strings(newargs);
12617a6eaa06SBram Moolenaar     ga_clear_strings(default_args);
126279efa2e3SBram Moolenaar     if (ufunc != NULL)
126379efa2e3SBram Moolenaar     {
126479efa2e3SBram Moolenaar 	func_clear(ufunc, TRUE);
126579efa2e3SBram Moolenaar 	func_free(ufunc, TRUE);
126679efa2e3SBram Moolenaar     }
12677a6eaa06SBram Moolenaar     return ret;
12687a6eaa06SBram Moolenaar }
12697a6eaa06SBram Moolenaar 
12707a6eaa06SBram Moolenaar /*
12717a6eaa06SBram Moolenaar  * Parse a lambda expression and get a Funcref from "*arg" into "rettv".
127265c44152SBram Moolenaar  * "arg" points to the { in "{arg -> expr}" or the ( in "(arg) => expr"
1273b4d16cb1SBram Moolenaar  * When "types_optional" is TRUE optionally take argument types.
1274a9b579f3SBram Moolenaar  * Return OK or FAIL.  Returns NOTDONE for dict or {expr}.
1275a9b579f3SBram Moolenaar  */
1276a9b579f3SBram Moolenaar     int
get_lambda_tv(char_u ** arg,typval_T * rettv,int types_optional,evalarg_T * evalarg)1277b4d16cb1SBram Moolenaar get_lambda_tv(
1278b4d16cb1SBram Moolenaar 	char_u	    **arg,
1279b4d16cb1SBram Moolenaar 	typval_T    *rettv,
1280b4d16cb1SBram Moolenaar 	int	    types_optional,
1281b4d16cb1SBram Moolenaar 	evalarg_T   *evalarg)
1282a9b579f3SBram Moolenaar {
1283e40fbc2cSBram Moolenaar     int		evaluate = evalarg != NULL
1284e40fbc2cSBram Moolenaar 				      && (evalarg->eval_flags & EVAL_EVALUATE);
1285a9b579f3SBram Moolenaar     garray_T	newargs;
1286a9b579f3SBram Moolenaar     garray_T	newlines;
12871e96d9bfSBram Moolenaar     garray_T	*pnewargs;
1288b4d16cb1SBram Moolenaar     garray_T	argtypes;
12897a6eaa06SBram Moolenaar     garray_T	default_args;
1290a9b579f3SBram Moolenaar     ufunc_T	*fp = NULL;
1291445e71c5SBram Moolenaar     partial_T   *pt = NULL;
1292a9b579f3SBram Moolenaar     int		varargs;
12939e68c325SBram Moolenaar     char_u	*ret_type = NULL;
1294a9b579f3SBram Moolenaar     int		ret;
12958e2730a3SBram Moolenaar     char_u	*s;
12968e2730a3SBram Moolenaar     char_u	*start, *end;
12971e96d9bfSBram Moolenaar     int		*old_eval_lavars = eval_lavars_used;
12981e96d9bfSBram Moolenaar     int		eval_lavars = FALSE;
1299f898f7c6SBram Moolenaar     char_u	*tofree1 = NULL;
1300f898f7c6SBram Moolenaar     char_u	*tofree2 = NULL;
130165c44152SBram Moolenaar     int		equal_arrow = **arg == '(';
1302c754b4ccSBram Moolenaar     int		white_error = FALSE;
13030346b799SBram Moolenaar     int		called_emsg_start = called_emsg;
130465c44152SBram Moolenaar 
130565c44152SBram Moolenaar     if (equal_arrow && !in_vim9script())
130665c44152SBram Moolenaar 	return NOTDONE;
1307a9b579f3SBram Moolenaar 
1308a9b579f3SBram Moolenaar     ga_init(&newargs);
1309a9b579f3SBram Moolenaar     ga_init(&newlines);
1310a9b579f3SBram Moolenaar 
13119e68c325SBram Moolenaar     // First, check if this is really a lambda expression. "->" or "=>" must
13129e68c325SBram Moolenaar     // be found after the arguments.
1313cef1270dSBram Moolenaar     s = *arg + 1;
131465c44152SBram Moolenaar     ret = get_function_args(&s, equal_arrow ? ')' : '-', NULL,
1315057e84afSBram Moolenaar 	    types_optional ? &argtypes : NULL, types_optional, evalarg,
131614ded11fSBram Moolenaar 					NULL, &default_args, TRUE, NULL, NULL);
1317c754b4ccSBram Moolenaar     if (ret == FAIL || skip_arrow(s, equal_arrow, &ret_type, NULL) == NULL)
13186dd41b1dSBram Moolenaar     {
13196dd41b1dSBram Moolenaar 	if (types_optional)
13206dd41b1dSBram Moolenaar 	    ga_clear_strings(&argtypes);
13210346b799SBram Moolenaar 	return called_emsg == called_emsg_start ? NOTDONE : FAIL;
13226dd41b1dSBram Moolenaar     }
1323a9b579f3SBram Moolenaar 
13249e68c325SBram Moolenaar     // Parse the arguments for real.
13251e96d9bfSBram Moolenaar     if (evaluate)
13261e96d9bfSBram Moolenaar 	pnewargs = &newargs;
13271e96d9bfSBram Moolenaar     else
13281e96d9bfSBram Moolenaar 	pnewargs = NULL;
1329cef1270dSBram Moolenaar     *arg += 1;
133065c44152SBram Moolenaar     ret = get_function_args(arg, equal_arrow ? ')' : '-', pnewargs,
1331057e84afSBram Moolenaar 	    types_optional ? &argtypes : NULL, types_optional, evalarg,
13327a6eaa06SBram Moolenaar 					    &varargs, &default_args,
13337a6eaa06SBram Moolenaar 					    FALSE, NULL, NULL);
13349e68c325SBram Moolenaar     if (ret == FAIL
1335c754b4ccSBram Moolenaar 		  || (s = skip_arrow(*arg, equal_arrow, &ret_type,
1336e462f52dSBram Moolenaar 		equal_arrow || in_vim9script() ? &white_error : NULL)) == NULL)
13376dd41b1dSBram Moolenaar     {
13386dd41b1dSBram Moolenaar 	if (types_optional)
13396dd41b1dSBram Moolenaar 	    ga_clear_strings(&argtypes);
1340e5730bdcSBram Moolenaar 	ga_clear_strings(&newargs);
1341c754b4ccSBram Moolenaar 	return white_error ? FAIL : NOTDONE;
13426dd41b1dSBram Moolenaar     }
1343c754b4ccSBram Moolenaar     *arg = s;
1344a9b579f3SBram Moolenaar 
1345f898f7c6SBram Moolenaar     // Skipping over linebreaks may make "ret_type" invalid, make a copy.
1346f898f7c6SBram Moolenaar     if (ret_type != NULL)
1347f898f7c6SBram Moolenaar     {
1348f898f7c6SBram Moolenaar 	ret_type = vim_strsave(ret_type);
1349f898f7c6SBram Moolenaar 	tofree2 = ret_type;
1350f898f7c6SBram Moolenaar     }
1351f898f7c6SBram Moolenaar 
1352e38eab22SBram Moolenaar     // Set up a flag for checking local variables and arguments.
13531e96d9bfSBram Moolenaar     if (evaluate)
13541e96d9bfSBram Moolenaar 	eval_lavars_used = &eval_lavars;
13551e96d9bfSBram Moolenaar 
135665c44152SBram Moolenaar     *arg = skipwhite_and_linebreak(*arg, evalarg);
135765c44152SBram Moolenaar 
13589e68c325SBram Moolenaar     // Recognize "{" as the start of a function body.
13599e68c325SBram Moolenaar     if (equal_arrow && **arg == '{')
136065c44152SBram Moolenaar     {
1361fed9e830SBram Moolenaar 	if (evalarg == NULL)
1362fed9e830SBram Moolenaar 	    // cannot happen?
1363fed9e830SBram Moolenaar 	    goto theend;
13647a6eaa06SBram Moolenaar 	if (lambda_function_body(arg, rettv, evalarg, pnewargs,
13657a6eaa06SBram Moolenaar 			   types_optional ? &argtypes : NULL, varargs,
13667a6eaa06SBram Moolenaar 			   &default_args, ret_type) == FAIL)
13677a6eaa06SBram Moolenaar 	    goto errret;
13687a6eaa06SBram Moolenaar 	goto theend;
13697a6eaa06SBram Moolenaar     }
13707a6eaa06SBram Moolenaar     if (default_args.ga_len > 0)
13717a6eaa06SBram Moolenaar     {
13727a6eaa06SBram Moolenaar 	emsg(_(e_cannot_use_default_values_in_lambda));
137365c44152SBram Moolenaar 	goto errret;
137465c44152SBram Moolenaar     }
137565c44152SBram Moolenaar 
1376e38eab22SBram Moolenaar     // Get the start and the end of the expression.
13778e2730a3SBram Moolenaar     start = *arg;
13788e2730a3SBram Moolenaar     ret = skip_expr_concatenate(arg, &start, &end, evalarg);
1379a9b579f3SBram Moolenaar     if (ret == FAIL)
1380a9b579f3SBram Moolenaar 	goto errret;
1381e40fbc2cSBram Moolenaar     if (evalarg != NULL)
1382e40fbc2cSBram Moolenaar     {
1383e40fbc2cSBram Moolenaar 	// avoid that the expression gets freed when another line break follows
1384f898f7c6SBram Moolenaar 	tofree1 = evalarg->eval_tofree;
1385e40fbc2cSBram Moolenaar 	evalarg->eval_tofree = NULL;
1386e40fbc2cSBram Moolenaar     }
1387e40fbc2cSBram Moolenaar 
138865c44152SBram Moolenaar     if (!equal_arrow)
138965c44152SBram Moolenaar     {
13909215f012SBram Moolenaar 	*arg = skipwhite_and_linebreak(*arg, evalarg);
1391a9b579f3SBram Moolenaar 	if (**arg != '}')
1392ee619e5bSBram Moolenaar 	{
1393ee619e5bSBram Moolenaar 	    semsg(_("E451: Expected }: %s"), *arg);
1394a9b579f3SBram Moolenaar 	    goto errret;
1395ee619e5bSBram Moolenaar 	}
1396a9b579f3SBram Moolenaar 	++*arg;
139765c44152SBram Moolenaar     }
1398a9b579f3SBram Moolenaar 
1399a9b579f3SBram Moolenaar     if (evaluate)
1400a9b579f3SBram Moolenaar     {
1401e40fbc2cSBram Moolenaar 	int	    len;
1402e40fbc2cSBram Moolenaar 	int	    flags = 0;
1403a9b579f3SBram Moolenaar 	char_u	    *p;
1404074f84c0SBram Moolenaar 	char_u	    *line_end;
140504b12697SBram Moolenaar 	char_u	    *name = get_lambda_name();
14061e96d9bfSBram Moolenaar 
140747ed553fSBram Moolenaar 	fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1);
1408a9b579f3SBram Moolenaar 	if (fp == NULL)
1409a9b579f3SBram Moolenaar 	    goto errret;
14100cb5bcf5SBram Moolenaar 	fp->uf_def_status = UF_NOT_COMPILED;
1411c799fe20SBram Moolenaar 	pt = ALLOC_CLEAR_ONE(partial_T);
1412437bafe4SBram Moolenaar 	if (pt == NULL)
1413437bafe4SBram Moolenaar 	    goto errret;
1414a9b579f3SBram Moolenaar 
1415a9b579f3SBram Moolenaar 	ga_init2(&newlines, (int)sizeof(char_u *), 1);
1416a9b579f3SBram Moolenaar 	if (ga_grow(&newlines, 1) == FAIL)
1417a9b579f3SBram Moolenaar 	    goto errret;
1418a9b579f3SBram Moolenaar 
1419074f84c0SBram Moolenaar 	// If there are line breaks, we need to split up the string.
1420074f84c0SBram Moolenaar 	line_end = vim_strchr(start, '\n');
14216868634aSBram Moolenaar 	if (line_end == NULL || line_end > end)
1422074f84c0SBram Moolenaar 	    line_end = end;
1423074f84c0SBram Moolenaar 
1424074f84c0SBram Moolenaar 	// Add "return " before the expression (or the first line).
1425074f84c0SBram Moolenaar 	len = 7 + (int)(line_end - start) + 1;
1426c799fe20SBram Moolenaar 	p = alloc(len);
1427a9b579f3SBram Moolenaar 	if (p == NULL)
1428a9b579f3SBram Moolenaar 	    goto errret;
1429a9b579f3SBram Moolenaar 	((char_u **)(newlines.ga_data))[newlines.ga_len++] = p;
1430a9b579f3SBram Moolenaar 	STRCPY(p, "return ");
1431074f84c0SBram Moolenaar 	vim_strncpy(p + 7, start, line_end - start);
1432074f84c0SBram Moolenaar 
1433074f84c0SBram Moolenaar 	if (line_end != end)
1434074f84c0SBram Moolenaar 	{
1435074f84c0SBram Moolenaar 	    // Add more lines, split by line breaks.  Thus is used when a
1436074f84c0SBram Moolenaar 	    // lambda with { cmds } is encountered.
1437074f84c0SBram Moolenaar 	    while (*line_end == '\n')
1438074f84c0SBram Moolenaar 	    {
1439074f84c0SBram Moolenaar 		if (ga_grow(&newlines, 1) == FAIL)
1440074f84c0SBram Moolenaar 		    goto errret;
1441074f84c0SBram Moolenaar 		start = line_end + 1;
1442074f84c0SBram Moolenaar 		line_end = vim_strchr(start, '\n');
1443074f84c0SBram Moolenaar 		if (line_end == NULL)
1444074f84c0SBram Moolenaar 		    line_end = end;
1445074f84c0SBram Moolenaar 		((char_u **)(newlines.ga_data))[newlines.ga_len++] =
1446074f84c0SBram Moolenaar 					 vim_strnsave(start, line_end - start);
1447074f84c0SBram Moolenaar 	    }
1448074f84c0SBram Moolenaar 	}
1449074f84c0SBram Moolenaar 
1450f10806b2SBram Moolenaar 	if (strstr((char *)p + 7, "a:") == NULL)
1451f10806b2SBram Moolenaar 	    // No a: variables are used for sure.
1452f10806b2SBram Moolenaar 	    flags |= FC_NOARGS;
1453a9b579f3SBram Moolenaar 
1454a9b579f3SBram Moolenaar 	fp->uf_refcount = 1;
14551a47ae32SBram Moolenaar 	set_ufunc_name(fp, name);
1456a9b579f3SBram Moolenaar 	fp->uf_args = newargs;
145742ae78cfSBram Moolenaar 	ga_init(&fp->uf_def_args);
14589e68c325SBram Moolenaar 	if (types_optional)
14599e68c325SBram Moolenaar 	{
14602a38908bSBram Moolenaar 	    if (parse_argument_types(fp, &argtypes,
14612a38908bSBram Moolenaar 					   in_vim9script() && varargs) == FAIL)
1462b4d16cb1SBram Moolenaar 		goto errret;
14639e68c325SBram Moolenaar 	    if (ret_type != NULL)
14649e68c325SBram Moolenaar 	    {
14659e68c325SBram Moolenaar 		fp->uf_ret_type = parse_type(&ret_type,
14669e68c325SBram Moolenaar 						      &fp->uf_type_list, TRUE);
14679e68c325SBram Moolenaar 		if (fp->uf_ret_type == NULL)
14689e68c325SBram Moolenaar 		    goto errret;
14699e68c325SBram Moolenaar 	    }
1470ca2f7e7aSBram Moolenaar 	    else
1471a9931535SBram Moolenaar 		fp->uf_ret_type = &t_unknown;
14729e68c325SBram Moolenaar 	}
1473b4d16cb1SBram Moolenaar 
1474a9b579f3SBram Moolenaar 	fp->uf_lines = newlines;
14751e96d9bfSBram Moolenaar 	if (current_funccal != NULL && eval_lavars)
14761e96d9bfSBram Moolenaar 	{
147710ce39a0SBram Moolenaar 	    flags |= FC_CLOSURE;
147858016448SBram Moolenaar 	    if (register_closure(fp) == FAIL)
14791e96d9bfSBram Moolenaar 		goto errret;
14801e96d9bfSBram Moolenaar 	}
1481a9b579f3SBram Moolenaar 
1482a9b579f3SBram Moolenaar #ifdef FEAT_PROFILE
1483a9b579f3SBram Moolenaar 	if (prof_def_func())
1484a9b579f3SBram Moolenaar 	    func_do_profile(fp);
1485a9b579f3SBram Moolenaar #endif
148693343725SBram Moolenaar 	if (sandbox)
148793343725SBram Moolenaar 	    flags |= FC_SANDBOX;
1488767034c5SBram Moolenaar 	// In legacy script a lambda can be called with more args than
14892a38908bSBram Moolenaar 	// uf_args.ga_len.  In Vim9 script "...name" has to be used.
14902a38908bSBram Moolenaar 	fp->uf_varargs = !in_vim9script() || varargs;
149110ce39a0SBram Moolenaar 	fp->uf_flags = flags;
1492a9b579f3SBram Moolenaar 	fp->uf_calls = 0;
1493f29c1c6aSBram Moolenaar 	fp->uf_script_ctx = current_sctx;
1494a755fdbeSBram Moolenaar 	fp->uf_script_ctx.sc_lnum += SOURCING_LNUM - newlines.ga_len + 1;
1495a9b579f3SBram Moolenaar 
14962eb6fc3bSBram Moolenaar 	function_using_block_scopes(fp, evalarg->eval_cstack);
14972eb6fc3bSBram Moolenaar 
1498437bafe4SBram Moolenaar 	pt->pt_func = fp;
1499437bafe4SBram Moolenaar 	pt->pt_refcount = 1;
1500437bafe4SBram Moolenaar 	rettv->vval.v_partial = pt;
1501437bafe4SBram Moolenaar 	rettv->v_type = VAR_PARTIAL;
1502057e84afSBram Moolenaar 
1503057e84afSBram Moolenaar 	hash_add(&func_hashtab, UF2HIKEY(fp));
1504a9b579f3SBram Moolenaar     }
1505a9b579f3SBram Moolenaar 
15067a6eaa06SBram Moolenaar theend:
15071e96d9bfSBram Moolenaar     eval_lavars_used = old_eval_lavars;
1508efaaaa68SBram Moolenaar     if (evalarg != NULL && evalarg->eval_tofree == NULL)
1509f898f7c6SBram Moolenaar 	evalarg->eval_tofree = tofree1;
15108e2730a3SBram Moolenaar     else
1511f898f7c6SBram Moolenaar 	vim_free(tofree1);
1512f898f7c6SBram Moolenaar     vim_free(tofree2);
1513b4d16cb1SBram Moolenaar     if (types_optional)
1514b4d16cb1SBram Moolenaar 	ga_clear_strings(&argtypes);
15152eb6fc3bSBram Moolenaar 
1516a9b579f3SBram Moolenaar     return OK;
1517a9b579f3SBram Moolenaar 
1518a9b579f3SBram Moolenaar errret:
1519a9b579f3SBram Moolenaar     ga_clear_strings(&newargs);
1520a9b579f3SBram Moolenaar     ga_clear_strings(&newlines);
15217a6eaa06SBram Moolenaar     ga_clear_strings(&default_args);
1522b4d16cb1SBram Moolenaar     if (types_optional)
152315bbb8f4SBram Moolenaar     {
1524b4d16cb1SBram Moolenaar 	ga_clear_strings(&argtypes);
152515bbb8f4SBram Moolenaar 	if (fp != NULL)
152615bbb8f4SBram Moolenaar 	    vim_free(fp->uf_arg_types);
152715bbb8f4SBram Moolenaar     }
1528a9b579f3SBram Moolenaar     vim_free(fp);
1529445e71c5SBram Moolenaar     vim_free(pt);
1530efaaaa68SBram Moolenaar     if (evalarg != NULL && evalarg->eval_tofree == NULL)
1531f898f7c6SBram Moolenaar 	evalarg->eval_tofree = tofree1;
15328e2730a3SBram Moolenaar     else
1533f898f7c6SBram Moolenaar 	vim_free(tofree1);
1534f898f7c6SBram Moolenaar     vim_free(tofree2);
15351e96d9bfSBram Moolenaar     eval_lavars_used = old_eval_lavars;
1536a9b579f3SBram Moolenaar     return FAIL;
1537a9b579f3SBram Moolenaar }
1538a9b579f3SBram Moolenaar 
1539a9b579f3SBram Moolenaar /*
1540a9b579f3SBram Moolenaar  * Check if "name" is a variable of type VAR_FUNC.  If so, return the function
1541a9b579f3SBram Moolenaar  * name it contains, otherwise return "name".
1542a9b579f3SBram Moolenaar  * If "partialp" is not NULL, and "name" is of type VAR_PARTIAL also set
1543a9b579f3SBram Moolenaar  * "partialp".
154432b3f820SBram Moolenaar  * If "type" is not NULL and a Vim9 script-local variable is found look up the
154532b3f820SBram Moolenaar  * type of the variable.
1546a9b579f3SBram Moolenaar  */
1547a9b579f3SBram Moolenaar     char_u *
deref_func_name(char_u * name,int * lenp,partial_T ** partialp,type_T ** type,int no_autoload)154832b3f820SBram Moolenaar deref_func_name(
154932b3f820SBram Moolenaar 	char_u	    *name,
155032b3f820SBram Moolenaar 	int	    *lenp,
155132b3f820SBram Moolenaar 	partial_T   **partialp,
155232b3f820SBram Moolenaar 	type_T	    **type,
155332b3f820SBram Moolenaar 	int	    no_autoload)
1554a9b579f3SBram Moolenaar {
1555a9b579f3SBram Moolenaar     dictitem_T	*v;
15565fe07d2eSBram Moolenaar     typval_T	*tv = NULL;
1557a9b579f3SBram Moolenaar     int		cc;
155832b3f820SBram Moolenaar     char_u	*s = NULL;
155932b3f820SBram Moolenaar     hashtab_T	*ht;
15605fe07d2eSBram Moolenaar     int		did_type = FALSE;
1561a9b579f3SBram Moolenaar 
1562a9b579f3SBram Moolenaar     if (partialp != NULL)
1563a9b579f3SBram Moolenaar 	*partialp = NULL;
1564a9b579f3SBram Moolenaar 
1565a9b579f3SBram Moolenaar     cc = name[*lenp];
1566a9b579f3SBram Moolenaar     name[*lenp] = NUL;
15672067733bSBram Moolenaar 
156832b3f820SBram Moolenaar     v = find_var(name, &ht, no_autoload);
1569a9b579f3SBram Moolenaar     name[*lenp] = cc;
157032b3f820SBram Moolenaar     if (v != NULL)
157132b3f820SBram Moolenaar     {
15725fe07d2eSBram Moolenaar 	tv = &v->di_tv;
15735fe07d2eSBram Moolenaar     }
15745fe07d2eSBram Moolenaar     else if (in_vim9script() || STRNCMP(name, "s:", 2) == 0)
1575a9b579f3SBram Moolenaar     {
15765fe07d2eSBram Moolenaar 	imported_T  *import;
15775fe07d2eSBram Moolenaar 	char_u	    *p = name;
15785fe07d2eSBram Moolenaar 	int	    len = *lenp;
15795fe07d2eSBram Moolenaar 
15805fe07d2eSBram Moolenaar 	if (STRNCMP(name, "s:", 2) == 0)
15815fe07d2eSBram Moolenaar 	{
15825fe07d2eSBram Moolenaar 	    p = name + 2;
15835fe07d2eSBram Moolenaar 	    len -= 2;
15845fe07d2eSBram Moolenaar 	}
15855fe07d2eSBram Moolenaar 	import = find_imported(p, len, NULL);
15865fe07d2eSBram Moolenaar 
15875fe07d2eSBram Moolenaar 	// imported variable from another script
15885fe07d2eSBram Moolenaar 	if (import != NULL)
15895fe07d2eSBram Moolenaar 	{
15905fe07d2eSBram Moolenaar 	    if (import->imp_funcname != NULL)
15915fe07d2eSBram Moolenaar 	    {
15925fe07d2eSBram Moolenaar 		s = import->imp_funcname;
15935fe07d2eSBram Moolenaar 		*lenp = (int)STRLEN(s);
15945fe07d2eSBram Moolenaar 		return s;
15955fe07d2eSBram Moolenaar 	    }
15965fe07d2eSBram Moolenaar 	    // TODO: what if (import->imp_flags & IMP_FLAGS_STAR)
15975fe07d2eSBram Moolenaar 	    {
15985fe07d2eSBram Moolenaar 		scriptitem_T    *si = SCRIPT_ITEM(import->imp_sid);
15995fe07d2eSBram Moolenaar 		svar_T		*sv = ((svar_T *)si->sn_var_vals.ga_data)
16005fe07d2eSBram Moolenaar 						    + import->imp_var_vals_idx;
16015fe07d2eSBram Moolenaar 		tv = sv->sv_tv;
16025fe07d2eSBram Moolenaar 		if (type != NULL)
16035fe07d2eSBram Moolenaar 		    *type = sv->sv_type;
16045fe07d2eSBram Moolenaar 		did_type = TRUE;
16055fe07d2eSBram Moolenaar 	    }
16065fe07d2eSBram Moolenaar 	}
16075fe07d2eSBram Moolenaar     }
16085fe07d2eSBram Moolenaar 
16095fe07d2eSBram Moolenaar     if (tv != NULL)
16105fe07d2eSBram Moolenaar     {
16115fe07d2eSBram Moolenaar 	if (tv->v_type == VAR_FUNC)
16125fe07d2eSBram Moolenaar 	{
16135fe07d2eSBram Moolenaar 	    if (tv->vval.v_string == NULL)
1614a9b579f3SBram Moolenaar 	    {
1615a9b579f3SBram Moolenaar 		*lenp = 0;
1616e38eab22SBram Moolenaar 		return (char_u *)"";	// just in case
1617a9b579f3SBram Moolenaar 	    }
16185fe07d2eSBram Moolenaar 	    s = tv->vval.v_string;
1619437bafe4SBram Moolenaar 	    *lenp = (int)STRLEN(s);
1620a9b579f3SBram Moolenaar 	}
1621a9b579f3SBram Moolenaar 
16225fe07d2eSBram Moolenaar 	if (tv->v_type == VAR_PARTIAL)
1623a9b579f3SBram Moolenaar 	{
16245fe07d2eSBram Moolenaar 	    partial_T *pt = tv->vval.v_partial;
1625a9b579f3SBram Moolenaar 
1626a9b579f3SBram Moolenaar 	    if (pt == NULL)
1627a9b579f3SBram Moolenaar 	    {
1628a9b579f3SBram Moolenaar 		*lenp = 0;
1629e38eab22SBram Moolenaar 		return (char_u *)"";	// just in case
1630a9b579f3SBram Moolenaar 	    }
1631a9b579f3SBram Moolenaar 	    if (partialp != NULL)
1632a9b579f3SBram Moolenaar 		*partialp = pt;
1633437bafe4SBram Moolenaar 	    s = partial_name(pt);
1634437bafe4SBram Moolenaar 	    *lenp = (int)STRLEN(s);
163532b3f820SBram Moolenaar 	}
163632b3f820SBram Moolenaar 
163732b3f820SBram Moolenaar 	if (s != NULL)
163832b3f820SBram Moolenaar 	{
16395fe07d2eSBram Moolenaar 	    if (!did_type && type != NULL && ht == get_script_local_ht())
164032b3f820SBram Moolenaar 	    {
16415fe07d2eSBram Moolenaar 		svar_T  *sv = find_typval_in_script(tv);
164232b3f820SBram Moolenaar 
164332b3f820SBram Moolenaar 		if (sv != NULL)
164432b3f820SBram Moolenaar 		    *type = sv->sv_type;
164532b3f820SBram Moolenaar 	    }
1646437bafe4SBram Moolenaar 	    return s;
1647a9b579f3SBram Moolenaar 	}
164832b3f820SBram Moolenaar     }
1649a9b579f3SBram Moolenaar 
1650a9b579f3SBram Moolenaar     return name;
1651a9b579f3SBram Moolenaar }
1652a9b579f3SBram Moolenaar 
1653a9b579f3SBram Moolenaar /*
1654a9b579f3SBram Moolenaar  * Give an error message with a function name.  Handle <SNR> things.
1655a9b579f3SBram Moolenaar  * "ermsg" is to be passed without translation, use N_() instead of _().
1656a9b579f3SBram Moolenaar  */
16574c054e9fSBram Moolenaar     void
emsg_funcname(char * ermsg,char_u * name)1658a9b579f3SBram Moolenaar emsg_funcname(char *ermsg, char_u *name)
1659a9b579f3SBram Moolenaar {
1660a9b579f3SBram Moolenaar     char_u	*p;
1661a9b579f3SBram Moolenaar 
1662a9b579f3SBram Moolenaar     if (*name == K_SPECIAL)
1663a9b579f3SBram Moolenaar 	p = concat_str((char_u *)"<SNR>", name + 3);
1664a9b579f3SBram Moolenaar     else
1665a9b579f3SBram Moolenaar 	p = name;
1666f9e3e09fSBram Moolenaar     semsg(_(ermsg), p);
1667a9b579f3SBram Moolenaar     if (p != name)
1668a9b579f3SBram Moolenaar 	vim_free(p);
1669a9b579f3SBram Moolenaar }
1670a9b579f3SBram Moolenaar 
1671a9b579f3SBram Moolenaar /*
1672a9b579f3SBram Moolenaar  * Allocate a variable for the result of a function.
1673a9b579f3SBram Moolenaar  * Return OK or FAIL.
1674a9b579f3SBram Moolenaar  */
1675a9b579f3SBram Moolenaar     int
get_func_tv(char_u * name,int len,typval_T * rettv,char_u ** arg,evalarg_T * evalarg,funcexe_T * funcexe)1676a9b579f3SBram Moolenaar get_func_tv(
16776ed88198SBram Moolenaar     char_u	*name,		// name of the function
16786ed88198SBram Moolenaar     int		len,		// length of "name" or -1 to use strlen()
1679a9b579f3SBram Moolenaar     typval_T	*rettv,
16806ed88198SBram Moolenaar     char_u	**arg,		// argument, pointing to the '('
1681e6b5324eSBram Moolenaar     evalarg_T	*evalarg,	// for line continuation
1682c6538bccSBram Moolenaar     funcexe_T	*funcexe)	// various values
1683a9b579f3SBram Moolenaar {
1684a9b579f3SBram Moolenaar     char_u	*argp;
1685a9b579f3SBram Moolenaar     int		ret = OK;
1686e38eab22SBram Moolenaar     typval_T	argvars[MAX_FUNC_ARGS + 1];	// vars for arguments
1687e38eab22SBram Moolenaar     int		argcount = 0;		// number of arguments found
16887cb6fc29SBram Moolenaar     int		vim9script = in_vim9script();
1689a9b579f3SBram Moolenaar 
1690a9b579f3SBram Moolenaar     /*
1691a9b579f3SBram Moolenaar      * Get the arguments.
1692a9b579f3SBram Moolenaar      */
1693a9b579f3SBram Moolenaar     argp = *arg;
1694c6538bccSBram Moolenaar     while (argcount < MAX_FUNC_ARGS - (funcexe->partial == NULL ? 0
1695c6538bccSBram Moolenaar 						  : funcexe->partial->pt_argc))
1696a9b579f3SBram Moolenaar     {
1697e6b5324eSBram Moolenaar 	// skip the '(' or ',' and possibly line breaks
1698e6b5324eSBram Moolenaar 	argp = skipwhite_and_linebreak(argp + 1, evalarg);
1699e6b5324eSBram Moolenaar 
1700a9b579f3SBram Moolenaar 	if (*argp == ')' || *argp == ',' || *argp == NUL)
1701a9b579f3SBram Moolenaar 	    break;
1702e6b5324eSBram Moolenaar 	if (eval1(&argp, &argvars[argcount], evalarg) == FAIL)
1703a9b579f3SBram Moolenaar 	{
1704a9b579f3SBram Moolenaar 	    ret = FAIL;
1705a9b579f3SBram Moolenaar 	    break;
1706a9b579f3SBram Moolenaar 	}
1707a9b579f3SBram Moolenaar 	++argcount;
17089d489566SBram Moolenaar 	// The comma should come right after the argument, but this wasn't
17099d489566SBram Moolenaar 	// checked previously, thus only enforce it in Vim9 script.
17107cb6fc29SBram Moolenaar 	if (vim9script)
17117cb6fc29SBram Moolenaar 	{
17127cb6fc29SBram Moolenaar 	    if (*argp != ',' && *skipwhite(argp) == ',')
17137cb6fc29SBram Moolenaar 	    {
1714ba98fb54SBram Moolenaar 		semsg(_(e_no_white_space_allowed_before_str_str), ",", argp);
17157cb6fc29SBram Moolenaar 		ret = FAIL;
17167cb6fc29SBram Moolenaar 		break;
17177cb6fc29SBram Moolenaar 	    }
17187cb6fc29SBram Moolenaar 	}
17197cb6fc29SBram Moolenaar 	else
17209d489566SBram Moolenaar 	    argp = skipwhite(argp);
1721a9b579f3SBram Moolenaar 	if (*argp != ',')
1722a9b579f3SBram Moolenaar 	    break;
17237cb6fc29SBram Moolenaar 	if (vim9script && !IS_WHITE_OR_NUL(argp[1]))
17247cb6fc29SBram Moolenaar 	{
1725c3fc75dbSBram Moolenaar 	    semsg(_(e_white_space_required_after_str_str), ",", argp);
17267cb6fc29SBram Moolenaar 	    ret = FAIL;
17277cb6fc29SBram Moolenaar 	    break;
17287cb6fc29SBram Moolenaar 	}
1729a9b579f3SBram Moolenaar     }
1730e6b5324eSBram Moolenaar     argp = skipwhite_and_linebreak(argp, evalarg);
1731a9b579f3SBram Moolenaar     if (*argp == ')')
1732a9b579f3SBram Moolenaar 	++argp;
1733a9b579f3SBram Moolenaar     else
1734a9b579f3SBram Moolenaar 	ret = FAIL;
1735a9b579f3SBram Moolenaar 
1736a9b579f3SBram Moolenaar     if (ret == OK)
1737a9b579f3SBram Moolenaar     {
1738a9b579f3SBram Moolenaar 	int	i = 0;
1739327d3ee4SBram Moolenaar 	int	did_emsg_before = did_emsg;
1740a9b579f3SBram Moolenaar 
1741a9b579f3SBram Moolenaar 	if (get_vim_var_nr(VV_TESTING))
1742a9b579f3SBram Moolenaar 	{
1743e38eab22SBram Moolenaar 	    // Prepare for calling test_garbagecollect_now(), need to know
1744e38eab22SBram Moolenaar 	    // what variables are used on the call stack.
1745a9b579f3SBram Moolenaar 	    if (funcargs.ga_itemsize == 0)
1746a9b579f3SBram Moolenaar 		ga_init2(&funcargs, (int)sizeof(typval_T *), 50);
1747a9b579f3SBram Moolenaar 	    for (i = 0; i < argcount; ++i)
1748a9b579f3SBram Moolenaar 		if (ga_grow(&funcargs, 1) == OK)
1749a9b579f3SBram Moolenaar 		    ((typval_T **)funcargs.ga_data)[funcargs.ga_len++] =
1750a9b579f3SBram Moolenaar 								  &argvars[i];
1751a9b579f3SBram Moolenaar 	}
1752a9b579f3SBram Moolenaar 
1753c6538bccSBram Moolenaar 	ret = call_func(name, len, rettv, argcount, argvars, funcexe);
1754327d3ee4SBram Moolenaar 	if (in_vim9script() && did_emsg > did_emsg_before)
17556e850a69SBram Moolenaar 	{
1756327d3ee4SBram Moolenaar 	    // An error in a builtin function does not return FAIL, but we do
1757327d3ee4SBram Moolenaar 	    // want to abort further processing if an error was given.
1758327d3ee4SBram Moolenaar 	    ret = FAIL;
17596e850a69SBram Moolenaar 	    clear_tv(rettv);
17606e850a69SBram Moolenaar 	}
1761a9b579f3SBram Moolenaar 
1762a9b579f3SBram Moolenaar 	funcargs.ga_len -= i;
1763a9b579f3SBram Moolenaar     }
1764a9b579f3SBram Moolenaar     else if (!aborting())
1765a9b579f3SBram Moolenaar     {
1766a9b579f3SBram Moolenaar 	if (argcount == MAX_FUNC_ARGS)
1767a9b579f3SBram Moolenaar 	    emsg_funcname(N_("E740: Too many arguments for function %s"), name);
1768a9b579f3SBram Moolenaar 	else
1769a9b579f3SBram Moolenaar 	    emsg_funcname(N_("E116: Invalid arguments for function %s"), name);
1770a9b579f3SBram Moolenaar     }
1771a9b579f3SBram Moolenaar 
1772a9b579f3SBram Moolenaar     while (--argcount >= 0)
1773a9b579f3SBram Moolenaar 	clear_tv(&argvars[argcount]);
1774a9b579f3SBram Moolenaar 
17758294d499SBram Moolenaar     if (in_vim9script())
17768294d499SBram Moolenaar 	*arg = argp;
17778294d499SBram Moolenaar     else
1778a9b579f3SBram Moolenaar 	*arg = skipwhite(argp);
1779a9b579f3SBram Moolenaar     return ret;
1780a9b579f3SBram Moolenaar }
1781a9b579f3SBram Moolenaar 
1782a9b579f3SBram Moolenaar /*
1783a9b579f3SBram Moolenaar  * Return TRUE if "p" starts with "<SID>" or "s:".
1784a9b579f3SBram Moolenaar  * Only works if eval_fname_script() returned non-zero for "p"!
1785a9b579f3SBram Moolenaar  */
1786a9b579f3SBram Moolenaar     static int
eval_fname_sid(char_u * p)1787a9b579f3SBram Moolenaar eval_fname_sid(char_u *p)
1788a9b579f3SBram Moolenaar {
1789a9b579f3SBram Moolenaar     return (*p == 's' || TOUPPER_ASC(p[2]) == 'I');
1790a9b579f3SBram Moolenaar }
1791a9b579f3SBram Moolenaar 
1792a9b579f3SBram Moolenaar /*
1793a9b579f3SBram Moolenaar  * In a script change <SID>name() and s:name() to K_SNR 123_name().
1794a9b579f3SBram Moolenaar  * Change <SNR>123_name() to K_SNR 123_name().
1795a9b579f3SBram Moolenaar  * Use "fname_buf[FLEN_FIXED + 1]" when it fits, otherwise allocate memory
1796a9b579f3SBram Moolenaar  * (slow).
1797a9b579f3SBram Moolenaar  */
17985cab73f8SBram Moolenaar     char_u *
fname_trans_sid(char_u * name,char_u * fname_buf,char_u ** tofree,int * error)1799a9b579f3SBram Moolenaar fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error)
1800a9b579f3SBram Moolenaar {
1801a9b579f3SBram Moolenaar     int		llen;
1802a9b579f3SBram Moolenaar     char_u	*fname;
1803a9b579f3SBram Moolenaar     int		i;
1804a9b579f3SBram Moolenaar 
1805a9b579f3SBram Moolenaar     llen = eval_fname_script(name);
1806a9b579f3SBram Moolenaar     if (llen > 0)
1807a9b579f3SBram Moolenaar     {
1808a9b579f3SBram Moolenaar 	fname_buf[0] = K_SPECIAL;
1809a9b579f3SBram Moolenaar 	fname_buf[1] = KS_EXTRA;
1810a9b579f3SBram Moolenaar 	fname_buf[2] = (int)KE_SNR;
1811a9b579f3SBram Moolenaar 	i = 3;
1812e38eab22SBram Moolenaar 	if (eval_fname_sid(name))	// "<SID>" or "s:"
1813a9b579f3SBram Moolenaar 	{
1814f29c1c6aSBram Moolenaar 	    if (current_sctx.sc_sid <= 0)
1815ef140544SBram Moolenaar 		*error = FCERR_SCRIPT;
1816a9b579f3SBram Moolenaar 	    else
1817a9b579f3SBram Moolenaar 	    {
1818ad3ec76bSBram Moolenaar 		sprintf((char *)fname_buf + 3, "%ld_",
1819ad3ec76bSBram Moolenaar 						    (long)current_sctx.sc_sid);
1820a9b579f3SBram Moolenaar 		i = (int)STRLEN(fname_buf);
1821a9b579f3SBram Moolenaar 	    }
1822a9b579f3SBram Moolenaar 	}
1823a9b579f3SBram Moolenaar 	if (i + STRLEN(name + llen) < FLEN_FIXED)
1824a9b579f3SBram Moolenaar 	{
1825a9b579f3SBram Moolenaar 	    STRCPY(fname_buf + i, name + llen);
1826a9b579f3SBram Moolenaar 	    fname = fname_buf;
1827a9b579f3SBram Moolenaar 	}
1828a9b579f3SBram Moolenaar 	else
1829a9b579f3SBram Moolenaar 	{
1830964b3746SBram Moolenaar 	    fname = alloc(i + STRLEN(name + llen) + 1);
1831a9b579f3SBram Moolenaar 	    if (fname == NULL)
1832ef140544SBram Moolenaar 		*error = FCERR_OTHER;
1833a9b579f3SBram Moolenaar 	    else
1834a9b579f3SBram Moolenaar 	    {
1835a9b579f3SBram Moolenaar 		*tofree = fname;
1836a9b579f3SBram Moolenaar 		mch_memmove(fname, fname_buf, (size_t)i);
1837a9b579f3SBram Moolenaar 		STRCPY(fname + i, name + llen);
1838a9b579f3SBram Moolenaar 	    }
1839a9b579f3SBram Moolenaar 	}
1840a9b579f3SBram Moolenaar     }
1841a9b579f3SBram Moolenaar     else
1842a9b579f3SBram Moolenaar 	fname = name;
1843a9b579f3SBram Moolenaar     return fname;
1844a9b579f3SBram Moolenaar }
1845a9b579f3SBram Moolenaar 
1846a9b579f3SBram Moolenaar /*
18478a7d6542SBram Moolenaar  * Find a function "name" in script "sid".
18488a7d6542SBram Moolenaar  */
18498a7d6542SBram Moolenaar     static ufunc_T *
find_func_with_sid(char_u * name,int sid)18508a7d6542SBram Moolenaar find_func_with_sid(char_u *name, int sid)
18518a7d6542SBram Moolenaar {
18528a7d6542SBram Moolenaar     hashitem_T	*hi;
18538a7d6542SBram Moolenaar     char_u	buffer[200];
18548a7d6542SBram Moolenaar 
18558a7d6542SBram Moolenaar     buffer[0] = K_SPECIAL;
18568a7d6542SBram Moolenaar     buffer[1] = KS_EXTRA;
18578a7d6542SBram Moolenaar     buffer[2] = (int)KE_SNR;
18588a7d6542SBram Moolenaar     vim_snprintf((char *)buffer + 3, sizeof(buffer) - 3, "%ld_%s",
18598a7d6542SBram Moolenaar 							      (long)sid, name);
18608a7d6542SBram Moolenaar     hi = hash_find(&func_hashtab, buffer);
18618a7d6542SBram Moolenaar     if (!HASHITEM_EMPTY(hi))
18628a7d6542SBram Moolenaar 	return HI2UF(hi);
18638a7d6542SBram Moolenaar 
18648a7d6542SBram Moolenaar     return NULL;
18658a7d6542SBram Moolenaar }
18668a7d6542SBram Moolenaar 
18678a7d6542SBram Moolenaar /*
1868a9b579f3SBram Moolenaar  * Find a function by name, return pointer to it in ufuncs.
18694c17ad94SBram Moolenaar  * When "is_global" is true don't find script-local or imported functions.
1870a9b579f3SBram Moolenaar  * Return NULL for unknown function.
1871a9b579f3SBram Moolenaar  */
1872ce658356SBram Moolenaar     ufunc_T *
find_func_even_dead(char_u * name,int is_global,cctx_T * cctx)18734c17ad94SBram Moolenaar find_func_even_dead(char_u *name, int is_global, cctx_T *cctx)
1874a9b579f3SBram Moolenaar {
1875a9b579f3SBram Moolenaar     hashitem_T	*hi;
18768a7d6542SBram Moolenaar     ufunc_T	*func;
18778a7d6542SBram Moolenaar     imported_T	*imported;
18788a7d6542SBram Moolenaar 
18799721fb4eSBram Moolenaar     if (!is_global)
18809721fb4eSBram Moolenaar     {
18819721fb4eSBram Moolenaar 	char_u	*after_script = NULL;
1882efa94447SBram Moolenaar 	long	sid = 0;
188395006e3dSBram Moolenaar 	int	find_script_local = in_vim9script()
188495006e3dSBram Moolenaar 				     && eval_isnamec1(*name) && name[1] != ':';
18859721fb4eSBram Moolenaar 
188695006e3dSBram Moolenaar 	if (find_script_local)
18878a7d6542SBram Moolenaar 	{
18888a7d6542SBram Moolenaar 	    // Find script-local function before global one.
18898a7d6542SBram Moolenaar 	    func = find_func_with_sid(name, current_sctx.sc_sid);
18908a7d6542SBram Moolenaar 	    if (func != NULL)
18918a7d6542SBram Moolenaar 		return func;
18929721fb4eSBram Moolenaar 	}
18938a7d6542SBram Moolenaar 
1894efa94447SBram Moolenaar 	if (name[0] == K_SPECIAL
18959721fb4eSBram Moolenaar 		&& name[1] == KS_EXTRA
18969721fb4eSBram Moolenaar 		&& name[2] == KE_SNR)
18979721fb4eSBram Moolenaar 	{
18989721fb4eSBram Moolenaar 	    // Caller changes s: to <SNR>99_name.
18999721fb4eSBram Moolenaar 
19009721fb4eSBram Moolenaar 	    after_script = name + 3;
19019721fb4eSBram Moolenaar 	    sid = getdigits(&after_script);
1902efa94447SBram Moolenaar 	    if (*after_script == '_')
19039721fb4eSBram Moolenaar 		++after_script;
19049721fb4eSBram Moolenaar 	    else
19059721fb4eSBram Moolenaar 		after_script = NULL;
19069721fb4eSBram Moolenaar 	}
190795006e3dSBram Moolenaar 	if (find_script_local || after_script != NULL)
19089721fb4eSBram Moolenaar 	{
19099721fb4eSBram Moolenaar 	    // Find imported function before global one.
1910efa94447SBram Moolenaar 	    if (after_script != NULL && sid != current_sctx.sc_sid)
1911efa94447SBram Moolenaar 		imported = find_imported_in_script(after_script, 0, sid);
1912efa94447SBram Moolenaar 	    else
1913efa94447SBram Moolenaar 		imported = find_imported(after_script == NULL
1914efa94447SBram Moolenaar 					       ? name : after_script, 0, cctx);
19158a7d6542SBram Moolenaar 	    if (imported != NULL && imported->imp_funcname != NULL)
19168a7d6542SBram Moolenaar 	    {
19178a7d6542SBram Moolenaar 		hi = hash_find(&func_hashtab, imported->imp_funcname);
19188a7d6542SBram Moolenaar 		if (!HASHITEM_EMPTY(hi))
19198a7d6542SBram Moolenaar 		    return HI2UF(hi);
19208a7d6542SBram Moolenaar 	    }
19218a7d6542SBram Moolenaar 	}
19229721fb4eSBram Moolenaar     }
1923a9b579f3SBram Moolenaar 
1924a26b9700SBram Moolenaar     hi = hash_find(&func_hashtab,
1925a26b9700SBram Moolenaar 				STRNCMP(name, "g:", 2) == 0 ? name + 2 : name);
1926a9b579f3SBram Moolenaar     if (!HASHITEM_EMPTY(hi))
1927a9b579f3SBram Moolenaar 	return HI2UF(hi);
19288a7d6542SBram Moolenaar 
19298a7d6542SBram Moolenaar     return NULL;
19308a7d6542SBram Moolenaar }
19318a7d6542SBram Moolenaar 
19328a7d6542SBram Moolenaar /*
19338a7d6542SBram Moolenaar  * Find a function by name, return pointer to it in ufuncs.
19348a7d6542SBram Moolenaar  * "cctx" is passed in a :def function to find imported functions.
19358a7d6542SBram Moolenaar  * Return NULL for unknown or dead function.
19368a7d6542SBram Moolenaar  */
19378a7d6542SBram Moolenaar     ufunc_T *
find_func(char_u * name,int is_global,cctx_T * cctx)19384c17ad94SBram Moolenaar find_func(char_u *name, int is_global, cctx_T *cctx)
19398a7d6542SBram Moolenaar {
19404c17ad94SBram Moolenaar     ufunc_T	*fp = find_func_even_dead(name, is_global, cctx);
19418a7d6542SBram Moolenaar 
19428a7d6542SBram Moolenaar     if (fp != NULL && (fp->uf_flags & FC_DEAD) == 0)
19438a7d6542SBram Moolenaar 	return fp;
1944a9b579f3SBram Moolenaar     return NULL;
1945a9b579f3SBram Moolenaar }
1946a9b579f3SBram Moolenaar 
1947a9b579f3SBram Moolenaar /*
19480f769815SBram Moolenaar  * Return TRUE if "ufunc" is a global function.
19490f769815SBram Moolenaar  */
19500f769815SBram Moolenaar     int
func_is_global(ufunc_T * ufunc)19510f769815SBram Moolenaar func_is_global(ufunc_T *ufunc)
19520f769815SBram Moolenaar {
19530f769815SBram Moolenaar     return ufunc->uf_name[0] != K_SPECIAL;
19540f769815SBram Moolenaar }
19550f769815SBram Moolenaar 
19560f769815SBram Moolenaar /*
1957a9b579f3SBram Moolenaar  * Copy the function name of "fp" to buffer "buf".
1958a9b579f3SBram Moolenaar  * "buf" must be able to hold the function name plus three bytes.
1959a9b579f3SBram Moolenaar  * Takes care of script-local function names.
1960a9b579f3SBram Moolenaar  */
1961a9b579f3SBram Moolenaar     static void
cat_func_name(char_u * buf,ufunc_T * fp)1962a9b579f3SBram Moolenaar cat_func_name(char_u *buf, ufunc_T *fp)
1963a9b579f3SBram Moolenaar {
19640f769815SBram Moolenaar     if (!func_is_global(fp))
1965a9b579f3SBram Moolenaar     {
1966a9b579f3SBram Moolenaar 	STRCPY(buf, "<SNR>");
1967a9b579f3SBram Moolenaar 	STRCAT(buf, fp->uf_name + 3);
1968a9b579f3SBram Moolenaar     }
1969a9b579f3SBram Moolenaar     else
1970a9b579f3SBram Moolenaar 	STRCPY(buf, fp->uf_name);
1971a9b579f3SBram Moolenaar }
1972a9b579f3SBram Moolenaar 
1973a9b579f3SBram Moolenaar /*
1974a9b579f3SBram Moolenaar  * Add a number variable "name" to dict "dp" with value "nr".
1975a9b579f3SBram Moolenaar  */
1976a9b579f3SBram Moolenaar     static void
add_nr_var(dict_T * dp,dictitem_T * v,char * name,varnumber_T nr)1977a9b579f3SBram Moolenaar add_nr_var(
1978a9b579f3SBram Moolenaar     dict_T	*dp,
1979a9b579f3SBram Moolenaar     dictitem_T	*v,
1980a9b579f3SBram Moolenaar     char	*name,
1981a9b579f3SBram Moolenaar     varnumber_T nr)
1982a9b579f3SBram Moolenaar {
1983a9b579f3SBram Moolenaar     STRCPY(v->di_key, name);
1984a9b579f3SBram Moolenaar     v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
1985a9b579f3SBram Moolenaar     hash_add(&dp->dv_hashtab, DI2HIKEY(v));
1986a9b579f3SBram Moolenaar     v->di_tv.v_type = VAR_NUMBER;
1987a9b579f3SBram Moolenaar     v->di_tv.v_lock = VAR_FIXED;
1988a9b579f3SBram Moolenaar     v->di_tv.vval.v_number = nr;
1989a9b579f3SBram Moolenaar }
1990a9b579f3SBram Moolenaar 
1991a9b579f3SBram Moolenaar /*
1992209b8e3eSBram Moolenaar  * Free "fc".
1993a9b579f3SBram Moolenaar  */
1994a9b579f3SBram Moolenaar     static void
free_funccal(funccall_T * fc)1995209b8e3eSBram Moolenaar free_funccal(funccall_T *fc)
1996a9b579f3SBram Moolenaar {
19971e96d9bfSBram Moolenaar     int	i;
19981e96d9bfSBram Moolenaar 
19991e96d9bfSBram Moolenaar     for (i = 0; i < fc->fc_funcs.ga_len; ++i)
20001e96d9bfSBram Moolenaar     {
20011e96d9bfSBram Moolenaar 	ufunc_T *fp = ((ufunc_T **)(fc->fc_funcs.ga_data))[i];
20021e96d9bfSBram Moolenaar 
2003209b8e3eSBram Moolenaar 	// When garbage collecting a funccall_T may be freed before the
2004209b8e3eSBram Moolenaar 	// function that references it, clear its uf_scoped field.
2005209b8e3eSBram Moolenaar 	// The function may have been redefined and point to another
2006209b8e3eSBram Moolenaar 	// funccall_T, don't clear it then.
2007bc7ce675SBram Moolenaar 	if (fp != NULL && fp->uf_scoped == fc)
20081e96d9bfSBram Moolenaar 	    fp->uf_scoped = NULL;
200958016448SBram Moolenaar     }
201058016448SBram Moolenaar     ga_clear(&fc->fc_funcs);
2011a9b579f3SBram Moolenaar 
2012209b8e3eSBram Moolenaar     func_ptr_unref(fc->func);
2013209b8e3eSBram Moolenaar     vim_free(fc);
2014209b8e3eSBram Moolenaar }
2015a9b579f3SBram Moolenaar 
2016209b8e3eSBram Moolenaar /*
2017209b8e3eSBram Moolenaar  * Free "fc" and what it contains.
2018209b8e3eSBram Moolenaar  * Can be called only when "fc" is kept beyond the period of it called,
2019209b8e3eSBram Moolenaar  * i.e. after cleanup_function_call(fc).
2020209b8e3eSBram Moolenaar  */
2021209b8e3eSBram Moolenaar    static void
free_funccal_contents(funccall_T * fc)2022209b8e3eSBram Moolenaar free_funccal_contents(funccall_T *fc)
2023209b8e3eSBram Moolenaar {
2024209b8e3eSBram Moolenaar     listitem_T	*li;
2025209b8e3eSBram Moolenaar 
2026209b8e3eSBram Moolenaar     // Free all l: variables.
2027a9b579f3SBram Moolenaar     vars_clear(&fc->l_vars.dv_hashtab);
2028a9b579f3SBram Moolenaar 
2029209b8e3eSBram Moolenaar     // Free all a: variables.
2030209b8e3eSBram Moolenaar     vars_clear(&fc->l_avars.dv_hashtab);
2031209b8e3eSBram Moolenaar 
2032209b8e3eSBram Moolenaar     // Free the a:000 variables.
2033aeea7215SBram Moolenaar     FOR_ALL_LIST_ITEMS(&fc->l_varlist, li)
2034a9b579f3SBram Moolenaar 	clear_tv(&li->li_tv);
2035a9b579f3SBram Moolenaar 
2036209b8e3eSBram Moolenaar     free_funccal(fc);
2037a9b579f3SBram Moolenaar }
2038a9b579f3SBram Moolenaar 
2039a9b579f3SBram Moolenaar /*
20406914c64eSBram Moolenaar  * Handle the last part of returning from a function: free the local hashtable.
20416914c64eSBram Moolenaar  * Unless it is still in use by a closure.
20426914c64eSBram Moolenaar  */
20436914c64eSBram Moolenaar     static void
cleanup_function_call(funccall_T * fc)20446914c64eSBram Moolenaar cleanup_function_call(funccall_T *fc)
20456914c64eSBram Moolenaar {
2046209b8e3eSBram Moolenaar     int	may_free_fc = fc->fc_refcount <= 0;
2047209b8e3eSBram Moolenaar     int	free_fc = TRUE;
2048209b8e3eSBram Moolenaar 
20496914c64eSBram Moolenaar     current_funccal = fc->caller;
20506914c64eSBram Moolenaar 
2051209b8e3eSBram Moolenaar     // Free all l: variables if not referred.
2052209b8e3eSBram Moolenaar     if (may_free_fc && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT)
2053209b8e3eSBram Moolenaar 	vars_clear(&fc->l_vars.dv_hashtab);
2054209b8e3eSBram Moolenaar     else
2055209b8e3eSBram Moolenaar 	free_fc = FALSE;
2056209b8e3eSBram Moolenaar 
2057209b8e3eSBram Moolenaar     // If the a:000 list and the l: and a: dicts are not referenced and
2058209b8e3eSBram Moolenaar     // there is no closure using it, we can free the funccall_T and what's
2059209b8e3eSBram Moolenaar     // in it.
2060209b8e3eSBram Moolenaar     if (may_free_fc && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT)
2061209b8e3eSBram Moolenaar 	vars_clear_ext(&fc->l_avars.dv_hashtab, FALSE);
20626914c64eSBram Moolenaar     else
20636914c64eSBram Moolenaar     {
20646914c64eSBram Moolenaar 	int	    todo;
2065209b8e3eSBram Moolenaar 	hashitem_T  *hi;
2066209b8e3eSBram Moolenaar 	dictitem_T  *di;
20676914c64eSBram Moolenaar 
2068209b8e3eSBram Moolenaar 	free_fc = FALSE;
20696914c64eSBram Moolenaar 
2070209b8e3eSBram Moolenaar 	// Make a copy of the a: variables, since we didn't do that above.
20716914c64eSBram Moolenaar 	todo = (int)fc->l_avars.dv_hashtab.ht_used;
20726914c64eSBram Moolenaar 	for (hi = fc->l_avars.dv_hashtab.ht_array; todo > 0; ++hi)
20736914c64eSBram Moolenaar 	{
20746914c64eSBram Moolenaar 	    if (!HASHITEM_EMPTY(hi))
20756914c64eSBram Moolenaar 	    {
20766914c64eSBram Moolenaar 		--todo;
2077209b8e3eSBram Moolenaar 		di = HI2DI(hi);
2078209b8e3eSBram Moolenaar 		copy_tv(&di->di_tv, &di->di_tv);
2079209b8e3eSBram Moolenaar 	    }
20806914c64eSBram Moolenaar 	}
20816914c64eSBram Moolenaar     }
20826914c64eSBram Moolenaar 
2083209b8e3eSBram Moolenaar     if (may_free_fc && fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT)
2084209b8e3eSBram Moolenaar 	fc->l_varlist.lv_first = NULL;
2085209b8e3eSBram Moolenaar     else
2086209b8e3eSBram Moolenaar     {
2087209b8e3eSBram Moolenaar 	listitem_T *li;
2088209b8e3eSBram Moolenaar 
2089209b8e3eSBram Moolenaar 	free_fc = FALSE;
2090209b8e3eSBram Moolenaar 
2091209b8e3eSBram Moolenaar 	// Make a copy of the a:000 items, since we didn't do that above.
2092aeea7215SBram Moolenaar 	FOR_ALL_LIST_ITEMS(&fc->l_varlist, li)
20936914c64eSBram Moolenaar 	    copy_tv(&li->li_tv, &li->li_tv);
2094209b8e3eSBram Moolenaar     }
20954456ab52SBram Moolenaar 
2096209b8e3eSBram Moolenaar     if (free_fc)
2097209b8e3eSBram Moolenaar 	free_funccal(fc);
2098209b8e3eSBram Moolenaar     else
20994456ab52SBram Moolenaar     {
2100209b8e3eSBram Moolenaar 	static int made_copy = 0;
2101209b8e3eSBram Moolenaar 
2102209b8e3eSBram Moolenaar 	// "fc" is still in use.  This can happen when returning "a:000",
2103209b8e3eSBram Moolenaar 	// assigning "l:" to a global variable or defining a closure.
2104209b8e3eSBram Moolenaar 	// Link "fc" in the list for garbage collection later.
2105209b8e3eSBram Moolenaar 	fc->caller = previous_funccal;
2106209b8e3eSBram Moolenaar 	previous_funccal = fc;
2107209b8e3eSBram Moolenaar 
2108209b8e3eSBram Moolenaar 	if (want_garbage_collect)
2109209b8e3eSBram Moolenaar 	    // If garbage collector is ready, clear count.
2110209b8e3eSBram Moolenaar 	    made_copy = 0;
2111209b8e3eSBram Moolenaar 	else if (++made_copy >= (int)((4096 * 1024) / sizeof(*fc)))
2112209b8e3eSBram Moolenaar 	{
2113209b8e3eSBram Moolenaar 	    // We have made a lot of copies, worth 4 Mbyte.  This can happen
2114209b8e3eSBram Moolenaar 	    // when repetitively calling a function that creates a reference to
2115889da2f2SBram Moolenaar 	    // itself somehow.  Call the garbage collector soon to avoid using
21164456ab52SBram Moolenaar 	    // too much memory.
21174456ab52SBram Moolenaar 	    made_copy = 0;
2118889da2f2SBram Moolenaar 	    want_garbage_collect = TRUE;
21194456ab52SBram Moolenaar 	}
21206914c64eSBram Moolenaar     }
21216914c64eSBram Moolenaar }
2122fdeab65dSBram Moolenaar 
2123fdeab65dSBram Moolenaar /*
2124fdeab65dSBram Moolenaar  * There are two kinds of function names:
2125fdeab65dSBram Moolenaar  * 1. ordinary names, function defined with :function or :def
2126fdeab65dSBram Moolenaar  * 2. numbered functions and lambdas
2127fdeab65dSBram Moolenaar  * For the first we only count the name stored in func_hashtab as a reference,
2128fdeab65dSBram Moolenaar  * using function() does not count as a reference, because the function is
2129fdeab65dSBram Moolenaar  * looked up by name.
2130fdeab65dSBram Moolenaar  */
2131a05e524fSBram Moolenaar     int
func_name_refcount(char_u * name)2132fdeab65dSBram Moolenaar func_name_refcount(char_u *name)
2133fdeab65dSBram Moolenaar {
2134fdeab65dSBram Moolenaar     return isdigit(*name) || *name == '<';
2135fdeab65dSBram Moolenaar }
2136fdeab65dSBram Moolenaar 
21378a7d6542SBram Moolenaar /*
21388a7d6542SBram Moolenaar  * Unreference "fc": decrement the reference count and free it when it
21398a7d6542SBram Moolenaar  * becomes zero.  "fp" is detached from "fc".
21408a7d6542SBram Moolenaar  * When "force" is TRUE we are exiting.
21418a7d6542SBram Moolenaar  */
21428a7d6542SBram Moolenaar     static void
funccal_unref(funccall_T * fc,ufunc_T * fp,int force)21438a7d6542SBram Moolenaar funccal_unref(funccall_T *fc, ufunc_T *fp, int force)
21448a7d6542SBram Moolenaar {
21458a7d6542SBram Moolenaar     funccall_T	**pfc;
21468a7d6542SBram Moolenaar     int		i;
21478a7d6542SBram Moolenaar 
21488a7d6542SBram Moolenaar     if (fc == NULL)
21498a7d6542SBram Moolenaar 	return;
21508a7d6542SBram Moolenaar 
21518a7d6542SBram Moolenaar     if (--fc->fc_refcount <= 0 && (force || (
21528a7d6542SBram Moolenaar 		fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT
21538a7d6542SBram Moolenaar 		&& fc->l_vars.dv_refcount == DO_NOT_FREE_CNT
21548a7d6542SBram Moolenaar 		&& fc->l_avars.dv_refcount == DO_NOT_FREE_CNT)))
21558a7d6542SBram Moolenaar 	for (pfc = &previous_funccal; *pfc != NULL; pfc = &(*pfc)->caller)
21568a7d6542SBram Moolenaar 	{
21578a7d6542SBram Moolenaar 	    if (fc == *pfc)
21588a7d6542SBram Moolenaar 	    {
21598a7d6542SBram Moolenaar 		*pfc = fc->caller;
21608a7d6542SBram Moolenaar 		free_funccal_contents(fc);
21618a7d6542SBram Moolenaar 		return;
21628a7d6542SBram Moolenaar 	    }
21638a7d6542SBram Moolenaar 	}
21648a7d6542SBram Moolenaar     for (i = 0; i < fc->fc_funcs.ga_len; ++i)
21658a7d6542SBram Moolenaar 	if (((ufunc_T **)(fc->fc_funcs.ga_data))[i] == fp)
21668a7d6542SBram Moolenaar 	    ((ufunc_T **)(fc->fc_funcs.ga_data))[i] = NULL;
21678a7d6542SBram Moolenaar }
21688a7d6542SBram Moolenaar 
21698a7d6542SBram Moolenaar /*
21708a7d6542SBram Moolenaar  * Remove the function from the function hashtable.  If the function was
21718a7d6542SBram Moolenaar  * deleted while it still has references this was already done.
21728a7d6542SBram Moolenaar  * Return TRUE if the entry was deleted, FALSE if it wasn't found.
21738a7d6542SBram Moolenaar  */
21748a7d6542SBram Moolenaar     static int
func_remove(ufunc_T * fp)21758a7d6542SBram Moolenaar func_remove(ufunc_T *fp)
21768a7d6542SBram Moolenaar {
21778a7d6542SBram Moolenaar     hashitem_T	*hi;
21788a7d6542SBram Moolenaar 
21798a7d6542SBram Moolenaar     // Return if it was already virtually deleted.
21808a7d6542SBram Moolenaar     if (fp->uf_flags & FC_DEAD)
21818a7d6542SBram Moolenaar 	return FALSE;
21828a7d6542SBram Moolenaar 
21838a7d6542SBram Moolenaar     hi = hash_find(&func_hashtab, UF2HIKEY(fp));
21848a7d6542SBram Moolenaar     if (!HASHITEM_EMPTY(hi))
21858a7d6542SBram Moolenaar     {
21868a7d6542SBram Moolenaar 	// When there is a def-function index do not actually remove the
21878a7d6542SBram Moolenaar 	// function, so we can find the index when defining the function again.
218838ddf333SBram Moolenaar 	// Do remove it when it's a copy.
218938ddf333SBram Moolenaar 	if (fp->uf_def_status == UF_COMPILED && (fp->uf_flags & FC_COPY) == 0)
2190c970e422SBram Moolenaar 	{
21918a7d6542SBram Moolenaar 	    fp->uf_flags |= FC_DEAD;
2192c970e422SBram Moolenaar 	    return FALSE;
2193c970e422SBram Moolenaar 	}
21948a7d6542SBram Moolenaar 	hash_remove(&func_hashtab, hi);
2195c970e422SBram Moolenaar 	fp->uf_flags |= FC_DELETED;
21968a7d6542SBram Moolenaar 	return TRUE;
21978a7d6542SBram Moolenaar     }
21988a7d6542SBram Moolenaar     return FALSE;
21998a7d6542SBram Moolenaar }
22008a7d6542SBram Moolenaar 
22018a7d6542SBram Moolenaar     static void
func_clear_items(ufunc_T * fp)22028a7d6542SBram Moolenaar func_clear_items(ufunc_T *fp)
22038a7d6542SBram Moolenaar {
22048a7d6542SBram Moolenaar     ga_clear_strings(&(fp->uf_args));
22058a7d6542SBram Moolenaar     ga_clear_strings(&(fp->uf_def_args));
22068a7d6542SBram Moolenaar     ga_clear_strings(&(fp->uf_lines));
22078a7d6542SBram Moolenaar     VIM_CLEAR(fp->uf_arg_types);
2208fbbcd003SBram Moolenaar     VIM_CLEAR(fp->uf_block_ids);
2209292b90d4SBram Moolenaar     VIM_CLEAR(fp->uf_va_name);
22106110e79aSBram Moolenaar     clear_type_list(&fp->uf_type_list);
22110d3de8cbSBram Moolenaar 
22120d3de8cbSBram Moolenaar     // Increment the refcount of this function to avoid it being freed
22130d3de8cbSBram Moolenaar     // recursively when the partial is freed.
22140d3de8cbSBram Moolenaar     fp->uf_refcount += 3;
2215f112f30aSBram Moolenaar     partial_unref(fp->uf_partial);
2216f112f30aSBram Moolenaar     fp->uf_partial = NULL;
22170d3de8cbSBram Moolenaar     fp->uf_refcount -= 3;
2218801ab069SBram Moolenaar 
2219801ab069SBram Moolenaar #ifdef FEAT_LUA
2220801ab069SBram Moolenaar     if (fp->uf_cb_free != NULL)
2221801ab069SBram Moolenaar     {
2222801ab069SBram Moolenaar 	fp->uf_cb_free(fp->uf_cb_state);
2223801ab069SBram Moolenaar 	fp->uf_cb_free = NULL;
2224801ab069SBram Moolenaar     }
2225801ab069SBram Moolenaar 
2226801ab069SBram Moolenaar     fp->uf_cb_state = NULL;
2227801ab069SBram Moolenaar     fp->uf_cb = NULL;
2228801ab069SBram Moolenaar #endif
22298a7d6542SBram Moolenaar #ifdef FEAT_PROFILE
22308a7d6542SBram Moolenaar     VIM_CLEAR(fp->uf_tml_count);
22318a7d6542SBram Moolenaar     VIM_CLEAR(fp->uf_tml_total);
22328a7d6542SBram Moolenaar     VIM_CLEAR(fp->uf_tml_self);
22338a7d6542SBram Moolenaar #endif
22348a7d6542SBram Moolenaar }
22358a7d6542SBram Moolenaar 
22368a7d6542SBram Moolenaar /*
22378a7d6542SBram Moolenaar  * Free all things that a function contains.  Does not free the function
22388a7d6542SBram Moolenaar  * itself, use func_free() for that.
22398a7d6542SBram Moolenaar  * When "force" is TRUE we are exiting.
22408a7d6542SBram Moolenaar  */
22418a7d6542SBram Moolenaar     static void
func_clear(ufunc_T * fp,int force)22428a7d6542SBram Moolenaar func_clear(ufunc_T *fp, int force)
22438a7d6542SBram Moolenaar {
22448a7d6542SBram Moolenaar     if (fp->uf_cleared)
22458a7d6542SBram Moolenaar 	return;
22468a7d6542SBram Moolenaar     fp->uf_cleared = TRUE;
22478a7d6542SBram Moolenaar 
22488a7d6542SBram Moolenaar     // clear this function
22498a7d6542SBram Moolenaar     func_clear_items(fp);
22508a7d6542SBram Moolenaar     funccal_unref(fp->uf_scoped, fp, force);
2251cd45ed03SBram Moolenaar     unlink_def_function(fp);
22528a7d6542SBram Moolenaar }
22538a7d6542SBram Moolenaar 
22548a7d6542SBram Moolenaar /*
22558a7d6542SBram Moolenaar  * Free a function and remove it from the list of functions.  Does not free
22568a7d6542SBram Moolenaar  * what a function contains, call func_clear() first.
2257f7779c63SBram Moolenaar  * When "force" is TRUE we are exiting.
2258a05e524fSBram Moolenaar  * Returns OK when the function was actually freed.
22598a7d6542SBram Moolenaar  */
2260a05e524fSBram Moolenaar     static int
func_free(ufunc_T * fp,int force)2261f7779c63SBram Moolenaar func_free(ufunc_T *fp, int force)
22628a7d6542SBram Moolenaar {
22638a7d6542SBram Moolenaar     // Only remove it when not done already, otherwise we would remove a newer
22648a7d6542SBram Moolenaar     // version of the function with the same name.
22658a7d6542SBram Moolenaar     if ((fp->uf_flags & (FC_DELETED | FC_REMOVED)) == 0)
22668a7d6542SBram Moolenaar 	func_remove(fp);
22678a7d6542SBram Moolenaar 
2268f7779c63SBram Moolenaar     if ((fp->uf_flags & FC_DEAD) == 0 || force)
2269c4ce36d4SBram Moolenaar     {
2270fdeab65dSBram Moolenaar 	if (fp->uf_dfunc_idx > 0)
2271fdeab65dSBram Moolenaar 	    unlink_def_function(fp);
2272c4ce36d4SBram Moolenaar 	VIM_CLEAR(fp->uf_name_exp);
22738a7d6542SBram Moolenaar 	vim_free(fp);
2274a05e524fSBram Moolenaar 	return OK;
22758a7d6542SBram Moolenaar     }
2276a05e524fSBram Moolenaar     return FAIL;
2277c4ce36d4SBram Moolenaar }
22788a7d6542SBram Moolenaar 
22798a7d6542SBram Moolenaar /*
22808a7d6542SBram Moolenaar  * Free all things that a function contains and free the function itself.
22818a7d6542SBram Moolenaar  * When "force" is TRUE we are exiting.
22828a7d6542SBram Moolenaar  */
22838a7d6542SBram Moolenaar     static void
func_clear_free(ufunc_T * fp,int force)22848a7d6542SBram Moolenaar func_clear_free(ufunc_T *fp, int force)
22858a7d6542SBram Moolenaar {
22868a7d6542SBram Moolenaar     func_clear(fp, force);
2287fdeab65dSBram Moolenaar     if (force || fp->uf_dfunc_idx == 0 || func_name_refcount(fp->uf_name)
2288fdeab65dSBram Moolenaar 						   || (fp->uf_flags & FC_COPY))
2289f7779c63SBram Moolenaar 	func_free(fp, force);
2290925e9fd6SBram Moolenaar     else
2291925e9fd6SBram Moolenaar 	fp->uf_flags |= FC_DEAD;
22928a7d6542SBram Moolenaar }
22938a7d6542SBram Moolenaar 
229438ddf333SBram Moolenaar /*
229538ddf333SBram Moolenaar  * Copy already defined function "lambda" to a new function with name "global".
229638ddf333SBram Moolenaar  * This is for when a compiled function defines a global function.
229738ddf333SBram Moolenaar  */
2298cd45ed03SBram Moolenaar     int
copy_func(char_u * lambda,char_u * global,ectx_T * ectx)2299cd45ed03SBram Moolenaar copy_func(char_u *lambda, char_u *global, ectx_T *ectx)
230038ddf333SBram Moolenaar {
230138ddf333SBram Moolenaar     ufunc_T *ufunc = find_func_even_dead(lambda, TRUE, NULL);
2302f112f30aSBram Moolenaar     ufunc_T *fp = NULL;
230338ddf333SBram Moolenaar 
230438ddf333SBram Moolenaar     if (ufunc == NULL)
230538ddf333SBram Moolenaar     {
2306cd45ed03SBram Moolenaar 	semsg(_(e_lambda_function_not_found_str), lambda);
2307cd45ed03SBram Moolenaar 	return FAIL;
2308cd45ed03SBram Moolenaar     }
2309cd45ed03SBram Moolenaar 
231038ddf333SBram Moolenaar     fp = find_func(global, TRUE, NULL);
231138ddf333SBram Moolenaar     if (fp != NULL)
231238ddf333SBram Moolenaar     {
23130d3de8cbSBram Moolenaar 	// TODO: handle ! to overwrite
231438ddf333SBram Moolenaar 	semsg(_(e_funcexts), global);
2315cd45ed03SBram Moolenaar 	return FAIL;
231638ddf333SBram Moolenaar     }
231738ddf333SBram Moolenaar 
231838ddf333SBram Moolenaar     fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(global) + 1);
231938ddf333SBram Moolenaar     if (fp == NULL)
2320cd45ed03SBram Moolenaar 	return FAIL;
232138ddf333SBram Moolenaar 
232238ddf333SBram Moolenaar     fp->uf_varargs = ufunc->uf_varargs;
232338ddf333SBram Moolenaar     fp->uf_flags = (ufunc->uf_flags & ~FC_VIM9) | FC_COPY;
232438ddf333SBram Moolenaar     fp->uf_def_status = ufunc->uf_def_status;
232538ddf333SBram Moolenaar     fp->uf_dfunc_idx = ufunc->uf_dfunc_idx;
2326af8edbb8SBram Moolenaar     if (ga_copy_strings(&ufunc->uf_args, &fp->uf_args) == FAIL
2327af8edbb8SBram Moolenaar 	    || ga_copy_strings(&ufunc->uf_def_args, &fp->uf_def_args)
232838ddf333SBram Moolenaar 								    == FAIL
2329af8edbb8SBram Moolenaar 	    || ga_copy_strings(&ufunc->uf_lines, &fp->uf_lines) == FAIL)
233038ddf333SBram Moolenaar 	goto failed;
233138ddf333SBram Moolenaar 
233238ddf333SBram Moolenaar     fp->uf_name_exp = ufunc->uf_name_exp == NULL ? NULL
233338ddf333SBram Moolenaar 					 : vim_strsave(ufunc->uf_name_exp);
233438ddf333SBram Moolenaar     if (ufunc->uf_arg_types != NULL)
233538ddf333SBram Moolenaar     {
233638ddf333SBram Moolenaar 	fp->uf_arg_types = ALLOC_MULT(type_T *, fp->uf_args.ga_len);
233738ddf333SBram Moolenaar 	if (fp->uf_arg_types == NULL)
233838ddf333SBram Moolenaar 	    goto failed;
233938ddf333SBram Moolenaar 	mch_memmove(fp->uf_arg_types, ufunc->uf_arg_types,
234038ddf333SBram Moolenaar 				    sizeof(type_T *) * fp->uf_args.ga_len);
234138ddf333SBram Moolenaar     }
234238ddf333SBram Moolenaar     if (ufunc->uf_va_name != NULL)
234338ddf333SBram Moolenaar     {
234438ddf333SBram Moolenaar 	fp->uf_va_name = vim_strsave(ufunc->uf_va_name);
234538ddf333SBram Moolenaar 	if (fp->uf_va_name == NULL)
234638ddf333SBram Moolenaar 	    goto failed;
234738ddf333SBram Moolenaar     }
2348f112f30aSBram Moolenaar     fp->uf_ret_type = ufunc->uf_ret_type;
234938ddf333SBram Moolenaar 
235038ddf333SBram Moolenaar     fp->uf_refcount = 1;
235138ddf333SBram Moolenaar     STRCPY(fp->uf_name, global);
235238ddf333SBram Moolenaar     hash_add(&func_hashtab, UF2HIKEY(fp));
2353cd45ed03SBram Moolenaar 
2354cd45ed03SBram Moolenaar     // the referenced dfunc_T is now used one more time
2355cd45ed03SBram Moolenaar     link_def_function(fp);
2356cd45ed03SBram Moolenaar 
23570d3de8cbSBram Moolenaar     // Create a partial to store the context of the function where it was
23580d3de8cbSBram Moolenaar     // instantiated.  Only needs to be done once.  Do this on the original
23590d3de8cbSBram Moolenaar     // function, "dfunc->df_ufunc" will point to it.
2360cd45ed03SBram Moolenaar     if ((ufunc->uf_flags & FC_CLOSURE) && ufunc->uf_partial == NULL)
2361cd45ed03SBram Moolenaar     {
2362cd45ed03SBram Moolenaar 	partial_T   *pt = ALLOC_CLEAR_ONE(partial_T);
2363cd45ed03SBram Moolenaar 
2364cd45ed03SBram Moolenaar 	if (pt == NULL)
2365cd45ed03SBram Moolenaar 	    goto failed;
2366cd45ed03SBram Moolenaar 	if (fill_partial_and_closure(pt, ufunc, ectx) == FAIL)
2367cd45ed03SBram Moolenaar 	{
23680d3de8cbSBram Moolenaar             vim_free(pt);
23690d3de8cbSBram Moolenaar 	    goto failed;
23700d3de8cbSBram Moolenaar 	}
23710d3de8cbSBram Moolenaar 	ufunc->uf_partial = pt;
23720d3de8cbSBram Moolenaar 	--pt->pt_refcount;  // not actually referenced here
2373cd45ed03SBram Moolenaar     }
2374cd45ed03SBram Moolenaar 
2375cd45ed03SBram Moolenaar     return OK;
237638ddf333SBram Moolenaar 
237738ddf333SBram Moolenaar failed:
237838ddf333SBram Moolenaar     func_clear_free(fp, TRUE);
2379cd45ed03SBram Moolenaar     return FAIL;
238038ddf333SBram Moolenaar }
238138ddf333SBram Moolenaar 
23820ba48e8cSBram Moolenaar static int	funcdepth = 0;
23830ba48e8cSBram Moolenaar 
23840ba48e8cSBram Moolenaar /*
23850ba48e8cSBram Moolenaar  * Increment the function call depth count.
23860ba48e8cSBram Moolenaar  * Return FAIL when going over 'maxfuncdepth'.
23870ba48e8cSBram Moolenaar  * Otherwise return OK, must call funcdepth_decrement() later!
23880ba48e8cSBram Moolenaar  */
23890ba48e8cSBram Moolenaar     int
funcdepth_increment(void)23900ba48e8cSBram Moolenaar funcdepth_increment(void)
23910ba48e8cSBram Moolenaar {
23920ba48e8cSBram Moolenaar     if (funcdepth >= p_mfd)
23930ba48e8cSBram Moolenaar     {
23940ba48e8cSBram Moolenaar 	emsg(_("E132: Function call depth is higher than 'maxfuncdepth'"));
23950ba48e8cSBram Moolenaar 	return FAIL;
23960ba48e8cSBram Moolenaar     }
23970ba48e8cSBram Moolenaar     ++funcdepth;
23980ba48e8cSBram Moolenaar     return OK;
23990ba48e8cSBram Moolenaar }
24000ba48e8cSBram Moolenaar 
24010ba48e8cSBram Moolenaar     void
funcdepth_decrement(void)24020ba48e8cSBram Moolenaar funcdepth_decrement(void)
24030ba48e8cSBram Moolenaar {
24040ba48e8cSBram Moolenaar     --funcdepth;
24050ba48e8cSBram Moolenaar }
24060ba48e8cSBram Moolenaar 
24070ba48e8cSBram Moolenaar /*
24080ba48e8cSBram Moolenaar  * Get the current function call depth.
24090ba48e8cSBram Moolenaar  */
24100ba48e8cSBram Moolenaar     int
funcdepth_get(void)24110ba48e8cSBram Moolenaar funcdepth_get(void)
24120ba48e8cSBram Moolenaar {
24130ba48e8cSBram Moolenaar     return funcdepth;
24140ba48e8cSBram Moolenaar }
24150ba48e8cSBram Moolenaar 
24160ba48e8cSBram Moolenaar /*
24170ba48e8cSBram Moolenaar  * Restore the function call depth.  This is for cases where there is no
24188e7d6223SBram Moolenaar  * guarantee funcdepth_decrement() can be called exactly the same number of
24190ba48e8cSBram Moolenaar  * times as funcdepth_increment().
24200ba48e8cSBram Moolenaar  */
24210ba48e8cSBram Moolenaar     void
funcdepth_restore(int depth)24220ba48e8cSBram Moolenaar funcdepth_restore(int depth)
24230ba48e8cSBram Moolenaar {
24240ba48e8cSBram Moolenaar     funcdepth = depth;
24250ba48e8cSBram Moolenaar }
24266914c64eSBram Moolenaar 
24276914c64eSBram Moolenaar /*
2428a9b579f3SBram Moolenaar  * Call a user function.
2429a9b579f3SBram Moolenaar  */
2430a9b579f3SBram Moolenaar     static void
call_user_func(ufunc_T * fp,int argcount,typval_T * argvars,typval_T * rettv,funcexe_T * funcexe,dict_T * selfdict)2431a9b579f3SBram Moolenaar call_user_func(
2432e38eab22SBram Moolenaar     ufunc_T	*fp,		// pointer to function
2433e38eab22SBram Moolenaar     int		argcount,	// nr of args
2434e38eab22SBram Moolenaar     typval_T	*argvars,	// arguments
2435e38eab22SBram Moolenaar     typval_T	*rettv,		// return value
24366f5b6dfbSBram Moolenaar     funcexe_T	*funcexe,	// context
2437e38eab22SBram Moolenaar     dict_T	*selfdict)	// Dictionary for "self"
2438a9b579f3SBram Moolenaar {
2439f29c1c6aSBram Moolenaar     sctx_T	save_current_sctx;
244093343725SBram Moolenaar     int		using_sandbox = FALSE;
2441a9b579f3SBram Moolenaar     funccall_T	*fc;
2442a9b579f3SBram Moolenaar     int		save_did_emsg;
244342ae78cfSBram Moolenaar     int		default_arg_err = FALSE;
2444a9b579f3SBram Moolenaar     dictitem_T	*v;
2445e38eab22SBram Moolenaar     int		fixvar_idx = 0;	// index in fixvar[]
2446a9b579f3SBram Moolenaar     int		i;
2447a9b579f3SBram Moolenaar     int		ai;
2448a9b579f3SBram Moolenaar     int		islambda = FALSE;
2449a9b579f3SBram Moolenaar     char_u	numbuf[NUMBUFLEN];
2450a9b579f3SBram Moolenaar     char_u	*name;
2451b47bed2fSBram Moolenaar     typval_T	*tv_to_free[MAX_FUNC_ARGS];
2452b47bed2fSBram Moolenaar     int		tv_to_free_len = 0;
2453a9b579f3SBram Moolenaar #ifdef FEAT_PROFILE
2454b2049903SBram Moolenaar     profinfo_T	profile_info;
2455a9b579f3SBram Moolenaar #endif
2456e31ee868SBram Moolenaar     ESTACK_CHECK_DECLARATION
2457a9b579f3SBram Moolenaar 
2458b2049903SBram Moolenaar #ifdef FEAT_PROFILE
2459b2049903SBram Moolenaar     CLEAR_FIELD(profile_info);
2460b2049903SBram Moolenaar #endif
2461b2049903SBram Moolenaar 
24620ba48e8cSBram Moolenaar     // If depth of calling is getting too high, don't execute the function.
24630ba48e8cSBram Moolenaar     if (funcdepth_increment() == FAIL)
2464a9b579f3SBram Moolenaar     {
2465a9b579f3SBram Moolenaar 	rettv->v_type = VAR_NUMBER;
2466a9b579f3SBram Moolenaar 	rettv->vval.v_number = -1;
2467a9b579f3SBram Moolenaar 	return;
2468a9b579f3SBram Moolenaar     }
2469a9b579f3SBram Moolenaar 
2470e38eab22SBram Moolenaar     line_breakcheck();		// check for CTRL-C hit
2471a9b579f3SBram Moolenaar 
2472c799fe20SBram Moolenaar     fc = ALLOC_CLEAR_ONE(funccall_T);
24734456ab52SBram Moolenaar     if (fc == NULL)
24744456ab52SBram Moolenaar 	return;
2475a9b579f3SBram Moolenaar     fc->caller = current_funccal;
2476a9b579f3SBram Moolenaar     current_funccal = fc;
2477a9b579f3SBram Moolenaar     fc->func = fp;
2478a9b579f3SBram Moolenaar     fc->rettv = rettv;
2479a9b579f3SBram Moolenaar     fc->level = ex_nesting_level;
2480e38eab22SBram Moolenaar     // Check if this function has a breakpoint.
2481a9b579f3SBram Moolenaar     fc->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0);
2482a9b579f3SBram Moolenaar     fc->dbg_tick = debug_tick;
2483e38eab22SBram Moolenaar     // Set up fields for closure.
24841e96d9bfSBram Moolenaar     ga_init2(&fc->fc_funcs, sizeof(ufunc_T *), 1);
2485437bafe4SBram Moolenaar     func_ptr_ref(fp);
2486a9b579f3SBram Moolenaar 
24870cb5bcf5SBram Moolenaar     if (fp->uf_def_status != UF_NOT_COMPILED)
24888a7d6542SBram Moolenaar     {
248912d26531SBram Moolenaar #ifdef FEAT_PROFILE
249012d26531SBram Moolenaar 	ufunc_T *caller = fc->caller == NULL ? NULL : fc->caller->func;
249112d26531SBram Moolenaar #endif
249225e0f586SBram Moolenaar 	// Execute the function, possibly compiling it first.
2493b2049903SBram Moolenaar #ifdef FEAT_PROFILE
249412d26531SBram Moolenaar 	if (do_profiling == PROF_YES)
249512d26531SBram Moolenaar 	    profile_may_start_func(&profile_info, fp, caller);
2496b2049903SBram Moolenaar #endif
24976f5b6dfbSBram Moolenaar 	call_def_function(fp, argcount, argvars, funcexe->partial, rettv);
24980ba48e8cSBram Moolenaar 	funcdepth_decrement();
2499b2049903SBram Moolenaar #ifdef FEAT_PROFILE
2500b2049903SBram Moolenaar 	if (do_profiling == PROF_YES && (fp->uf_profiling
250112d26531SBram Moolenaar 				  || (caller != NULL && caller->uf_profiling)))
250212d26531SBram Moolenaar 	    profile_may_end_func(&profile_info, fp, caller);
2503b2049903SBram Moolenaar #endif
25048a7d6542SBram Moolenaar 	current_funccal = fc->caller;
25058a7d6542SBram Moolenaar 	free_funccal(fc);
25068a7d6542SBram Moolenaar 	return;
25078a7d6542SBram Moolenaar     }
25088a7d6542SBram Moolenaar 
2509a9b579f3SBram Moolenaar     if (STRNCMP(fp->uf_name, "<lambda>", 8) == 0)
2510a9b579f3SBram Moolenaar 	islambda = TRUE;
2511a9b579f3SBram Moolenaar 
2512a9b579f3SBram Moolenaar     /*
2513a9b579f3SBram Moolenaar      * Note about using fc->fixvar[]: This is an array of FIXVAR_CNT variables
2514a9b579f3SBram Moolenaar      * with names up to VAR_SHORT_LEN long.  This avoids having to alloc/free
2515a9b579f3SBram Moolenaar      * each argument variable and saves a lot of time.
2516a9b579f3SBram Moolenaar      */
2517a9b579f3SBram Moolenaar     /*
2518a9b579f3SBram Moolenaar      * Init l: variables.
2519a9b579f3SBram Moolenaar      */
2520a9b579f3SBram Moolenaar     init_var_dict(&fc->l_vars, &fc->l_vars_var, VAR_DEF_SCOPE);
2521a9b579f3SBram Moolenaar     if (selfdict != NULL)
2522a9b579f3SBram Moolenaar     {
2523e38eab22SBram Moolenaar 	// Set l:self to "selfdict".  Use "name" to avoid a warning from
2524e38eab22SBram Moolenaar 	// some compiler that checks the destination size.
2525a9b579f3SBram Moolenaar 	v = &fc->fixvar[fixvar_idx++].var;
2526a9b579f3SBram Moolenaar 	name = v->di_key;
2527a9b579f3SBram Moolenaar 	STRCPY(name, "self");
252831b81604SBram Moolenaar 	v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
2529a9b579f3SBram Moolenaar 	hash_add(&fc->l_vars.dv_hashtab, DI2HIKEY(v));
2530a9b579f3SBram Moolenaar 	v->di_tv.v_type = VAR_DICT;
2531a9b579f3SBram Moolenaar 	v->di_tv.v_lock = 0;
2532a9b579f3SBram Moolenaar 	v->di_tv.vval.v_dict = selfdict;
2533a9b579f3SBram Moolenaar 	++selfdict->dv_refcount;
2534a9b579f3SBram Moolenaar     }
2535a9b579f3SBram Moolenaar 
2536a9b579f3SBram Moolenaar     /*
2537f10806b2SBram Moolenaar      * Init a: variables, unless none found (in lambda).
253842ae78cfSBram Moolenaar      * Set a:0 to "argcount" less number of named arguments, if >= 0.
2539a9b579f3SBram Moolenaar      * Set a:000 to a list with room for the "..." arguments.
2540a9b579f3SBram Moolenaar      */
2541a9b579f3SBram Moolenaar     init_var_dict(&fc->l_avars, &fc->l_avars_var, VAR_SCOPE);
2542f10806b2SBram Moolenaar     if ((fp->uf_flags & FC_NOARGS) == 0)
2543a9b579f3SBram Moolenaar 	add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "0",
254442ae78cfSBram Moolenaar 				(varnumber_T)(argcount >= fp->uf_args.ga_len
254542ae78cfSBram Moolenaar 				    ? argcount - fp->uf_args.ga_len : 0));
254631b81604SBram Moolenaar     fc->l_avars.dv_lock = VAR_FIXED;
2547f10806b2SBram Moolenaar     if ((fp->uf_flags & FC_NOARGS) == 0)
2548f10806b2SBram Moolenaar     {
2549e38eab22SBram Moolenaar 	// Use "name" to avoid a warning from some compiler that checks the
2550e38eab22SBram Moolenaar 	// destination size.
2551a9b579f3SBram Moolenaar 	v = &fc->fixvar[fixvar_idx++].var;
2552a9b579f3SBram Moolenaar 	name = v->di_key;
2553a9b579f3SBram Moolenaar 	STRCPY(name, "000");
2554a9b579f3SBram Moolenaar 	v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
2555a9b579f3SBram Moolenaar 	hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v));
2556a9b579f3SBram Moolenaar 	v->di_tv.v_type = VAR_LIST;
2557a9b579f3SBram Moolenaar 	v->di_tv.v_lock = VAR_FIXED;
2558a9b579f3SBram Moolenaar 	v->di_tv.vval.v_list = &fc->l_varlist;
2559f10806b2SBram Moolenaar     }
2560a80faa89SBram Moolenaar     CLEAR_FIELD(fc->l_varlist);
2561a9b579f3SBram Moolenaar     fc->l_varlist.lv_refcount = DO_NOT_FREE_CNT;
2562a9b579f3SBram Moolenaar     fc->l_varlist.lv_lock = VAR_FIXED;
2563a9b579f3SBram Moolenaar 
2564a9b579f3SBram Moolenaar     /*
2565a9b579f3SBram Moolenaar      * Set a:firstline to "firstline" and a:lastline to "lastline".
2566a9b579f3SBram Moolenaar      * Set a:name to named arguments.
2567a9b579f3SBram Moolenaar      * Set a:N to the "..." arguments.
2568f10806b2SBram Moolenaar      * Skipped when no a: variables used (in lambda).
2569a9b579f3SBram Moolenaar      */
2570f10806b2SBram Moolenaar     if ((fp->uf_flags & FC_NOARGS) == 0)
2571f10806b2SBram Moolenaar     {
2572a9b579f3SBram Moolenaar 	add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "firstline",
25736f5b6dfbSBram Moolenaar 					      (varnumber_T)funcexe->firstline);
2574a9b579f3SBram Moolenaar 	add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "lastline",
25756f5b6dfbSBram Moolenaar 					       (varnumber_T)funcexe->lastline);
2576f10806b2SBram Moolenaar     }
257742ae78cfSBram Moolenaar     for (i = 0; i < argcount || i < fp->uf_args.ga_len; ++i)
2578a9b579f3SBram Moolenaar     {
2579a9b579f3SBram Moolenaar 	int	    addlocal = FALSE;
258042ae78cfSBram Moolenaar 	typval_T    def_rettv;
258142ae78cfSBram Moolenaar 	int	    isdefault = FALSE;
2582a9b579f3SBram Moolenaar 
2583a9b579f3SBram Moolenaar 	ai = i - fp->uf_args.ga_len;
2584a9b579f3SBram Moolenaar 	if (ai < 0)
2585a9b579f3SBram Moolenaar 	{
2586e38eab22SBram Moolenaar 	    // named argument a:name
2587a9b579f3SBram Moolenaar 	    name = FUNCARG(fp, i);
2588a9b579f3SBram Moolenaar 	    if (islambda)
2589a9b579f3SBram Moolenaar 		addlocal = TRUE;
259042ae78cfSBram Moolenaar 
259142ae78cfSBram Moolenaar 	    // evaluate named argument default expression
259242ae78cfSBram Moolenaar 	    isdefault = ai + fp->uf_def_args.ga_len >= 0
259342ae78cfSBram Moolenaar 		       && (i >= argcount || (argvars[i].v_type == VAR_SPECIAL
259442ae78cfSBram Moolenaar 				   && argvars[i].vval.v_number == VVAL_NONE));
259542ae78cfSBram Moolenaar 	    if (isdefault)
259642ae78cfSBram Moolenaar 	    {
259742ae78cfSBram Moolenaar 		char_u	    *default_expr = NULL;
2598b47bed2fSBram Moolenaar 
259942ae78cfSBram Moolenaar 		def_rettv.v_type = VAR_NUMBER;
260042ae78cfSBram Moolenaar 		def_rettv.vval.v_number = -1;
260142ae78cfSBram Moolenaar 
260242ae78cfSBram Moolenaar 		default_expr = ((char_u **)(fp->uf_def_args.ga_data))
260342ae78cfSBram Moolenaar 						 [ai + fp->uf_def_args.ga_len];
26045409f5d8SBram Moolenaar 		if (eval1(&default_expr, &def_rettv, &EVALARG_EVALUATE) == FAIL)
260542ae78cfSBram Moolenaar 		{
260642ae78cfSBram Moolenaar 		    default_arg_err = 1;
260742ae78cfSBram Moolenaar 		    break;
260842ae78cfSBram Moolenaar 		}
260942ae78cfSBram Moolenaar 	    }
2610a9b579f3SBram Moolenaar 	}
2611a9b579f3SBram Moolenaar 	else
2612a9b579f3SBram Moolenaar 	{
2613f10806b2SBram Moolenaar 	    if ((fp->uf_flags & FC_NOARGS) != 0)
2614f10806b2SBram Moolenaar 		// Bail out if no a: arguments used (in lambda).
2615f10806b2SBram Moolenaar 		break;
2616f10806b2SBram Moolenaar 
2617e38eab22SBram Moolenaar 	    // "..." argument a:1, a:2, etc.
2618a9b579f3SBram Moolenaar 	    sprintf((char *)numbuf, "%d", ai + 1);
2619a9b579f3SBram Moolenaar 	    name = numbuf;
2620a9b579f3SBram Moolenaar 	}
2621a9b579f3SBram Moolenaar 	if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN)
2622a9b579f3SBram Moolenaar 	{
2623a9b579f3SBram Moolenaar 	    v = &fc->fixvar[fixvar_idx++].var;
2624a9b579f3SBram Moolenaar 	    v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
2625209b8e3eSBram Moolenaar 	    STRCPY(v->di_key, name);
2626a9b579f3SBram Moolenaar 	}
2627a9b579f3SBram Moolenaar 	else
2628a9b579f3SBram Moolenaar 	{
2629209b8e3eSBram Moolenaar 	    v = dictitem_alloc(name);
2630a9b579f3SBram Moolenaar 	    if (v == NULL)
2631a9b579f3SBram Moolenaar 		break;
2632209b8e3eSBram Moolenaar 	    v->di_flags |= DI_FLAGS_RO | DI_FLAGS_FIX;
2633a9b579f3SBram Moolenaar 	}
2634a9b579f3SBram Moolenaar 
263542ae78cfSBram Moolenaar 	// Note: the values are copied directly to avoid alloc/free.
263642ae78cfSBram Moolenaar 	// "argvars" must have VAR_FIXED for v_lock.
26376e5000d4SBram Moolenaar 	v->di_tv = isdefault ? def_rettv : argvars[i];
2638a9b579f3SBram Moolenaar 	v->di_tv.v_lock = VAR_FIXED;
2639a9b579f3SBram Moolenaar 
2640b47bed2fSBram Moolenaar 	if (isdefault)
2641b47bed2fSBram Moolenaar 	    // Need to free this later, no matter where it's stored.
2642b47bed2fSBram Moolenaar 	    tv_to_free[tv_to_free_len++] = &v->di_tv;
2643b47bed2fSBram Moolenaar 
2644a9b579f3SBram Moolenaar 	if (addlocal)
2645a9b579f3SBram Moolenaar 	{
2646e38eab22SBram Moolenaar 	    // Named arguments should be accessed without the "a:" prefix in
2647e38eab22SBram Moolenaar 	    // lambda expressions.  Add to the l: dict.
26481e96d9bfSBram Moolenaar 	    copy_tv(&v->di_tv, &v->di_tv);
26491e96d9bfSBram Moolenaar 	    hash_add(&fc->l_vars.dv_hashtab, DI2HIKEY(v));
2650a9b579f3SBram Moolenaar 	}
26511e96d9bfSBram Moolenaar 	else
26521e96d9bfSBram Moolenaar 	    hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v));
2653a9b579f3SBram Moolenaar 
2654a9b579f3SBram Moolenaar 	if (ai >= 0 && ai < MAX_FUNC_ARGS)
2655a9b579f3SBram Moolenaar 	{
2656209b8e3eSBram Moolenaar 	    listitem_T *li = &fc->l_listitems[ai];
2657209b8e3eSBram Moolenaar 
2658209b8e3eSBram Moolenaar 	    li->li_tv = argvars[i];
2659209b8e3eSBram Moolenaar 	    li->li_tv.v_lock = VAR_FIXED;
2660209b8e3eSBram Moolenaar 	    list_append(&fc->l_varlist, li);
2661a9b579f3SBram Moolenaar 	}
2662a9b579f3SBram Moolenaar     }
2663a9b579f3SBram Moolenaar 
2664e38eab22SBram Moolenaar     // Don't redraw while executing the function.
2665a9b579f3SBram Moolenaar     ++RedrawingDisabled;
266693343725SBram Moolenaar 
266793343725SBram Moolenaar     if (fp->uf_flags & FC_SANDBOX)
266893343725SBram Moolenaar     {
266993343725SBram Moolenaar 	using_sandbox = TRUE;
267093343725SBram Moolenaar 	++sandbox;
267193343725SBram Moolenaar     }
267293343725SBram Moolenaar 
267325e0f586SBram Moolenaar     estack_push_ufunc(fp, 1);
2674e31ee868SBram Moolenaar     ESTACK_CHECK_SETUP
2675a9b579f3SBram Moolenaar     if (p_verbose >= 12)
2676a9b579f3SBram Moolenaar     {
2677a9b579f3SBram Moolenaar 	++no_wait_return;
2678a9b579f3SBram Moolenaar 	verbose_enter_scroll();
2679a9b579f3SBram Moolenaar 
26801a47ae32SBram Moolenaar 	smsg(_("calling %s"), SOURCING_NAME);
2681a9b579f3SBram Moolenaar 	if (p_verbose >= 14)
2682a9b579f3SBram Moolenaar 	{
2683a9b579f3SBram Moolenaar 	    char_u	buf[MSG_BUF_LEN];
2684a9b579f3SBram Moolenaar 	    char_u	numbuf2[NUMBUFLEN];
2685a9b579f3SBram Moolenaar 	    char_u	*tofree;
2686a9b579f3SBram Moolenaar 	    char_u	*s;
2687a9b579f3SBram Moolenaar 
268832526b3cSBram Moolenaar 	    msg_puts("(");
2689a9b579f3SBram Moolenaar 	    for (i = 0; i < argcount; ++i)
2690a9b579f3SBram Moolenaar 	    {
2691a9b579f3SBram Moolenaar 		if (i > 0)
269232526b3cSBram Moolenaar 		    msg_puts(", ");
2693a9b579f3SBram Moolenaar 		if (argvars[i].v_type == VAR_NUMBER)
2694a9b579f3SBram Moolenaar 		    msg_outnum((long)argvars[i].vval.v_number);
2695a9b579f3SBram Moolenaar 		else
2696a9b579f3SBram Moolenaar 		{
2697e38eab22SBram Moolenaar 		    // Do not want errors such as E724 here.
2698a9b579f3SBram Moolenaar 		    ++emsg_off;
2699a9b579f3SBram Moolenaar 		    s = tv2string(&argvars[i], &tofree, numbuf2, 0);
2700a9b579f3SBram Moolenaar 		    --emsg_off;
2701a9b579f3SBram Moolenaar 		    if (s != NULL)
2702a9b579f3SBram Moolenaar 		    {
2703a9b579f3SBram Moolenaar 			if (vim_strsize(s) > MSG_BUF_CLEN)
2704a9b579f3SBram Moolenaar 			{
2705a9b579f3SBram Moolenaar 			    trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN);
2706a9b579f3SBram Moolenaar 			    s = buf;
2707a9b579f3SBram Moolenaar 			}
270832526b3cSBram Moolenaar 			msg_puts((char *)s);
2709a9b579f3SBram Moolenaar 			vim_free(tofree);
2710a9b579f3SBram Moolenaar 		    }
2711a9b579f3SBram Moolenaar 		}
2712a9b579f3SBram Moolenaar 	    }
271332526b3cSBram Moolenaar 	    msg_puts(")");
2714a9b579f3SBram Moolenaar 	}
2715e38eab22SBram Moolenaar 	msg_puts("\n");   // don't overwrite this either
2716a9b579f3SBram Moolenaar 
2717a9b579f3SBram Moolenaar 	verbose_leave_scroll();
2718a9b579f3SBram Moolenaar 	--no_wait_return;
2719a9b579f3SBram Moolenaar     }
2720a9b579f3SBram Moolenaar #ifdef FEAT_PROFILE
272112d26531SBram Moolenaar     if (do_profiling == PROF_YES)
272212d26531SBram Moolenaar 	profile_may_start_func(&profile_info, fp,
272312d26531SBram Moolenaar 				 fc->caller == NULL ? NULL : fc->caller->func);
2724a9b579f3SBram Moolenaar #endif
2725a9b579f3SBram Moolenaar 
2726f29c1c6aSBram Moolenaar     save_current_sctx = current_sctx;
2727f29c1c6aSBram Moolenaar     current_sctx = fp->uf_script_ctx;
2728a9b579f3SBram Moolenaar     save_did_emsg = did_emsg;
2729a9b579f3SBram Moolenaar     did_emsg = FALSE;
2730a9b579f3SBram Moolenaar 
273142ae78cfSBram Moolenaar     if (default_arg_err && (fp->uf_flags & FC_ABORT))
273242ae78cfSBram Moolenaar 	did_emsg = TRUE;
2733f10806b2SBram Moolenaar     else if (islambda)
2734f10806b2SBram Moolenaar     {
2735f10806b2SBram Moolenaar 	char_u *p = *(char_u **)fp->uf_lines.ga_data + 7;
2736f10806b2SBram Moolenaar 
2737f10806b2SBram Moolenaar 	// A Lambda always has the command "return {expr}".  It is much faster
2738f10806b2SBram Moolenaar 	// to evaluate {expr} directly.
2739f10806b2SBram Moolenaar 	++ex_nesting_level;
27405409f5d8SBram Moolenaar 	(void)eval1(&p, rettv, &EVALARG_EVALUATE);
2741f10806b2SBram Moolenaar 	--ex_nesting_level;
2742f10806b2SBram Moolenaar     }
274342ae78cfSBram Moolenaar     else
274442ae78cfSBram Moolenaar 	// call do_cmdline() to execute the lines
2745a9b579f3SBram Moolenaar 	do_cmdline(NULL, get_func_line, (void *)fc,
2746a9b579f3SBram Moolenaar 				     DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
2747a9b579f3SBram Moolenaar 
2748a9b579f3SBram Moolenaar     --RedrawingDisabled;
2749a9b579f3SBram Moolenaar 
2750e38eab22SBram Moolenaar     // when the function was aborted because of an error, return -1
2751a9b579f3SBram Moolenaar     if ((did_emsg && (fp->uf_flags & FC_ABORT)) || rettv->v_type == VAR_UNKNOWN)
2752a9b579f3SBram Moolenaar     {
2753a9b579f3SBram Moolenaar 	clear_tv(rettv);
2754a9b579f3SBram Moolenaar 	rettv->v_type = VAR_NUMBER;
2755a9b579f3SBram Moolenaar 	rettv->vval.v_number = -1;
2756a9b579f3SBram Moolenaar     }
2757a9b579f3SBram Moolenaar 
2758a9b579f3SBram Moolenaar #ifdef FEAT_PROFILE
275912d26531SBram Moolenaar     if (do_profiling == PROF_YES)
276012d26531SBram Moolenaar     {
276112d26531SBram Moolenaar 	ufunc_T *caller = fc->caller == NULL ? NULL : fc->caller->func;
276212d26531SBram Moolenaar 
276312d26531SBram Moolenaar 	if (fp->uf_profiling || (caller != NULL && caller->uf_profiling))
276412d26531SBram Moolenaar 	    profile_may_end_func(&profile_info, fp, caller);
276512d26531SBram Moolenaar     }
2766a9b579f3SBram Moolenaar #endif
2767a9b579f3SBram Moolenaar 
2768e38eab22SBram Moolenaar     // when being verbose, mention the return value
2769a9b579f3SBram Moolenaar     if (p_verbose >= 12)
2770a9b579f3SBram Moolenaar     {
2771a9b579f3SBram Moolenaar 	++no_wait_return;
2772a9b579f3SBram Moolenaar 	verbose_enter_scroll();
2773a9b579f3SBram Moolenaar 
2774a9b579f3SBram Moolenaar 	if (aborting())
27751a47ae32SBram Moolenaar 	    smsg(_("%s aborted"), SOURCING_NAME);
2776a9b579f3SBram Moolenaar 	else if (fc->rettv->v_type == VAR_NUMBER)
27771a47ae32SBram Moolenaar 	    smsg(_("%s returning #%ld"), SOURCING_NAME,
2778a9b579f3SBram Moolenaar 					       (long)fc->rettv->vval.v_number);
2779a9b579f3SBram Moolenaar 	else
2780a9b579f3SBram Moolenaar 	{
2781a9b579f3SBram Moolenaar 	    char_u	buf[MSG_BUF_LEN];
2782a9b579f3SBram Moolenaar 	    char_u	numbuf2[NUMBUFLEN];
2783a9b579f3SBram Moolenaar 	    char_u	*tofree;
2784a9b579f3SBram Moolenaar 	    char_u	*s;
2785a9b579f3SBram Moolenaar 
2786e38eab22SBram Moolenaar 	    // The value may be very long.  Skip the middle part, so that we
2787e38eab22SBram Moolenaar 	    // have some idea how it starts and ends. smsg() would always
2788e38eab22SBram Moolenaar 	    // truncate it at the end. Don't want errors such as E724 here.
2789a9b579f3SBram Moolenaar 	    ++emsg_off;
2790a9b579f3SBram Moolenaar 	    s = tv2string(fc->rettv, &tofree, numbuf2, 0);
2791a9b579f3SBram Moolenaar 	    --emsg_off;
2792a9b579f3SBram Moolenaar 	    if (s != NULL)
2793a9b579f3SBram Moolenaar 	    {
2794a9b579f3SBram Moolenaar 		if (vim_strsize(s) > MSG_BUF_CLEN)
2795a9b579f3SBram Moolenaar 		{
2796a9b579f3SBram Moolenaar 		    trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN);
2797a9b579f3SBram Moolenaar 		    s = buf;
2798a9b579f3SBram Moolenaar 		}
27991a47ae32SBram Moolenaar 		smsg(_("%s returning %s"), SOURCING_NAME, s);
2800a9b579f3SBram Moolenaar 		vim_free(tofree);
2801a9b579f3SBram Moolenaar 	    }
2802a9b579f3SBram Moolenaar 	}
2803e38eab22SBram Moolenaar 	msg_puts("\n");   // don't overwrite this either
2804a9b579f3SBram Moolenaar 
2805a9b579f3SBram Moolenaar 	verbose_leave_scroll();
2806a9b579f3SBram Moolenaar 	--no_wait_return;
2807a9b579f3SBram Moolenaar     }
2808a9b579f3SBram Moolenaar 
2809e31ee868SBram Moolenaar     ESTACK_CHECK_NOW
28101a47ae32SBram Moolenaar     estack_pop();
2811f29c1c6aSBram Moolenaar     current_sctx = save_current_sctx;
2812a9b579f3SBram Moolenaar #ifdef FEAT_PROFILE
2813a9b579f3SBram Moolenaar     if (do_profiling == PROF_YES)
2814b2049903SBram Moolenaar 	script_prof_restore(&profile_info.pi_wait_start);
2815a9b579f3SBram Moolenaar #endif
281693343725SBram Moolenaar     if (using_sandbox)
281793343725SBram Moolenaar 	--sandbox;
2818a9b579f3SBram Moolenaar 
28191a47ae32SBram Moolenaar     if (p_verbose >= 12 && SOURCING_NAME != NULL)
2820a9b579f3SBram Moolenaar     {
2821a9b579f3SBram Moolenaar 	++no_wait_return;
2822a9b579f3SBram Moolenaar 	verbose_enter_scroll();
2823a9b579f3SBram Moolenaar 
28241a47ae32SBram Moolenaar 	smsg(_("continuing in %s"), SOURCING_NAME);
2825e38eab22SBram Moolenaar 	msg_puts("\n");   // don't overwrite this either
2826a9b579f3SBram Moolenaar 
2827a9b579f3SBram Moolenaar 	verbose_leave_scroll();
2828a9b579f3SBram Moolenaar 	--no_wait_return;
2829a9b579f3SBram Moolenaar     }
2830a9b579f3SBram Moolenaar 
2831a9b579f3SBram Moolenaar     did_emsg |= save_did_emsg;
28320ba48e8cSBram Moolenaar     funcdepth_decrement();
2833b47bed2fSBram Moolenaar     for (i = 0; i < tv_to_free_len; ++i)
2834b47bed2fSBram Moolenaar 	clear_tv(tv_to_free[i]);
28356914c64eSBram Moolenaar     cleanup_function_call(fc);
2836a9b579f3SBram Moolenaar }
2837a9b579f3SBram Moolenaar 
2838a9b579f3SBram Moolenaar /*
28395082471fSBram Moolenaar  * Check the argument count for user function "fp".
28405082471fSBram Moolenaar  * Return FCERR_UNKNOWN if OK, FCERR_TOOFEW or FCERR_TOOMANY otherwise.
28415082471fSBram Moolenaar  */
28425082471fSBram Moolenaar     int
check_user_func_argcount(ufunc_T * fp,int argcount)28435082471fSBram Moolenaar check_user_func_argcount(ufunc_T *fp, int argcount)
28445082471fSBram Moolenaar {
28455082471fSBram Moolenaar     int regular_args = fp->uf_args.ga_len;
28465082471fSBram Moolenaar 
28475082471fSBram Moolenaar     if (argcount < regular_args - fp->uf_def_args.ga_len)
28485082471fSBram Moolenaar 	return FCERR_TOOFEW;
28495082471fSBram Moolenaar     else if (!has_varargs(fp) && argcount > regular_args)
28505082471fSBram Moolenaar 	return FCERR_TOOMANY;
28515082471fSBram Moolenaar     return FCERR_UNKNOWN;
28525082471fSBram Moolenaar }
28535082471fSBram Moolenaar 
28545082471fSBram Moolenaar /*
28558a7d6542SBram Moolenaar  * Call a user function after checking the arguments.
28561e96d9bfSBram Moolenaar  */
28578a7d6542SBram Moolenaar     int
call_user_func_check(ufunc_T * fp,int argcount,typval_T * argvars,typval_T * rettv,funcexe_T * funcexe,dict_T * selfdict)28588a7d6542SBram Moolenaar call_user_func_check(
28598a7d6542SBram Moolenaar 	ufunc_T	    *fp,
28608a7d6542SBram Moolenaar 	int	    argcount,
28618a7d6542SBram Moolenaar 	typval_T    *argvars,
28628a7d6542SBram Moolenaar 	typval_T    *rettv,
28638a7d6542SBram Moolenaar 	funcexe_T   *funcexe,
28648a7d6542SBram Moolenaar 	dict_T	    *selfdict)
28651e96d9bfSBram Moolenaar {
28668a7d6542SBram Moolenaar     int error;
28671e96d9bfSBram Moolenaar 
28688a7d6542SBram Moolenaar     if (fp->uf_flags & FC_RANGE && funcexe->doesrange != NULL)
28698a7d6542SBram Moolenaar 	*funcexe->doesrange = TRUE;
28705082471fSBram Moolenaar     error = check_user_func_argcount(fp, argcount);
28715082471fSBram Moolenaar     if (error != FCERR_UNKNOWN)
28725082471fSBram Moolenaar 	return error;
28735082471fSBram Moolenaar     if ((fp->uf_flags & FC_DICT) && selfdict == NULL)
28748a7d6542SBram Moolenaar 	error = FCERR_DICT;
28758a7d6542SBram Moolenaar     else
28761e96d9bfSBram Moolenaar     {
28778a7d6542SBram Moolenaar 	int		did_save_redo = FALSE;
28788a7d6542SBram Moolenaar 	save_redo_T	save_redo;
28791e96d9bfSBram Moolenaar 
28801e96d9bfSBram Moolenaar 	/*
28818a7d6542SBram Moolenaar 	 * Call the user function.
28828a7d6542SBram Moolenaar 	 * Save and restore search patterns, script variables and
28838a7d6542SBram Moolenaar 	 * redo buffer.
2884437bafe4SBram Moolenaar 	 */
28858a7d6542SBram Moolenaar 	save_search_patterns();
28868a7d6542SBram Moolenaar 	if (!ins_compl_active())
2887437bafe4SBram Moolenaar 	{
28888a7d6542SBram Moolenaar 	    saveRedobuff(&save_redo);
28898a7d6542SBram Moolenaar 	    did_save_redo = TRUE;
28908dd3a43dSBram Moolenaar 	}
28918a7d6542SBram Moolenaar 	++fp->uf_calls;
28926f5b6dfbSBram Moolenaar 	call_user_func(fp, argcount, argvars, rettv, funcexe,
28938a7d6542SBram Moolenaar 				   (fp->uf_flags & FC_DICT) ? selfdict : NULL);
28948a7d6542SBram Moolenaar 	if (--fp->uf_calls <= 0 && fp->uf_refcount <= 0)
28958a7d6542SBram Moolenaar 	    // Function was unreferenced while being used, free it now.
28968a7d6542SBram Moolenaar 	    func_clear_free(fp, FALSE);
28978a7d6542SBram Moolenaar 	if (did_save_redo)
28988a7d6542SBram Moolenaar 	    restoreRedobuff(&save_redo);
28998a7d6542SBram Moolenaar 	restore_search_patterns();
29008a7d6542SBram Moolenaar 	error = FCERR_NONE;
2901437bafe4SBram Moolenaar     }
29028a7d6542SBram Moolenaar     return error;
290303ff9bcbSBram Moolenaar }
290403ff9bcbSBram Moolenaar 
290527e80c88SBram Moolenaar static funccal_entry_T *funccal_stack = NULL;
290627e80c88SBram Moolenaar 
290727e80c88SBram Moolenaar /*
290827e80c88SBram Moolenaar  * Save the current function call pointer, and set it to NULL.
290927e80c88SBram Moolenaar  * Used when executing autocommands and for ":source".
291027e80c88SBram Moolenaar  */
291127e80c88SBram Moolenaar     void
save_funccal(funccal_entry_T * entry)291227e80c88SBram Moolenaar save_funccal(funccal_entry_T *entry)
291327e80c88SBram Moolenaar {
291427e80c88SBram Moolenaar     entry->top_funccal = current_funccal;
291527e80c88SBram Moolenaar     entry->next = funccal_stack;
291627e80c88SBram Moolenaar     funccal_stack = entry;
291727e80c88SBram Moolenaar     current_funccal = NULL;
291827e80c88SBram Moolenaar }
291927e80c88SBram Moolenaar 
292027e80c88SBram Moolenaar     void
restore_funccal(void)292127e80c88SBram Moolenaar restore_funccal(void)
292227e80c88SBram Moolenaar {
292327e80c88SBram Moolenaar     if (funccal_stack == NULL)
2924f9e3e09fSBram Moolenaar 	iemsg("INTERNAL: restore_funccal()");
292527e80c88SBram Moolenaar     else
292627e80c88SBram Moolenaar     {
292727e80c88SBram Moolenaar 	current_funccal = funccal_stack->top_funccal;
292827e80c88SBram Moolenaar 	funccal_stack = funccal_stack->next;
292927e80c88SBram Moolenaar     }
293027e80c88SBram Moolenaar }
293127e80c88SBram Moolenaar 
2932fa55cfc6SBram Moolenaar     funccall_T *
get_current_funccal(void)2933fa55cfc6SBram Moolenaar get_current_funccal(void)
2934fa55cfc6SBram Moolenaar {
2935fa55cfc6SBram Moolenaar     return current_funccal;
2936fa55cfc6SBram Moolenaar }
2937fa55cfc6SBram Moolenaar 
29384c17ad94SBram Moolenaar /*
29394c17ad94SBram Moolenaar  * Mark all functions of script "sid" as deleted.
29404c17ad94SBram Moolenaar  */
29414c17ad94SBram Moolenaar     void
delete_script_functions(int sid)29424c17ad94SBram Moolenaar delete_script_functions(int sid)
29434c17ad94SBram Moolenaar {
29444c17ad94SBram Moolenaar     hashitem_T	*hi;
29454c17ad94SBram Moolenaar     ufunc_T	*fp;
2946ce658356SBram Moolenaar     long_u	todo = 1;
2947909ed7e9SBram Moolenaar     char_u	buf[30];
29484c17ad94SBram Moolenaar     size_t	len;
29494c17ad94SBram Moolenaar 
29504c17ad94SBram Moolenaar     buf[0] = K_SPECIAL;
29514c17ad94SBram Moolenaar     buf[1] = KS_EXTRA;
29524c17ad94SBram Moolenaar     buf[2] = (int)KE_SNR;
2953909ed7e9SBram Moolenaar     sprintf((char *)buf + 3, "%d_", sid);
29544c17ad94SBram Moolenaar     len = STRLEN(buf);
29554c17ad94SBram Moolenaar 
2956ce658356SBram Moolenaar     while (todo > 0)
2957ce658356SBram Moolenaar     {
29584c17ad94SBram Moolenaar 	todo = func_hashtab.ht_used;
29594c17ad94SBram Moolenaar 	for (hi = func_hashtab.ht_array; todo > 0; ++hi)
29604c17ad94SBram Moolenaar 	    if (!HASHITEM_EMPTY(hi))
29614c17ad94SBram Moolenaar 	    {
296203afdcf1SBram Moolenaar 		fp = HI2UF(hi);
29634c17ad94SBram Moolenaar 		if (STRNCMP(fp->uf_name, buf, len) == 0)
29644c17ad94SBram Moolenaar 		{
2965ce658356SBram Moolenaar 		    int changed = func_hashtab.ht_changed;
2966ce658356SBram Moolenaar 
29674c17ad94SBram Moolenaar 		    fp->uf_flags |= FC_DEAD;
2968c970e422SBram Moolenaar 
2969c970e422SBram Moolenaar 		    if (fp->uf_calls > 0)
2970c970e422SBram Moolenaar 		    {
2971c970e422SBram Moolenaar 			// Function is executing, don't free it but do remove
2972c970e422SBram Moolenaar 			// it from the hashtable.
2973c970e422SBram Moolenaar 			if (func_remove(fp))
2974c970e422SBram Moolenaar 			    fp->uf_refcount--;
2975c970e422SBram Moolenaar 		    }
2976c970e422SBram Moolenaar 		    else
2977c970e422SBram Moolenaar 		    {
29784c17ad94SBram Moolenaar 			func_clear(fp, TRUE);
2979c970e422SBram Moolenaar 			// When clearing a function another function can be
2980c970e422SBram Moolenaar 			// cleared as a side effect.  When that happens start
2981c970e422SBram Moolenaar 			// over.
2982ce658356SBram Moolenaar 			if (changed != func_hashtab.ht_changed)
2983ce658356SBram Moolenaar 			    break;
29844c17ad94SBram Moolenaar 		    }
2985c970e422SBram Moolenaar 		}
29864c17ad94SBram Moolenaar 		--todo;
29874c17ad94SBram Moolenaar 	    }
29884c17ad94SBram Moolenaar     }
2989ce658356SBram Moolenaar }
29904c17ad94SBram Moolenaar 
2991a9b579f3SBram Moolenaar #if defined(EXITFREE) || defined(PROTO)
2992a9b579f3SBram Moolenaar     void
free_all_functions(void)2993a9b579f3SBram Moolenaar free_all_functions(void)
2994a9b579f3SBram Moolenaar {
2995a9b579f3SBram Moolenaar     hashitem_T	*hi;
2996c2574870SBram Moolenaar     ufunc_T	*fp;
2997c2574870SBram Moolenaar     long_u	skipped = 0;
299803ff9bcbSBram Moolenaar     long_u	todo = 1;
29991f22cc5cSBram Moolenaar     int		changed;
3000a9b579f3SBram Moolenaar 
3001e38eab22SBram Moolenaar     // Clean up the current_funccal chain and the funccal stack.
30026914c64eSBram Moolenaar     while (current_funccal != NULL)
30036914c64eSBram Moolenaar     {
30046914c64eSBram Moolenaar 	clear_tv(current_funccal->rettv);
30056914c64eSBram Moolenaar 	cleanup_function_call(current_funccal);
300627e80c88SBram Moolenaar 	if (current_funccal == NULL && funccal_stack != NULL)
300727e80c88SBram Moolenaar 	    restore_funccal();
30086914c64eSBram Moolenaar     }
30096914c64eSBram Moolenaar 
3010e38eab22SBram Moolenaar     // First clear what the functions contain.  Since this may lower the
3011e38eab22SBram Moolenaar     // reference count of a function, it may also free a function and change
3012e38eab22SBram Moolenaar     // the hash table. Restart if that happens.
301303ff9bcbSBram Moolenaar     while (todo > 0)
301403ff9bcbSBram Moolenaar     {
301503ff9bcbSBram Moolenaar 	todo = func_hashtab.ht_used;
301603ff9bcbSBram Moolenaar 	for (hi = func_hashtab.ht_array; todo > 0; ++hi)
301703ff9bcbSBram Moolenaar 	    if (!HASHITEM_EMPTY(hi))
301803ff9bcbSBram Moolenaar 	    {
30198a7d6542SBram Moolenaar 		// clear the def function index now
30208a7d6542SBram Moolenaar 		fp = HI2UF(hi);
30218a7d6542SBram Moolenaar 		fp->uf_flags &= ~FC_DEAD;
30220cb5bcf5SBram Moolenaar 		fp->uf_def_status = UF_NOT_COMPILED;
30238a7d6542SBram Moolenaar 
3024e38eab22SBram Moolenaar 		// Only free functions that are not refcounted, those are
3025e38eab22SBram Moolenaar 		// supposed to be freed when no longer referenced.
302603ff9bcbSBram Moolenaar 		if (func_name_refcount(fp->uf_name))
302703ff9bcbSBram Moolenaar 		    ++skipped;
302803ff9bcbSBram Moolenaar 		else
302903ff9bcbSBram Moolenaar 		{
30301f22cc5cSBram Moolenaar 		    changed = func_hashtab.ht_changed;
303103ff9bcbSBram Moolenaar 		    func_clear(fp, TRUE);
30321f22cc5cSBram Moolenaar 		    if (changed != func_hashtab.ht_changed)
303303ff9bcbSBram Moolenaar 		    {
303403ff9bcbSBram Moolenaar 			skipped = 0;
303503ff9bcbSBram Moolenaar 			break;
303603ff9bcbSBram Moolenaar 		    }
303703ff9bcbSBram Moolenaar 		}
303803ff9bcbSBram Moolenaar 		--todo;
303903ff9bcbSBram Moolenaar 	    }
304003ff9bcbSBram Moolenaar     }
304103ff9bcbSBram Moolenaar 
3042e38eab22SBram Moolenaar     // Now actually free the functions.  Need to start all over every time,
3043e38eab22SBram Moolenaar     // because func_free() may change the hash table.
304403ff9bcbSBram Moolenaar     skipped = 0;
3045c2574870SBram Moolenaar     while (func_hashtab.ht_used > skipped)
3046c2574870SBram Moolenaar     {
3047c2574870SBram Moolenaar 	todo = func_hashtab.ht_used;
3048c2574870SBram Moolenaar 	for (hi = func_hashtab.ht_array; todo > 0; ++hi)
3049a9b579f3SBram Moolenaar 	    if (!HASHITEM_EMPTY(hi))
3050a9b579f3SBram Moolenaar 	    {
3051c2574870SBram Moolenaar 		--todo;
3052e38eab22SBram Moolenaar 		// Only free functions that are not refcounted, those are
3053e38eab22SBram Moolenaar 		// supposed to be freed when no longer referenced.
3054c2574870SBram Moolenaar 		fp = HI2UF(hi);
3055c2574870SBram Moolenaar 		if (func_name_refcount(fp->uf_name))
3056c2574870SBram Moolenaar 		    ++skipped;
3057c2574870SBram Moolenaar 		else
3058c2574870SBram Moolenaar 		{
3059a05e524fSBram Moolenaar 		    if (func_free(fp, FALSE) == OK)
3060a05e524fSBram Moolenaar 		    {
3061c2574870SBram Moolenaar 			skipped = 0;
3062a9b579f3SBram Moolenaar 			break;
3063a9b579f3SBram Moolenaar 		    }
3064a05e524fSBram Moolenaar 		    // did not actually free it
3065a05e524fSBram Moolenaar 		    ++skipped;
3066a05e524fSBram Moolenaar 		}
3067c2574870SBram Moolenaar 	    }
3068c2574870SBram Moolenaar     }
3069c2574870SBram Moolenaar     if (skipped == 0)
3070a9b579f3SBram Moolenaar 	hash_clear(&func_hashtab);
30718a7d6542SBram Moolenaar 
30728a7d6542SBram Moolenaar     free_def_functions();
3073a9b579f3SBram Moolenaar }
3074a9b579f3SBram Moolenaar #endif
3075a9b579f3SBram Moolenaar 
3076a9b579f3SBram Moolenaar /*
3077a9b579f3SBram Moolenaar  * Return TRUE if "name" looks like a builtin function name: starts with a
3078a26b9700SBram Moolenaar  * lower case letter and doesn't contain AUTOLOAD_CHAR or ':'.
3079a9b579f3SBram Moolenaar  * "len" is the length of "name", or -1 for NUL terminated.
3080a9b579f3SBram Moolenaar  */
30818a7d6542SBram Moolenaar     int
builtin_function(char_u * name,int len)3082a9b579f3SBram Moolenaar builtin_function(char_u *name, int len)
3083a9b579f3SBram Moolenaar {
3084a9b579f3SBram Moolenaar     char_u *p;
3085a9b579f3SBram Moolenaar 
3086a26b9700SBram Moolenaar     if (!ASCII_ISLOWER(name[0]) || name[1] == ':')
3087a9b579f3SBram Moolenaar 	return FALSE;
3088a9b579f3SBram Moolenaar     p = vim_strchr(name, AUTOLOAD_CHAR);
3089a9b579f3SBram Moolenaar     return p == NULL || (len > 0 && p > name + len);
3090a9b579f3SBram Moolenaar }
3091a9b579f3SBram Moolenaar 
3092a9b579f3SBram Moolenaar     int
func_call(char_u * name,typval_T * args,partial_T * partial,dict_T * selfdict,typval_T * rettv)3093a9b579f3SBram Moolenaar func_call(
3094a9b579f3SBram Moolenaar     char_u	*name,
3095a9b579f3SBram Moolenaar     typval_T	*args,
3096a9b579f3SBram Moolenaar     partial_T	*partial,
3097a9b579f3SBram Moolenaar     dict_T	*selfdict,
3098a9b579f3SBram Moolenaar     typval_T	*rettv)
3099a9b579f3SBram Moolenaar {
310050985eb1SBram Moolenaar     list_T	*l = args->vval.v_list;
3101a9b579f3SBram Moolenaar     listitem_T	*item;
3102a9b579f3SBram Moolenaar     typval_T	argv[MAX_FUNC_ARGS + 1];
3103a9b579f3SBram Moolenaar     int		argc = 0;
3104a9b579f3SBram Moolenaar     int		r = 0;
3105a9b579f3SBram Moolenaar 
31067e9f351bSBram Moolenaar     CHECK_LIST_MATERIALIZE(l);
310700d253e2SBram Moolenaar     FOR_ALL_LIST_ITEMS(l, item)
3108a9b579f3SBram Moolenaar     {
3109a9b579f3SBram Moolenaar 	if (argc == MAX_FUNC_ARGS - (partial == NULL ? 0 : partial->pt_argc))
3110a9b579f3SBram Moolenaar 	{
3111f9e3e09fSBram Moolenaar 	    emsg(_("E699: Too many arguments"));
3112a9b579f3SBram Moolenaar 	    break;
3113a9b579f3SBram Moolenaar 	}
3114e38eab22SBram Moolenaar 	// Make a copy of each argument.  This is needed to be able to set
3115e38eab22SBram Moolenaar 	// v_lock to VAR_FIXED in the copy without changing the original list.
3116a9b579f3SBram Moolenaar 	copy_tv(&item->li_tv, &argv[argc++]);
3117a9b579f3SBram Moolenaar     }
3118a9b579f3SBram Moolenaar 
3119a9b579f3SBram Moolenaar     if (item == NULL)
3120c6538bccSBram Moolenaar     {
3121c6538bccSBram Moolenaar 	funcexe_T funcexe;
3122c6538bccSBram Moolenaar 
3123a80faa89SBram Moolenaar 	CLEAR_FIELD(funcexe);
3124c6538bccSBram Moolenaar 	funcexe.firstline = curwin->w_cursor.lnum;
3125c6538bccSBram Moolenaar 	funcexe.lastline = curwin->w_cursor.lnum;
3126c6538bccSBram Moolenaar 	funcexe.evaluate = TRUE;
3127c6538bccSBram Moolenaar 	funcexe.partial = partial;
3128c6538bccSBram Moolenaar 	funcexe.selfdict = selfdict;
3129c6538bccSBram Moolenaar 	r = call_func(name, -1, rettv, argc, argv, &funcexe);
3130c6538bccSBram Moolenaar     }
3131a9b579f3SBram Moolenaar 
3132e38eab22SBram Moolenaar     // Free the arguments.
3133a9b579f3SBram Moolenaar     while (argc > 0)
3134a9b579f3SBram Moolenaar 	clear_tv(&argv[--argc]);
3135a9b579f3SBram Moolenaar 
3136a9b579f3SBram Moolenaar     return r;
3137a9b579f3SBram Moolenaar }
3138a9b579f3SBram Moolenaar 
31390e57dd85SBram Moolenaar static int callback_depth = 0;
31400e57dd85SBram Moolenaar 
31410e57dd85SBram Moolenaar     int
get_callback_depth(void)31420e57dd85SBram Moolenaar get_callback_depth(void)
31430e57dd85SBram Moolenaar {
31440e57dd85SBram Moolenaar     return callback_depth;
31450e57dd85SBram Moolenaar }
31460e57dd85SBram Moolenaar 
3147a9b579f3SBram Moolenaar /*
31483a97bb3fSBram Moolenaar  * Invoke call_func() with a callback.
31493a97bb3fSBram Moolenaar  */
31503a97bb3fSBram Moolenaar     int
call_callback(callback_T * callback,int len,typval_T * rettv,int argcount,typval_T * argvars)31513a97bb3fSBram Moolenaar call_callback(
31523a97bb3fSBram Moolenaar     callback_T	*callback,
31533a97bb3fSBram Moolenaar     int		len,		// length of "name" or -1 to use strlen()
31543a97bb3fSBram Moolenaar     typval_T	*rettv,		// return value goes here
31553a97bb3fSBram Moolenaar     int		argcount,	// number of "argvars"
3156c6538bccSBram Moolenaar     typval_T	*argvars)	// vars for arguments, must have "argcount"
31573a97bb3fSBram Moolenaar 				// PLUS ONE elements!
31583a97bb3fSBram Moolenaar {
3159c6538bccSBram Moolenaar     funcexe_T	funcexe;
31600e57dd85SBram Moolenaar     int		ret;
3161c6538bccSBram Moolenaar 
3162a80faa89SBram Moolenaar     CLEAR_FIELD(funcexe);
3163c6538bccSBram Moolenaar     funcexe.evaluate = TRUE;
3164c6538bccSBram Moolenaar     funcexe.partial = callback->cb_partial;
31650e57dd85SBram Moolenaar     ++callback_depth;
31660e57dd85SBram Moolenaar     ret = call_func(callback->cb_name, len, rettv, argcount, argvars, &funcexe);
31670e57dd85SBram Moolenaar     --callback_depth;
31680e57dd85SBram Moolenaar     return ret;
31693a97bb3fSBram Moolenaar }
31703a97bb3fSBram Moolenaar 
31713a97bb3fSBram Moolenaar /*
31728a7d6542SBram Moolenaar  * Give an error message for the result of a function.
31738a7d6542SBram Moolenaar  * Nothing if "error" is FCERR_NONE.
31748a7d6542SBram Moolenaar  */
31758a7d6542SBram Moolenaar     void
user_func_error(int error,char_u * name)31768a7d6542SBram Moolenaar user_func_error(int error, char_u *name)
31778a7d6542SBram Moolenaar {
31788a7d6542SBram Moolenaar     switch (error)
31798a7d6542SBram Moolenaar     {
31808a7d6542SBram Moolenaar 	case FCERR_UNKNOWN:
31818a7d6542SBram Moolenaar 		emsg_funcname(e_unknownfunc, name);
31828a7d6542SBram Moolenaar 		break;
31838a7d6542SBram Moolenaar 	case FCERR_NOTMETHOD:
31848a7d6542SBram Moolenaar 		emsg_funcname(
31858a7d6542SBram Moolenaar 			N_("E276: Cannot use function as a method: %s"), name);
31868a7d6542SBram Moolenaar 		break;
31878a7d6542SBram Moolenaar 	case FCERR_DELETED:
31888a7d6542SBram Moolenaar 		emsg_funcname(N_(e_func_deleted), name);
31898a7d6542SBram Moolenaar 		break;
31908a7d6542SBram Moolenaar 	case FCERR_TOOMANY:
31918a7d6542SBram Moolenaar 		emsg_funcname((char *)e_toomanyarg, name);
31928a7d6542SBram Moolenaar 		break;
31938a7d6542SBram Moolenaar 	case FCERR_TOOFEW:
31948a7d6542SBram Moolenaar 		emsg_funcname((char *)e_toofewarg, name);
31958a7d6542SBram Moolenaar 		break;
31968a7d6542SBram Moolenaar 	case FCERR_SCRIPT:
31978a7d6542SBram Moolenaar 		emsg_funcname(
31988a7d6542SBram Moolenaar 		    N_("E120: Using <SID> not in a script context: %s"), name);
31998a7d6542SBram Moolenaar 		break;
32008a7d6542SBram Moolenaar 	case FCERR_DICT:
32018a7d6542SBram Moolenaar 		emsg_funcname(
32028a7d6542SBram Moolenaar 		      N_("E725: Calling dict function without Dictionary: %s"),
32038a7d6542SBram Moolenaar 			name);
32048a7d6542SBram Moolenaar 		break;
32058a7d6542SBram Moolenaar     }
32068a7d6542SBram Moolenaar }
32078a7d6542SBram Moolenaar 
32088a7d6542SBram Moolenaar /*
3209a9b579f3SBram Moolenaar  * Call a function with its resolved parameters
3210df48fb45SBram Moolenaar  *
3211a9b579f3SBram Moolenaar  * Return FAIL when the function can't be called,  OK otherwise.
3212a9b579f3SBram Moolenaar  * Also returns OK when an error was encountered while executing the function.
3213a9b579f3SBram Moolenaar  */
3214a9b579f3SBram Moolenaar     int
call_func(char_u * funcname,int len,typval_T * rettv,int argcount_in,typval_T * argvars_in,funcexe_T * funcexe)3215a9b579f3SBram Moolenaar call_func(
32166ed88198SBram Moolenaar     char_u	*funcname,	// name of the function
32176ed88198SBram Moolenaar     int		len,		// length of "name" or -1 to use strlen()
32186ed88198SBram Moolenaar     typval_T	*rettv,		// return value goes here
32196ed88198SBram Moolenaar     int		argcount_in,	// number of "argvars"
32206ed88198SBram Moolenaar     typval_T	*argvars_in,	// vars for arguments, must have "argcount"
32216ed88198SBram Moolenaar 				// PLUS ONE elements!
3222c6538bccSBram Moolenaar     funcexe_T	*funcexe)	// more arguments
3223a9b579f3SBram Moolenaar {
3224a9b579f3SBram Moolenaar     int		ret = FAIL;
3225ef140544SBram Moolenaar     int		error = FCERR_NONE;
3226a9b579f3SBram Moolenaar     int		i;
3227f10806b2SBram Moolenaar     ufunc_T	*fp = NULL;
3228a9b579f3SBram Moolenaar     char_u	fname_buf[FLEN_FIXED + 1];
3229a9b579f3SBram Moolenaar     char_u	*tofree = NULL;
3230f10806b2SBram Moolenaar     char_u	*fname = NULL;
3231f10806b2SBram Moolenaar     char_u	*name = NULL;
3232a9b579f3SBram Moolenaar     int		argcount = argcount_in;
3233a9b579f3SBram Moolenaar     typval_T	*argvars = argvars_in;
3234c6538bccSBram Moolenaar     dict_T	*selfdict = funcexe->selfdict;
3235fcfe1a9bSBram Moolenaar     typval_T	argv[MAX_FUNC_ARGS + 1]; // used when "partial" or
3236fcfe1a9bSBram Moolenaar 					 // "funcexe->basetv" is not NULL
3237a9b579f3SBram Moolenaar     int		argv_clear = 0;
3238761fdf01SBram Moolenaar     int		argv_base = 0;
3239c6538bccSBram Moolenaar     partial_T	*partial = funcexe->partial;
324097f227d9SBram Moolenaar     type_T	check_type;
3241a9b579f3SBram Moolenaar 
3242c507a2d1SBram Moolenaar     // Initialize rettv so that it is safe for caller to invoke clear_tv(rettv)
3243c507a2d1SBram Moolenaar     // even when call_func() returns FAIL.
3244c507a2d1SBram Moolenaar     rettv->v_type = VAR_UNKNOWN;
3245c507a2d1SBram Moolenaar 
3246f10806b2SBram Moolenaar     if (partial != NULL)
3247f10806b2SBram Moolenaar 	fp = partial->pt_func;
3248f10806b2SBram Moolenaar     if (fp == NULL)
3249f10806b2SBram Moolenaar     {
3250f10806b2SBram Moolenaar 	// Make a copy of the name, if it comes from a funcref variable it
3251f10806b2SBram Moolenaar 	// could be changed or deleted in the called function.
32526ed88198SBram Moolenaar 	name = len > 0 ? vim_strnsave(funcname, len) : vim_strsave(funcname);
3253a9b579f3SBram Moolenaar 	if (name == NULL)
3254a9b579f3SBram Moolenaar 	    return ret;
3255a9b579f3SBram Moolenaar 
3256a9b579f3SBram Moolenaar 	fname = fname_trans_sid(name, fname_buf, &tofree, &error);
3257f10806b2SBram Moolenaar     }
3258a9b579f3SBram Moolenaar 
3259c6538bccSBram Moolenaar     if (funcexe->doesrange != NULL)
3260c6538bccSBram Moolenaar 	*funcexe->doesrange = FALSE;
3261a9b579f3SBram Moolenaar 
3262a9b579f3SBram Moolenaar     if (partial != NULL)
3263a9b579f3SBram Moolenaar     {
3264e38eab22SBram Moolenaar 	// When the function has a partial with a dict and there is a dict
3265e38eab22SBram Moolenaar 	// argument, use the dict argument.  That is backwards compatible.
3266e38eab22SBram Moolenaar 	// When the dict was bound explicitly use the one from the partial.
3267c6538bccSBram Moolenaar 	if (partial->pt_dict != NULL && (selfdict == NULL || !partial->pt_auto))
3268a9b579f3SBram Moolenaar 	    selfdict = partial->pt_dict;
3269ef140544SBram Moolenaar 	if (error == FCERR_NONE && partial->pt_argc > 0)
3270a9b579f3SBram Moolenaar 	{
3271a9b579f3SBram Moolenaar 	    for (argv_clear = 0; argv_clear < partial->pt_argc; ++argv_clear)
32724c054e9fSBram Moolenaar 	    {
32734c054e9fSBram Moolenaar 		if (argv_clear + argcount_in >= MAX_FUNC_ARGS)
32744c054e9fSBram Moolenaar 		{
3275ef140544SBram Moolenaar 		    error = FCERR_TOOMANY;
32764c054e9fSBram Moolenaar 		    goto theend;
32774c054e9fSBram Moolenaar 		}
3278a9b579f3SBram Moolenaar 		copy_tv(&partial->pt_argv[argv_clear], &argv[argv_clear]);
32794c054e9fSBram Moolenaar 	    }
3280a9b579f3SBram Moolenaar 	    for (i = 0; i < argcount_in; ++i)
3281a9b579f3SBram Moolenaar 		argv[i + argv_clear] = argvars_in[i];
3282a9b579f3SBram Moolenaar 	    argvars = argv;
3283a9b579f3SBram Moolenaar 	    argcount = partial->pt_argc + argcount_in;
328497f227d9SBram Moolenaar 
328522f85d04SBram Moolenaar 	    if (funcexe->check_type != NULL
328622f85d04SBram Moolenaar 				     && funcexe->check_type->tt_argcount != -1)
328797f227d9SBram Moolenaar 	    {
328897f227d9SBram Moolenaar 		// Now funcexe->check_type is missing the added arguments, make
328997f227d9SBram Moolenaar 		// a copy of the type with the correction.
329097f227d9SBram Moolenaar 		check_type = *funcexe->check_type;
329197f227d9SBram Moolenaar 		funcexe->check_type = &check_type;
329297f227d9SBram Moolenaar 		check_type.tt_argcount += partial->pt_argc;
329397f227d9SBram Moolenaar 		check_type.tt_min_argcount += partial->pt_argc;
329497f227d9SBram Moolenaar 	    }
3295a9b579f3SBram Moolenaar 	}
3296a9b579f3SBram Moolenaar     }
3297a9b579f3SBram Moolenaar 
329832b3f820SBram Moolenaar     if (error == FCERR_NONE && funcexe->check_type != NULL && funcexe->evaluate)
329932b3f820SBram Moolenaar     {
330032b3f820SBram Moolenaar 	// Check that the argument types are OK for the types of the funcref.
330132b3f820SBram Moolenaar 	if (check_argument_types(funcexe->check_type, argvars, argcount,
33027a6eaa06SBram Moolenaar 				     (name != NULL) ? name : funcname) == FAIL)
330332b3f820SBram Moolenaar 	    error = FCERR_OTHER;
330432b3f820SBram Moolenaar     }
330532b3f820SBram Moolenaar 
3306ef140544SBram Moolenaar     if (error == FCERR_NONE && funcexe->evaluate)
3307a9b579f3SBram Moolenaar     {
3308a9b579f3SBram Moolenaar 	char_u *rfname = fname;
3309333894b1SBram Moolenaar 	int	is_global = FALSE;
3310a9b579f3SBram Moolenaar 
3311333894b1SBram Moolenaar 	// Skip "g:" before a function name.
3312f10806b2SBram Moolenaar 	if (fp == NULL && fname[0] == 'g' && fname[1] == ':')
3313333894b1SBram Moolenaar 	{
3314333894b1SBram Moolenaar 	    is_global = TRUE;
3315a9b579f3SBram Moolenaar 	    rfname = fname + 2;
3316333894b1SBram Moolenaar 	}
3317a9b579f3SBram Moolenaar 
3318e38eab22SBram Moolenaar 	rettv->v_type = VAR_NUMBER;	// default rettv is number zero
3319a9b579f3SBram Moolenaar 	rettv->vval.v_number = 0;
3320ef140544SBram Moolenaar 	error = FCERR_UNKNOWN;
3321a9b579f3SBram Moolenaar 
3322f10806b2SBram Moolenaar 	if (fp != NULL || !builtin_function(rfname, -1))
3323a9b579f3SBram Moolenaar 	{
3324a9b579f3SBram Moolenaar 	    /*
3325a9b579f3SBram Moolenaar 	     * User defined function.
3326a9b579f3SBram Moolenaar 	     */
3327f10806b2SBram Moolenaar 	    if (fp == NULL)
3328333894b1SBram Moolenaar 		fp = find_func(rfname, is_global, NULL);
3329a9b579f3SBram Moolenaar 
3330e38eab22SBram Moolenaar 	    // Trigger FuncUndefined event, may load the function.
3331a9b579f3SBram Moolenaar 	    if (fp == NULL
3332a9b579f3SBram Moolenaar 		    && apply_autocmds(EVENT_FUNCUNDEFINED,
3333a9b579f3SBram Moolenaar 						    rfname, rfname, TRUE, NULL)
3334a9b579f3SBram Moolenaar 		    && !aborting())
3335a9b579f3SBram Moolenaar 	    {
3336e38eab22SBram Moolenaar 		// executed an autocommand, search for the function again
3337333894b1SBram Moolenaar 		fp = find_func(rfname, is_global, NULL);
3338a9b579f3SBram Moolenaar 	    }
3339e38eab22SBram Moolenaar 	    // Try loading a package.
3340a9b579f3SBram Moolenaar 	    if (fp == NULL && script_autoload(rfname, TRUE) && !aborting())
3341a9b579f3SBram Moolenaar 	    {
3342e38eab22SBram Moolenaar 		// loaded a package, search for the function again
3343333894b1SBram Moolenaar 		fp = find_func(rfname, is_global, NULL);
3344a9b579f3SBram Moolenaar 	    }
3345a26b9700SBram Moolenaar 	    if (fp == NULL)
3346a26b9700SBram Moolenaar 	    {
3347a26b9700SBram Moolenaar 		char_u *p = untrans_function_name(rfname);
3348a26b9700SBram Moolenaar 
3349a26b9700SBram Moolenaar 		// If using Vim9 script try not local to the script.
3350035d6e91SBram Moolenaar 		// Don't do this if the name starts with "s:".
3351035d6e91SBram Moolenaar 		if (p != NULL && (funcname[0] != 's' || funcname[1] != ':'))
3352333894b1SBram Moolenaar 		    fp = find_func(p, is_global, NULL);
3353a26b9700SBram Moolenaar 	    }
3354a9b579f3SBram Moolenaar 
3355437bafe4SBram Moolenaar 	    if (fp != NULL && (fp->uf_flags & FC_DELETED))
3356ef140544SBram Moolenaar 		error = FCERR_DELETED;
3357801ab069SBram Moolenaar #ifdef FEAT_LUA
3358801ab069SBram Moolenaar 	    else if (fp != NULL && (fp->uf_flags & FC_CFUNC))
3359801ab069SBram Moolenaar 	    {
3360801ab069SBram Moolenaar 		cfunc_T cb = fp->uf_cb;
3361801ab069SBram Moolenaar 
3362801ab069SBram Moolenaar 		error = (*cb)(argcount, argvars, rettv, fp->uf_cb_state);
3363801ab069SBram Moolenaar 	    }
3364801ab069SBram Moolenaar #endif
3365437bafe4SBram Moolenaar 	    else if (fp != NULL)
3366a9b579f3SBram Moolenaar 	    {
3367c6538bccSBram Moolenaar 		if (funcexe->argv_func != NULL)
3368b0745b22SBram Moolenaar 		    // postponed filling in the arguments, do it now
3369b0745b22SBram Moolenaar 		    argcount = funcexe->argv_func(argcount, argvars, argv_clear,
3370c6538bccSBram Moolenaar 							   fp->uf_args.ga_len);
3371df48fb45SBram Moolenaar 
3372fcfe1a9bSBram Moolenaar 		if (funcexe->basetv != NULL)
3373fcfe1a9bSBram Moolenaar 		{
3374fcfe1a9bSBram Moolenaar 		    // Method call: base->Method()
3375fcfe1a9bSBram Moolenaar 		    mch_memmove(&argv[1], argvars, sizeof(typval_T) * argcount);
3376fcfe1a9bSBram Moolenaar 		    argv[0] = *funcexe->basetv;
3377fcfe1a9bSBram Moolenaar 		    argcount++;
3378761fdf01SBram Moolenaar 		    argvars = argv;
3379761fdf01SBram Moolenaar 		    argv_base = 1;
3380fcfe1a9bSBram Moolenaar 		}
3381fcfe1a9bSBram Moolenaar 
33828a7d6542SBram Moolenaar 		error = call_user_func_check(fp, argcount, argvars, rettv,
33838a7d6542SBram Moolenaar 							    funcexe, selfdict);
3384a9b579f3SBram Moolenaar 	    }
3385a9b579f3SBram Moolenaar 	}
3386ac92e25aSBram Moolenaar 	else if (funcexe->basetv != NULL)
3387ac92e25aSBram Moolenaar 	{
3388ac92e25aSBram Moolenaar 	    /*
3389fcfe1a9bSBram Moolenaar 	     * expr->method(): Find the method name in the table, call its
3390fcfe1a9bSBram Moolenaar 	     * implementation with the base as one of the arguments.
3391ac92e25aSBram Moolenaar 	     */
3392ac92e25aSBram Moolenaar 	    error = call_internal_method(fname, argcount, argvars, rettv,
3393ac92e25aSBram Moolenaar 							      funcexe->basetv);
3394ac92e25aSBram Moolenaar 	}
3395a9b579f3SBram Moolenaar 	else
3396a9b579f3SBram Moolenaar 	{
3397a9b579f3SBram Moolenaar 	    /*
3398a9b579f3SBram Moolenaar 	     * Find the function name in the table, call its implementation.
3399a9b579f3SBram Moolenaar 	     */
3400a9b579f3SBram Moolenaar 	    error = call_internal_func(fname, argcount, argvars, rettv);
3401a9b579f3SBram Moolenaar 	}
3402333894b1SBram Moolenaar 
3403a9b579f3SBram Moolenaar 	/*
3404a9b579f3SBram Moolenaar 	 * The function call (or "FuncUndefined" autocommand sequence) might
3405a9b579f3SBram Moolenaar 	 * have been aborted by an error, an interrupt, or an explicitly thrown
3406a9b579f3SBram Moolenaar 	 * exception that has not been caught so far.  This situation can be
3407a9b579f3SBram Moolenaar 	 * tested for by calling aborting().  For an error in an internal
3408a9b579f3SBram Moolenaar 	 * function or for the "E132" error in call_user_func(), however, the
3409a9b579f3SBram Moolenaar 	 * throw point at which the "force_abort" flag (temporarily reset by
3410a9b579f3SBram Moolenaar 	 * emsg()) is normally updated has not been reached yet. We need to
3411a9b579f3SBram Moolenaar 	 * update that flag first to make aborting() reliable.
3412a9b579f3SBram Moolenaar 	 */
3413a9b579f3SBram Moolenaar 	update_force_abort();
3414a9b579f3SBram Moolenaar     }
3415ef140544SBram Moolenaar     if (error == FCERR_NONE)
3416a9b579f3SBram Moolenaar 	ret = OK;
3417a9b579f3SBram Moolenaar 
34184c054e9fSBram Moolenaar theend:
3419a9b579f3SBram Moolenaar     /*
3420a9b579f3SBram Moolenaar      * Report an error unless the argument evaluation or function call has been
3421a9b579f3SBram Moolenaar      * cancelled due to an aborting error, an interrupt, or an exception.
3422a9b579f3SBram Moolenaar      */
3423a9b579f3SBram Moolenaar     if (!aborting())
3424a9b579f3SBram Moolenaar     {
3425f10806b2SBram Moolenaar 	user_func_error(error, (name != NULL) ? name : funcname);
3426a9b579f3SBram Moolenaar     }
3427a9b579f3SBram Moolenaar 
3428761fdf01SBram Moolenaar     // clear the copies made from the partial
3429a9b579f3SBram Moolenaar     while (argv_clear > 0)
3430761fdf01SBram Moolenaar 	clear_tv(&argv[--argv_clear + argv_base]);
3431761fdf01SBram Moolenaar 
3432a9b579f3SBram Moolenaar     vim_free(tofree);
3433a9b579f3SBram Moolenaar     vim_free(name);
3434a9b579f3SBram Moolenaar 
3435a9b579f3SBram Moolenaar     return ret;
3436a9b579f3SBram Moolenaar }
3437a9b579f3SBram Moolenaar 
3438682d0a15SBram Moolenaar     char_u *
printable_func_name(ufunc_T * fp)34398a7d6542SBram Moolenaar printable_func_name(ufunc_T *fp)
34408a7d6542SBram Moolenaar {
34418a7d6542SBram Moolenaar     return fp->uf_name_exp != NULL ? fp->uf_name_exp : fp->uf_name;
34428a7d6542SBram Moolenaar }
34438a7d6542SBram Moolenaar 
3444a9b579f3SBram Moolenaar /*
344561a6d4e4SBram Moolenaar  * List the head of the function: "function name(arg1, arg2)".
3446a9b579f3SBram Moolenaar  */
3447a9b579f3SBram Moolenaar     static void
list_func_head(ufunc_T * fp,int indent)3448a9b579f3SBram Moolenaar list_func_head(ufunc_T *fp, int indent)
3449a9b579f3SBram Moolenaar {
3450a9b579f3SBram Moolenaar     int		j;
3451a9b579f3SBram Moolenaar 
3452a9b579f3SBram Moolenaar     msg_start();
3453a9b579f3SBram Moolenaar     if (indent)
345432526b3cSBram Moolenaar 	msg_puts("   ");
34550cb5bcf5SBram Moolenaar     if (fp->uf_def_status != UF_NOT_COMPILED)
345661a6d4e4SBram Moolenaar 	msg_puts("def ");
345761a6d4e4SBram Moolenaar     else
345832526b3cSBram Moolenaar 	msg_puts("function ");
34598a7d6542SBram Moolenaar     msg_puts((char *)printable_func_name(fp));
3460a9b579f3SBram Moolenaar     msg_putchar('(');
3461a9b579f3SBram Moolenaar     for (j = 0; j < fp->uf_args.ga_len; ++j)
3462a9b579f3SBram Moolenaar     {
3463a9b579f3SBram Moolenaar 	if (j)
346432526b3cSBram Moolenaar 	    msg_puts(", ");
346532526b3cSBram Moolenaar 	msg_puts((char *)FUNCARG(fp, j));
34668a7d6542SBram Moolenaar 	if (fp->uf_arg_types != NULL)
34678a7d6542SBram Moolenaar 	{
34688a7d6542SBram Moolenaar 	    char *tofree;
34698a7d6542SBram Moolenaar 
34708a7d6542SBram Moolenaar 	    msg_puts(": ");
34718a7d6542SBram Moolenaar 	    msg_puts(type_name(fp->uf_arg_types[j], &tofree));
34728a7d6542SBram Moolenaar 	    vim_free(tofree);
34738a7d6542SBram Moolenaar 	}
347442ae78cfSBram Moolenaar 	if (j >= fp->uf_args.ga_len - fp->uf_def_args.ga_len)
347542ae78cfSBram Moolenaar 	{
347642ae78cfSBram Moolenaar 	    msg_puts(" = ");
347742ae78cfSBram Moolenaar 	    msg_puts(((char **)(fp->uf_def_args.ga_data))
347842ae78cfSBram Moolenaar 		       [j - fp->uf_args.ga_len + fp->uf_def_args.ga_len]);
347942ae78cfSBram Moolenaar 	}
3480a9b579f3SBram Moolenaar     }
3481a9b579f3SBram Moolenaar     if (fp->uf_varargs)
3482a9b579f3SBram Moolenaar     {
3483a9b579f3SBram Moolenaar 	if (j)
348432526b3cSBram Moolenaar 	    msg_puts(", ");
348532526b3cSBram Moolenaar 	msg_puts("...");
3486a9b579f3SBram Moolenaar     }
34878a7d6542SBram Moolenaar     if (fp->uf_va_name != NULL)
34888a7d6542SBram Moolenaar     {
34898a7d6542SBram Moolenaar 	if (j)
34908a7d6542SBram Moolenaar 	    msg_puts(", ");
34918a7d6542SBram Moolenaar 	msg_puts("...");
34928a7d6542SBram Moolenaar 	msg_puts((char *)fp->uf_va_name);
34932a38908bSBram Moolenaar 	if (fp->uf_va_type != NULL)
34948a7d6542SBram Moolenaar 	{
34958a7d6542SBram Moolenaar 	    char *tofree;
34968a7d6542SBram Moolenaar 
34978a7d6542SBram Moolenaar 	    msg_puts(": ");
34988a7d6542SBram Moolenaar 	    msg_puts(type_name(fp->uf_va_type, &tofree));
34998a7d6542SBram Moolenaar 	    vim_free(tofree);
35008a7d6542SBram Moolenaar 	}
35018a7d6542SBram Moolenaar     }
3502a9b579f3SBram Moolenaar     msg_putchar(')');
350361a6d4e4SBram Moolenaar 
35040cb5bcf5SBram Moolenaar     if (fp->uf_def_status != UF_NOT_COMPILED)
350561a6d4e4SBram Moolenaar     {
350661a6d4e4SBram Moolenaar 	if (fp->uf_ret_type != &t_void)
350761a6d4e4SBram Moolenaar 	{
350861a6d4e4SBram Moolenaar 	    char *tofree;
350961a6d4e4SBram Moolenaar 
351061a6d4e4SBram Moolenaar 	    msg_puts(": ");
351161a6d4e4SBram Moolenaar 	    msg_puts(type_name(fp->uf_ret_type, &tofree));
351261a6d4e4SBram Moolenaar 	    vim_free(tofree);
351361a6d4e4SBram Moolenaar 	}
351461a6d4e4SBram Moolenaar     }
351561a6d4e4SBram Moolenaar     else if (fp->uf_flags & FC_ABORT)
351632526b3cSBram Moolenaar 	msg_puts(" abort");
3517a9b579f3SBram Moolenaar     if (fp->uf_flags & FC_RANGE)
351832526b3cSBram Moolenaar 	msg_puts(" range");
3519a9b579f3SBram Moolenaar     if (fp->uf_flags & FC_DICT)
352032526b3cSBram Moolenaar 	msg_puts(" dict");
352110ce39a0SBram Moolenaar     if (fp->uf_flags & FC_CLOSURE)
352232526b3cSBram Moolenaar 	msg_puts(" closure");
3523a9b579f3SBram Moolenaar     msg_clr_eos();
3524a9b579f3SBram Moolenaar     if (p_verbose > 0)
3525f29c1c6aSBram Moolenaar 	last_set_msg(fp->uf_script_ctx);
3526a9b579f3SBram Moolenaar }
3527a9b579f3SBram Moolenaar 
3528a9b579f3SBram Moolenaar /*
3529a9b579f3SBram Moolenaar  * Get a function name, translating "<SID>" and "<SNR>".
3530a9b579f3SBram Moolenaar  * Also handles a Funcref in a List or Dictionary.
3531a9b579f3SBram Moolenaar  * Returns the function name in allocated memory, or NULL for failure.
35324c17ad94SBram Moolenaar  * Set "*is_global" to TRUE when the function must be global, unless
35334c17ad94SBram Moolenaar  * "is_global" is NULL.
3534a9b579f3SBram Moolenaar  * flags:
3535a9b579f3SBram Moolenaar  * TFN_INT:	    internal function name OK
3536a9b579f3SBram Moolenaar  * TFN_QUIET:	    be quiet
3537a9b579f3SBram Moolenaar  * TFN_NO_AUTOLOAD: do not use script autoloading
3538b54c3ff3SBram Moolenaar  * TFN_NO_DEREF:    do not dereference a Funcref
3539a9b579f3SBram Moolenaar  * Advances "pp" to just after the function name (if no error).
3540a9b579f3SBram Moolenaar  */
3541437bafe4SBram Moolenaar     char_u *
trans_function_name(char_u ** pp,int * is_global,int skip,int flags,funcdict_T * fdp,partial_T ** partial,type_T ** type)3542a9b579f3SBram Moolenaar trans_function_name(
3543a9b579f3SBram Moolenaar     char_u	**pp,
35444c17ad94SBram Moolenaar     int		*is_global,
3545e38eab22SBram Moolenaar     int		skip,		// only find the end, don't evaluate
3546a9b579f3SBram Moolenaar     int		flags,
3547e38eab22SBram Moolenaar     funcdict_T	*fdp,		// return: info about dictionary used
354832b3f820SBram Moolenaar     partial_T	**partial,	// return: partial of a FuncRef
354932b3f820SBram Moolenaar     type_T	**type)		// return: type of funcref if not NULL
3550a9b579f3SBram Moolenaar {
3551a9b579f3SBram Moolenaar     char_u	*name = NULL;
3552a9b579f3SBram Moolenaar     char_u	*start;
3553a9b579f3SBram Moolenaar     char_u	*end;
3554a9b579f3SBram Moolenaar     int		lead;
3555a9b579f3SBram Moolenaar     char_u	sid_buf[20];
3556a9b579f3SBram Moolenaar     int		len;
35578a7d6542SBram Moolenaar     int		extra = 0;
3558a9b579f3SBram Moolenaar     lval_T	lv;
35598a7d6542SBram Moolenaar     int		vim9script;
35607b5d5442SBram Moolenaar     static char *e_function_name = N_("E129: Function name required");
3561a9b579f3SBram Moolenaar 
3562a9b579f3SBram Moolenaar     if (fdp != NULL)
3563a80faa89SBram Moolenaar 	CLEAR_POINTER(fdp);
3564a9b579f3SBram Moolenaar     start = *pp;
3565a9b579f3SBram Moolenaar 
3566e38eab22SBram Moolenaar     // Check for hard coded <SNR>: already translated function ID (from a user
3567e38eab22SBram Moolenaar     // command).
3568a9b579f3SBram Moolenaar     if ((*pp)[0] == K_SPECIAL && (*pp)[1] == KS_EXTRA
3569a9b579f3SBram Moolenaar 						   && (*pp)[2] == (int)KE_SNR)
3570a9b579f3SBram Moolenaar     {
3571a9b579f3SBram Moolenaar 	*pp += 3;
3572a9b579f3SBram Moolenaar 	len = get_id_len(pp) + 3;
3573a9b579f3SBram Moolenaar 	return vim_strnsave(start, len);
3574a9b579f3SBram Moolenaar     }
3575a9b579f3SBram Moolenaar 
3576e38eab22SBram Moolenaar     // A name starting with "<SID>" or "<SNR>" is local to a script.  But
3577e38eab22SBram Moolenaar     // don't skip over "s:", get_lval() needs it for "s:dict.func".
3578a9b579f3SBram Moolenaar     lead = eval_fname_script(start);
3579a9b579f3SBram Moolenaar     if (lead > 2)
3580a9b579f3SBram Moolenaar 	start += lead;
3581a9b579f3SBram Moolenaar 
3582e38eab22SBram Moolenaar     // Note that TFN_ flags use the same values as GLV_ flags.
35836e65d594SBram Moolenaar     end = get_lval(start, NULL, &lv, FALSE, skip, flags | GLV_READ_ONLY,
3584a9b579f3SBram Moolenaar 					      lead > 2 ? 0 : FNE_CHECK_START);
3585a9b579f3SBram Moolenaar     if (end == start)
3586a9b579f3SBram Moolenaar     {
3587a9b579f3SBram Moolenaar 	if (!skip)
35887b5d5442SBram Moolenaar 	    emsg(_(e_function_name));
3589a9b579f3SBram Moolenaar 	goto theend;
3590a9b579f3SBram Moolenaar     }
3591a9b579f3SBram Moolenaar     if (end == NULL || (lv.ll_tv != NULL && (lead > 2 || lv.ll_range)))
3592a9b579f3SBram Moolenaar     {
3593a9b579f3SBram Moolenaar 	/*
3594a9b579f3SBram Moolenaar 	 * Report an invalid expression in braces, unless the expression
3595a9b579f3SBram Moolenaar 	 * evaluation has been cancelled due to an aborting error, an
3596a9b579f3SBram Moolenaar 	 * interrupt, or an exception.
3597a9b579f3SBram Moolenaar 	 */
3598a9b579f3SBram Moolenaar 	if (!aborting())
3599a9b579f3SBram Moolenaar 	{
3600a9b579f3SBram Moolenaar 	    if (end != NULL)
3601f9e3e09fSBram Moolenaar 		semsg(_(e_invarg2), start);
3602a9b579f3SBram Moolenaar 	}
3603a9b579f3SBram Moolenaar 	else
3604a9b579f3SBram Moolenaar 	    *pp = find_name_end(start, NULL, NULL, FNE_INCL_BR);
3605a9b579f3SBram Moolenaar 	goto theend;
3606a9b579f3SBram Moolenaar     }
3607a9b579f3SBram Moolenaar 
3608a9b579f3SBram Moolenaar     if (lv.ll_tv != NULL)
3609a9b579f3SBram Moolenaar     {
3610a9b579f3SBram Moolenaar 	if (fdp != NULL)
3611a9b579f3SBram Moolenaar 	{
3612a9b579f3SBram Moolenaar 	    fdp->fd_dict = lv.ll_dict;
3613a9b579f3SBram Moolenaar 	    fdp->fd_newkey = lv.ll_newkey;
3614a9b579f3SBram Moolenaar 	    lv.ll_newkey = NULL;
3615a9b579f3SBram Moolenaar 	    fdp->fd_di = lv.ll_di;
3616a9b579f3SBram Moolenaar 	}
3617a9b579f3SBram Moolenaar 	if (lv.ll_tv->v_type == VAR_FUNC && lv.ll_tv->vval.v_string != NULL)
3618a9b579f3SBram Moolenaar 	{
3619a9b579f3SBram Moolenaar 	    name = vim_strsave(lv.ll_tv->vval.v_string);
3620a9b579f3SBram Moolenaar 	    *pp = end;
3621a9b579f3SBram Moolenaar 	}
3622a9b579f3SBram Moolenaar 	else if (lv.ll_tv->v_type == VAR_PARTIAL
3623a9b579f3SBram Moolenaar 					  && lv.ll_tv->vval.v_partial != NULL)
3624a9b579f3SBram Moolenaar 	{
3625437bafe4SBram Moolenaar 	    name = vim_strsave(partial_name(lv.ll_tv->vval.v_partial));
3626a9b579f3SBram Moolenaar 	    *pp = end;
3627a9b579f3SBram Moolenaar 	    if (partial != NULL)
3628a9b579f3SBram Moolenaar 		*partial = lv.ll_tv->vval.v_partial;
3629a9b579f3SBram Moolenaar 	}
3630a9b579f3SBram Moolenaar 	else
3631a9b579f3SBram Moolenaar 	{
3632a9b579f3SBram Moolenaar 	    if (!skip && !(flags & TFN_QUIET) && (fdp == NULL
3633a9b579f3SBram Moolenaar 			     || lv.ll_dict == NULL || fdp->fd_newkey == NULL))
3634f9e3e09fSBram Moolenaar 		emsg(_(e_funcref));
3635a9b579f3SBram Moolenaar 	    else
3636a9b579f3SBram Moolenaar 		*pp = end;
3637a9b579f3SBram Moolenaar 	    name = NULL;
3638a9b579f3SBram Moolenaar 	}
3639a9b579f3SBram Moolenaar 	goto theend;
3640a9b579f3SBram Moolenaar     }
3641a9b579f3SBram Moolenaar 
3642a9b579f3SBram Moolenaar     if (lv.ll_name == NULL)
3643a9b579f3SBram Moolenaar     {
3644e38eab22SBram Moolenaar 	// Error found, but continue after the function name.
3645a9b579f3SBram Moolenaar 	*pp = end;
3646a9b579f3SBram Moolenaar 	goto theend;
3647a9b579f3SBram Moolenaar     }
3648a9b579f3SBram Moolenaar 
3649e38eab22SBram Moolenaar     // Check if the name is a Funcref.  If so, use the value.
3650a9b579f3SBram Moolenaar     if (lv.ll_exp_name != NULL)
3651a9b579f3SBram Moolenaar     {
3652a9b579f3SBram Moolenaar 	len = (int)STRLEN(lv.ll_exp_name);
365332b3f820SBram Moolenaar 	name = deref_func_name(lv.ll_exp_name, &len, partial, type,
3654a9b579f3SBram Moolenaar 						     flags & TFN_NO_AUTOLOAD);
3655a9b579f3SBram Moolenaar 	if (name == lv.ll_exp_name)
3656a9b579f3SBram Moolenaar 	    name = NULL;
3657a9b579f3SBram Moolenaar     }
3658b54c3ff3SBram Moolenaar     else if (!(flags & TFN_NO_DEREF))
3659a9b579f3SBram Moolenaar     {
3660a9b579f3SBram Moolenaar 	len = (int)(end - *pp);
366132b3f820SBram Moolenaar 	name = deref_func_name(*pp, &len, partial, type,
366232b3f820SBram Moolenaar 						      flags & TFN_NO_AUTOLOAD);
3663a9b579f3SBram Moolenaar 	if (name == *pp)
3664a9b579f3SBram Moolenaar 	    name = NULL;
3665a9b579f3SBram Moolenaar     }
3666a9b579f3SBram Moolenaar     if (name != NULL)
3667a9b579f3SBram Moolenaar     {
3668a9b579f3SBram Moolenaar 	name = vim_strsave(name);
3669a9b579f3SBram Moolenaar 	*pp = end;
3670a9b579f3SBram Moolenaar 	if (STRNCMP(name, "<SNR>", 5) == 0)
3671a9b579f3SBram Moolenaar 	{
3672e38eab22SBram Moolenaar 	    // Change "<SNR>" to the byte sequence.
3673a9b579f3SBram Moolenaar 	    name[0] = K_SPECIAL;
3674a9b579f3SBram Moolenaar 	    name[1] = KS_EXTRA;
3675a9b579f3SBram Moolenaar 	    name[2] = (int)KE_SNR;
3676a9b579f3SBram Moolenaar 	    mch_memmove(name + 3, name + 5, STRLEN(name + 5) + 1);
3677a9b579f3SBram Moolenaar 	}
3678a9b579f3SBram Moolenaar 	goto theend;
3679a9b579f3SBram Moolenaar     }
3680a9b579f3SBram Moolenaar 
3681a9b579f3SBram Moolenaar     if (lv.ll_exp_name != NULL)
3682a9b579f3SBram Moolenaar     {
3683a9b579f3SBram Moolenaar 	len = (int)STRLEN(lv.ll_exp_name);
3684a9b579f3SBram Moolenaar 	if (lead <= 2 && lv.ll_name == lv.ll_exp_name
3685a9b579f3SBram Moolenaar 					 && STRNCMP(lv.ll_name, "s:", 2) == 0)
3686a9b579f3SBram Moolenaar 	{
3687e38eab22SBram Moolenaar 	    // When there was "s:" already or the name expanded to get a
3688e38eab22SBram Moolenaar 	    // leading "s:" then remove it.
3689a9b579f3SBram Moolenaar 	    lv.ll_name += 2;
3690a9b579f3SBram Moolenaar 	    len -= 2;
3691a9b579f3SBram Moolenaar 	    lead = 2;
3692a9b579f3SBram Moolenaar 	}
3693a9b579f3SBram Moolenaar     }
3694a9b579f3SBram Moolenaar     else
3695a9b579f3SBram Moolenaar     {
3696e38eab22SBram Moolenaar 	// skip over "s:" and "g:"
3697a9b579f3SBram Moolenaar 	if (lead == 2 || (lv.ll_name[0] == 'g' && lv.ll_name[1] == ':'))
36984c17ad94SBram Moolenaar 	{
36994c17ad94SBram Moolenaar 	    if (is_global != NULL && lv.ll_name[0] == 'g')
37004c17ad94SBram Moolenaar 		*is_global = TRUE;
3701a9b579f3SBram Moolenaar 	    lv.ll_name += 2;
37024c17ad94SBram Moolenaar 	}
3703a9b579f3SBram Moolenaar 	len = (int)(end - lv.ll_name);
3704a9b579f3SBram Moolenaar     }
37057b5d5442SBram Moolenaar     if (len <= 0)
37067b5d5442SBram Moolenaar     {
37077b5d5442SBram Moolenaar 	if (!skip)
37087b5d5442SBram Moolenaar 	    emsg(_(e_function_name));
37097b5d5442SBram Moolenaar 	goto theend;
37107b5d5442SBram Moolenaar     }
3711a9b579f3SBram Moolenaar 
371217f700acSBram Moolenaar     // In Vim9 script a user function is script-local by default, unless it
371317f700acSBram Moolenaar     // starts with a lower case character: dict.func().
3714eb6880b6SBram Moolenaar     vim9script = ASCII_ISUPPER(*start) && in_vim9script();
371517f700acSBram Moolenaar     if (vim9script)
371617f700acSBram Moolenaar     {
371717f700acSBram Moolenaar 	char_u *p;
371817f700acSBram Moolenaar 
371917f700acSBram Moolenaar 	// SomeScript#func() is a global function.
372017f700acSBram Moolenaar 	for (p = start; *p != NUL && *p != '('; ++p)
372117f700acSBram Moolenaar 	    if (*p == AUTOLOAD_CHAR)
372217f700acSBram Moolenaar 		vim9script = FALSE;
372317f700acSBram Moolenaar     }
37248a7d6542SBram Moolenaar 
3725a9b579f3SBram Moolenaar     /*
3726a9b579f3SBram Moolenaar      * Copy the function name to allocated memory.
3727a9b579f3SBram Moolenaar      * Accept <SID>name() inside a script, translate into <SNR>123_name().
3728a9b579f3SBram Moolenaar      * Accept <SNR>123_name() outside a script.
3729a9b579f3SBram Moolenaar      */
3730a9b579f3SBram Moolenaar     if (skip)
3731e38eab22SBram Moolenaar 	lead = 0;	// do nothing
37328a7d6542SBram Moolenaar     else if (lead > 0 || vim9script)
3733a9b579f3SBram Moolenaar     {
37348a7d6542SBram Moolenaar 	if (!vim9script)
3735a9b579f3SBram Moolenaar 	    lead = 3;
37368a7d6542SBram Moolenaar 	if (vim9script || (lv.ll_exp_name != NULL
37378a7d6542SBram Moolenaar 					     && eval_fname_sid(lv.ll_exp_name))
3738a9b579f3SBram Moolenaar 						       || eval_fname_sid(*pp))
3739a9b579f3SBram Moolenaar 	{
37408a7d6542SBram Moolenaar 	    // It's script-local, "s:" or "<SID>"
3741f29c1c6aSBram Moolenaar 	    if (current_sctx.sc_sid <= 0)
3742a9b579f3SBram Moolenaar 	    {
3743f9e3e09fSBram Moolenaar 		emsg(_(e_usingsid));
3744a9b579f3SBram Moolenaar 		goto theend;
3745a9b579f3SBram Moolenaar 	    }
3746f29c1c6aSBram Moolenaar 	    sprintf((char *)sid_buf, "%ld_", (long)current_sctx.sc_sid);
37478a7d6542SBram Moolenaar 	    if (vim9script)
37488a7d6542SBram Moolenaar 		extra = 3 + (int)STRLEN(sid_buf);
37498a7d6542SBram Moolenaar 	    else
3750a9b579f3SBram Moolenaar 		lead += (int)STRLEN(sid_buf);
3751a9b579f3SBram Moolenaar 	}
3752a9b579f3SBram Moolenaar     }
375322f17a29SBram Moolenaar     else if (!(flags & TFN_INT) && (builtin_function(lv.ll_name, len)
375422f17a29SBram Moolenaar 				   || (in_vim9script() && *lv.ll_name == '_')))
3755a9b579f3SBram Moolenaar     {
3756f9e3e09fSBram Moolenaar 	semsg(_("E128: Function name must start with a capital or \"s:\": %s"),
3757a9b579f3SBram Moolenaar 								       start);
3758a9b579f3SBram Moolenaar 	goto theend;
3759a9b579f3SBram Moolenaar     }
3760b54c3ff3SBram Moolenaar     if (!skip && !(flags & TFN_QUIET) && !(flags & TFN_NO_DEREF))
3761a9b579f3SBram Moolenaar     {
3762a9b579f3SBram Moolenaar 	char_u *cp = vim_strchr(lv.ll_name, ':');
3763a9b579f3SBram Moolenaar 
3764a9b579f3SBram Moolenaar 	if (cp != NULL && cp < end)
3765a9b579f3SBram Moolenaar 	{
3766f9e3e09fSBram Moolenaar 	    semsg(_("E884: Function name cannot contain a colon: %s"), start);
3767a9b579f3SBram Moolenaar 	    goto theend;
3768a9b579f3SBram Moolenaar 	}
3769a9b579f3SBram Moolenaar     }
3770a9b579f3SBram Moolenaar 
37718a7d6542SBram Moolenaar     name = alloc(len + lead + extra + 1);
3772a9b579f3SBram Moolenaar     if (name != NULL)
3773a9b579f3SBram Moolenaar     {
37749a5e5a3eSBram Moolenaar 	if (!skip && (lead > 0 || vim9script))
3775a9b579f3SBram Moolenaar 	{
3776a9b579f3SBram Moolenaar 	    name[0] = K_SPECIAL;
3777a9b579f3SBram Moolenaar 	    name[1] = KS_EXTRA;
3778a9b579f3SBram Moolenaar 	    name[2] = (int)KE_SNR;
37798a7d6542SBram Moolenaar 	    if (vim9script || lead > 3)	// If it's "<SID>"
3780a9b579f3SBram Moolenaar 		STRCPY(name + 3, sid_buf);
3781a9b579f3SBram Moolenaar 	}
37828a7d6542SBram Moolenaar 	mch_memmove(name + lead + extra, lv.ll_name, (size_t)len);
37838a7d6542SBram Moolenaar 	name[lead + extra + len] = NUL;
3784a9b579f3SBram Moolenaar     }
3785a9b579f3SBram Moolenaar     *pp = end;
3786a9b579f3SBram Moolenaar 
3787a9b579f3SBram Moolenaar theend:
3788a9b579f3SBram Moolenaar     clear_lval(&lv);
3789a9b579f3SBram Moolenaar     return name;
3790a9b579f3SBram Moolenaar }
3791a9b579f3SBram Moolenaar 
3792a9b579f3SBram Moolenaar /*
3793a26b9700SBram Moolenaar  * Assuming "name" is the result of trans_function_name() and it was prefixed
3794a26b9700SBram Moolenaar  * to use the script-local name, return the unmodified name (points into
3795a26b9700SBram Moolenaar  * "name").  Otherwise return NULL.
3796a26b9700SBram Moolenaar  * This can be used to first search for a script-local function and fall back
3797a26b9700SBram Moolenaar  * to the global function if not found.
3798a26b9700SBram Moolenaar  */
3799a26b9700SBram Moolenaar     char_u *
untrans_function_name(char_u * name)3800a26b9700SBram Moolenaar untrans_function_name(char_u *name)
3801a26b9700SBram Moolenaar {
3802a26b9700SBram Moolenaar     char_u *p;
3803a26b9700SBram Moolenaar 
3804eb6880b6SBram Moolenaar     if (*name == K_SPECIAL && in_vim9script())
3805a26b9700SBram Moolenaar     {
3806a26b9700SBram Moolenaar 	p = vim_strchr(name, '_');
3807a26b9700SBram Moolenaar 	if (p != NULL)
3808a26b9700SBram Moolenaar 	    return p + 1;
3809a26b9700SBram Moolenaar     }
3810a26b9700SBram Moolenaar     return NULL;
3811a26b9700SBram Moolenaar }
3812a26b9700SBram Moolenaar 
3813a26b9700SBram Moolenaar /*
38143fffa971SBram Moolenaar  * List functions.  When "regmatch" is NULL all of then.
38153fffa971SBram Moolenaar  * Otherwise functions matching "regmatch".
38163fffa971SBram Moolenaar  */
38176abdcf82SBram Moolenaar     void
list_functions(regmatch_T * regmatch)38183fffa971SBram Moolenaar list_functions(regmatch_T *regmatch)
38193fffa971SBram Moolenaar {
38201f22cc5cSBram Moolenaar     int		changed = func_hashtab.ht_changed;
38211f22cc5cSBram Moolenaar     long_u	todo = func_hashtab.ht_used;
38223fffa971SBram Moolenaar     hashitem_T	*hi;
38233fffa971SBram Moolenaar 
38241f22cc5cSBram Moolenaar     for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
38253fffa971SBram Moolenaar     {
38263fffa971SBram Moolenaar 	if (!HASHITEM_EMPTY(hi))
38273fffa971SBram Moolenaar 	{
38283fffa971SBram Moolenaar 	    ufunc_T	*fp = HI2UF(hi);
38293fffa971SBram Moolenaar 
38303fffa971SBram Moolenaar 	    --todo;
38313fffa971SBram Moolenaar 	    if ((fp->uf_flags & FC_DEAD) == 0
38323fffa971SBram Moolenaar 		    && (regmatch == NULL
38333fffa971SBram Moolenaar 			? !message_filtered(fp->uf_name)
38343fffa971SBram Moolenaar 			    && !func_name_refcount(fp->uf_name)
38353fffa971SBram Moolenaar 			: !isdigit(*fp->uf_name)
38363fffa971SBram Moolenaar 			    && vim_regexec(regmatch, fp->uf_name, 0)))
38373fffa971SBram Moolenaar 	    {
38383fffa971SBram Moolenaar 		list_func_head(fp, FALSE);
38391f22cc5cSBram Moolenaar 		if (changed != func_hashtab.ht_changed)
38403fffa971SBram Moolenaar 		{
38413fffa971SBram Moolenaar 		    emsg(_("E454: function list was modified"));
38423fffa971SBram Moolenaar 		    return;
38433fffa971SBram Moolenaar 		}
38443fffa971SBram Moolenaar 	    }
38453fffa971SBram Moolenaar 	}
38463fffa971SBram Moolenaar     }
38473fffa971SBram Moolenaar }
38483fffa971SBram Moolenaar 
38493fffa971SBram Moolenaar /*
385004b12697SBram Moolenaar  * ":function" also supporting nested ":def".
385138ddf333SBram Moolenaar  * When "name_arg" is not NULL this is a nested function, using "name_arg" for
385238ddf333SBram Moolenaar  * the function name.
385304b12697SBram Moolenaar  * Returns a pointer to the function or NULL if no function defined.
3854a9b579f3SBram Moolenaar  */
385504b12697SBram Moolenaar     ufunc_T *
define_function(exarg_T * eap,char_u * name_arg)3856fbbcd003SBram Moolenaar define_function(exarg_T *eap, char_u *name_arg)
3857a9b579f3SBram Moolenaar {
385853564f7cSBram Moolenaar     char_u	*line_to_free = NULL;
3859a9b579f3SBram Moolenaar     int		j;
3860a9b579f3SBram Moolenaar     int		c;
3861a9b579f3SBram Moolenaar     int		saved_did_emsg;
386204b12697SBram Moolenaar     char_u	*name = name_arg;
38634c17ad94SBram Moolenaar     int		is_global = FALSE;
3864a9b579f3SBram Moolenaar     char_u	*p;
3865a9b579f3SBram Moolenaar     char_u	*arg;
3866cef1270dSBram Moolenaar     char_u	*whitep;
3867a9b579f3SBram Moolenaar     char_u	*line_arg = NULL;
3868a9b579f3SBram Moolenaar     garray_T	newargs;
38698a7d6542SBram Moolenaar     garray_T	argtypes;
387042ae78cfSBram Moolenaar     garray_T	default_args;
3871a9b579f3SBram Moolenaar     garray_T	newlines;
3872a9b579f3SBram Moolenaar     int		varargs = FALSE;
3873a9b579f3SBram Moolenaar     int		flags = 0;
38748a7d6542SBram Moolenaar     char_u	*ret_type = NULL;
387504b12697SBram Moolenaar     ufunc_T	*fp = NULL;
3876437bafe4SBram Moolenaar     int		overwrite = FALSE;
3877a9b579f3SBram Moolenaar     dictitem_T	*v;
3878a9b579f3SBram Moolenaar     funcdict_T	fudi;
3879e38eab22SBram Moolenaar     static int	func_nr = 0;	    // number for nameless function
3880a9b579f3SBram Moolenaar     int		paren;
3881a9b579f3SBram Moolenaar     hashitem_T	*hi;
3882bc2cfe46SBram Moolenaar     linenr_T	sourcing_lnum_top;
3883e7e4838fSBram Moolenaar     int		vim9script = in_vim9script();
3884eef2102eSBram Moolenaar     imported_T	*import = NULL;
3885a9b579f3SBram Moolenaar 
3886a9b579f3SBram Moolenaar     /*
3887a9b579f3SBram Moolenaar      * ":function" without argument: list functions.
3888a9b579f3SBram Moolenaar      */
3889a72cfb80SBram Moolenaar     if (ends_excmd2(eap->cmd, eap->arg))
3890a9b579f3SBram Moolenaar     {
3891a9b579f3SBram Moolenaar 	if (!eap->skip)
38923fffa971SBram Moolenaar 	    list_functions(NULL);
389363b91736SBram Moolenaar 	set_nextcmd(eap, eap->arg);
389404b12697SBram Moolenaar 	return NULL;
3895a9b579f3SBram Moolenaar     }
3896a9b579f3SBram Moolenaar 
3897a9b579f3SBram Moolenaar     /*
3898a9b579f3SBram Moolenaar      * ":function /pat": list functions matching pattern.
3899a9b579f3SBram Moolenaar      */
3900a9b579f3SBram Moolenaar     if (*eap->arg == '/')
3901a9b579f3SBram Moolenaar     {
3902e8c4abbbSBram Moolenaar 	p = skip_regexp(eap->arg + 1, '/', TRUE);
3903a9b579f3SBram Moolenaar 	if (!eap->skip)
3904a9b579f3SBram Moolenaar 	{
3905a9b579f3SBram Moolenaar 	    regmatch_T	regmatch;
3906a9b579f3SBram Moolenaar 
3907a9b579f3SBram Moolenaar 	    c = *p;
3908a9b579f3SBram Moolenaar 	    *p = NUL;
3909a9b579f3SBram Moolenaar 	    regmatch.regprog = vim_regcomp(eap->arg + 1, RE_MAGIC);
3910a9b579f3SBram Moolenaar 	    *p = c;
3911a9b579f3SBram Moolenaar 	    if (regmatch.regprog != NULL)
3912a9b579f3SBram Moolenaar 	    {
3913a9b579f3SBram Moolenaar 		regmatch.rm_ic = p_ic;
39143fffa971SBram Moolenaar 		list_functions(&regmatch);
3915a9b579f3SBram Moolenaar 		vim_regfree(regmatch.regprog);
3916a9b579f3SBram Moolenaar 	    }
3917a9b579f3SBram Moolenaar 	}
3918a9b579f3SBram Moolenaar 	if (*p == '/')
3919a9b579f3SBram Moolenaar 	    ++p;
392063b91736SBram Moolenaar 	set_nextcmd(eap, p);
392104b12697SBram Moolenaar 	return NULL;
3922a9b579f3SBram Moolenaar     }
3923a9b579f3SBram Moolenaar 
39248a7d6542SBram Moolenaar     ga_init(&newargs);
39258a7d6542SBram Moolenaar     ga_init(&argtypes);
39268a7d6542SBram Moolenaar     ga_init(&default_args);
39278a7d6542SBram Moolenaar 
3928a9b579f3SBram Moolenaar     /*
3929a9b579f3SBram Moolenaar      * Get the function name.  There are these situations:
3930a9b579f3SBram Moolenaar      * func	    normal function name
3931a9b579f3SBram Moolenaar      *		    "name" == func, "fudi.fd_dict" == NULL
3932a9b579f3SBram Moolenaar      * dict.func    new dictionary entry
3933a9b579f3SBram Moolenaar      *		    "name" == NULL, "fudi.fd_dict" set,
3934a9b579f3SBram Moolenaar      *		    "fudi.fd_di" == NULL, "fudi.fd_newkey" == func
3935a9b579f3SBram Moolenaar      * dict.func    existing dict entry with a Funcref
3936a9b579f3SBram Moolenaar      *		    "name" == func, "fudi.fd_dict" set,
3937a9b579f3SBram Moolenaar      *		    "fudi.fd_di" set, "fudi.fd_newkey" == NULL
3938a9b579f3SBram Moolenaar      * dict.func    existing dict entry that's not a Funcref
3939a9b579f3SBram Moolenaar      *		    "name" == NULL, "fudi.fd_dict" set,
3940a9b579f3SBram Moolenaar      *		    "fudi.fd_di" set, "fudi.fd_newkey" == NULL
3941a9b579f3SBram Moolenaar      * s:func	    script-local function name
3942a9b579f3SBram Moolenaar      * g:func	    global function name, same as "func"
3943a9b579f3SBram Moolenaar      */
3944a9b579f3SBram Moolenaar     p = eap->arg;
394504b12697SBram Moolenaar     if (name_arg != NULL)
394604b12697SBram Moolenaar     {
394704b12697SBram Moolenaar 	// nested function, argument is (args).
394804b12697SBram Moolenaar 	paren = TRUE;
394904b12697SBram Moolenaar 	CLEAR_FIELD(fudi);
395004b12697SBram Moolenaar     }
395104b12697SBram Moolenaar     else
395204b12697SBram Moolenaar     {
3953b657198cSBram Moolenaar 	if (STRNCMP(p, "<lambda>", 8) == 0)
3954b657198cSBram Moolenaar 	{
3955b657198cSBram Moolenaar 	    p += 8;
3956b657198cSBram Moolenaar 	    (void)getdigits(&p);
3957b657198cSBram Moolenaar 	    name = vim_strnsave(eap->arg, p - eap->arg);
3958b657198cSBram Moolenaar 	    CLEAR_FIELD(fudi);
3959b657198cSBram Moolenaar 	}
3960b657198cSBram Moolenaar 	else
39614c17ad94SBram Moolenaar 	    name = trans_function_name(&p, &is_global, eap->skip,
396232b3f820SBram Moolenaar 					   TFN_NO_AUTOLOAD, &fudi, NULL, NULL);
3963a9b579f3SBram Moolenaar 	paren = (vim_strchr(p, '(') != NULL);
3964a9b579f3SBram Moolenaar 	if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
3965a9b579f3SBram Moolenaar 	{
3966a9b579f3SBram Moolenaar 	    /*
3967a9b579f3SBram Moolenaar 	     * Return on an invalid expression in braces, unless the expression
3968a9b579f3SBram Moolenaar 	     * evaluation has been cancelled due to an aborting error, an
3969a9b579f3SBram Moolenaar 	     * interrupt, or an exception.
3970a9b579f3SBram Moolenaar 	     */
3971a9b579f3SBram Moolenaar 	    if (!aborting())
3972a9b579f3SBram Moolenaar 	    {
3973a9b579f3SBram Moolenaar 		if (!eap->skip && fudi.fd_newkey != NULL)
3974f9e3e09fSBram Moolenaar 		    semsg(_(e_dictkey), fudi.fd_newkey);
3975a9b579f3SBram Moolenaar 		vim_free(fudi.fd_newkey);
397604b12697SBram Moolenaar 		return NULL;
3977a9b579f3SBram Moolenaar 	    }
3978a9b579f3SBram Moolenaar 	    else
3979a9b579f3SBram Moolenaar 		eap->skip = TRUE;
3980a9b579f3SBram Moolenaar 	}
398104b12697SBram Moolenaar     }
3982a9b579f3SBram Moolenaar 
3983e38eab22SBram Moolenaar     // An error in a function call during evaluation of an expression in magic
3984e38eab22SBram Moolenaar     // braces should not cause the function not to be defined.
3985a9b579f3SBram Moolenaar     saved_did_emsg = did_emsg;
3986a9b579f3SBram Moolenaar     did_emsg = FALSE;
3987a9b579f3SBram Moolenaar 
3988a9b579f3SBram Moolenaar     /*
3989a9b579f3SBram Moolenaar      * ":function func" with only function name: list function.
3990a9b579f3SBram Moolenaar      */
3991a9b579f3SBram Moolenaar     if (!paren)
3992a9b579f3SBram Moolenaar     {
3993a9b579f3SBram Moolenaar 	if (!ends_excmd(*skipwhite(p)))
3994a9b579f3SBram Moolenaar 	{
39952d06bfdeSBram Moolenaar 	    semsg(_(e_trailing_arg), p);
3996a9b579f3SBram Moolenaar 	    goto ret_free;
3997a9b579f3SBram Moolenaar 	}
399863b91736SBram Moolenaar 	set_nextcmd(eap, p);
3999a9b579f3SBram Moolenaar 	if (eap->nextcmd != NULL)
4000a9b579f3SBram Moolenaar 	    *p = NUL;
4001a9b579f3SBram Moolenaar 	if (!eap->skip && !got_int)
4002a9b579f3SBram Moolenaar 	{
40034c17ad94SBram Moolenaar 	    fp = find_func(name, is_global, NULL);
4004a26b9700SBram Moolenaar 	    if (fp == NULL && ASCII_ISUPPER(*eap->arg))
4005a26b9700SBram Moolenaar 	    {
4006a26b9700SBram Moolenaar 		char_u *up = untrans_function_name(name);
4007a26b9700SBram Moolenaar 
4008a26b9700SBram Moolenaar 		// With Vim9 script the name was made script-local, if not
4009a26b9700SBram Moolenaar 		// found try again with the original name.
4010ec9749f3SBram Moolenaar 		if (up != NULL)
40114c17ad94SBram Moolenaar 		    fp = find_func(up, FALSE, NULL);
4012a26b9700SBram Moolenaar 	    }
4013a26b9700SBram Moolenaar 
4014a9b579f3SBram Moolenaar 	    if (fp != NULL)
4015a9b579f3SBram Moolenaar 	    {
4016a9b579f3SBram Moolenaar 		list_func_head(fp, TRUE);
4017a9b579f3SBram Moolenaar 		for (j = 0; j < fp->uf_lines.ga_len && !got_int; ++j)
4018a9b579f3SBram Moolenaar 		{
4019a9b579f3SBram Moolenaar 		    if (FUNCLINE(fp, j) == NULL)
4020a9b579f3SBram Moolenaar 			continue;
4021a9b579f3SBram Moolenaar 		    msg_putchar('\n');
4022a9b579f3SBram Moolenaar 		    msg_outnum((long)(j + 1));
4023a9b579f3SBram Moolenaar 		    if (j < 9)
4024a9b579f3SBram Moolenaar 			msg_putchar(' ');
4025a9b579f3SBram Moolenaar 		    if (j < 99)
4026a9b579f3SBram Moolenaar 			msg_putchar(' ');
4027a9b579f3SBram Moolenaar 		    msg_prt_line(FUNCLINE(fp, j), FALSE);
4028e38eab22SBram Moolenaar 		    out_flush();	// show a line at a time
4029a9b579f3SBram Moolenaar 		    ui_breakcheck();
4030a9b579f3SBram Moolenaar 		}
4031a9b579f3SBram Moolenaar 		if (!got_int)
4032a9b579f3SBram Moolenaar 		{
4033a9b579f3SBram Moolenaar 		    msg_putchar('\n');
40340cb5bcf5SBram Moolenaar 		    if (fp->uf_def_status != UF_NOT_COMPILED)
40358a7d6542SBram Moolenaar 			msg_puts("   enddef");
40368a7d6542SBram Moolenaar 		    else
403732526b3cSBram Moolenaar 			msg_puts("   endfunction");
4038a9b579f3SBram Moolenaar 		}
4039a9b579f3SBram Moolenaar 	    }
4040a9b579f3SBram Moolenaar 	    else
4041a26b9700SBram Moolenaar 		emsg_funcname(N_("E123: Undefined function: %s"), eap->arg);
4042a9b579f3SBram Moolenaar 	}
4043a9b579f3SBram Moolenaar 	goto ret_free;
4044a9b579f3SBram Moolenaar     }
4045a9b579f3SBram Moolenaar 
4046a9b579f3SBram Moolenaar     /*
4047a9b579f3SBram Moolenaar      * ":function name(arg1, arg2)" Define function.
4048a9b579f3SBram Moolenaar      */
4049a9b579f3SBram Moolenaar     p = skipwhite(p);
4050a9b579f3SBram Moolenaar     if (*p != '(')
4051a9b579f3SBram Moolenaar     {
4052a9b579f3SBram Moolenaar 	if (!eap->skip)
4053a9b579f3SBram Moolenaar 	{
4054f9e3e09fSBram Moolenaar 	    semsg(_("E124: Missing '(': %s"), eap->arg);
4055a9b579f3SBram Moolenaar 	    goto ret_free;
4056a9b579f3SBram Moolenaar 	}
4057e38eab22SBram Moolenaar 	// attempt to continue by skipping some text
4058a9b579f3SBram Moolenaar 	if (vim_strchr(p, '(') != NULL)
4059a9b579f3SBram Moolenaar 	    p = vim_strchr(p, '(');
4060a9b579f3SBram Moolenaar     }
4061a9b579f3SBram Moolenaar 
40624efd9948SBram Moolenaar     if ((vim9script || eap->cmdidx == CMD_def) && VIM_ISWHITE(p[-1]))
40634efd9948SBram Moolenaar     {
4064ba98fb54SBram Moolenaar 	semsg(_(e_no_white_space_allowed_before_str_str), "(", p - 1);
40654efd9948SBram Moolenaar 	goto ret_free;
40664efd9948SBram Moolenaar     }
40674efd9948SBram Moolenaar 
4068925e9fd6SBram Moolenaar     // In Vim9 script only global functions can be redefined.
4069925e9fd6SBram Moolenaar     if (vim9script && eap->forceit && !is_global)
4070925e9fd6SBram Moolenaar     {
4071925e9fd6SBram Moolenaar 	emsg(_(e_nobang));
4072925e9fd6SBram Moolenaar 	goto ret_free;
4073925e9fd6SBram Moolenaar     }
4074925e9fd6SBram Moolenaar 
40757a6eaa06SBram Moolenaar     ga_init2(&newlines, (int)sizeof(char_u *), 10);
4076a9b579f3SBram Moolenaar 
407704b12697SBram Moolenaar     if (!eap->skip && name_arg == NULL)
4078a9b579f3SBram Moolenaar     {
4079e38eab22SBram Moolenaar 	// Check the name of the function.  Unless it's a dictionary function
4080e38eab22SBram Moolenaar 	// (that we are overwriting).
4081a9b579f3SBram Moolenaar 	if (name != NULL)
4082a9b579f3SBram Moolenaar 	    arg = name;
4083a9b579f3SBram Moolenaar 	else
4084a9b579f3SBram Moolenaar 	    arg = fudi.fd_newkey;
4085a9b579f3SBram Moolenaar 	if (arg != NULL && (fudi.fd_di == NULL
4086a9b579f3SBram Moolenaar 				     || (fudi.fd_di->di_tv.v_type != VAR_FUNC
4087a9b579f3SBram Moolenaar 				 && fudi.fd_di->di_tv.v_type != VAR_PARTIAL)))
4088a9b579f3SBram Moolenaar 	{
4089a9b579f3SBram Moolenaar 	    if (*arg == K_SPECIAL)
4090a9b579f3SBram Moolenaar 		j = 3;
4091a9b579f3SBram Moolenaar 	    else
4092a9b579f3SBram Moolenaar 		j = 0;
4093a9b579f3SBram Moolenaar 	    while (arg[j] != NUL && (j == 0 ? eval_isnamec1(arg[j])
4094a9b579f3SBram Moolenaar 						      : eval_isnamec(arg[j])))
4095a9b579f3SBram Moolenaar 		++j;
4096a9b579f3SBram Moolenaar 	    if (arg[j] != NUL)
4097a9b579f3SBram Moolenaar 		emsg_funcname((char *)e_invarg2, arg);
4098a9b579f3SBram Moolenaar 	}
4099e38eab22SBram Moolenaar 	// Disallow using the g: dict.
4100a9b579f3SBram Moolenaar 	if (fudi.fd_dict != NULL && fudi.fd_dict->dv_scope == VAR_DEF_SCOPE)
4101f9e3e09fSBram Moolenaar 	    emsg(_("E862: Cannot use g: here"));
4102a9b579f3SBram Moolenaar     }
4103a9b579f3SBram Moolenaar 
41045e774c75SBram Moolenaar     // This may get more lines and make the pointers into the first line
41055e774c75SBram Moolenaar     // invalid.
4106cef1270dSBram Moolenaar     ++p;
41078a7d6542SBram Moolenaar     if (get_function_args(&p, ')', &newargs,
4108b4d16cb1SBram Moolenaar 			eap->cmdidx == CMD_def ? &argtypes : NULL, FALSE,
4109057e84afSBram Moolenaar 			 NULL, &varargs, &default_args, eap->skip,
41105e774c75SBram Moolenaar 			 eap, &line_to_free) == FAIL)
4111a9b579f3SBram Moolenaar 	goto errret_2;
4112cef1270dSBram Moolenaar     whitep = p;
4113a9b579f3SBram Moolenaar 
41148a7d6542SBram Moolenaar     if (eap->cmdidx == CMD_def)
41158a7d6542SBram Moolenaar     {
41168a7d6542SBram Moolenaar 	// find the return type: :def Func(): type
411733ea9fd4SBram Moolenaar 	if (*skipwhite(p) == ':')
41188a7d6542SBram Moolenaar 	{
411933ea9fd4SBram Moolenaar 	    if (*p != ':')
412033ea9fd4SBram Moolenaar 	    {
412133ea9fd4SBram Moolenaar 		semsg(_(e_no_white_space_allowed_before_colon_str), p);
412233ea9fd4SBram Moolenaar 		p = skipwhite(p);
412333ea9fd4SBram Moolenaar 	    }
412433ea9fd4SBram Moolenaar 	    else if (!IS_WHITE_OR_NUL(p[1]))
412533ea9fd4SBram Moolenaar 		semsg(_(e_white_space_required_after_str_str), ":", p);
41268a7d6542SBram Moolenaar 	    ret_type = skipwhite(p + 1);
41274fc224caSBram Moolenaar 	    p = skip_type(ret_type, FALSE);
41288a7d6542SBram Moolenaar 	    if (p > ret_type)
41295e774c75SBram Moolenaar 	    {
413071ccd03eSBram Moolenaar 		ret_type = vim_strnsave(ret_type, p - ret_type);
4131cef1270dSBram Moolenaar 		whitep = p;
41328a7d6542SBram Moolenaar 		p = skipwhite(p);
41335e774c75SBram Moolenaar 	    }
41348a7d6542SBram Moolenaar 	    else
41355e774c75SBram Moolenaar 	    {
4136451c2e35SBram Moolenaar 		semsg(_(e_expected_type_str), ret_type);
4137b8ce6b00SBram Moolenaar 		ret_type = NULL;
41388a7d6542SBram Moolenaar 	    }
41398a7d6542SBram Moolenaar 	}
4140e7e4838fSBram Moolenaar 	p = skipwhite(p);
41415e774c75SBram Moolenaar     }
41428a7d6542SBram Moolenaar     else
4143e38eab22SBram Moolenaar 	// find extra arguments "range", "dict", "abort" and "closure"
4144a9b579f3SBram Moolenaar 	for (;;)
4145a9b579f3SBram Moolenaar 	{
4146cef1270dSBram Moolenaar 	    whitep = p;
4147a9b579f3SBram Moolenaar 	    p = skipwhite(p);
4148a9b579f3SBram Moolenaar 	    if (STRNCMP(p, "range", 5) == 0)
4149a9b579f3SBram Moolenaar 	    {
4150a9b579f3SBram Moolenaar 		flags |= FC_RANGE;
4151a9b579f3SBram Moolenaar 		p += 5;
4152a9b579f3SBram Moolenaar 	    }
4153a9b579f3SBram Moolenaar 	    else if (STRNCMP(p, "dict", 4) == 0)
4154a9b579f3SBram Moolenaar 	    {
4155a9b579f3SBram Moolenaar 		flags |= FC_DICT;
4156a9b579f3SBram Moolenaar 		p += 4;
4157a9b579f3SBram Moolenaar 	    }
4158a9b579f3SBram Moolenaar 	    else if (STRNCMP(p, "abort", 5) == 0)
4159a9b579f3SBram Moolenaar 	    {
4160a9b579f3SBram Moolenaar 		flags |= FC_ABORT;
4161a9b579f3SBram Moolenaar 		p += 5;
4162a9b579f3SBram Moolenaar 	    }
416310ce39a0SBram Moolenaar 	    else if (STRNCMP(p, "closure", 7) == 0)
416410ce39a0SBram Moolenaar 	    {
416510ce39a0SBram Moolenaar 		flags |= FC_CLOSURE;
416610ce39a0SBram Moolenaar 		p += 7;
416758016448SBram Moolenaar 		if (current_funccal == NULL)
416858016448SBram Moolenaar 		{
4169ba209903SBram Moolenaar 		    emsg_funcname(N_("E932: Closure function should not be at top level: %s"),
417058016448SBram Moolenaar 			    name == NULL ? (char_u *)"" : name);
417158016448SBram Moolenaar 		    goto erret;
417258016448SBram Moolenaar 		}
417310ce39a0SBram Moolenaar 	    }
4174a9b579f3SBram Moolenaar 	    else
4175a9b579f3SBram Moolenaar 		break;
4176a9b579f3SBram Moolenaar 	}
4177a9b579f3SBram Moolenaar 
4178e38eab22SBram Moolenaar     // When there is a line break use what follows for the function body.
4179e38eab22SBram Moolenaar     // Makes 'exe "func Test()\n...\nendfunc"' work.
4180a9b579f3SBram Moolenaar     if (*p == '\n')
4181a9b579f3SBram Moolenaar 	line_arg = p + 1;
4182e7e4838fSBram Moolenaar     else if (*p != NUL
41839898107fSBram Moolenaar 	    && !(*p == '"' && (!vim9script || eap->cmdidx == CMD_function)
41849898107fSBram Moolenaar 						     && eap->cmdidx != CMD_def)
4185cef1270dSBram Moolenaar 	    && !(VIM_ISWHITE(*whitep) && *p == '#'
4186cef1270dSBram Moolenaar 				     && (vim9script || eap->cmdidx == CMD_def))
4187e7e4838fSBram Moolenaar 	    && !eap->skip
4188e7e4838fSBram Moolenaar 	    && !did_emsg)
41892d06bfdeSBram Moolenaar 	semsg(_(e_trailing_arg), p);
4190a9b579f3SBram Moolenaar 
4191a9b579f3SBram Moolenaar     /*
41928a7d6542SBram Moolenaar      * Read the body of the function, until "}", ":endfunction" or ":enddef" is
41938a7d6542SBram Moolenaar      * found.
4194a9b579f3SBram Moolenaar      */
4195a9b579f3SBram Moolenaar     if (KeyTyped)
4196a9b579f3SBram Moolenaar     {
4197e38eab22SBram Moolenaar 	// Check if the function already exists, don't let the user type the
4198e38eab22SBram Moolenaar 	// whole function before telling him it doesn't work!  For a script we
4199e38eab22SBram Moolenaar 	// need to skip the body to be able to find what follows.
4200a9b579f3SBram Moolenaar 	if (!eap->skip && !eap->forceit)
4201a9b579f3SBram Moolenaar 	{
4202a9b579f3SBram Moolenaar 	    if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL)
4203f9e3e09fSBram Moolenaar 		emsg(_(e_funcdict));
42044c17ad94SBram Moolenaar 	    else if (name != NULL && find_func(name, is_global, NULL) != NULL)
4205a9b579f3SBram Moolenaar 		emsg_funcname(e_funcexts, name);
4206a9b579f3SBram Moolenaar 	}
4207a9b579f3SBram Moolenaar 
4208a9b579f3SBram Moolenaar 	if (!eap->skip && did_emsg)
4209a9b579f3SBram Moolenaar 	    goto erret;
4210a9b579f3SBram Moolenaar 
4211e38eab22SBram Moolenaar 	msg_putchar('\n');	    // don't overwrite the function name
4212a9b579f3SBram Moolenaar 	cmdline_row = msg_row;
4213a9b579f3SBram Moolenaar     }
4214a9b579f3SBram Moolenaar 
4215bc2cfe46SBram Moolenaar     // Save the starting line number.
42161a47ae32SBram Moolenaar     sourcing_lnum_top = SOURCING_LNUM;
4217bc2cfe46SBram Moolenaar 
4218d87c21a9SBram Moolenaar     // Do not define the function when getting the body fails and when
4219d87c21a9SBram Moolenaar     // skipping.
4220d87c21a9SBram Moolenaar     if (get_function_body(eap, &newlines, line_arg, &line_to_free) == FAIL
4221d87c21a9SBram Moolenaar 	    || eap->skip)
4222a9b579f3SBram Moolenaar 	goto erret;
4223a9b579f3SBram Moolenaar 
4224a9b579f3SBram Moolenaar     /*
4225a9b579f3SBram Moolenaar      * If there are no errors, add the function
4226a9b579f3SBram Moolenaar      */
4227a9b579f3SBram Moolenaar     if (fudi.fd_dict == NULL)
4228a9b579f3SBram Moolenaar     {
42298a7d6542SBram Moolenaar 	hashtab_T	*ht;
42308a7d6542SBram Moolenaar 
423132b3f820SBram Moolenaar 	v = find_var(name, &ht, TRUE);
4232a9b579f3SBram Moolenaar 	if (v != NULL && v->di_tv.v_type == VAR_FUNC)
4233a9b579f3SBram Moolenaar 	{
4234a9b579f3SBram Moolenaar 	    emsg_funcname(N_("E707: Function name conflicts with variable: %s"),
4235a9b579f3SBram Moolenaar 									name);
4236a9b579f3SBram Moolenaar 	    goto erret;
4237a9b579f3SBram Moolenaar 	}
4238a9b579f3SBram Moolenaar 
42394c17ad94SBram Moolenaar 	fp = find_func_even_dead(name, is_global, NULL);
4240eef2102eSBram Moolenaar 	if (vim9script)
4241a9b579f3SBram Moolenaar 	{
4242eef2102eSBram Moolenaar 	    char_u *uname = untrans_function_name(name);
4243eef2102eSBram Moolenaar 
4244eef2102eSBram Moolenaar 	    import = find_imported(uname == NULL ? name : uname, 0, NULL);
4245eef2102eSBram Moolenaar 	}
4246eef2102eSBram Moolenaar 
4247eef2102eSBram Moolenaar 	if (fp != NULL || import != NULL)
4248eef2102eSBram Moolenaar 	{
4249eef2102eSBram Moolenaar 	    int dead = fp != NULL && (fp->uf_flags & FC_DEAD);
42508a7d6542SBram Moolenaar 
4251ded5f1beSBram Moolenaar 	    // Function can be replaced with "function!" and when sourcing the
4252ded5f1beSBram Moolenaar 	    // same script again, but only once.
4253eef2102eSBram Moolenaar 	    // A name that is used by an import can not be overruled.
4254eef2102eSBram Moolenaar 	    if (import != NULL
4255eef2102eSBram Moolenaar 		    || (!dead && !eap->forceit
4256ded5f1beSBram Moolenaar 			&& (fp->uf_script_ctx.sc_sid != current_sctx.sc_sid
4257eef2102eSBram Moolenaar 			  || fp->uf_script_ctx.sc_seq == current_sctx.sc_seq)))
4258a9b579f3SBram Moolenaar 	    {
4259*d604d78eSBram Moolenaar 		SOURCING_LNUM = sourcing_lnum_top;
4260eef2102eSBram Moolenaar 		if (vim9script)
42617cb6fc29SBram Moolenaar 		    emsg_funcname(e_name_already_defined_str, name);
4262eef2102eSBram Moolenaar 		else
4263a9b579f3SBram Moolenaar 		    emsg_funcname(e_funcexts, name);
4264a9b579f3SBram Moolenaar 		goto erret;
4265a9b579f3SBram Moolenaar 	    }
4266a9b579f3SBram Moolenaar 	    if (fp->uf_calls > 0)
4267a9b579f3SBram Moolenaar 	    {
4268ded5f1beSBram Moolenaar 		emsg_funcname(
4269ded5f1beSBram Moolenaar 			N_("E127: Cannot redefine function %s: It is in use"),
4270a9b579f3SBram Moolenaar 									name);
4271a9b579f3SBram Moolenaar 		goto erret;
4272a9b579f3SBram Moolenaar 	    }
4273437bafe4SBram Moolenaar 	    if (fp->uf_refcount > 1)
4274437bafe4SBram Moolenaar 	    {
4275e38eab22SBram Moolenaar 		// This function is referenced somewhere, don't redefine it but
4276e38eab22SBram Moolenaar 		// create a new one.
4277437bafe4SBram Moolenaar 		--fp->uf_refcount;
42788dd3a43dSBram Moolenaar 		fp->uf_flags |= FC_REMOVED;
4279437bafe4SBram Moolenaar 		fp = NULL;
4280437bafe4SBram Moolenaar 		overwrite = TRUE;
4281437bafe4SBram Moolenaar 	    }
4282437bafe4SBram Moolenaar 	    else
4283437bafe4SBram Moolenaar 	    {
4284b9adef79SBram Moolenaar 		char_u *exp_name = fp->uf_name_exp;
4285b9adef79SBram Moolenaar 
4286b9adef79SBram Moolenaar 		// redefine existing function, keep the expanded name
4287d23a8236SBram Moolenaar 		VIM_CLEAR(name);
4288b9adef79SBram Moolenaar 		fp->uf_name_exp = NULL;
428979c2ad50SBram Moolenaar 		func_clear_items(fp);
4290b9adef79SBram Moolenaar 		fp->uf_name_exp = exp_name;
42918a7d6542SBram Moolenaar 		fp->uf_flags &= ~FC_DEAD;
429279c2ad50SBram Moolenaar #ifdef FEAT_PROFILE
429379c2ad50SBram Moolenaar 		fp->uf_profiling = FALSE;
429479c2ad50SBram Moolenaar 		fp->uf_prof_initialized = FALSE;
429579c2ad50SBram Moolenaar #endif
4296cdc40c43SBram Moolenaar 		fp->uf_def_status = UF_NOT_COMPILED;
4297a9b579f3SBram Moolenaar 	    }
4298a9b579f3SBram Moolenaar 	}
4299437bafe4SBram Moolenaar     }
4300a9b579f3SBram Moolenaar     else
4301a9b579f3SBram Moolenaar     {
4302a9b579f3SBram Moolenaar 	char	numbuf[20];
4303a9b579f3SBram Moolenaar 
4304a9b579f3SBram Moolenaar 	fp = NULL;
4305a9b579f3SBram Moolenaar 	if (fudi.fd_newkey == NULL && !eap->forceit)
4306a9b579f3SBram Moolenaar 	{
4307f9e3e09fSBram Moolenaar 	    emsg(_(e_funcdict));
4308a9b579f3SBram Moolenaar 	    goto erret;
4309a9b579f3SBram Moolenaar 	}
4310a9b579f3SBram Moolenaar 	if (fudi.fd_di == NULL)
4311a9b579f3SBram Moolenaar 	{
4312e38eab22SBram Moolenaar 	    // Can't add a function to a locked dictionary
4313a187c43cSBram Moolenaar 	    if (value_check_lock(fudi.fd_dict->dv_lock, eap->arg, FALSE))
4314a9b579f3SBram Moolenaar 		goto erret;
4315a9b579f3SBram Moolenaar 	}
4316e38eab22SBram Moolenaar 	    // Can't change an existing function if it is locked
4317a187c43cSBram Moolenaar 	else if (value_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg, FALSE))
4318a9b579f3SBram Moolenaar 	    goto erret;
4319a9b579f3SBram Moolenaar 
4320e38eab22SBram Moolenaar 	// Give the function a sequential number.  Can only be used with a
4321e38eab22SBram Moolenaar 	// Funcref!
4322a9b579f3SBram Moolenaar 	vim_free(name);
4323a9b579f3SBram Moolenaar 	sprintf(numbuf, "%d", ++func_nr);
4324a9b579f3SBram Moolenaar 	name = vim_strsave((char_u *)numbuf);
4325a9b579f3SBram Moolenaar 	if (name == NULL)
4326a9b579f3SBram Moolenaar 	    goto erret;
4327a9b579f3SBram Moolenaar     }
4328a9b579f3SBram Moolenaar 
4329a9b579f3SBram Moolenaar     if (fp == NULL)
4330a9b579f3SBram Moolenaar     {
4331a9b579f3SBram Moolenaar 	if (fudi.fd_dict == NULL && vim_strchr(name, AUTOLOAD_CHAR) != NULL)
4332a9b579f3SBram Moolenaar 	{
4333a9b579f3SBram Moolenaar 	    int	    slen, plen;
4334a9b579f3SBram Moolenaar 	    char_u  *scriptname;
4335a9b579f3SBram Moolenaar 
4336e38eab22SBram Moolenaar 	    // Check that the autoload name matches the script name.
4337a9b579f3SBram Moolenaar 	    j = FAIL;
43381a47ae32SBram Moolenaar 	    if (SOURCING_NAME != NULL)
4339a9b579f3SBram Moolenaar 	    {
4340a9b579f3SBram Moolenaar 		scriptname = autoload_name(name);
4341a9b579f3SBram Moolenaar 		if (scriptname != NULL)
4342a9b579f3SBram Moolenaar 		{
4343a9b579f3SBram Moolenaar 		    p = vim_strchr(scriptname, '/');
4344a9b579f3SBram Moolenaar 		    plen = (int)STRLEN(p);
43451a47ae32SBram Moolenaar 		    slen = (int)STRLEN(SOURCING_NAME);
4346a9b579f3SBram Moolenaar 		    if (slen > plen && fnamecmp(p,
43471a47ae32SBram Moolenaar 					    SOURCING_NAME + slen - plen) == 0)
4348a9b579f3SBram Moolenaar 			j = OK;
4349a9b579f3SBram Moolenaar 		    vim_free(scriptname);
4350a9b579f3SBram Moolenaar 		}
4351a9b579f3SBram Moolenaar 	    }
4352a9b579f3SBram Moolenaar 	    if (j == FAIL)
4353a9b579f3SBram Moolenaar 	    {
4354f48b2fa3SBram Moolenaar 		linenr_T save_lnum = SOURCING_LNUM;
4355f48b2fa3SBram Moolenaar 
4356f48b2fa3SBram Moolenaar 		SOURCING_LNUM = sourcing_lnum_top;
4357f9e3e09fSBram Moolenaar 		semsg(_("E746: Function name does not match script file name: %s"), name);
4358f48b2fa3SBram Moolenaar 		SOURCING_LNUM = save_lnum;
4359a9b579f3SBram Moolenaar 		goto erret;
4360a9b579f3SBram Moolenaar 	    }
4361a9b579f3SBram Moolenaar 	}
4362a9b579f3SBram Moolenaar 
436347ed553fSBram Moolenaar 	fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1);
4364a9b579f3SBram Moolenaar 	if (fp == NULL)
4365a9b579f3SBram Moolenaar 	    goto erret;
4366a9b579f3SBram Moolenaar 
4367a9b579f3SBram Moolenaar 	if (fudi.fd_dict != NULL)
4368a9b579f3SBram Moolenaar 	{
4369a9b579f3SBram Moolenaar 	    if (fudi.fd_di == NULL)
4370a9b579f3SBram Moolenaar 	    {
4371e38eab22SBram Moolenaar 		// add new dict entry
4372a9b579f3SBram Moolenaar 		fudi.fd_di = dictitem_alloc(fudi.fd_newkey);
4373a9b579f3SBram Moolenaar 		if (fudi.fd_di == NULL)
4374a9b579f3SBram Moolenaar 		{
4375a9b579f3SBram Moolenaar 		    vim_free(fp);
4376a14e6975SBram Moolenaar 		    fp = NULL;
4377a9b579f3SBram Moolenaar 		    goto erret;
4378a9b579f3SBram Moolenaar 		}
4379a9b579f3SBram Moolenaar 		if (dict_add(fudi.fd_dict, fudi.fd_di) == FAIL)
4380a9b579f3SBram Moolenaar 		{
4381a9b579f3SBram Moolenaar 		    vim_free(fudi.fd_di);
4382a9b579f3SBram Moolenaar 		    vim_free(fp);
4383a14e6975SBram Moolenaar 		    fp = NULL;
4384a9b579f3SBram Moolenaar 		    goto erret;
4385a9b579f3SBram Moolenaar 		}
4386a9b579f3SBram Moolenaar 	    }
4387a9b579f3SBram Moolenaar 	    else
4388e38eab22SBram Moolenaar 		// overwrite existing dict entry
4389a9b579f3SBram Moolenaar 		clear_tv(&fudi.fd_di->di_tv);
4390a9b579f3SBram Moolenaar 	    fudi.fd_di->di_tv.v_type = VAR_FUNC;
4391a9b579f3SBram Moolenaar 	    fudi.fd_di->di_tv.vval.v_string = vim_strsave(name);
4392a9b579f3SBram Moolenaar 
4393e38eab22SBram Moolenaar 	    // behave like "dict" was used
4394a9b579f3SBram Moolenaar 	    flags |= FC_DICT;
4395a9b579f3SBram Moolenaar 	}
4396a9b579f3SBram Moolenaar 
4397e38eab22SBram Moolenaar 	// insert the new function in the function list
43981a47ae32SBram Moolenaar 	set_ufunc_name(fp, name);
4399437bafe4SBram Moolenaar 	if (overwrite)
4400437bafe4SBram Moolenaar 	{
4401437bafe4SBram Moolenaar 	    hi = hash_find(&func_hashtab, name);
4402437bafe4SBram Moolenaar 	    hi->hi_key = UF2HIKEY(fp);
4403437bafe4SBram Moolenaar 	}
4404437bafe4SBram Moolenaar 	else if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL)
4405a9b579f3SBram Moolenaar 	{
4406a9b579f3SBram Moolenaar 	    vim_free(fp);
4407a14e6975SBram Moolenaar 	    fp = NULL;
4408a9b579f3SBram Moolenaar 	    goto erret;
4409a9b579f3SBram Moolenaar 	}
4410437bafe4SBram Moolenaar 	fp->uf_refcount = 1;
4411a9b579f3SBram Moolenaar     }
4412a9b579f3SBram Moolenaar     fp->uf_args = newargs;
441342ae78cfSBram Moolenaar     fp->uf_def_args = default_args;
44148a7d6542SBram Moolenaar     fp->uf_ret_type = &t_any;
44155deeb3f1SBram Moolenaar     fp->uf_func_type = &t_func_any;
44168a7d6542SBram Moolenaar 
44178a7d6542SBram Moolenaar     if (eap->cmdidx == CMD_def)
44188a7d6542SBram Moolenaar     {
4419bfe12043SBram Moolenaar 	int	    lnum_save = SOURCING_LNUM;
442039ca4127SBram Moolenaar 	cstack_T    *cstack = eap->cstack;
4421bfe12043SBram Moolenaar 
44220cb5bcf5SBram Moolenaar 	fp->uf_def_status = UF_TO_BE_COMPILED;
4423822ba247SBram Moolenaar 
4424bfe12043SBram Moolenaar 	// error messages are for the first function line
4425bfe12043SBram Moolenaar 	SOURCING_LNUM = sourcing_lnum_top;
4426bfe12043SBram Moolenaar 
44272eb6fc3bSBram Moolenaar 	// The function may use script variables from the context.
44282eb6fc3bSBram Moolenaar 	function_using_block_scopes(fp, cstack);
4429fbbcd003SBram Moolenaar 
4430b4d16cb1SBram Moolenaar 	if (parse_argument_types(fp, &argtypes, varargs) == FAIL)
4431bfe12043SBram Moolenaar 	{
4432bfe12043SBram Moolenaar 	    SOURCING_LNUM = lnum_save;
4433bfe12043SBram Moolenaar 	    goto errret_2;
4434bfe12043SBram Moolenaar 	}
44358a7d6542SBram Moolenaar 	varargs = FALSE;
44368a7d6542SBram Moolenaar 
44378a7d6542SBram Moolenaar 	// parse the return type, if any
44387a6eaa06SBram Moolenaar 	if (parse_return_type(fp, ret_type) == FAIL)
44398a7d6542SBram Moolenaar 	{
4440648ea76eSBram Moolenaar 	    SOURCING_LNUM = lnum_save;
4441648ea76eSBram Moolenaar 	    goto erret;
4442648ea76eSBram Moolenaar 	}
444309689a02SBram Moolenaar 	SOURCING_LNUM = lnum_save;
44448a7d6542SBram Moolenaar     }
4445822ba247SBram Moolenaar     else
44460cb5bcf5SBram Moolenaar 	fp->uf_def_status = UF_NOT_COMPILED;
44478a7d6542SBram Moolenaar 
4448a9b579f3SBram Moolenaar     fp->uf_lines = newlines;
444910ce39a0SBram Moolenaar     if ((flags & FC_CLOSURE) != 0)
445010ce39a0SBram Moolenaar     {
445158016448SBram Moolenaar 	if (register_closure(fp) == FAIL)
445210ce39a0SBram Moolenaar 	    goto erret;
445310ce39a0SBram Moolenaar     }
445410ce39a0SBram Moolenaar     else
44551e96d9bfSBram Moolenaar 	fp->uf_scoped = NULL;
445610ce39a0SBram Moolenaar 
4457a9b579f3SBram Moolenaar #ifdef FEAT_PROFILE
4458a9b579f3SBram Moolenaar     if (prof_def_func())
4459a9b579f3SBram Moolenaar 	func_do_profile(fp);
4460a9b579f3SBram Moolenaar #endif
4461a9b579f3SBram Moolenaar     fp->uf_varargs = varargs;
446293343725SBram Moolenaar     if (sandbox)
446393343725SBram Moolenaar 	flags |= FC_SANDBOX;
4464e7e4838fSBram Moolenaar     if (vim9script && !ASCII_ISUPPER(*fp->uf_name))
44654c17ad94SBram Moolenaar 	flags |= FC_VIM9;
4466a9b579f3SBram Moolenaar     fp->uf_flags = flags;
4467a9b579f3SBram Moolenaar     fp->uf_calls = 0;
446863ce4849SBram Moolenaar     fp->uf_cleared = FALSE;
4469f29c1c6aSBram Moolenaar     fp->uf_script_ctx = current_sctx;
4470f9b2b496SBram Moolenaar     fp->uf_script_ctx_version = current_sctx.sc_version;
4471bc2cfe46SBram Moolenaar     fp->uf_script_ctx.sc_lnum += sourcing_lnum_top;
44728a7d6542SBram Moolenaar     if (is_export)
44738a7d6542SBram Moolenaar     {
44748a7d6542SBram Moolenaar 	fp->uf_flags |= FC_EXPORT;
44758a7d6542SBram Moolenaar 	// let ex_export() know the export worked.
44768a7d6542SBram Moolenaar 	is_export = FALSE;
44778a7d6542SBram Moolenaar     }
44788a7d6542SBram Moolenaar 
44796ff71d8bSBram Moolenaar     if (eap->cmdidx == CMD_def)
44806ff71d8bSBram Moolenaar 	set_function_type(fp);
44816797966dSBram Moolenaar     else if (fp->uf_script_ctx.sc_version == SCRIPT_VERSION_VIM9)
44826797966dSBram Moolenaar 	// :func does not use Vim9 script syntax, even in a Vim9 script file
44836797966dSBram Moolenaar 	fp->uf_script_ctx.sc_version = SCRIPT_VERSION_MAX;
44846ff71d8bSBram Moolenaar 
4485a9b579f3SBram Moolenaar     goto ret_free;
4486a9b579f3SBram Moolenaar 
4487a9b579f3SBram Moolenaar erret:
4488a9b579f3SBram Moolenaar     ga_clear_strings(&newargs);
448942ae78cfSBram Moolenaar     ga_clear_strings(&default_args);
449031842cd0SBram Moolenaar     if (fp != NULL)
449131842cd0SBram Moolenaar     {
449231842cd0SBram Moolenaar 	ga_init(&fp->uf_args);
449331842cd0SBram Moolenaar 	ga_init(&fp->uf_def_args);
449431842cd0SBram Moolenaar     }
4495a9b579f3SBram Moolenaar errret_2:
4496a9b579f3SBram Moolenaar     ga_clear_strings(&newlines);
449731842cd0SBram Moolenaar     if (fp != NULL)
449831842cd0SBram Moolenaar 	VIM_CLEAR(fp->uf_arg_types);
4499a9b579f3SBram Moolenaar ret_free:
4500292b90d4SBram Moolenaar     ga_clear_strings(&argtypes);
450153564f7cSBram Moolenaar     vim_free(line_to_free);
4502a9b579f3SBram Moolenaar     vim_free(fudi.fd_newkey);
450304b12697SBram Moolenaar     if (name != name_arg)
4504a9b579f3SBram Moolenaar 	vim_free(name);
45055e774c75SBram Moolenaar     vim_free(ret_type);
4506a9b579f3SBram Moolenaar     did_emsg |= saved_did_emsg;
450704b12697SBram Moolenaar 
450804b12697SBram Moolenaar     return fp;
450904b12697SBram Moolenaar }
451004b12697SBram Moolenaar 
451104b12697SBram Moolenaar /*
451204b12697SBram Moolenaar  * ":function"
451304b12697SBram Moolenaar  */
451404b12697SBram Moolenaar     void
ex_function(exarg_T * eap)451504b12697SBram Moolenaar ex_function(exarg_T *eap)
451604b12697SBram Moolenaar {
4517fbbcd003SBram Moolenaar     (void)define_function(eap, NULL);
4518822ba247SBram Moolenaar }
4519822ba247SBram Moolenaar 
4520822ba247SBram Moolenaar /*
452196f8f499SBram Moolenaar  * :defcompile - compile all :def functions in the current script that need to
4522b2049903SBram Moolenaar  * be compiled.  Except dead functions.  Doesn't do profiling.
4523822ba247SBram Moolenaar  */
4524822ba247SBram Moolenaar     void
ex_defcompile(exarg_T * eap UNUSED)4525822ba247SBram Moolenaar ex_defcompile(exarg_T *eap UNUSED)
4526822ba247SBram Moolenaar {
45277ce85be6SBram Moolenaar     long	todo = (long)func_hashtab.ht_used;
45287ce85be6SBram Moolenaar     int		changed = func_hashtab.ht_changed;
4529822ba247SBram Moolenaar     hashitem_T	*hi;
4530822ba247SBram Moolenaar     ufunc_T	*ufunc;
4531822ba247SBram Moolenaar 
4532822ba247SBram Moolenaar     for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
4533822ba247SBram Moolenaar     {
4534822ba247SBram Moolenaar 	if (!HASHITEM_EMPTY(hi))
4535822ba247SBram Moolenaar 	{
4536822ba247SBram Moolenaar 	    --todo;
4537822ba247SBram Moolenaar 	    ufunc = HI2UF(hi);
4538822ba247SBram Moolenaar 	    if (ufunc->uf_script_ctx.sc_sid == current_sctx.sc_sid
453996f8f499SBram Moolenaar 		    && ufunc->uf_def_status == UF_TO_BE_COMPILED
454096f8f499SBram Moolenaar 		    && (ufunc->uf_flags & FC_DEAD) == 0)
4541ebc3de63SBram Moolenaar 	    {
4542e99d422bSBram Moolenaar 		(void)compile_def_function(ufunc, FALSE, CT_NONE, NULL);
4543ebc3de63SBram Moolenaar 
45447ce85be6SBram Moolenaar 		if (func_hashtab.ht_changed != changed)
4545ebc3de63SBram Moolenaar 		{
45467ce85be6SBram Moolenaar 		    // a function has been added or removed, need to start over
45477ce85be6SBram Moolenaar 		    todo = (long)func_hashtab.ht_used;
45487ce85be6SBram Moolenaar 		    changed = func_hashtab.ht_changed;
4549ebc3de63SBram Moolenaar 		    hi = func_hashtab.ht_array;
4550285b1892SBram Moolenaar 		    --hi;
4551ebc3de63SBram Moolenaar 		}
4552ebc3de63SBram Moolenaar 	    }
4553822ba247SBram Moolenaar 	}
4554822ba247SBram Moolenaar     }
4555a9b579f3SBram Moolenaar }
4556a9b579f3SBram Moolenaar 
4557a9b579f3SBram Moolenaar /*
4558a9b579f3SBram Moolenaar  * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case).
4559a9b579f3SBram Moolenaar  * Return 2 if "p" starts with "s:".
4560a9b579f3SBram Moolenaar  * Return 0 otherwise.
4561a9b579f3SBram Moolenaar  */
4562a9b579f3SBram Moolenaar     int
eval_fname_script(char_u * p)4563a9b579f3SBram Moolenaar eval_fname_script(char_u *p)
4564a9b579f3SBram Moolenaar {
4565e38eab22SBram Moolenaar     // Use MB_STRICMP() because in Turkish comparing the "I" may not work with
4566e38eab22SBram Moolenaar     // the standard library function.
4567a9b579f3SBram Moolenaar     if (p[0] == '<' && (MB_STRNICMP(p + 1, "SID>", 4) == 0
4568a9b579f3SBram Moolenaar 				       || MB_STRNICMP(p + 1, "SNR>", 4) == 0))
4569a9b579f3SBram Moolenaar 	return 5;
4570a9b579f3SBram Moolenaar     if (p[0] == 's' && p[1] == ':')
4571a9b579f3SBram Moolenaar 	return 2;
4572a9b579f3SBram Moolenaar     return 0;
4573a9b579f3SBram Moolenaar }
4574a9b579f3SBram Moolenaar 
4575a9b579f3SBram Moolenaar     int
translated_function_exists(char_u * name,int is_global)45764c17ad94SBram Moolenaar translated_function_exists(char_u *name, int is_global)
4577a9b579f3SBram Moolenaar {
4578a9b579f3SBram Moolenaar     if (builtin_function(name, -1))
4579ac92e25aSBram Moolenaar 	return has_internal_func(name);
45804c17ad94SBram Moolenaar     return find_func(name, is_global, NULL) != NULL;
45818a7d6542SBram Moolenaar }
45828a7d6542SBram Moolenaar 
45838a7d6542SBram Moolenaar /*
45848a7d6542SBram Moolenaar  * Return TRUE when "ufunc" has old-style "..." varargs
45858a7d6542SBram Moolenaar  * or named varargs "...name: type".
45868a7d6542SBram Moolenaar  */
45878a7d6542SBram Moolenaar     int
has_varargs(ufunc_T * ufunc)45888a7d6542SBram Moolenaar has_varargs(ufunc_T *ufunc)
45898a7d6542SBram Moolenaar {
45908a7d6542SBram Moolenaar     return ufunc->uf_varargs || ufunc->uf_va_name != NULL;
4591a9b579f3SBram Moolenaar }
4592a9b579f3SBram Moolenaar 
4593a9b579f3SBram Moolenaar /*
4594a9b579f3SBram Moolenaar  * Return TRUE if a function "name" exists.
4595b54c3ff3SBram Moolenaar  * If "no_defef" is TRUE, do not dereference a Funcref.
4596a9b579f3SBram Moolenaar  */
4597a9b579f3SBram Moolenaar     int
function_exists(char_u * name,int no_deref)4598b54c3ff3SBram Moolenaar function_exists(char_u *name, int no_deref)
4599a9b579f3SBram Moolenaar {
4600a9b579f3SBram Moolenaar     char_u  *nm = name;
4601a9b579f3SBram Moolenaar     char_u  *p;
4602a9b579f3SBram Moolenaar     int	    n = FALSE;
4603b54c3ff3SBram Moolenaar     int	    flag;
46044c17ad94SBram Moolenaar     int	    is_global = FALSE;
4605a9b579f3SBram Moolenaar 
4606b54c3ff3SBram Moolenaar     flag = TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD;
4607b54c3ff3SBram Moolenaar     if (no_deref)
4608b54c3ff3SBram Moolenaar 	flag |= TFN_NO_DEREF;
460932b3f820SBram Moolenaar     p = trans_function_name(&nm, &is_global, FALSE, flag, NULL, NULL, NULL);
4610a9b579f3SBram Moolenaar     nm = skipwhite(nm);
4611a9b579f3SBram Moolenaar 
4612e38eab22SBram Moolenaar     // Only accept "funcname", "funcname ", "funcname (..." and
4613e38eab22SBram Moolenaar     // "funcname(...", not "funcname!...".
4614a9b579f3SBram Moolenaar     if (p != NULL && (*nm == NUL || *nm == '('))
46154c17ad94SBram Moolenaar 	n = translated_function_exists(p, is_global);
4616a9b579f3SBram Moolenaar     vim_free(p);
4617a9b579f3SBram Moolenaar     return n;
4618a9b579f3SBram Moolenaar }
4619a9b579f3SBram Moolenaar 
4620113e1072SBram Moolenaar #if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) || defined(PROTO)
4621a9b579f3SBram Moolenaar     char_u *
get_expanded_name(char_u * name,int check)4622a9b579f3SBram Moolenaar get_expanded_name(char_u *name, int check)
4623a9b579f3SBram Moolenaar {
4624a9b579f3SBram Moolenaar     char_u	*nm = name;
4625a9b579f3SBram Moolenaar     char_u	*p;
46264c17ad94SBram Moolenaar     int		is_global = FALSE;
4627a9b579f3SBram Moolenaar 
46284c17ad94SBram Moolenaar     p = trans_function_name(&nm, &is_global, FALSE,
462932b3f820SBram Moolenaar 					  TFN_INT|TFN_QUIET, NULL, NULL, NULL);
4630a9b579f3SBram Moolenaar 
46314c17ad94SBram Moolenaar     if (p != NULL && *nm == NUL
46324c17ad94SBram Moolenaar 		       && (!check || translated_function_exists(p, is_global)))
4633a9b579f3SBram Moolenaar 	return p;
4634a9b579f3SBram Moolenaar 
4635a9b579f3SBram Moolenaar     vim_free(p);
4636a9b579f3SBram Moolenaar     return NULL;
4637a9b579f3SBram Moolenaar }
4638113e1072SBram Moolenaar #endif
4639a9b579f3SBram Moolenaar 
4640a9b579f3SBram Moolenaar /*
4641a9b579f3SBram Moolenaar  * Function given to ExpandGeneric() to obtain the list of user defined
4642a9b579f3SBram Moolenaar  * function names.
4643a9b579f3SBram Moolenaar  */
4644a9b579f3SBram Moolenaar     char_u *
get_user_func_name(expand_T * xp,int idx)4645a9b579f3SBram Moolenaar get_user_func_name(expand_T *xp, int idx)
4646a9b579f3SBram Moolenaar {
4647a9b579f3SBram Moolenaar     static long_u	done;
46481f22cc5cSBram Moolenaar     static int		changed;
4649a9b579f3SBram Moolenaar     static hashitem_T	*hi;
4650a9b579f3SBram Moolenaar     ufunc_T		*fp;
4651a9b579f3SBram Moolenaar 
4652a9b579f3SBram Moolenaar     if (idx == 0)
4653a9b579f3SBram Moolenaar     {
4654a9b579f3SBram Moolenaar 	done = 0;
4655a9b579f3SBram Moolenaar 	hi = func_hashtab.ht_array;
46561f22cc5cSBram Moolenaar 	changed = func_hashtab.ht_changed;
4657a9b579f3SBram Moolenaar     }
46581f22cc5cSBram Moolenaar     if (changed == func_hashtab.ht_changed && done < func_hashtab.ht_used)
4659a9b579f3SBram Moolenaar     {
4660a9b579f3SBram Moolenaar 	if (done++ > 0)
4661a9b579f3SBram Moolenaar 	    ++hi;
4662a9b579f3SBram Moolenaar 	while (HASHITEM_EMPTY(hi))
4663a9b579f3SBram Moolenaar 	    ++hi;
4664a9b579f3SBram Moolenaar 	fp = HI2UF(hi);
4665a9b579f3SBram Moolenaar 
46668a7d6542SBram Moolenaar 	// don't show dead, dict and lambda functions
46678a7d6542SBram Moolenaar 	if ((fp->uf_flags & FC_DEAD) || (fp->uf_flags & FC_DICT)
4668b49edc11SBram Moolenaar 				|| STRNCMP(fp->uf_name, "<lambda>", 8) == 0)
46698a7d6542SBram Moolenaar 	    return (char_u *)"";
4670a9b579f3SBram Moolenaar 
4671a9b579f3SBram Moolenaar 	if (STRLEN(fp->uf_name) + 4 >= IOSIZE)
4672e38eab22SBram Moolenaar 	    return fp->uf_name;	// prevents overflow
4673a9b579f3SBram Moolenaar 
4674a9b579f3SBram Moolenaar 	cat_func_name(IObuff, fp);
46759aecf79cSnaohiro ono 	if (xp->xp_context != EXPAND_USER_FUNC
46769aecf79cSnaohiro ono 				       && xp->xp_context != EXPAND_DISASSEMBLE)
4677a9b579f3SBram Moolenaar 	{
4678a9b579f3SBram Moolenaar 	    STRCAT(IObuff, "(");
46798a7d6542SBram Moolenaar 	    if (!has_varargs(fp) && fp->uf_args.ga_len == 0)
4680a9b579f3SBram Moolenaar 		STRCAT(IObuff, ")");
4681a9b579f3SBram Moolenaar 	}
4682a9b579f3SBram Moolenaar 	return IObuff;
4683a9b579f3SBram Moolenaar     }
4684a9b579f3SBram Moolenaar     return NULL;
4685a9b579f3SBram Moolenaar }
4686a9b579f3SBram Moolenaar 
4687a9b579f3SBram Moolenaar /*
4688a9b579f3SBram Moolenaar  * ":delfunction {name}"
4689a9b579f3SBram Moolenaar  */
4690a9b579f3SBram Moolenaar     void
ex_delfunction(exarg_T * eap)4691a9b579f3SBram Moolenaar ex_delfunction(exarg_T *eap)
4692a9b579f3SBram Moolenaar {
4693a9b579f3SBram Moolenaar     ufunc_T	*fp = NULL;
4694a9b579f3SBram Moolenaar     char_u	*p;
4695a9b579f3SBram Moolenaar     char_u	*name;
4696a9b579f3SBram Moolenaar     funcdict_T	fudi;
46974c17ad94SBram Moolenaar     int		is_global = FALSE;
4698a9b579f3SBram Moolenaar 
4699a9b579f3SBram Moolenaar     p = eap->arg;
470032b3f820SBram Moolenaar     name = trans_function_name(&p, &is_global, eap->skip, 0, &fudi,
470132b3f820SBram Moolenaar 								   NULL, NULL);
4702a9b579f3SBram Moolenaar     vim_free(fudi.fd_newkey);
4703a9b579f3SBram Moolenaar     if (name == NULL)
4704a9b579f3SBram Moolenaar     {
4705a9b579f3SBram Moolenaar 	if (fudi.fd_dict != NULL && !eap->skip)
4706f9e3e09fSBram Moolenaar 	    emsg(_(e_funcref));
4707a9b579f3SBram Moolenaar 	return;
4708a9b579f3SBram Moolenaar     }
4709a9b579f3SBram Moolenaar     if (!ends_excmd(*skipwhite(p)))
4710a9b579f3SBram Moolenaar     {
4711a9b579f3SBram Moolenaar 	vim_free(name);
47122d06bfdeSBram Moolenaar 	semsg(_(e_trailing_arg), p);
4713a9b579f3SBram Moolenaar 	return;
4714a9b579f3SBram Moolenaar     }
471563b91736SBram Moolenaar     set_nextcmd(eap, p);
4716a9b579f3SBram Moolenaar     if (eap->nextcmd != NULL)
4717a9b579f3SBram Moolenaar 	*p = NUL;
4718a9b579f3SBram Moolenaar 
4719ddfc0510SBram Moolenaar     if (isdigit(*name) && fudi.fd_dict == NULL)
4720ddfc0510SBram Moolenaar     {
4721ddfc0510SBram Moolenaar 	if (!eap->skip)
4722ddfc0510SBram Moolenaar 	    semsg(_(e_invarg2), eap->arg);
4723ddfc0510SBram Moolenaar 	vim_free(name);
4724ddfc0510SBram Moolenaar 	return;
4725ddfc0510SBram Moolenaar     }
4726a9b579f3SBram Moolenaar     if (!eap->skip)
47274c17ad94SBram Moolenaar 	fp = find_func(name, is_global, NULL);
4728a9b579f3SBram Moolenaar     vim_free(name);
4729a9b579f3SBram Moolenaar 
4730a9b579f3SBram Moolenaar     if (!eap->skip)
4731a9b579f3SBram Moolenaar     {
4732a9b579f3SBram Moolenaar 	if (fp == NULL)
4733a9b579f3SBram Moolenaar 	{
4734d6abcd15SBram Moolenaar 	    if (!eap->forceit)
4735f9e3e09fSBram Moolenaar 		semsg(_(e_nofunc), eap->arg);
4736a9b579f3SBram Moolenaar 	    return;
4737a9b579f3SBram Moolenaar 	}
4738a9b579f3SBram Moolenaar 	if (fp->uf_calls > 0)
4739a9b579f3SBram Moolenaar 	{
4740f9e3e09fSBram Moolenaar 	    semsg(_("E131: Cannot delete function %s: It is in use"), eap->arg);
4741a9b579f3SBram Moolenaar 	    return;
4742a9b579f3SBram Moolenaar 	}
47434c17ad94SBram Moolenaar 	if (fp->uf_flags & FC_VIM9)
47444c17ad94SBram Moolenaar 	{
4745451c2e35SBram Moolenaar 	    semsg(_(e_cannot_delete_vim9_script_function_str), eap->arg);
47464c17ad94SBram Moolenaar 	    return;
47474c17ad94SBram Moolenaar 	}
4748a9b579f3SBram Moolenaar 
4749a9b579f3SBram Moolenaar 	if (fudi.fd_dict != NULL)
4750a9b579f3SBram Moolenaar 	{
4751e38eab22SBram Moolenaar 	    // Delete the dict item that refers to the function, it will
4752e38eab22SBram Moolenaar 	    // invoke func_unref() and possibly delete the function.
4753a9b579f3SBram Moolenaar 	    dictitem_remove(fudi.fd_dict, fudi.fd_di);
4754a9b579f3SBram Moolenaar 	}
4755a9b579f3SBram Moolenaar 	else
4756437bafe4SBram Moolenaar 	{
4757e38eab22SBram Moolenaar 	    // A normal function (not a numbered function or lambda) has a
4758e38eab22SBram Moolenaar 	    // refcount of 1 for the entry in the hashtable.  When deleting
4759e38eab22SBram Moolenaar 	    // it and the refcount is more than one, it should be kept.
4760e38eab22SBram Moolenaar 	    // A numbered function and lambda should be kept if the refcount is
4761e38eab22SBram Moolenaar 	    // one or more.
47628dd3a43dSBram Moolenaar 	    if (fp->uf_refcount > (func_name_refcount(fp->uf_name) ? 0 : 1))
4763437bafe4SBram Moolenaar 	    {
4764e38eab22SBram Moolenaar 		// Function is still referenced somewhere.  Don't free it but
4765e38eab22SBram Moolenaar 		// do remove it from the hashtable.
47668dd3a43dSBram Moolenaar 		if (func_remove(fp))
4767437bafe4SBram Moolenaar 		    fp->uf_refcount--;
4768437bafe4SBram Moolenaar 	    }
4769437bafe4SBram Moolenaar 	    else
477003ff9bcbSBram Moolenaar 		func_clear_free(fp, FALSE);
4771a9b579f3SBram Moolenaar 	}
4772a9b579f3SBram Moolenaar     }
4773437bafe4SBram Moolenaar }
4774a9b579f3SBram Moolenaar 
4775a9b579f3SBram Moolenaar /*
4776a9b579f3SBram Moolenaar  * Unreference a Function: decrement the reference count and free it when it
4777437bafe4SBram Moolenaar  * becomes zero.
4778a9b579f3SBram Moolenaar  */
4779a9b579f3SBram Moolenaar     void
func_unref(char_u * name)4780a9b579f3SBram Moolenaar func_unref(char_u *name)
4781a9b579f3SBram Moolenaar {
478297baee80SBram Moolenaar     ufunc_T *fp = NULL;
4783a9b579f3SBram Moolenaar 
47848dd3a43dSBram Moolenaar     if (name == NULL || !func_name_refcount(name))
4785a9b579f3SBram Moolenaar 	return;
47864c17ad94SBram Moolenaar     fp = find_func(name, FALSE, NULL);
4787437bafe4SBram Moolenaar     if (fp == NULL && isdigit(*name))
4788a9b579f3SBram Moolenaar     {
4789a9b579f3SBram Moolenaar #ifdef EXITFREE
4790a9b579f3SBram Moolenaar 	if (!entered_free_all_mem)
4791a9b579f3SBram Moolenaar #endif
479295f09603SBram Moolenaar 	    internal_error("func_unref()");
4793a9b579f3SBram Moolenaar     }
47940d3de8cbSBram Moolenaar     func_ptr_unref(fp);
4795437bafe4SBram Moolenaar }
4796437bafe4SBram Moolenaar 
4797437bafe4SBram Moolenaar /*
4798437bafe4SBram Moolenaar  * Unreference a Function: decrement the reference count and free it when it
4799437bafe4SBram Moolenaar  * becomes zero.
48000d3de8cbSBram Moolenaar  * Also when it becomes one and uf_partial points to the function.
4801437bafe4SBram Moolenaar  */
4802437bafe4SBram Moolenaar     void
func_ptr_unref(ufunc_T * fp)4803437bafe4SBram Moolenaar func_ptr_unref(ufunc_T *fp)
4804437bafe4SBram Moolenaar {
48050d3de8cbSBram Moolenaar     if (fp != NULL && (--fp->uf_refcount <= 0
48060d3de8cbSBram Moolenaar 		|| (fp->uf_refcount == 1 && fp->uf_partial != NULL
48070d3de8cbSBram Moolenaar 					 && fp->uf_partial->pt_refcount <= 1
48080d3de8cbSBram Moolenaar 					 && fp->uf_partial->pt_func == fp)))
4809a9b579f3SBram Moolenaar     {
4810e38eab22SBram Moolenaar 	// Only delete it when it's not being used.  Otherwise it's done
4811e38eab22SBram Moolenaar 	// when "uf_calls" becomes zero.
4812a9b579f3SBram Moolenaar 	if (fp->uf_calls == 0)
481303ff9bcbSBram Moolenaar 	    func_clear_free(fp, FALSE);
4814a9b579f3SBram Moolenaar     }
4815a9b579f3SBram Moolenaar }
4816a9b579f3SBram Moolenaar 
4817a9b579f3SBram Moolenaar /*
4818a9b579f3SBram Moolenaar  * Count a reference to a Function.
4819a9b579f3SBram Moolenaar  */
4820a9b579f3SBram Moolenaar     void
func_ref(char_u * name)4821a9b579f3SBram Moolenaar func_ref(char_u *name)
4822a9b579f3SBram Moolenaar {
4823a9b579f3SBram Moolenaar     ufunc_T *fp;
4824a9b579f3SBram Moolenaar 
48258dd3a43dSBram Moolenaar     if (name == NULL || !func_name_refcount(name))
4826a9b579f3SBram Moolenaar 	return;
48274c17ad94SBram Moolenaar     fp = find_func(name, FALSE, NULL);
4828a9b579f3SBram Moolenaar     if (fp != NULL)
4829a9b579f3SBram Moolenaar 	++fp->uf_refcount;
4830437bafe4SBram Moolenaar     else if (isdigit(*name))
4831e38eab22SBram Moolenaar 	// Only give an error for a numbered function.
4832e38eab22SBram Moolenaar 	// Fail silently, when named or lambda function isn't found.
483395f09603SBram Moolenaar 	internal_error("func_ref()");
4834a9b579f3SBram Moolenaar }
4835437bafe4SBram Moolenaar 
4836437bafe4SBram Moolenaar /*
4837437bafe4SBram Moolenaar  * Count a reference to a Function.
4838437bafe4SBram Moolenaar  */
4839437bafe4SBram Moolenaar     void
func_ptr_ref(ufunc_T * fp)4840437bafe4SBram Moolenaar func_ptr_ref(ufunc_T *fp)
4841437bafe4SBram Moolenaar {
4842437bafe4SBram Moolenaar     if (fp != NULL)
4843437bafe4SBram Moolenaar 	++fp->uf_refcount;
4844a9b579f3SBram Moolenaar }
4845a9b579f3SBram Moolenaar 
4846a9b579f3SBram Moolenaar /*
4847a9b579f3SBram Moolenaar  * Return TRUE if items in "fc" do not have "copyID".  That means they are not
4848a9b579f3SBram Moolenaar  * referenced from anywhere that is in use.
4849a9b579f3SBram Moolenaar  */
4850a9b579f3SBram Moolenaar     static int
can_free_funccal(funccall_T * fc,int copyID)4851a9b579f3SBram Moolenaar can_free_funccal(funccall_T *fc, int copyID)
4852a9b579f3SBram Moolenaar {
4853a9b579f3SBram Moolenaar     return (fc->l_varlist.lv_copyID != copyID
4854a9b579f3SBram Moolenaar 	    && fc->l_vars.dv_copyID != copyID
48551e96d9bfSBram Moolenaar 	    && fc->l_avars.dv_copyID != copyID
48561e96d9bfSBram Moolenaar 	    && fc->fc_copyID != copyID);
4857a9b579f3SBram Moolenaar }
4858a9b579f3SBram Moolenaar 
4859a9b579f3SBram Moolenaar /*
4860a9b579f3SBram Moolenaar  * ":return [expr]"
4861a9b579f3SBram Moolenaar  */
4862a9b579f3SBram Moolenaar     void
ex_return(exarg_T * eap)4863a9b579f3SBram Moolenaar ex_return(exarg_T *eap)
4864a9b579f3SBram Moolenaar {
4865a9b579f3SBram Moolenaar     char_u	*arg = eap->arg;
4866a9b579f3SBram Moolenaar     typval_T	rettv;
4867a9b579f3SBram Moolenaar     int		returning = FALSE;
48685409f5d8SBram Moolenaar     evalarg_T	evalarg;
4869a9b579f3SBram Moolenaar 
4870a9b579f3SBram Moolenaar     if (current_funccal == NULL)
4871a9b579f3SBram Moolenaar     {
4872f9e3e09fSBram Moolenaar 	emsg(_("E133: :return not inside a function"));
4873a9b579f3SBram Moolenaar 	return;
4874a9b579f3SBram Moolenaar     }
4875a9b579f3SBram Moolenaar 
4876844fb64aSBram Moolenaar     init_evalarg(&evalarg);
48775409f5d8SBram Moolenaar     evalarg.eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
48785409f5d8SBram Moolenaar 
4879a9b579f3SBram Moolenaar     if (eap->skip)
4880a9b579f3SBram Moolenaar 	++emsg_skip;
4881a9b579f3SBram Moolenaar 
4882a9b579f3SBram Moolenaar     eap->nextcmd = NULL;
4883a9b579f3SBram Moolenaar     if ((*arg != NUL && *arg != '|' && *arg != '\n')
4884b171fb17SBram Moolenaar 				  && eval0(arg, &rettv, eap, &evalarg) != FAIL)
4885a9b579f3SBram Moolenaar     {
4886a9b579f3SBram Moolenaar 	if (!eap->skip)
4887a9b579f3SBram Moolenaar 	    returning = do_return(eap, FALSE, TRUE, &rettv);
4888a9b579f3SBram Moolenaar 	else
4889a9b579f3SBram Moolenaar 	    clear_tv(&rettv);
4890a9b579f3SBram Moolenaar     }
4891e38eab22SBram Moolenaar     // It's safer to return also on error.
4892a9b579f3SBram Moolenaar     else if (!eap->skip)
4893a9b579f3SBram Moolenaar     {
4894e38eab22SBram Moolenaar 	// In return statement, cause_abort should be force_abort.
4895fabaf753SBram Moolenaar 	update_force_abort();
4896fabaf753SBram Moolenaar 
4897a9b579f3SBram Moolenaar 	/*
4898a9b579f3SBram Moolenaar 	 * Return unless the expression evaluation has been cancelled due to an
4899a9b579f3SBram Moolenaar 	 * aborting error, an interrupt, or an exception.
4900a9b579f3SBram Moolenaar 	 */
4901a9b579f3SBram Moolenaar 	if (!aborting())
4902a9b579f3SBram Moolenaar 	    returning = do_return(eap, FALSE, TRUE, NULL);
4903a9b579f3SBram Moolenaar     }
4904a9b579f3SBram Moolenaar 
4905e38eab22SBram Moolenaar     // When skipping or the return gets pending, advance to the next command
4906e38eab22SBram Moolenaar     // in this line (!returning).  Otherwise, ignore the rest of the line.
4907e38eab22SBram Moolenaar     // Following lines will be ignored by get_func_line().
4908a9b579f3SBram Moolenaar     if (returning)
4909a9b579f3SBram Moolenaar 	eap->nextcmd = NULL;
4910e38eab22SBram Moolenaar     else if (eap->nextcmd == NULL)	    // no argument
491163b91736SBram Moolenaar 	set_nextcmd(eap, arg);
4912a9b579f3SBram Moolenaar 
4913a9b579f3SBram Moolenaar     if (eap->skip)
4914a9b579f3SBram Moolenaar 	--emsg_skip;
4915b7a78f7aSBram Moolenaar     clear_evalarg(&evalarg, eap);
4916a9b579f3SBram Moolenaar }
4917a9b579f3SBram Moolenaar 
4918a9b579f3SBram Moolenaar /*
4919a9b579f3SBram Moolenaar  * ":1,25call func(arg1, arg2)"	function call.
4920a9b579f3SBram Moolenaar  */
4921a9b579f3SBram Moolenaar     void
ex_call(exarg_T * eap)4922a9b579f3SBram Moolenaar ex_call(exarg_T *eap)
4923a9b579f3SBram Moolenaar {
4924a9b579f3SBram Moolenaar     char_u	*arg = eap->arg;
4925a9b579f3SBram Moolenaar     char_u	*startarg;
4926a9b579f3SBram Moolenaar     char_u	*name;
4927a9b579f3SBram Moolenaar     char_u	*tofree;
4928a9b579f3SBram Moolenaar     int		len;
4929a9b579f3SBram Moolenaar     typval_T	rettv;
4930a9b579f3SBram Moolenaar     linenr_T	lnum;
4931a9b579f3SBram Moolenaar     int		doesrange;
4932a9b579f3SBram Moolenaar     int		failed = FALSE;
4933a9b579f3SBram Moolenaar     funcdict_T	fudi;
4934a9b579f3SBram Moolenaar     partial_T	*partial = NULL;
4935e6b5324eSBram Moolenaar     evalarg_T	evalarg;
493632b3f820SBram Moolenaar     type_T	*type = NULL;
4937a9b579f3SBram Moolenaar 
4938e6b5324eSBram Moolenaar     fill_evalarg_from_eap(&evalarg, eap, eap->skip);
4939a9b579f3SBram Moolenaar     if (eap->skip)
4940a9b579f3SBram Moolenaar     {
4941e38eab22SBram Moolenaar 	// trans_function_name() doesn't work well when skipping, use eval0()
4942e38eab22SBram Moolenaar 	// instead to skip to any following command, e.g. for:
4943e38eab22SBram Moolenaar 	//   :if 0 | call dict.foo().bar() | endif
4944a9b579f3SBram Moolenaar 	++emsg_skip;
4945e6b5324eSBram Moolenaar 	if (eval0(eap->arg, &rettv, eap, &evalarg) != FAIL)
4946a9b579f3SBram Moolenaar 	    clear_tv(&rettv);
4947a9b579f3SBram Moolenaar 	--emsg_skip;
4948e6b5324eSBram Moolenaar 	clear_evalarg(&evalarg, eap);
4949a9b579f3SBram Moolenaar 	return;
4950a9b579f3SBram Moolenaar     }
4951a9b579f3SBram Moolenaar 
495232b3f820SBram Moolenaar     tofree = trans_function_name(&arg, NULL, eap->skip, TFN_INT,
495332b3f820SBram Moolenaar 			      &fudi, &partial, in_vim9script() ? &type : NULL);
4954a9b579f3SBram Moolenaar     if (fudi.fd_newkey != NULL)
4955a9b579f3SBram Moolenaar     {
4956e38eab22SBram Moolenaar 	// Still need to give an error message for missing key.
4957f9e3e09fSBram Moolenaar 	semsg(_(e_dictkey), fudi.fd_newkey);
4958a9b579f3SBram Moolenaar 	vim_free(fudi.fd_newkey);
4959a9b579f3SBram Moolenaar     }
4960a9b579f3SBram Moolenaar     if (tofree == NULL)
4961a9b579f3SBram Moolenaar 	return;
4962a9b579f3SBram Moolenaar 
4963e38eab22SBram Moolenaar     // Increase refcount on dictionary, it could get deleted when evaluating
4964e38eab22SBram Moolenaar     // the arguments.
4965a9b579f3SBram Moolenaar     if (fudi.fd_dict != NULL)
4966a9b579f3SBram Moolenaar 	++fudi.fd_dict->dv_refcount;
4967a9b579f3SBram Moolenaar 
4968e38eab22SBram Moolenaar     // If it is the name of a variable of type VAR_FUNC or VAR_PARTIAL use its
4969e38eab22SBram Moolenaar     // contents.  For VAR_PARTIAL get its partial, unless we already have one
4970e38eab22SBram Moolenaar     // from trans_function_name().
4971a9b579f3SBram Moolenaar     len = (int)STRLEN(tofree);
497232b3f820SBram Moolenaar     name = deref_func_name(tofree, &len, partial != NULL ? NULL : &partial,
497332b3f820SBram Moolenaar 			in_vim9script() && type == NULL ? &type : NULL, FALSE);
4974a9b579f3SBram Moolenaar 
4975e38eab22SBram Moolenaar     // Skip white space to allow ":call func ()".  Not good, but required for
4976e38eab22SBram Moolenaar     // backward compatibility.
4977a9b579f3SBram Moolenaar     startarg = skipwhite(arg);
4978a9b579f3SBram Moolenaar     if (*startarg != '(')
4979a9b579f3SBram Moolenaar     {
49808a7d6542SBram Moolenaar 	semsg(_(e_missing_paren), eap->arg);
4981a9b579f3SBram Moolenaar 	goto end;
4982a9b579f3SBram Moolenaar     }
498301dd6c37SBram Moolenaar     if (in_vim9script() && startarg > arg)
498401dd6c37SBram Moolenaar     {
498501dd6c37SBram Moolenaar 	semsg(_(e_no_white_space_allowed_before_str_str), "(", eap->arg);
498601dd6c37SBram Moolenaar 	goto end;
498701dd6c37SBram Moolenaar     }
4988a9b579f3SBram Moolenaar 
4989a9b579f3SBram Moolenaar     /*
4990a9b579f3SBram Moolenaar      * When skipping, evaluate the function once, to find the end of the
4991a9b579f3SBram Moolenaar      * arguments.
4992a9b579f3SBram Moolenaar      * When the function takes a range, this is discovered after the first
4993a9b579f3SBram Moolenaar      * call, and the loop is broken.
4994a9b579f3SBram Moolenaar      */
4995a9b579f3SBram Moolenaar     if (eap->skip)
4996a9b579f3SBram Moolenaar     {
4997a9b579f3SBram Moolenaar 	++emsg_skip;
4998e38eab22SBram Moolenaar 	lnum = eap->line2;	// do it once, also with an invalid range
4999a9b579f3SBram Moolenaar     }
5000a9b579f3SBram Moolenaar     else
5001a9b579f3SBram Moolenaar 	lnum = eap->line1;
5002a9b579f3SBram Moolenaar     for ( ; lnum <= eap->line2; ++lnum)
5003a9b579f3SBram Moolenaar     {
5004c6538bccSBram Moolenaar 	funcexe_T funcexe;
5005c6538bccSBram Moolenaar 
5006a9b579f3SBram Moolenaar 	if (!eap->skip && eap->addr_count > 0)
5007a9b579f3SBram Moolenaar 	{
50089e353b52SBram Moolenaar 	    if (lnum > curbuf->b_ml.ml_line_count)
50099e353b52SBram Moolenaar 	    {
50109e353b52SBram Moolenaar 		// If the function deleted lines or switched to another buffer
50119e353b52SBram Moolenaar 		// the line number may become invalid.
5012108010aaSBram Moolenaar 		emsg(_(e_invalid_range));
50139e353b52SBram Moolenaar 		break;
50149e353b52SBram Moolenaar 	    }
5015a9b579f3SBram Moolenaar 	    curwin->w_cursor.lnum = lnum;
5016a9b579f3SBram Moolenaar 	    curwin->w_cursor.col = 0;
5017a9b579f3SBram Moolenaar 	    curwin->w_cursor.coladd = 0;
5018a9b579f3SBram Moolenaar 	}
5019a9b579f3SBram Moolenaar 	arg = startarg;
5020c6538bccSBram Moolenaar 
5021a80faa89SBram Moolenaar 	CLEAR_FIELD(funcexe);
5022c6538bccSBram Moolenaar 	funcexe.firstline = eap->line1;
5023c6538bccSBram Moolenaar 	funcexe.lastline = eap->line2;
5024c6538bccSBram Moolenaar 	funcexe.doesrange = &doesrange;
5025c6538bccSBram Moolenaar 	funcexe.evaluate = !eap->skip;
5026c6538bccSBram Moolenaar 	funcexe.partial = partial;
5027c6538bccSBram Moolenaar 	funcexe.selfdict = fudi.fd_dict;
502832b3f820SBram Moolenaar 	funcexe.check_type = type;
502901dd6c37SBram Moolenaar 	rettv.v_type = VAR_UNKNOWN;	// clear_tv() uses this
5030e6b5324eSBram Moolenaar 	if (get_func_tv(name, -1, &rettv, &arg, &evalarg, &funcexe) == FAIL)
5031a9b579f3SBram Moolenaar 	{
5032a9b579f3SBram Moolenaar 	    failed = TRUE;
5033a9b579f3SBram Moolenaar 	    break;
5034a9b579f3SBram Moolenaar 	}
5035c6f9f739SBram Moolenaar 	if (has_watchexpr())
5036c6f9f739SBram Moolenaar 	    dbg_check_breakpoint(eap);
5037a9b579f3SBram Moolenaar 
50389cfe8f6eSBram Moolenaar 	// Handle a function returning a Funcref, Dictionary or List.
5039e40fbc2cSBram Moolenaar 	if (handle_subscript(&arg, &rettv,
5040e40fbc2cSBram Moolenaar 			   eap->skip ? NULL : &EVALARG_EVALUATE, TRUE) == FAIL)
5041a9b579f3SBram Moolenaar 	{
5042a9b579f3SBram Moolenaar 	    failed = TRUE;
5043a9b579f3SBram Moolenaar 	    break;
5044a9b579f3SBram Moolenaar 	}
5045a9b579f3SBram Moolenaar 
5046a9b579f3SBram Moolenaar 	clear_tv(&rettv);
5047a9b579f3SBram Moolenaar 	if (doesrange || eap->skip)
5048a9b579f3SBram Moolenaar 	    break;
5049a9b579f3SBram Moolenaar 
5050e38eab22SBram Moolenaar 	// Stop when immediately aborting on error, or when an interrupt
5051e38eab22SBram Moolenaar 	// occurred or an exception was thrown but not caught.
5052e38eab22SBram Moolenaar 	// get_func_tv() returned OK, so that the check for trailing
5053e38eab22SBram Moolenaar 	// characters below is executed.
5054a9b579f3SBram Moolenaar 	if (aborting())
5055a9b579f3SBram Moolenaar 	    break;
5056a9b579f3SBram Moolenaar     }
5057a9b579f3SBram Moolenaar     if (eap->skip)
5058a9b579f3SBram Moolenaar 	--emsg_skip;
5059e6b5324eSBram Moolenaar     clear_evalarg(&evalarg, eap);
5060a9b579f3SBram Moolenaar 
50611d34189eSBram Moolenaar     // When inside :try we need to check for following "| catch" or "| endtry".
50621d34189eSBram Moolenaar     // Not when there was an error, but do check if an exception was thrown.
50631d34189eSBram Moolenaar     if ((!aborting() || did_throw)
50641d34189eSBram Moolenaar 				  && (!failed || eap->cstack->cs_trylevel > 0))
5065a9b579f3SBram Moolenaar     {
5066e38eab22SBram Moolenaar 	// Check for trailing illegal characters and a following command.
50678294d499SBram Moolenaar 	arg = skipwhite(arg);
5068a72cfb80SBram Moolenaar 	if (!ends_excmd2(eap->arg, arg))
5069a9b579f3SBram Moolenaar 	{
50701d34189eSBram Moolenaar 	    if (!failed && !aborting())
507140d9da2aSBram Moolenaar 	    {
5072a9b579f3SBram Moolenaar 		emsg_severe = TRUE;
50732d06bfdeSBram Moolenaar 		semsg(_(e_trailing_arg), arg);
5074a9b579f3SBram Moolenaar 	    }
507540d9da2aSBram Moolenaar 	}
5076a9b579f3SBram Moolenaar 	else
507763b91736SBram Moolenaar 	    set_nextcmd(eap, arg);
5078a9b579f3SBram Moolenaar     }
5079a9b579f3SBram Moolenaar 
5080a9b579f3SBram Moolenaar end:
5081a9b579f3SBram Moolenaar     dict_unref(fudi.fd_dict);
5082a9b579f3SBram Moolenaar     vim_free(tofree);
5083a9b579f3SBram Moolenaar }
5084a9b579f3SBram Moolenaar 
5085a9b579f3SBram Moolenaar /*
5086a9b579f3SBram Moolenaar  * Return from a function.  Possibly makes the return pending.  Also called
5087a9b579f3SBram Moolenaar  * for a pending return at the ":endtry" or after returning from an extra
5088a9b579f3SBram Moolenaar  * do_cmdline().  "reanimate" is used in the latter case.  "is_cmd" is set
5089a9b579f3SBram Moolenaar  * when called due to a ":return" command.  "rettv" may point to a typval_T
5090a9b579f3SBram Moolenaar  * with the return rettv.  Returns TRUE when the return can be carried out,
5091a9b579f3SBram Moolenaar  * FALSE when the return gets pending.
5092a9b579f3SBram Moolenaar  */
5093a9b579f3SBram Moolenaar     int
do_return(exarg_T * eap,int reanimate,int is_cmd,void * rettv)5094a9b579f3SBram Moolenaar do_return(
5095a9b579f3SBram Moolenaar     exarg_T	*eap,
5096a9b579f3SBram Moolenaar     int		reanimate,
5097a9b579f3SBram Moolenaar     int		is_cmd,
5098a9b579f3SBram Moolenaar     void	*rettv)
5099a9b579f3SBram Moolenaar {
5100a9b579f3SBram Moolenaar     int		idx;
5101ddef1291SBram Moolenaar     cstack_T	*cstack = eap->cstack;
5102a9b579f3SBram Moolenaar 
5103a9b579f3SBram Moolenaar     if (reanimate)
5104e38eab22SBram Moolenaar 	// Undo the return.
5105a9b579f3SBram Moolenaar 	current_funccal->returned = FALSE;
5106a9b579f3SBram Moolenaar 
5107a9b579f3SBram Moolenaar     /*
5108a9b579f3SBram Moolenaar      * Cleanup (and inactivate) conditionals, but stop when a try conditional
5109a9b579f3SBram Moolenaar      * not in its finally clause (which then is to be executed next) is found.
5110a9b579f3SBram Moolenaar      * In this case, make the ":return" pending for execution at the ":endtry".
5111a9b579f3SBram Moolenaar      * Otherwise, return normally.
5112a9b579f3SBram Moolenaar      */
5113a9b579f3SBram Moolenaar     idx = cleanup_conditionals(eap->cstack, 0, TRUE);
5114a9b579f3SBram Moolenaar     if (idx >= 0)
5115a9b579f3SBram Moolenaar     {
5116a9b579f3SBram Moolenaar 	cstack->cs_pending[idx] = CSTP_RETURN;
5117a9b579f3SBram Moolenaar 
5118a9b579f3SBram Moolenaar 	if (!is_cmd && !reanimate)
5119e38eab22SBram Moolenaar 	    // A pending return again gets pending.  "rettv" points to an
5120e38eab22SBram Moolenaar 	    // allocated variable with the rettv of the original ":return"'s
5121e38eab22SBram Moolenaar 	    // argument if present or is NULL else.
5122a9b579f3SBram Moolenaar 	    cstack->cs_rettv[idx] = rettv;
5123a9b579f3SBram Moolenaar 	else
5124a9b579f3SBram Moolenaar 	{
5125e38eab22SBram Moolenaar 	    // When undoing a return in order to make it pending, get the stored
5126e38eab22SBram Moolenaar 	    // return rettv.
5127a9b579f3SBram Moolenaar 	    if (reanimate)
5128a9b579f3SBram Moolenaar 		rettv = current_funccal->rettv;
5129a9b579f3SBram Moolenaar 
5130a9b579f3SBram Moolenaar 	    if (rettv != NULL)
5131a9b579f3SBram Moolenaar 	    {
5132e38eab22SBram Moolenaar 		// Store the value of the pending return.
5133a9b579f3SBram Moolenaar 		if ((cstack->cs_rettv[idx] = alloc_tv()) != NULL)
5134a9b579f3SBram Moolenaar 		    *(typval_T *)cstack->cs_rettv[idx] = *(typval_T *)rettv;
5135a9b579f3SBram Moolenaar 		else
5136e29a27f6SBram Moolenaar 		    emsg(_(e_out_of_memory));
5137a9b579f3SBram Moolenaar 	    }
5138a9b579f3SBram Moolenaar 	    else
5139a9b579f3SBram Moolenaar 		cstack->cs_rettv[idx] = NULL;
5140a9b579f3SBram Moolenaar 
5141a9b579f3SBram Moolenaar 	    if (reanimate)
5142a9b579f3SBram Moolenaar 	    {
5143e38eab22SBram Moolenaar 		// The pending return value could be overwritten by a ":return"
5144e38eab22SBram Moolenaar 		// without argument in a finally clause; reset the default
5145e38eab22SBram Moolenaar 		// return value.
5146a9b579f3SBram Moolenaar 		current_funccal->rettv->v_type = VAR_NUMBER;
5147a9b579f3SBram Moolenaar 		current_funccal->rettv->vval.v_number = 0;
5148a9b579f3SBram Moolenaar 	    }
5149a9b579f3SBram Moolenaar 	}
5150a9b579f3SBram Moolenaar 	report_make_pending(CSTP_RETURN, rettv);
5151a9b579f3SBram Moolenaar     }
5152a9b579f3SBram Moolenaar     else
5153a9b579f3SBram Moolenaar     {
5154a9b579f3SBram Moolenaar 	current_funccal->returned = TRUE;
5155a9b579f3SBram Moolenaar 
5156e38eab22SBram Moolenaar 	// If the return is carried out now, store the return value.  For
5157e38eab22SBram Moolenaar 	// a return immediately after reanimation, the value is already
5158e38eab22SBram Moolenaar 	// there.
5159a9b579f3SBram Moolenaar 	if (!reanimate && rettv != NULL)
5160a9b579f3SBram Moolenaar 	{
5161a9b579f3SBram Moolenaar 	    clear_tv(current_funccal->rettv);
5162a9b579f3SBram Moolenaar 	    *current_funccal->rettv = *(typval_T *)rettv;
5163a9b579f3SBram Moolenaar 	    if (!is_cmd)
5164a9b579f3SBram Moolenaar 		vim_free(rettv);
5165a9b579f3SBram Moolenaar 	}
5166a9b579f3SBram Moolenaar     }
5167a9b579f3SBram Moolenaar 
5168a9b579f3SBram Moolenaar     return idx < 0;
5169a9b579f3SBram Moolenaar }
5170a9b579f3SBram Moolenaar 
5171a9b579f3SBram Moolenaar /*
5172a9b579f3SBram Moolenaar  * Free the variable with a pending return value.
5173a9b579f3SBram Moolenaar  */
5174a9b579f3SBram Moolenaar     void
discard_pending_return(void * rettv)5175a9b579f3SBram Moolenaar discard_pending_return(void *rettv)
5176a9b579f3SBram Moolenaar {
5177a9b579f3SBram Moolenaar     free_tv((typval_T *)rettv);
5178a9b579f3SBram Moolenaar }
5179a9b579f3SBram Moolenaar 
5180a9b579f3SBram Moolenaar /*
5181a9b579f3SBram Moolenaar  * Generate a return command for producing the value of "rettv".  The result
5182a9b579f3SBram Moolenaar  * is an allocated string.  Used by report_pending() for verbose messages.
5183a9b579f3SBram Moolenaar  */
5184a9b579f3SBram Moolenaar     char_u *
get_return_cmd(void * rettv)5185a9b579f3SBram Moolenaar get_return_cmd(void *rettv)
5186a9b579f3SBram Moolenaar {
5187a9b579f3SBram Moolenaar     char_u	*s = NULL;
5188a9b579f3SBram Moolenaar     char_u	*tofree = NULL;
5189a9b579f3SBram Moolenaar     char_u	numbuf[NUMBUFLEN];
5190a9b579f3SBram Moolenaar 
5191a9b579f3SBram Moolenaar     if (rettv != NULL)
5192a9b579f3SBram Moolenaar 	s = echo_string((typval_T *)rettv, &tofree, numbuf, 0);
5193a9b579f3SBram Moolenaar     if (s == NULL)
5194a9b579f3SBram Moolenaar 	s = (char_u *)"";
5195a9b579f3SBram Moolenaar 
5196a9b579f3SBram Moolenaar     STRCPY(IObuff, ":return ");
5197a9b579f3SBram Moolenaar     STRNCPY(IObuff + 8, s, IOSIZE - 8);
5198a9b579f3SBram Moolenaar     if (STRLEN(s) + 8 >= IOSIZE)
5199a9b579f3SBram Moolenaar 	STRCPY(IObuff + IOSIZE - 4, "...");
5200a9b579f3SBram Moolenaar     vim_free(tofree);
5201a9b579f3SBram Moolenaar     return vim_strsave(IObuff);
5202a9b579f3SBram Moolenaar }
5203a9b579f3SBram Moolenaar 
5204a9b579f3SBram Moolenaar /*
5205a9b579f3SBram Moolenaar  * Get next function line.
5206a9b579f3SBram Moolenaar  * Called by do_cmdline() to get the next line.
5207a9b579f3SBram Moolenaar  * Returns allocated string, or NULL for end of function.
5208a9b579f3SBram Moolenaar  */
5209a9b579f3SBram Moolenaar     char_u *
get_func_line(int c UNUSED,void * cookie,int indent UNUSED,getline_opt_T options UNUSED)5210a9b579f3SBram Moolenaar get_func_line(
5211a9b579f3SBram Moolenaar     int	    c UNUSED,
5212a9b579f3SBram Moolenaar     void    *cookie,
5213e96a2498SBram Moolenaar     int	    indent UNUSED,
521466250c93SBram Moolenaar     getline_opt_T options UNUSED)
5215a9b579f3SBram Moolenaar {
5216a9b579f3SBram Moolenaar     funccall_T	*fcp = (funccall_T *)cookie;
5217a9b579f3SBram Moolenaar     ufunc_T	*fp = fcp->func;
5218a9b579f3SBram Moolenaar     char_u	*retval;
5219e38eab22SBram Moolenaar     garray_T	*gap;  // growarray with function lines
5220a9b579f3SBram Moolenaar 
5221e38eab22SBram Moolenaar     // If breakpoints have been added/deleted need to check for it.
5222a9b579f3SBram Moolenaar     if (fcp->dbg_tick != debug_tick)
5223a9b579f3SBram Moolenaar     {
5224a9b579f3SBram Moolenaar 	fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
52251a47ae32SBram Moolenaar 							       SOURCING_LNUM);
5226a9b579f3SBram Moolenaar 	fcp->dbg_tick = debug_tick;
5227a9b579f3SBram Moolenaar     }
5228a9b579f3SBram Moolenaar #ifdef FEAT_PROFILE
5229a9b579f3SBram Moolenaar     if (do_profiling == PROF_YES)
5230a9b579f3SBram Moolenaar 	func_line_end(cookie);
5231a9b579f3SBram Moolenaar #endif
5232a9b579f3SBram Moolenaar 
5233a9b579f3SBram Moolenaar     gap = &fp->uf_lines;
5234a9b579f3SBram Moolenaar     if (((fp->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
5235a9b579f3SBram Moolenaar 	    || fcp->returned)
5236a9b579f3SBram Moolenaar 	retval = NULL;
5237a9b579f3SBram Moolenaar     else
5238a9b579f3SBram Moolenaar     {
5239e38eab22SBram Moolenaar 	// Skip NULL lines (continuation lines).
5240a9b579f3SBram Moolenaar 	while (fcp->linenr < gap->ga_len
5241a9b579f3SBram Moolenaar 			  && ((char_u **)(gap->ga_data))[fcp->linenr] == NULL)
5242a9b579f3SBram Moolenaar 	    ++fcp->linenr;
5243a9b579f3SBram Moolenaar 	if (fcp->linenr >= gap->ga_len)
5244a9b579f3SBram Moolenaar 	    retval = NULL;
5245a9b579f3SBram Moolenaar 	else
5246a9b579f3SBram Moolenaar 	{
5247a9b579f3SBram Moolenaar 	    retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]);
52481a47ae32SBram Moolenaar 	    SOURCING_LNUM = fcp->linenr;
5249a9b579f3SBram Moolenaar #ifdef FEAT_PROFILE
5250a9b579f3SBram Moolenaar 	    if (do_profiling == PROF_YES)
5251b2049903SBram Moolenaar 		func_line_start(cookie, SOURCING_LNUM);
5252a9b579f3SBram Moolenaar #endif
5253a9b579f3SBram Moolenaar 	}
5254a9b579f3SBram Moolenaar     }
5255a9b579f3SBram Moolenaar 
5256e38eab22SBram Moolenaar     // Did we encounter a breakpoint?
52571a47ae32SBram Moolenaar     if (fcp->breakpoint != 0 && fcp->breakpoint <= SOURCING_LNUM)
5258a9b579f3SBram Moolenaar     {
52591a47ae32SBram Moolenaar 	dbg_breakpoint(fp->uf_name, SOURCING_LNUM);
5260e38eab22SBram Moolenaar 	// Find next breakpoint.
5261a9b579f3SBram Moolenaar 	fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
52621a47ae32SBram Moolenaar 							       SOURCING_LNUM);
5263a9b579f3SBram Moolenaar 	fcp->dbg_tick = debug_tick;
5264a9b579f3SBram Moolenaar     }
5265a9b579f3SBram Moolenaar 
5266a9b579f3SBram Moolenaar     return retval;
5267a9b579f3SBram Moolenaar }
5268a9b579f3SBram Moolenaar 
5269a9b579f3SBram Moolenaar /*
5270a9b579f3SBram Moolenaar  * Return TRUE if the currently active function should be ended, because a
5271a9b579f3SBram Moolenaar  * return was encountered or an error occurred.  Used inside a ":while".
5272a9b579f3SBram Moolenaar  */
5273a9b579f3SBram Moolenaar     int
func_has_ended(void * cookie)5274a9b579f3SBram Moolenaar func_has_ended(void *cookie)
5275a9b579f3SBram Moolenaar {
5276a9b579f3SBram Moolenaar     funccall_T  *fcp = (funccall_T *)cookie;
5277a9b579f3SBram Moolenaar 
5278e38eab22SBram Moolenaar     // Ignore the "abort" flag if the abortion behavior has been changed due to
5279e38eab22SBram Moolenaar     // an error inside a try conditional.
5280a9b579f3SBram Moolenaar     return (((fcp->func->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
5281a9b579f3SBram Moolenaar 	    || fcp->returned);
5282a9b579f3SBram Moolenaar }
5283a9b579f3SBram Moolenaar 
5284a9b579f3SBram Moolenaar /*
5285a9b579f3SBram Moolenaar  * return TRUE if cookie indicates a function which "abort"s on errors.
5286a9b579f3SBram Moolenaar  */
5287a9b579f3SBram Moolenaar     int
func_has_abort(void * cookie)5288a9b579f3SBram Moolenaar func_has_abort(
5289a9b579f3SBram Moolenaar     void    *cookie)
5290a9b579f3SBram Moolenaar {
5291a9b579f3SBram Moolenaar     return ((funccall_T *)cookie)->func->uf_flags & FC_ABORT;
5292a9b579f3SBram Moolenaar }
5293a9b579f3SBram Moolenaar 
5294a9b579f3SBram Moolenaar 
5295a9b579f3SBram Moolenaar /*
5296a9b579f3SBram Moolenaar  * Turn "dict.Func" into a partial for "Func" bound to "dict".
5297a9b579f3SBram Moolenaar  * Don't do this when "Func" is already a partial that was bound
5298a9b579f3SBram Moolenaar  * explicitly (pt_auto is FALSE).
5299a9b579f3SBram Moolenaar  * Changes "rettv" in-place.
5300a9b579f3SBram Moolenaar  * Returns the updated "selfdict_in".
5301a9b579f3SBram Moolenaar  */
5302a9b579f3SBram Moolenaar     dict_T *
make_partial(dict_T * selfdict_in,typval_T * rettv)5303a9b579f3SBram Moolenaar make_partial(dict_T *selfdict_in, typval_T *rettv)
5304a9b579f3SBram Moolenaar {
5305437bafe4SBram Moolenaar     char_u	*fname;
5306a9b579f3SBram Moolenaar     char_u	*tofree = NULL;
5307a9b579f3SBram Moolenaar     ufunc_T	*fp;
5308a9b579f3SBram Moolenaar     char_u	fname_buf[FLEN_FIXED + 1];
5309a9b579f3SBram Moolenaar     int		error;
5310a9b579f3SBram Moolenaar     dict_T	*selfdict = selfdict_in;
5311a9b579f3SBram Moolenaar 
5312437bafe4SBram Moolenaar     if (rettv->v_type == VAR_PARTIAL && rettv->vval.v_partial->pt_func != NULL)
5313437bafe4SBram Moolenaar 	fp = rettv->vval.v_partial->pt_func;
5314437bafe4SBram Moolenaar     else
5315437bafe4SBram Moolenaar     {
5316437bafe4SBram Moolenaar 	fname = rettv->v_type == VAR_FUNC ? rettv->vval.v_string
5317437bafe4SBram Moolenaar 					      : rettv->vval.v_partial->pt_name;
5318e38eab22SBram Moolenaar 	// Translate "s:func" to the stored function name.
5319a9b579f3SBram Moolenaar 	fname = fname_trans_sid(fname, fname_buf, &tofree, &error);
53204c17ad94SBram Moolenaar 	fp = find_func(fname, FALSE, NULL);
5321a9b579f3SBram Moolenaar 	vim_free(tofree);
5322437bafe4SBram Moolenaar     }
5323a9b579f3SBram Moolenaar 
5324a9b579f3SBram Moolenaar     if (fp != NULL && (fp->uf_flags & FC_DICT))
5325a9b579f3SBram Moolenaar     {
5326c799fe20SBram Moolenaar 	partial_T	*pt = ALLOC_CLEAR_ONE(partial_T);
5327a9b579f3SBram Moolenaar 
5328a9b579f3SBram Moolenaar 	if (pt != NULL)
5329a9b579f3SBram Moolenaar 	{
5330a9b579f3SBram Moolenaar 	    pt->pt_refcount = 1;
5331a9b579f3SBram Moolenaar 	    pt->pt_dict = selfdict;
5332a9b579f3SBram Moolenaar 	    pt->pt_auto = TRUE;
5333a9b579f3SBram Moolenaar 	    selfdict = NULL;
5334a9b579f3SBram Moolenaar 	    if (rettv->v_type == VAR_FUNC)
5335a9b579f3SBram Moolenaar 	    {
5336e38eab22SBram Moolenaar 		// Just a function: Take over the function name and use
5337e38eab22SBram Moolenaar 		// selfdict.
5338a9b579f3SBram Moolenaar 		pt->pt_name = rettv->vval.v_string;
5339a9b579f3SBram Moolenaar 	    }
5340a9b579f3SBram Moolenaar 	    else
5341a9b579f3SBram Moolenaar 	    {
5342a9b579f3SBram Moolenaar 		partial_T	*ret_pt = rettv->vval.v_partial;
5343a9b579f3SBram Moolenaar 		int		i;
5344a9b579f3SBram Moolenaar 
5345e38eab22SBram Moolenaar 		// Partial: copy the function name, use selfdict and copy
5346e38eab22SBram Moolenaar 		// args.  Can't take over name or args, the partial might
5347e38eab22SBram Moolenaar 		// be referenced elsewhere.
5348437bafe4SBram Moolenaar 		if (ret_pt->pt_name != NULL)
5349437bafe4SBram Moolenaar 		{
5350a9b579f3SBram Moolenaar 		    pt->pt_name = vim_strsave(ret_pt->pt_name);
5351a9b579f3SBram Moolenaar 		    func_ref(pt->pt_name);
5352437bafe4SBram Moolenaar 		}
5353437bafe4SBram Moolenaar 		else
5354437bafe4SBram Moolenaar 		{
5355437bafe4SBram Moolenaar 		    pt->pt_func = ret_pt->pt_func;
5356437bafe4SBram Moolenaar 		    func_ptr_ref(pt->pt_func);
5357437bafe4SBram Moolenaar 		}
5358a9b579f3SBram Moolenaar 		if (ret_pt->pt_argc > 0)
5359a9b579f3SBram Moolenaar 		{
5360c799fe20SBram Moolenaar 		    pt->pt_argv = ALLOC_MULT(typval_T, ret_pt->pt_argc);
5361a9b579f3SBram Moolenaar 		    if (pt->pt_argv == NULL)
5362e38eab22SBram Moolenaar 			// out of memory: drop the arguments
5363a9b579f3SBram Moolenaar 			pt->pt_argc = 0;
5364a9b579f3SBram Moolenaar 		    else
5365a9b579f3SBram Moolenaar 		    {
5366a9b579f3SBram Moolenaar 			pt->pt_argc = ret_pt->pt_argc;
5367a9b579f3SBram Moolenaar 			for (i = 0; i < pt->pt_argc; i++)
5368a9b579f3SBram Moolenaar 			    copy_tv(&ret_pt->pt_argv[i], &pt->pt_argv[i]);
5369a9b579f3SBram Moolenaar 		    }
5370a9b579f3SBram Moolenaar 		}
5371a9b579f3SBram Moolenaar 		partial_unref(ret_pt);
5372a9b579f3SBram Moolenaar 	    }
5373a9b579f3SBram Moolenaar 	    rettv->v_type = VAR_PARTIAL;
5374a9b579f3SBram Moolenaar 	    rettv->vval.v_partial = pt;
5375a9b579f3SBram Moolenaar 	}
5376a9b579f3SBram Moolenaar     }
5377a9b579f3SBram Moolenaar     return selfdict;
5378a9b579f3SBram Moolenaar }
5379a9b579f3SBram Moolenaar 
5380a9b579f3SBram Moolenaar /*
5381a9b579f3SBram Moolenaar  * Return the name of the executed function.
5382a9b579f3SBram Moolenaar  */
5383a9b579f3SBram Moolenaar     char_u *
func_name(void * cookie)5384a9b579f3SBram Moolenaar func_name(void *cookie)
5385a9b579f3SBram Moolenaar {
5386a9b579f3SBram Moolenaar     return ((funccall_T *)cookie)->func->uf_name;
5387a9b579f3SBram Moolenaar }
5388a9b579f3SBram Moolenaar 
5389a9b579f3SBram Moolenaar /*
5390a9b579f3SBram Moolenaar  * Return the address holding the next breakpoint line for a funccall cookie.
5391a9b579f3SBram Moolenaar  */
5392a9b579f3SBram Moolenaar     linenr_T *
func_breakpoint(void * cookie)5393a9b579f3SBram Moolenaar func_breakpoint(void *cookie)
5394a9b579f3SBram Moolenaar {
5395a9b579f3SBram Moolenaar     return &((funccall_T *)cookie)->breakpoint;
5396a9b579f3SBram Moolenaar }
5397a9b579f3SBram Moolenaar 
5398a9b579f3SBram Moolenaar /*
5399a9b579f3SBram Moolenaar  * Return the address holding the debug tick for a funccall cookie.
5400a9b579f3SBram Moolenaar  */
5401a9b579f3SBram Moolenaar     int *
func_dbg_tick(void * cookie)5402a9b579f3SBram Moolenaar func_dbg_tick(void *cookie)
5403a9b579f3SBram Moolenaar {
5404a9b579f3SBram Moolenaar     return &((funccall_T *)cookie)->dbg_tick;
5405a9b579f3SBram Moolenaar }
5406a9b579f3SBram Moolenaar 
5407a9b579f3SBram Moolenaar /*
5408a9b579f3SBram Moolenaar  * Return the nesting level for a funccall cookie.
5409a9b579f3SBram Moolenaar  */
5410a9b579f3SBram Moolenaar     int
func_level(void * cookie)5411a9b579f3SBram Moolenaar func_level(void *cookie)
5412a9b579f3SBram Moolenaar {
5413a9b579f3SBram Moolenaar     return ((funccall_T *)cookie)->level;
5414a9b579f3SBram Moolenaar }
5415a9b579f3SBram Moolenaar 
5416a9b579f3SBram Moolenaar /*
5417a9b579f3SBram Moolenaar  * Return TRUE when a function was ended by a ":return" command.
5418a9b579f3SBram Moolenaar  */
5419a9b579f3SBram Moolenaar     int
current_func_returned(void)5420a9b579f3SBram Moolenaar current_func_returned(void)
5421a9b579f3SBram Moolenaar {
5422a9b579f3SBram Moolenaar     return current_funccal->returned;
5423a9b579f3SBram Moolenaar }
5424a9b579f3SBram Moolenaar 
5425a9b579f3SBram Moolenaar     int
free_unref_funccal(int copyID,int testing)5426a9b579f3SBram Moolenaar free_unref_funccal(int copyID, int testing)
5427a9b579f3SBram Moolenaar {
5428a9b579f3SBram Moolenaar     int		did_free = FALSE;
5429a9b579f3SBram Moolenaar     int		did_free_funccal = FALSE;
5430a9b579f3SBram Moolenaar     funccall_T	*fc, **pfc;
5431a9b579f3SBram Moolenaar 
5432a9b579f3SBram Moolenaar     for (pfc = &previous_funccal; *pfc != NULL; )
5433a9b579f3SBram Moolenaar     {
5434a9b579f3SBram Moolenaar 	if (can_free_funccal(*pfc, copyID))
5435a9b579f3SBram Moolenaar 	{
5436a9b579f3SBram Moolenaar 	    fc = *pfc;
5437a9b579f3SBram Moolenaar 	    *pfc = fc->caller;
5438209b8e3eSBram Moolenaar 	    free_funccal_contents(fc);
5439a9b579f3SBram Moolenaar 	    did_free = TRUE;
5440a9b579f3SBram Moolenaar 	    did_free_funccal = TRUE;
5441a9b579f3SBram Moolenaar 	}
5442a9b579f3SBram Moolenaar 	else
5443a9b579f3SBram Moolenaar 	    pfc = &(*pfc)->caller;
5444a9b579f3SBram Moolenaar     }
5445a9b579f3SBram Moolenaar     if (did_free_funccal)
5446e38eab22SBram Moolenaar 	// When a funccal was freed some more items might be garbage
5447e38eab22SBram Moolenaar 	// collected, so run again.
5448a9b579f3SBram Moolenaar 	(void)garbage_collect(testing);
5449a9b579f3SBram Moolenaar 
5450a9b579f3SBram Moolenaar     return did_free;
5451a9b579f3SBram Moolenaar }
5452a9b579f3SBram Moolenaar 
5453a9b579f3SBram Moolenaar /*
5454ba209903SBram Moolenaar  * Get function call environment based on backtrace debug level
5455a9b579f3SBram Moolenaar  */
5456a9b579f3SBram Moolenaar     static funccall_T *
get_funccal(void)5457a9b579f3SBram Moolenaar get_funccal(void)
5458a9b579f3SBram Moolenaar {
5459a9b579f3SBram Moolenaar     int		i;
5460a9b579f3SBram Moolenaar     funccall_T	*funccal;
5461a9b579f3SBram Moolenaar     funccall_T	*temp_funccal;
5462a9b579f3SBram Moolenaar 
5463a9b579f3SBram Moolenaar     funccal = current_funccal;
5464a9b579f3SBram Moolenaar     if (debug_backtrace_level > 0)
5465a9b579f3SBram Moolenaar     {
5466a9b579f3SBram Moolenaar 	for (i = 0; i < debug_backtrace_level; i++)
5467a9b579f3SBram Moolenaar 	{
5468a9b579f3SBram Moolenaar 	    temp_funccal = funccal->caller;
5469a9b579f3SBram Moolenaar 	    if (temp_funccal)
5470a9b579f3SBram Moolenaar 		funccal = temp_funccal;
5471a9b579f3SBram Moolenaar 	    else
5472e38eab22SBram Moolenaar 		// backtrace level overflow. reset to max
5473a9b579f3SBram Moolenaar 		debug_backtrace_level = i;
5474a9b579f3SBram Moolenaar 	}
5475a9b579f3SBram Moolenaar     }
5476a9b579f3SBram Moolenaar     return funccal;
5477a9b579f3SBram Moolenaar }
5478a9b579f3SBram Moolenaar 
5479a9b579f3SBram Moolenaar /*
5480a9b579f3SBram Moolenaar  * Return the hashtable used for local variables in the current funccal.
5481a9b579f3SBram Moolenaar  * Return NULL if there is no current funccal.
5482a9b579f3SBram Moolenaar  */
5483a9b579f3SBram Moolenaar     hashtab_T *
get_funccal_local_ht()5484a9b579f3SBram Moolenaar get_funccal_local_ht()
5485a9b579f3SBram Moolenaar {
54868a7d6542SBram Moolenaar     if (current_funccal == NULL || current_funccal->l_vars.dv_refcount == 0)
5487a9b579f3SBram Moolenaar 	return NULL;
5488a9b579f3SBram Moolenaar     return &get_funccal()->l_vars.dv_hashtab;
5489a9b579f3SBram Moolenaar }
5490a9b579f3SBram Moolenaar 
5491a9b579f3SBram Moolenaar /*
5492a9b579f3SBram Moolenaar  * Return the l: scope variable.
5493a9b579f3SBram Moolenaar  * Return NULL if there is no current funccal.
5494a9b579f3SBram Moolenaar  */
5495a9b579f3SBram Moolenaar     dictitem_T *
get_funccal_local_var()5496a9b579f3SBram Moolenaar get_funccal_local_var()
5497a9b579f3SBram Moolenaar {
54988a7d6542SBram Moolenaar     if (current_funccal == NULL || current_funccal->l_vars.dv_refcount == 0)
5499a9b579f3SBram Moolenaar 	return NULL;
5500a9b579f3SBram Moolenaar     return &get_funccal()->l_vars_var;
5501a9b579f3SBram Moolenaar }
5502a9b579f3SBram Moolenaar 
5503a9b579f3SBram Moolenaar /*
5504a9b579f3SBram Moolenaar  * Return the hashtable used for argument in the current funccal.
5505a9b579f3SBram Moolenaar  * Return NULL if there is no current funccal.
5506a9b579f3SBram Moolenaar  */
5507a9b579f3SBram Moolenaar     hashtab_T *
get_funccal_args_ht()5508a9b579f3SBram Moolenaar get_funccal_args_ht()
5509a9b579f3SBram Moolenaar {
55108a7d6542SBram Moolenaar     if (current_funccal == NULL || current_funccal->l_vars.dv_refcount == 0)
5511a9b579f3SBram Moolenaar 	return NULL;
5512a9b579f3SBram Moolenaar     return &get_funccal()->l_avars.dv_hashtab;
5513a9b579f3SBram Moolenaar }
5514a9b579f3SBram Moolenaar 
5515a9b579f3SBram Moolenaar /*
5516a9b579f3SBram Moolenaar  * Return the a: scope variable.
5517a9b579f3SBram Moolenaar  * Return NULL if there is no current funccal.
5518a9b579f3SBram Moolenaar  */
5519a9b579f3SBram Moolenaar     dictitem_T *
get_funccal_args_var()5520a9b579f3SBram Moolenaar get_funccal_args_var()
5521a9b579f3SBram Moolenaar {
55228a7d6542SBram Moolenaar     if (current_funccal == NULL || current_funccal->l_vars.dv_refcount == 0)
5523a9b579f3SBram Moolenaar 	return NULL;
5524c7d9eaceSBram Moolenaar     return &get_funccal()->l_avars_var;
5525a9b579f3SBram Moolenaar }
5526a9b579f3SBram Moolenaar 
5527a9b579f3SBram Moolenaar /*
5528a9b579f3SBram Moolenaar  * List function variables, if there is a function.
5529a9b579f3SBram Moolenaar  */
5530a9b579f3SBram Moolenaar     void
list_func_vars(int * first)5531a9b579f3SBram Moolenaar list_func_vars(int *first)
5532a9b579f3SBram Moolenaar {
55338a7d6542SBram Moolenaar     if (current_funccal != NULL && current_funccal->l_vars.dv_refcount > 0)
5534a9b579f3SBram Moolenaar 	list_hashtable_vars(&current_funccal->l_vars.dv_hashtab,
553532526b3cSBram Moolenaar 							   "l:", FALSE, first);
5536a9b579f3SBram Moolenaar }
5537a9b579f3SBram Moolenaar 
5538a9b579f3SBram Moolenaar /*
5539a9b579f3SBram Moolenaar  * If "ht" is the hashtable for local variables in the current funccal, return
5540a9b579f3SBram Moolenaar  * the dict that contains it.
5541a9b579f3SBram Moolenaar  * Otherwise return NULL.
5542a9b579f3SBram Moolenaar  */
5543a9b579f3SBram Moolenaar     dict_T *
get_current_funccal_dict(hashtab_T * ht)5544a9b579f3SBram Moolenaar get_current_funccal_dict(hashtab_T *ht)
5545a9b579f3SBram Moolenaar {
5546a9b579f3SBram Moolenaar     if (current_funccal != NULL
5547a9b579f3SBram Moolenaar 	    && ht == &current_funccal->l_vars.dv_hashtab)
5548a9b579f3SBram Moolenaar 	return &current_funccal->l_vars;
5549a9b579f3SBram Moolenaar     return NULL;
5550a9b579f3SBram Moolenaar }
5551a9b579f3SBram Moolenaar 
5552a9b579f3SBram Moolenaar /*
555310ce39a0SBram Moolenaar  * Search hashitem in parent scope.
555410ce39a0SBram Moolenaar  */
555510ce39a0SBram Moolenaar     hashitem_T *
find_hi_in_scoped_ht(char_u * name,hashtab_T ** pht)5556ba96e9afSBram Moolenaar find_hi_in_scoped_ht(char_u *name, hashtab_T **pht)
555710ce39a0SBram Moolenaar {
555810ce39a0SBram Moolenaar     funccall_T	*old_current_funccal = current_funccal;
555910ce39a0SBram Moolenaar     hashtab_T	*ht;
556010ce39a0SBram Moolenaar     hashitem_T	*hi = NULL;
5561ba96e9afSBram Moolenaar     char_u	*varname;
556210ce39a0SBram Moolenaar 
556310ce39a0SBram Moolenaar     if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL)
556410ce39a0SBram Moolenaar       return NULL;
556510ce39a0SBram Moolenaar 
55666f5b6dfbSBram Moolenaar     // Search in parent scope, which can be referenced from a lambda.
556710ce39a0SBram Moolenaar     current_funccal = current_funccal->func->uf_scoped;
556858016448SBram Moolenaar     while (current_funccal != NULL)
556910ce39a0SBram Moolenaar     {
5570ba96e9afSBram Moolenaar 	ht = find_var_ht(name, &varname);
5571ba96e9afSBram Moolenaar 	if (ht != NULL && *varname != NUL)
557210ce39a0SBram Moolenaar 	{
5573ba96e9afSBram Moolenaar 	    hi = hash_find(ht, varname);
557410ce39a0SBram Moolenaar 	    if (!HASHITEM_EMPTY(hi))
557510ce39a0SBram Moolenaar 	    {
557610ce39a0SBram Moolenaar 		*pht = ht;
557710ce39a0SBram Moolenaar 		break;
557810ce39a0SBram Moolenaar 	    }
557910ce39a0SBram Moolenaar 	}
558010ce39a0SBram Moolenaar 	if (current_funccal == current_funccal->func->uf_scoped)
558110ce39a0SBram Moolenaar 	    break;
558210ce39a0SBram Moolenaar 	current_funccal = current_funccal->func->uf_scoped;
558310ce39a0SBram Moolenaar     }
558410ce39a0SBram Moolenaar     current_funccal = old_current_funccal;
558510ce39a0SBram Moolenaar 
558610ce39a0SBram Moolenaar     return hi;
558710ce39a0SBram Moolenaar }
558810ce39a0SBram Moolenaar 
558910ce39a0SBram Moolenaar /*
55901e96d9bfSBram Moolenaar  * Search variable in parent scope.
55911e96d9bfSBram Moolenaar  */
55921e96d9bfSBram Moolenaar     dictitem_T *
find_var_in_scoped_ht(char_u * name,int no_autoload)5593ba96e9afSBram Moolenaar find_var_in_scoped_ht(char_u *name, int no_autoload)
55941e96d9bfSBram Moolenaar {
55951e96d9bfSBram Moolenaar     dictitem_T	*v = NULL;
55961e96d9bfSBram Moolenaar     funccall_T	*old_current_funccal = current_funccal;
55971e96d9bfSBram Moolenaar     hashtab_T	*ht;
5598ba96e9afSBram Moolenaar     char_u	*varname;
55991e96d9bfSBram Moolenaar 
56001e96d9bfSBram Moolenaar     if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL)
56011e96d9bfSBram Moolenaar 	return NULL;
56021e96d9bfSBram Moolenaar 
5603e38eab22SBram Moolenaar     // Search in parent scope which is possible to reference from lambda
56041e96d9bfSBram Moolenaar     current_funccal = current_funccal->func->uf_scoped;
56051e96d9bfSBram Moolenaar     while (current_funccal)
56061e96d9bfSBram Moolenaar     {
5607ba96e9afSBram Moolenaar 	ht = find_var_ht(name, &varname);
5608ba96e9afSBram Moolenaar 	if (ht != NULL && *varname != NUL)
56091e96d9bfSBram Moolenaar 	{
5610ba96e9afSBram Moolenaar 	    v = find_var_in_ht(ht, *name, varname, no_autoload);
56111e96d9bfSBram Moolenaar 	    if (v != NULL)
56121e96d9bfSBram Moolenaar 		break;
56131e96d9bfSBram Moolenaar 	}
56141e96d9bfSBram Moolenaar 	if (current_funccal == current_funccal->func->uf_scoped)
56151e96d9bfSBram Moolenaar 	    break;
56161e96d9bfSBram Moolenaar 	current_funccal = current_funccal->func->uf_scoped;
56171e96d9bfSBram Moolenaar     }
56181e96d9bfSBram Moolenaar     current_funccal = old_current_funccal;
56191e96d9bfSBram Moolenaar 
56201e96d9bfSBram Moolenaar     return v;
56211e96d9bfSBram Moolenaar }
56221e96d9bfSBram Moolenaar 
56231e96d9bfSBram Moolenaar /*
5624a9b579f3SBram Moolenaar  * Set "copyID + 1" in previous_funccal and callers.
5625a9b579f3SBram Moolenaar  */
5626a9b579f3SBram Moolenaar     int
set_ref_in_previous_funccal(int copyID)5627a9b579f3SBram Moolenaar set_ref_in_previous_funccal(int copyID)
5628a9b579f3SBram Moolenaar {
5629a9b579f3SBram Moolenaar     funccall_T	*fc;
5630a9b579f3SBram Moolenaar 
563120cc5283SBram Moolenaar     for (fc = previous_funccal; fc != NULL; fc = fc->caller)
5632a9b579f3SBram Moolenaar     {
56331e96d9bfSBram Moolenaar 	fc->fc_copyID = copyID + 1;
563420cc5283SBram Moolenaar 	if (set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1, NULL)
56356e5000d4SBram Moolenaar 		|| set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1, NULL)
563620cc5283SBram Moolenaar 		|| set_ref_in_list_items(&fc->l_varlist, copyID + 1, NULL))
563720cc5283SBram Moolenaar 	    return TRUE;
5638a9b579f3SBram Moolenaar     }
563920cc5283SBram Moolenaar     return FALSE;
5640a9b579f3SBram Moolenaar }
5641a9b579f3SBram Moolenaar 
5642bc7ce675SBram Moolenaar     static int
set_ref_in_funccal(funccall_T * fc,int copyID)5643bc7ce675SBram Moolenaar set_ref_in_funccal(funccall_T *fc, int copyID)
5644bc7ce675SBram Moolenaar {
5645bc7ce675SBram Moolenaar     if (fc->fc_copyID != copyID)
5646bc7ce675SBram Moolenaar     {
5647bc7ce675SBram Moolenaar 	fc->fc_copyID = copyID;
564820cc5283SBram Moolenaar 	if (set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL)
56496e5000d4SBram Moolenaar 		|| set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL)
56507be3ab25SBram Moolenaar 		|| set_ref_in_list_items(&fc->l_varlist, copyID, NULL)
565120cc5283SBram Moolenaar 		|| set_ref_in_func(NULL, fc->func, copyID))
565220cc5283SBram Moolenaar 	    return TRUE;
5653bc7ce675SBram Moolenaar     }
565420cc5283SBram Moolenaar     return FALSE;
5655bc7ce675SBram Moolenaar }
5656bc7ce675SBram Moolenaar 
5657a9b579f3SBram Moolenaar /*
5658a9b579f3SBram Moolenaar  * Set "copyID" in all local vars and arguments in the call stack.
5659a9b579f3SBram Moolenaar  */
5660a9b579f3SBram Moolenaar     int
set_ref_in_call_stack(int copyID)5661a9b579f3SBram Moolenaar set_ref_in_call_stack(int copyID)
5662a9b579f3SBram Moolenaar {
5663a9b579f3SBram Moolenaar     funccall_T		*fc;
5664c07f67adSBram Moolenaar     funccal_entry_T	*entry;
5665a9b579f3SBram Moolenaar 
566620cc5283SBram Moolenaar     for (fc = current_funccal; fc != NULL; fc = fc->caller)
566720cc5283SBram Moolenaar 	if (set_ref_in_funccal(fc, copyID))
566820cc5283SBram Moolenaar 	    return TRUE;
5669c07f67adSBram Moolenaar 
5670c07f67adSBram Moolenaar     // Also go through the funccal_stack.
567120cc5283SBram Moolenaar     for (entry = funccal_stack; entry != NULL; entry = entry->next)
567220cc5283SBram Moolenaar 	for (fc = entry->top_funccal; fc != NULL; fc = fc->caller)
567320cc5283SBram Moolenaar 	    if (set_ref_in_funccal(fc, copyID))
567420cc5283SBram Moolenaar 		return TRUE;
567520cc5283SBram Moolenaar     return FALSE;
5676bc7ce675SBram Moolenaar }
5677bc7ce675SBram Moolenaar 
5678bc7ce675SBram Moolenaar /*
5679bc7ce675SBram Moolenaar  * Set "copyID" in all functions available by name.
5680bc7ce675SBram Moolenaar  */
5681bc7ce675SBram Moolenaar     int
set_ref_in_functions(int copyID)5682bc7ce675SBram Moolenaar set_ref_in_functions(int copyID)
5683a9b579f3SBram Moolenaar {
5684bc7ce675SBram Moolenaar     int		todo;
5685bc7ce675SBram Moolenaar     hashitem_T	*hi = NULL;
5686bc7ce675SBram Moolenaar     ufunc_T	*fp;
5687bc7ce675SBram Moolenaar 
5688bc7ce675SBram Moolenaar     todo = (int)func_hashtab.ht_used;
5689bc7ce675SBram Moolenaar     for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
5690bc7ce675SBram Moolenaar     {
5691bc7ce675SBram Moolenaar 	if (!HASHITEM_EMPTY(hi))
5692bc7ce675SBram Moolenaar 	{
5693bc7ce675SBram Moolenaar 	    --todo;
5694bc7ce675SBram Moolenaar 	    fp = HI2UF(hi);
569520cc5283SBram Moolenaar 	    if (!func_name_refcount(fp->uf_name)
569620cc5283SBram Moolenaar 					  && set_ref_in_func(NULL, fp, copyID))
569720cc5283SBram Moolenaar 		return TRUE;
5698bc7ce675SBram Moolenaar 	}
5699a9b579f3SBram Moolenaar     }
570020cc5283SBram Moolenaar     return FALSE;
5701a9b579f3SBram Moolenaar }
5702a9b579f3SBram Moolenaar 
5703a9b579f3SBram Moolenaar /*
5704a9b579f3SBram Moolenaar  * Set "copyID" in all function arguments.
5705a9b579f3SBram Moolenaar  */
5706a9b579f3SBram Moolenaar     int
set_ref_in_func_args(int copyID)5707a9b579f3SBram Moolenaar set_ref_in_func_args(int copyID)
5708a9b579f3SBram Moolenaar {
5709a9b579f3SBram Moolenaar     int i;
5710a9b579f3SBram Moolenaar 
5711a9b579f3SBram Moolenaar     for (i = 0; i < funcargs.ga_len; ++i)
571220cc5283SBram Moolenaar 	if (set_ref_in_item(((typval_T **)funcargs.ga_data)[i],
571320cc5283SBram Moolenaar 							  copyID, NULL, NULL))
571420cc5283SBram Moolenaar 	    return TRUE;
571520cc5283SBram Moolenaar     return FALSE;
5716a9b579f3SBram Moolenaar }
5717a9b579f3SBram Moolenaar 
57181e96d9bfSBram Moolenaar /*
57191e96d9bfSBram Moolenaar  * Mark all lists and dicts referenced through function "name" with "copyID".
57201e96d9bfSBram Moolenaar  * Returns TRUE if setting references failed somehow.
57211e96d9bfSBram Moolenaar  */
57221e96d9bfSBram Moolenaar     int
set_ref_in_func(char_u * name,ufunc_T * fp_in,int copyID)5723437bafe4SBram Moolenaar set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID)
57241e96d9bfSBram Moolenaar {
5725437bafe4SBram Moolenaar     ufunc_T	*fp = fp_in;
57261e96d9bfSBram Moolenaar     funccall_T	*fc;
5727ef140544SBram Moolenaar     int		error = FCERR_NONE;
57281e96d9bfSBram Moolenaar     char_u	fname_buf[FLEN_FIXED + 1];
57291e96d9bfSBram Moolenaar     char_u	*tofree = NULL;
57301e96d9bfSBram Moolenaar     char_u	*fname;
5731bc7ce675SBram Moolenaar     int		abort = FALSE;
57321e96d9bfSBram Moolenaar 
5733437bafe4SBram Moolenaar     if (name == NULL && fp_in == NULL)
57341e96d9bfSBram Moolenaar 	return FALSE;
57351e96d9bfSBram Moolenaar 
5736437bafe4SBram Moolenaar     if (fp_in == NULL)
5737437bafe4SBram Moolenaar     {
57381e96d9bfSBram Moolenaar 	fname = fname_trans_sid(name, fname_buf, &tofree, &error);
57394c17ad94SBram Moolenaar 	fp = find_func(fname, FALSE, NULL);
5740437bafe4SBram Moolenaar     }
57411e96d9bfSBram Moolenaar     if (fp != NULL)
57421e96d9bfSBram Moolenaar     {
57431e96d9bfSBram Moolenaar 	for (fc = fp->uf_scoped; fc != NULL; fc = fc->func->uf_scoped)
5744bc7ce675SBram Moolenaar 	    abort = abort || set_ref_in_funccal(fc, copyID);
57451e96d9bfSBram Moolenaar     }
57465adc55cbSBram Moolenaar 
57471e96d9bfSBram Moolenaar     vim_free(tofree);
5748bc7ce675SBram Moolenaar     return abort;
57491e96d9bfSBram Moolenaar }
57501e96d9bfSBram Moolenaar 
5751e38eab22SBram Moolenaar #endif // FEAT_EVAL
5752