xref: /vim-8.2.3635/src/vim9script.c (revision 9721fb4e)
18a7d6542SBram Moolenaar /* vi:set ts=8 sts=4 sw=4 noet:
28a7d6542SBram Moolenaar  *
38a7d6542SBram Moolenaar  * VIM - Vi IMproved	by Bram Moolenaar
48a7d6542SBram Moolenaar  *
58a7d6542SBram Moolenaar  * Do ":help uganda"  in Vim to read copying and usage conditions.
68a7d6542SBram Moolenaar  * Do ":help credits" in Vim to see a list of people who contributed.
78a7d6542SBram Moolenaar  * See README.txt for an overview of the Vim source code.
88a7d6542SBram Moolenaar  */
98a7d6542SBram Moolenaar 
108a7d6542SBram Moolenaar /*
118a7d6542SBram Moolenaar  * vim9script.c: :vim9script, :import, :export and friends
128a7d6542SBram Moolenaar  */
138a7d6542SBram Moolenaar 
148a7d6542SBram Moolenaar #include "vim.h"
158a7d6542SBram Moolenaar 
168a7d6542SBram Moolenaar #if defined(FEAT_EVAL) || defined(PROTO)
178a7d6542SBram Moolenaar 
188a7d6542SBram Moolenaar #include "vim9.h"
198a7d6542SBram Moolenaar 
20*9721fb4eSBram Moolenaar static char e_needs_vim9[] = N_("E1042: export can only be used in vim9script");
218a7d6542SBram Moolenaar 
228a7d6542SBram Moolenaar     int
238a7d6542SBram Moolenaar in_vim9script(void)
248a7d6542SBram Moolenaar {
258a7d6542SBram Moolenaar     // TODO: go up the stack?
268a7d6542SBram Moolenaar     return current_sctx.sc_version == SCRIPT_VERSION_VIM9;
278a7d6542SBram Moolenaar }
288a7d6542SBram Moolenaar 
298a7d6542SBram Moolenaar /*
308a7d6542SBram Moolenaar  * ":vim9script".
318a7d6542SBram Moolenaar  */
328a7d6542SBram Moolenaar     void
338a7d6542SBram Moolenaar ex_vim9script(exarg_T *eap)
348a7d6542SBram Moolenaar {
3521b9e977SBram Moolenaar     scriptitem_T    *si = SCRIPT_ITEM(current_sctx.sc_sid);
368a7d6542SBram Moolenaar 
378a7d6542SBram Moolenaar     if (!getline_equal(eap->getline, eap->cookie, getsourceline))
388a7d6542SBram Moolenaar     {
398a7d6542SBram Moolenaar 	emsg(_("E1038: vim9script can only be used in a script"));
408a7d6542SBram Moolenaar 	return;
418a7d6542SBram Moolenaar     }
428a7d6542SBram Moolenaar     if (si->sn_had_command)
438a7d6542SBram Moolenaar     {
448a7d6542SBram Moolenaar 	emsg(_("E1039: vim9script must be the first command in a script"));
458a7d6542SBram Moolenaar 	return;
468a7d6542SBram Moolenaar     }
478a7d6542SBram Moolenaar     current_sctx.sc_version = SCRIPT_VERSION_VIM9;
488a7d6542SBram Moolenaar     si->sn_version = SCRIPT_VERSION_VIM9;
498a7d6542SBram Moolenaar     si->sn_had_command = TRUE;
508a7d6542SBram Moolenaar 
518a7d6542SBram Moolenaar     if (STRCMP(p_cpo, CPO_VIM) != 0)
528a7d6542SBram Moolenaar     {
538a7d6542SBram Moolenaar 	si->sn_save_cpo = p_cpo;
548a7d6542SBram Moolenaar 	p_cpo = vim_strsave((char_u *)CPO_VIM);
558a7d6542SBram Moolenaar     }
56227a69deSBram Moolenaar }
578a7d6542SBram Moolenaar 
588a7d6542SBram Moolenaar /*
598a7d6542SBram Moolenaar  * ":export let Name: type"
608a7d6542SBram Moolenaar  * ":export const Name: type"
618a7d6542SBram Moolenaar  * ":export def Name(..."
628a7d6542SBram Moolenaar  * ":export class Name ..."
638a7d6542SBram Moolenaar  *
648a7d6542SBram Moolenaar  * ":export {Name, ...}"
658a7d6542SBram Moolenaar  */
668a7d6542SBram Moolenaar     void
6709689a02SBram Moolenaar ex_export(exarg_T *eap)
688a7d6542SBram Moolenaar {
698a7d6542SBram Moolenaar     if (current_sctx.sc_version != SCRIPT_VERSION_VIM9)
708a7d6542SBram Moolenaar     {
718a7d6542SBram Moolenaar 	emsg(_(e_needs_vim9));
728a7d6542SBram Moolenaar 	return;
738a7d6542SBram Moolenaar     }
748a7d6542SBram Moolenaar 
758a7d6542SBram Moolenaar     eap->cmd = eap->arg;
768a7d6542SBram Moolenaar     (void)find_ex_command(eap, NULL, lookup_scriptvar, NULL);
778a7d6542SBram Moolenaar     switch (eap->cmdidx)
788a7d6542SBram Moolenaar     {
798a7d6542SBram Moolenaar 	case CMD_let:
808a7d6542SBram Moolenaar 	case CMD_const:
818a7d6542SBram Moolenaar 	case CMD_def:
828a7d6542SBram Moolenaar 	// case CMD_class:
838a7d6542SBram Moolenaar 	    is_export = TRUE;
848a7d6542SBram Moolenaar 	    do_cmdline(eap->cmd, eap->getline, eap->cookie,
858a7d6542SBram Moolenaar 						DOCMD_VERBOSE + DOCMD_NOWAIT);
868a7d6542SBram Moolenaar 
878a7d6542SBram Moolenaar 	    // The command will reset "is_export" when exporting an item.
888a7d6542SBram Moolenaar 	    if (is_export)
898a7d6542SBram Moolenaar 	    {
908a7d6542SBram Moolenaar 		emsg(_("E1044: export with invalid argument"));
918a7d6542SBram Moolenaar 		is_export = FALSE;
928a7d6542SBram Moolenaar 	    }
938a7d6542SBram Moolenaar 	    break;
948a7d6542SBram Moolenaar 	default:
958a7d6542SBram Moolenaar 	    emsg(_("E1043: Invalid command after :export"));
968a7d6542SBram Moolenaar 	    break;
978a7d6542SBram Moolenaar     }
988a7d6542SBram Moolenaar }
998a7d6542SBram Moolenaar 
1008a7d6542SBram Moolenaar /*
1018a7d6542SBram Moolenaar  * Add a new imported item entry to the current script.
1028a7d6542SBram Moolenaar  */
1038a7d6542SBram Moolenaar     static imported_T *
1048a7d6542SBram Moolenaar new_imported(garray_T *gap)
1058a7d6542SBram Moolenaar {
1068a7d6542SBram Moolenaar     if (ga_grow(gap, 1) == OK)
1078a7d6542SBram Moolenaar 	return ((imported_T *)gap->ga_data + gap->ga_len++);
1088a7d6542SBram Moolenaar     return NULL;
1098a7d6542SBram Moolenaar }
1108a7d6542SBram Moolenaar 
1118a7d6542SBram Moolenaar /*
1128a7d6542SBram Moolenaar  * Free all imported items in script "sid".
1138a7d6542SBram Moolenaar  */
1148a7d6542SBram Moolenaar     void
1158a7d6542SBram Moolenaar free_imports(int sid)
1168a7d6542SBram Moolenaar {
11721b9e977SBram Moolenaar     scriptitem_T    *si = SCRIPT_ITEM(sid);
1188a7d6542SBram Moolenaar     int		    idx;
1198a7d6542SBram Moolenaar 
1208a7d6542SBram Moolenaar     for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
1218a7d6542SBram Moolenaar     {
12220431c9dSBram Moolenaar 	imported_T *imp = ((imported_T *)si->sn_imports.ga_data) + idx;
1238a7d6542SBram Moolenaar 
1248a7d6542SBram Moolenaar 	vim_free(imp->imp_name);
1258a7d6542SBram Moolenaar     }
1268a7d6542SBram Moolenaar     ga_clear(&si->sn_imports);
12720431c9dSBram Moolenaar     ga_clear(&si->sn_var_vals);
12820431c9dSBram Moolenaar     ga_clear(&si->sn_type_list);
1298a7d6542SBram Moolenaar }
1308a7d6542SBram Moolenaar 
1318a7d6542SBram Moolenaar /*
1328a7d6542SBram Moolenaar  * ":import Item from 'filename'"
1338a7d6542SBram Moolenaar  * ":import Item as Alias from 'filename'"
1348a7d6542SBram Moolenaar  * ":import {Item} from 'filename'".
1358a7d6542SBram Moolenaar  * ":import {Item as Alias} from 'filename'"
1368a7d6542SBram Moolenaar  * ":import {Item, Item} from 'filename'"
1378a7d6542SBram Moolenaar  * ":import {Item, Item as Alias} from 'filename'"
1388a7d6542SBram Moolenaar  *
1398a7d6542SBram Moolenaar  * ":import * as Name from 'filename'"
1408a7d6542SBram Moolenaar  */
1418a7d6542SBram Moolenaar     void
1428a7d6542SBram Moolenaar ex_import(exarg_T *eap)
1438a7d6542SBram Moolenaar {
144*9721fb4eSBram Moolenaar     char_u *cmd_end = handle_import(eap->arg, NULL, current_sctx.sc_sid, NULL);
1458a7d6542SBram Moolenaar 
1468a7d6542SBram Moolenaar     if (cmd_end != NULL)
1478a7d6542SBram Moolenaar 	eap->nextcmd = check_nextcmd(cmd_end);
1488a7d6542SBram Moolenaar }
1498a7d6542SBram Moolenaar 
1508a7d6542SBram Moolenaar /*
151f2d5c240SBram Moolenaar  * Find an exported item in "sid" matching the name at "*argp".
152f2d5c240SBram Moolenaar  * When it is a variable return the index.
153f2d5c240SBram Moolenaar  * When it is a user function return "*ufunc".
154f2d5c240SBram Moolenaar  * When not found returns -1 and "*ufunc" is NULL.
155f2d5c240SBram Moolenaar  */
156f2d5c240SBram Moolenaar     int
157f2d5c240SBram Moolenaar find_exported(
158f2d5c240SBram Moolenaar 	int	    sid,
159f2d5c240SBram Moolenaar 	char_u	    **argp,
160f2d5c240SBram Moolenaar 	int	    *name_len,
161f2d5c240SBram Moolenaar 	ufunc_T	    **ufunc,
162f2d5c240SBram Moolenaar 	type_T	    **type)
163f2d5c240SBram Moolenaar {
164f2d5c240SBram Moolenaar     char_u	*name = *argp;
165f2d5c240SBram Moolenaar     char_u	*arg = *argp;
166f2d5c240SBram Moolenaar     int		cc;
167f2d5c240SBram Moolenaar     int		idx = -1;
168f2d5c240SBram Moolenaar     svar_T	*sv;
169f2d5c240SBram Moolenaar     scriptitem_T *script = SCRIPT_ITEM(sid);
170f2d5c240SBram Moolenaar 
171f2d5c240SBram Moolenaar     // isolate one name
172fa29c8abSBram Moolenaar     while (eval_isnamec(*arg))
173f2d5c240SBram Moolenaar 	++arg;
174f2d5c240SBram Moolenaar     *name_len = (int)(arg - name);
175f2d5c240SBram Moolenaar 
176f2d5c240SBram Moolenaar     // find name in "script"
177f2d5c240SBram Moolenaar     // TODO: also find script-local user function
178f2d5c240SBram Moolenaar     cc = *arg;
179f2d5c240SBram Moolenaar     *arg = NUL;
180f2d5c240SBram Moolenaar     idx = get_script_item_idx(sid, name, FALSE);
181f2d5c240SBram Moolenaar     if (idx >= 0)
182f2d5c240SBram Moolenaar     {
183f2d5c240SBram Moolenaar 	sv = ((svar_T *)script->sn_var_vals.ga_data) + idx;
184f2d5c240SBram Moolenaar 	if (!sv->sv_export)
185f2d5c240SBram Moolenaar 	{
186f2d5c240SBram Moolenaar 	    semsg(_("E1049: Item not exported in script: %s"), name);
187f2d5c240SBram Moolenaar 	    *arg = cc;
188f2d5c240SBram Moolenaar 	    return -1;
189f2d5c240SBram Moolenaar 	}
190f2d5c240SBram Moolenaar 	*type = sv->sv_type;
191f2d5c240SBram Moolenaar 	*ufunc = NULL;
192f2d5c240SBram Moolenaar     }
193f2d5c240SBram Moolenaar     else
194f2d5c240SBram Moolenaar     {
195f2d5c240SBram Moolenaar 	char_u	buffer[200];
196f2d5c240SBram Moolenaar 	char_u	*funcname;
197f2d5c240SBram Moolenaar 
198f2d5c240SBram Moolenaar 	// it could be a user function.
199f2d5c240SBram Moolenaar 	if (STRLEN(name) < sizeof(buffer) - 10)
200f2d5c240SBram Moolenaar 	    funcname = buffer;
201f2d5c240SBram Moolenaar 	else
202f2d5c240SBram Moolenaar 	{
203f2d5c240SBram Moolenaar 	    funcname = alloc(STRLEN(name) + 10);
204f2d5c240SBram Moolenaar 	    if (funcname == NULL)
205f2d5c240SBram Moolenaar 	    {
206f2d5c240SBram Moolenaar 		*arg = cc;
207f2d5c240SBram Moolenaar 		return -1;
208f2d5c240SBram Moolenaar 	    }
209f2d5c240SBram Moolenaar 	}
210f2d5c240SBram Moolenaar 	funcname[0] = K_SPECIAL;
211f2d5c240SBram Moolenaar 	funcname[1] = KS_EXTRA;
212f2d5c240SBram Moolenaar 	funcname[2] = (int)KE_SNR;
213f2d5c240SBram Moolenaar 	sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name);
2144c17ad94SBram Moolenaar 	*ufunc = find_func(funcname, FALSE, NULL);
215f2d5c240SBram Moolenaar 	if (funcname != buffer)
216f2d5c240SBram Moolenaar 	    vim_free(funcname);
217f2d5c240SBram Moolenaar 
218f2d5c240SBram Moolenaar 	if (*ufunc == NULL)
219f2d5c240SBram Moolenaar 	{
220f2d5c240SBram Moolenaar 	    semsg(_("E1048: Item not found in script: %s"), name);
221f2d5c240SBram Moolenaar 	    *arg = cc;
222f2d5c240SBram Moolenaar 	    return -1;
223f2d5c240SBram Moolenaar 	}
224f2d5c240SBram Moolenaar     }
225f2d5c240SBram Moolenaar     *arg = cc;
226f2d5c240SBram Moolenaar     arg = skipwhite(arg);
227f2d5c240SBram Moolenaar     *argp = arg;
228f2d5c240SBram Moolenaar 
229f2d5c240SBram Moolenaar     return idx;
230f2d5c240SBram Moolenaar }
231f2d5c240SBram Moolenaar 
232f2d5c240SBram Moolenaar /*
2338a7d6542SBram Moolenaar  * Handle an ":import" command and add the resulting imported_T to "gap", when
2348a7d6542SBram Moolenaar  * not NULL, or script "import_sid" sn_imports.
2358a7d6542SBram Moolenaar  * Returns a pointer to after the command or NULL in case of failure
2368a7d6542SBram Moolenaar  */
2378a7d6542SBram Moolenaar     char_u *
2385269bd2aSBram Moolenaar handle_import(char_u *arg_start, garray_T *gap, int import_sid, void *cctx)
2398a7d6542SBram Moolenaar {
2408a7d6542SBram Moolenaar     char_u	*arg = arg_start;
2418a7d6542SBram Moolenaar     char_u	*cmd_end;
2428a7d6542SBram Moolenaar     char_u	*as_ptr = NULL;
2438a7d6542SBram Moolenaar     char_u	*from_ptr;
2448a7d6542SBram Moolenaar     int		as_len = 0;
2458a7d6542SBram Moolenaar     int		ret = FAIL;
2468a7d6542SBram Moolenaar     typval_T	tv;
2478a7d6542SBram Moolenaar     int		sid = -1;
2488a7d6542SBram Moolenaar     int		res;
2498a7d6542SBram Moolenaar 
2508a7d6542SBram Moolenaar     if (*arg == '{')
2518a7d6542SBram Moolenaar     {
2528a7d6542SBram Moolenaar 	// skip over {item} list
2538a7d6542SBram Moolenaar 	while (*arg != NUL && *arg != '}')
2548a7d6542SBram Moolenaar 	    ++arg;
2558a7d6542SBram Moolenaar 	if (*arg == '}')
2568a7d6542SBram Moolenaar 	    arg = skipwhite(arg + 1);
2578a7d6542SBram Moolenaar     }
2588a7d6542SBram Moolenaar     else
2598a7d6542SBram Moolenaar     {
2608a7d6542SBram Moolenaar 	if (*arg == '*')
2618a7d6542SBram Moolenaar 	    arg = skipwhite(arg + 1);
262fa29c8abSBram Moolenaar 	else if (eval_isnamec1(*arg))
2638a7d6542SBram Moolenaar 	{
264fa29c8abSBram Moolenaar 	    while (eval_isnamec(*arg))
2658a7d6542SBram Moolenaar 		++arg;
2668a7d6542SBram Moolenaar 	    arg = skipwhite(arg);
2678a7d6542SBram Moolenaar 	}
2688a7d6542SBram Moolenaar 	if (STRNCMP("as", arg, 2) == 0 && VIM_ISWHITE(arg[2]))
2698a7d6542SBram Moolenaar 	{
2708a7d6542SBram Moolenaar 	    // skip over "as Name "
2718a7d6542SBram Moolenaar 	    arg = skipwhite(arg + 2);
2728a7d6542SBram Moolenaar 	    as_ptr = arg;
273fa29c8abSBram Moolenaar 	    if (eval_isnamec1(*arg))
274fa29c8abSBram Moolenaar 		while (eval_isnamec(*arg))
2758a7d6542SBram Moolenaar 		    ++arg;
2768a7d6542SBram Moolenaar 	    as_len = (int)(arg - as_ptr);
2778a7d6542SBram Moolenaar 	    arg = skipwhite(arg);
2785269bd2aSBram Moolenaar 	    if (check_defined(as_ptr, as_len, cctx) == FAIL)
2795269bd2aSBram Moolenaar 		return NULL;
2808a7d6542SBram Moolenaar 	}
2818a7d6542SBram Moolenaar 	else if (*arg_start == '*')
2828a7d6542SBram Moolenaar 	{
2838a7d6542SBram Moolenaar 	    emsg(_("E1045: Missing \"as\" after *"));
2848a7d6542SBram Moolenaar 	    return NULL;
2858a7d6542SBram Moolenaar 	}
2868a7d6542SBram Moolenaar     }
2878a7d6542SBram Moolenaar     if (STRNCMP("from", arg, 4) != 0 || !VIM_ISWHITE(arg[4]))
2888a7d6542SBram Moolenaar     {
289fa29c8abSBram Moolenaar 	emsg(_("E1070: Missing \"from\""));
2908a7d6542SBram Moolenaar 	return NULL;
2918a7d6542SBram Moolenaar     }
2928a7d6542SBram Moolenaar     from_ptr = arg;
2938a7d6542SBram Moolenaar     arg = skipwhite(arg + 4);
2948a7d6542SBram Moolenaar     tv.v_type = VAR_UNKNOWN;
2958a7d6542SBram Moolenaar     // TODO: should we accept any expression?
2968a7d6542SBram Moolenaar     if (*arg == '\'')
2978a7d6542SBram Moolenaar 	ret = get_lit_string_tv(&arg, &tv, TRUE);
2988a7d6542SBram Moolenaar     else if (*arg == '"')
2998a7d6542SBram Moolenaar 	ret = get_string_tv(&arg, &tv, TRUE);
3008a7d6542SBram Moolenaar     if (ret == FAIL || tv.vval.v_string == NULL || *tv.vval.v_string == NUL)
3018a7d6542SBram Moolenaar     {
302fa29c8abSBram Moolenaar 	emsg(_("E1071: Invalid string after \"from\""));
3038a7d6542SBram Moolenaar 	return NULL;
3048a7d6542SBram Moolenaar     }
3058a7d6542SBram Moolenaar     cmd_end = arg;
3068a7d6542SBram Moolenaar 
3078a7d6542SBram Moolenaar     // find script tv.vval.v_string
3088a7d6542SBram Moolenaar     if (*tv.vval.v_string == '.')
3098a7d6542SBram Moolenaar     {
3108a7d6542SBram Moolenaar 	size_t		len;
31121b9e977SBram Moolenaar 	scriptitem_T	*si = SCRIPT_ITEM(current_sctx.sc_sid);
3128a7d6542SBram Moolenaar 	char_u		*tail = gettail(si->sn_name);
3138a7d6542SBram Moolenaar 	char_u		*from_name;
3148a7d6542SBram Moolenaar 
3158a7d6542SBram Moolenaar 	// Relative to current script: "./name.vim", "../../name.vim".
3168a7d6542SBram Moolenaar 	len = STRLEN(si->sn_name) - STRLEN(tail) + STRLEN(tv.vval.v_string) + 2;
3178a7d6542SBram Moolenaar 	from_name = alloc((int)len);
3188a7d6542SBram Moolenaar 	if (from_name == NULL)
3198a7d6542SBram Moolenaar 	{
3208a7d6542SBram Moolenaar 	    clear_tv(&tv);
3218a7d6542SBram Moolenaar 	    return NULL;
3228a7d6542SBram Moolenaar 	}
3238a7d6542SBram Moolenaar 	vim_strncpy(from_name, si->sn_name, tail - si->sn_name);
3248a7d6542SBram Moolenaar 	add_pathsep(from_name);
3258a7d6542SBram Moolenaar 	STRCAT(from_name, tv.vval.v_string);
3268a7d6542SBram Moolenaar 	simplify_filename(from_name);
3278a7d6542SBram Moolenaar 
3288a7d6542SBram Moolenaar 	res = do_source(from_name, FALSE, DOSO_NONE, &sid);
3298a7d6542SBram Moolenaar 	vim_free(from_name);
3308a7d6542SBram Moolenaar     }
3318a7d6542SBram Moolenaar     else if (mch_isFullName(tv.vval.v_string))
3328a7d6542SBram Moolenaar     {
3338a7d6542SBram Moolenaar 	// Absolute path: "/tmp/name.vim"
3348a7d6542SBram Moolenaar 	res = do_source(tv.vval.v_string, FALSE, DOSO_NONE, &sid);
3358a7d6542SBram Moolenaar     }
3368a7d6542SBram Moolenaar     else
3378a7d6542SBram Moolenaar     {
3388a7d6542SBram Moolenaar 	size_t	    len = 7 + STRLEN(tv.vval.v_string) + 1;
3398a7d6542SBram Moolenaar 	char_u	    *from_name;
3408a7d6542SBram Moolenaar 
3418a7d6542SBram Moolenaar 	// Find file in "import" subdirs in 'runtimepath'.
3428a7d6542SBram Moolenaar 	from_name = alloc((int)len);
3438a7d6542SBram Moolenaar 	if (from_name == NULL)
3448a7d6542SBram Moolenaar 	{
3458a7d6542SBram Moolenaar 	    clear_tv(&tv);
3468a7d6542SBram Moolenaar 	    return NULL;
3478a7d6542SBram Moolenaar 	}
3488a7d6542SBram Moolenaar 	vim_snprintf((char *)from_name, len, "import/%s", tv.vval.v_string);
3498a7d6542SBram Moolenaar 	res = source_in_path(p_rtp, from_name, DIP_NOAFTER, &sid);
3508a7d6542SBram Moolenaar 	vim_free(from_name);
3518a7d6542SBram Moolenaar     }
3528a7d6542SBram Moolenaar 
3538a7d6542SBram Moolenaar     if (res == FAIL || sid <= 0)
3548a7d6542SBram Moolenaar     {
3558a7d6542SBram Moolenaar 	semsg(_("E1053: Could not import \"%s\""), tv.vval.v_string);
3568a7d6542SBram Moolenaar 	clear_tv(&tv);
3578a7d6542SBram Moolenaar 	return NULL;
3588a7d6542SBram Moolenaar     }
3598a7d6542SBram Moolenaar     clear_tv(&tv);
3608a7d6542SBram Moolenaar 
3618a7d6542SBram Moolenaar     if (*arg_start == '*')
3628a7d6542SBram Moolenaar     {
3638a7d6542SBram Moolenaar 	imported_T *imported = new_imported(gap != NULL ? gap
36421b9e977SBram Moolenaar 					: &SCRIPT_ITEM(import_sid)->sn_imports);
3658a7d6542SBram Moolenaar 
3668a7d6542SBram Moolenaar 	if (imported == NULL)
3678a7d6542SBram Moolenaar 	    return NULL;
3688a7d6542SBram Moolenaar 	imported->imp_name = vim_strnsave(as_ptr, as_len);
3698a7d6542SBram Moolenaar 	imported->imp_sid = sid;
3708a7d6542SBram Moolenaar 	imported->imp_all = TRUE;
3718a7d6542SBram Moolenaar     }
3728a7d6542SBram Moolenaar     else
3738a7d6542SBram Moolenaar     {
3748a7d6542SBram Moolenaar 	arg = arg_start;
3758a7d6542SBram Moolenaar 	if (*arg == '{')
3768a7d6542SBram Moolenaar 	    arg = skipwhite(arg + 1);
3778a7d6542SBram Moolenaar 	for (;;)
3788a7d6542SBram Moolenaar 	{
3798a7d6542SBram Moolenaar 	    char_u	*name = arg;
3808a7d6542SBram Moolenaar 	    int		name_len;
3818a7d6542SBram Moolenaar 	    int		idx;
3828a7d6542SBram Moolenaar 	    imported_T	*imported;
383f2d5c240SBram Moolenaar 	    ufunc_T	*ufunc = NULL;
384f2d5c240SBram Moolenaar 	    type_T	*type;
3858a7d6542SBram Moolenaar 
386f2d5c240SBram Moolenaar 	    idx = find_exported(sid, &arg, &name_len, &ufunc, &type);
3878a7d6542SBram Moolenaar 
388f2d5c240SBram Moolenaar 	    if (idx < 0 && ufunc == NULL)
3898a7d6542SBram Moolenaar 		return NULL;
3908a7d6542SBram Moolenaar 
3915269bd2aSBram Moolenaar 	    if (check_defined(name, name_len, cctx) == FAIL)
3925269bd2aSBram Moolenaar 		return NULL;
3935269bd2aSBram Moolenaar 
3948a7d6542SBram Moolenaar 	    imported = new_imported(gap != NULL ? gap
39521b9e977SBram Moolenaar 				       : &SCRIPT_ITEM(import_sid)->sn_imports);
3968a7d6542SBram Moolenaar 	    if (imported == NULL)
3978a7d6542SBram Moolenaar 		return NULL;
3988a7d6542SBram Moolenaar 
3998a7d6542SBram Moolenaar 	    // TODO: check for "as" following
4008a7d6542SBram Moolenaar 	    // imported->imp_name = vim_strnsave(as_ptr, as_len);
4018a7d6542SBram Moolenaar 	    imported->imp_name = vim_strnsave(name, name_len);
4028a7d6542SBram Moolenaar 	    imported->imp_sid = sid;
4038a7d6542SBram Moolenaar 	    if (idx >= 0)
4048a7d6542SBram Moolenaar 	    {
405f2d5c240SBram Moolenaar 		imported->imp_type = type;
4068a7d6542SBram Moolenaar 		imported->imp_var_vals_idx = idx;
4078a7d6542SBram Moolenaar 	    }
4088a7d6542SBram Moolenaar 	    else
4098a7d6542SBram Moolenaar 		imported->imp_funcname = ufunc->uf_name;
4108a7d6542SBram Moolenaar 
4118a7d6542SBram Moolenaar 	    arg = skipwhite(arg);
4128a7d6542SBram Moolenaar 	    if (*arg_start != '{')
4138a7d6542SBram Moolenaar 		break;
4148a7d6542SBram Moolenaar 	    if (*arg == '}')
4158a7d6542SBram Moolenaar 	    {
4168a7d6542SBram Moolenaar 		arg = skipwhite(arg + 1);
4178a7d6542SBram Moolenaar 		break;
4188a7d6542SBram Moolenaar 	    }
4198a7d6542SBram Moolenaar 
4208a7d6542SBram Moolenaar 	    if (*arg != ',')
4218a7d6542SBram Moolenaar 	    {
4228a7d6542SBram Moolenaar 		emsg(_("E1046: Missing comma in import"));
4238a7d6542SBram Moolenaar 		return NULL;
4248a7d6542SBram Moolenaar 	    }
4258a7d6542SBram Moolenaar 	    arg = skipwhite(arg + 1);
4268a7d6542SBram Moolenaar 	}
4278a7d6542SBram Moolenaar 	if (arg != from_ptr)
4288a7d6542SBram Moolenaar 	{
429fa29c8abSBram Moolenaar 	    // cannot happen, just in case the above has a flaw
4308a7d6542SBram Moolenaar 	    emsg(_("E1047: syntax error in import"));
4318a7d6542SBram Moolenaar 	    return NULL;
4328a7d6542SBram Moolenaar 	}
4338a7d6542SBram Moolenaar     }
4348a7d6542SBram Moolenaar     return cmd_end;
4358a7d6542SBram Moolenaar }
4368a7d6542SBram Moolenaar 
4378a7d6542SBram Moolenaar #endif // FEAT_EVAL
438