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 208a7d6542SBram Moolenaar static char e_needs_vim9[] = N_("E1042: import/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); 36*09689a02SBram Moolenaar garray_T *gap; 37*09689a02SBram Moolenaar garray_T func_ga; 38*09689a02SBram Moolenaar int idx; 39*09689a02SBram Moolenaar ufunc_T *ufunc; 408a7d6542SBram Moolenaar 418a7d6542SBram Moolenaar if (!getline_equal(eap->getline, eap->cookie, getsourceline)) 428a7d6542SBram Moolenaar { 438a7d6542SBram Moolenaar emsg(_("E1038: vim9script can only be used in a script")); 448a7d6542SBram Moolenaar return; 458a7d6542SBram Moolenaar } 468a7d6542SBram Moolenaar if (si->sn_had_command) 478a7d6542SBram Moolenaar { 488a7d6542SBram Moolenaar emsg(_("E1039: vim9script must be the first command in a script")); 498a7d6542SBram Moolenaar return; 508a7d6542SBram Moolenaar } 518a7d6542SBram Moolenaar current_sctx.sc_version = SCRIPT_VERSION_VIM9; 528a7d6542SBram Moolenaar si->sn_version = SCRIPT_VERSION_VIM9; 538a7d6542SBram Moolenaar si->sn_had_command = TRUE; 54*09689a02SBram Moolenaar ga_init2(&func_ga, sizeof(ufunc_T *), 20); 558a7d6542SBram Moolenaar 568a7d6542SBram Moolenaar if (STRCMP(p_cpo, CPO_VIM) != 0) 578a7d6542SBram Moolenaar { 588a7d6542SBram Moolenaar si->sn_save_cpo = p_cpo; 598a7d6542SBram Moolenaar p_cpo = vim_strsave((char_u *)CPO_VIM); 608a7d6542SBram Moolenaar } 61*09689a02SBram Moolenaar 62*09689a02SBram Moolenaar // Make a pass through the script to find: 63*09689a02SBram Moolenaar // - function declarations 64*09689a02SBram Moolenaar // - variable and constant declarations 65*09689a02SBram Moolenaar // - imports 66*09689a02SBram Moolenaar // The types are recognized, so that they can be used when compiling a 67*09689a02SBram Moolenaar // function. 68*09689a02SBram Moolenaar gap = source_get_line_ga(eap->cookie); 69*09689a02SBram Moolenaar for (;;) 70*09689a02SBram Moolenaar { 71*09689a02SBram Moolenaar char_u *line; 72*09689a02SBram Moolenaar char_u *p; 73*09689a02SBram Moolenaar 74*09689a02SBram Moolenaar if (ga_grow(gap, 1) == FAIL) 75*09689a02SBram Moolenaar return; 76*09689a02SBram Moolenaar line = eap->getline(':', eap->cookie, 0, TRUE); 77*09689a02SBram Moolenaar if (line == NULL) 78*09689a02SBram Moolenaar break; 79*09689a02SBram Moolenaar ((char_u **)(gap->ga_data))[gap->ga_len++] = line; 80*09689a02SBram Moolenaar line = skipwhite(line); 81*09689a02SBram Moolenaar p = line; 82*09689a02SBram Moolenaar if (checkforcmd(&p, "function", 2) || checkforcmd(&p, "def", 3)) 83*09689a02SBram Moolenaar { 84*09689a02SBram Moolenaar int lnum_start = SOURCING_LNUM - 1; 85*09689a02SBram Moolenaar 86*09689a02SBram Moolenaar // Handle :function and :def by calling def_function(). 87*09689a02SBram Moolenaar // It will read upto the matching :endded or :endfunction. 88*09689a02SBram Moolenaar eap->cmdidx = *line == 'f' ? CMD_function : CMD_def; 89*09689a02SBram Moolenaar eap->cmd = line; 90*09689a02SBram Moolenaar eap->arg = p; 91*09689a02SBram Moolenaar eap->forceit = FALSE; 92*09689a02SBram Moolenaar ufunc = def_function(eap, NULL, NULL, FALSE); 93*09689a02SBram Moolenaar 94*09689a02SBram Moolenaar if (ufunc != NULL && *line == 'd' && ga_grow(&func_ga, 1) == OK) 95*09689a02SBram Moolenaar { 96*09689a02SBram Moolenaar // Add the function to the list of :def functions, so that it 97*09689a02SBram Moolenaar // can be referenced by index. It's compiled below. 98*09689a02SBram Moolenaar add_def_function(ufunc); 99*09689a02SBram Moolenaar ((ufunc_T **)(func_ga.ga_data))[func_ga.ga_len++] = ufunc; 100*09689a02SBram Moolenaar } 101*09689a02SBram Moolenaar 102*09689a02SBram Moolenaar // Store empty lines in place of the function, we don't need to 103*09689a02SBram Moolenaar // process it again. 104*09689a02SBram Moolenaar vim_free(((char_u **)(gap->ga_data))[--gap->ga_len]); 105*09689a02SBram Moolenaar if (ga_grow(gap, SOURCING_LNUM - lnum_start) == OK) 106*09689a02SBram Moolenaar while (lnum_start < SOURCING_LNUM) 107*09689a02SBram Moolenaar { 108*09689a02SBram Moolenaar // getsourceline() will skip over NULL lines. 109*09689a02SBram Moolenaar ((char_u **)(gap->ga_data))[gap->ga_len++] = NULL; 110*09689a02SBram Moolenaar ++lnum_start; 111*09689a02SBram Moolenaar } 112*09689a02SBram Moolenaar } 113*09689a02SBram Moolenaar else if (checkforcmd(&p, "let", 3) || checkforcmd(&p, "const", 4)) 114*09689a02SBram Moolenaar { 115*09689a02SBram Moolenaar eap->cmd = line; 116*09689a02SBram Moolenaar eap->arg = p; 117*09689a02SBram Moolenaar eap->forceit = FALSE; 118*09689a02SBram Moolenaar eap->cmdidx = *line == 'l' ? CMD_let: CMD_const; 119*09689a02SBram Moolenaar 120*09689a02SBram Moolenaar // The command will be executed again, it's OK to redefine the 121*09689a02SBram Moolenaar // variable then. 122*09689a02SBram Moolenaar ex_let_const(eap, TRUE); 123*09689a02SBram Moolenaar } 124*09689a02SBram Moolenaar else if (checkforcmd(&p, "import", 3)) 125*09689a02SBram Moolenaar { 126*09689a02SBram Moolenaar eap->arg = p; 127*09689a02SBram Moolenaar ex_import(eap); 128*09689a02SBram Moolenaar 129*09689a02SBram Moolenaar // Store empty line, we don't need to process the command again. 130*09689a02SBram Moolenaar vim_free(((char_u **)(gap->ga_data))[--gap->ga_len]); 131*09689a02SBram Moolenaar ((char_u **)(gap->ga_data))[gap->ga_len++] = NULL; 132*09689a02SBram Moolenaar } 133*09689a02SBram Moolenaar } 134*09689a02SBram Moolenaar 135*09689a02SBram Moolenaar // Compile the :def functions. 136*09689a02SBram Moolenaar for (idx = 0; idx < func_ga.ga_len; ++idx) 137*09689a02SBram Moolenaar { 138*09689a02SBram Moolenaar ufunc = ((ufunc_T **)(func_ga.ga_data))[idx]; 139*09689a02SBram Moolenaar compile_def_function(ufunc, FALSE, NULL); 140*09689a02SBram Moolenaar } 141*09689a02SBram Moolenaar ga_clear(&func_ga); 142*09689a02SBram Moolenaar 143*09689a02SBram Moolenaar // Return to process the commands at the script level. 144*09689a02SBram Moolenaar source_use_line_ga(eap->cookie); 1458a7d6542SBram Moolenaar } 1468a7d6542SBram Moolenaar 1478a7d6542SBram Moolenaar /* 1488a7d6542SBram Moolenaar * ":export let Name: type" 1498a7d6542SBram Moolenaar * ":export const Name: type" 1508a7d6542SBram Moolenaar * ":export def Name(..." 1518a7d6542SBram Moolenaar * ":export class Name ..." 1528a7d6542SBram Moolenaar * 1538a7d6542SBram Moolenaar * ":export {Name, ...}" 1548a7d6542SBram Moolenaar */ 1558a7d6542SBram Moolenaar void 156*09689a02SBram Moolenaar ex_export(exarg_T *eap) 1578a7d6542SBram Moolenaar { 1588a7d6542SBram Moolenaar if (current_sctx.sc_version != SCRIPT_VERSION_VIM9) 1598a7d6542SBram Moolenaar { 1608a7d6542SBram Moolenaar emsg(_(e_needs_vim9)); 1618a7d6542SBram Moolenaar return; 1628a7d6542SBram Moolenaar } 1638a7d6542SBram Moolenaar 1648a7d6542SBram Moolenaar eap->cmd = eap->arg; 1658a7d6542SBram Moolenaar (void)find_ex_command(eap, NULL, lookup_scriptvar, NULL); 1668a7d6542SBram Moolenaar switch (eap->cmdidx) 1678a7d6542SBram Moolenaar { 1688a7d6542SBram Moolenaar case CMD_let: 1698a7d6542SBram Moolenaar case CMD_const: 1708a7d6542SBram Moolenaar case CMD_def: 1718a7d6542SBram Moolenaar // case CMD_class: 1728a7d6542SBram Moolenaar is_export = TRUE; 1738a7d6542SBram Moolenaar do_cmdline(eap->cmd, eap->getline, eap->cookie, 1748a7d6542SBram Moolenaar DOCMD_VERBOSE + DOCMD_NOWAIT); 1758a7d6542SBram Moolenaar 1768a7d6542SBram Moolenaar // The command will reset "is_export" when exporting an item. 1778a7d6542SBram Moolenaar if (is_export) 1788a7d6542SBram Moolenaar { 1798a7d6542SBram Moolenaar emsg(_("E1044: export with invalid argument")); 1808a7d6542SBram Moolenaar is_export = FALSE; 1818a7d6542SBram Moolenaar } 1828a7d6542SBram Moolenaar break; 1838a7d6542SBram Moolenaar default: 1848a7d6542SBram Moolenaar emsg(_("E1043: Invalid command after :export")); 1858a7d6542SBram Moolenaar break; 1868a7d6542SBram Moolenaar } 1878a7d6542SBram Moolenaar } 1888a7d6542SBram Moolenaar 1898a7d6542SBram Moolenaar /* 1908a7d6542SBram Moolenaar * Add a new imported item entry to the current script. 1918a7d6542SBram Moolenaar */ 1928a7d6542SBram Moolenaar static imported_T * 1938a7d6542SBram Moolenaar new_imported(garray_T *gap) 1948a7d6542SBram Moolenaar { 1958a7d6542SBram Moolenaar if (ga_grow(gap, 1) == OK) 1968a7d6542SBram Moolenaar return ((imported_T *)gap->ga_data + gap->ga_len++); 1978a7d6542SBram Moolenaar return NULL; 1988a7d6542SBram Moolenaar } 1998a7d6542SBram Moolenaar 2008a7d6542SBram Moolenaar /* 2018a7d6542SBram Moolenaar * Free all imported items in script "sid". 2028a7d6542SBram Moolenaar */ 2038a7d6542SBram Moolenaar void 2048a7d6542SBram Moolenaar free_imports(int sid) 2058a7d6542SBram Moolenaar { 20621b9e977SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM(sid); 2078a7d6542SBram Moolenaar int idx; 2088a7d6542SBram Moolenaar 2098a7d6542SBram Moolenaar for (idx = 0; idx < si->sn_imports.ga_len; ++idx) 2108a7d6542SBram Moolenaar { 21120431c9dSBram Moolenaar imported_T *imp = ((imported_T *)si->sn_imports.ga_data) + idx; 2128a7d6542SBram Moolenaar 2138a7d6542SBram Moolenaar vim_free(imp->imp_name); 2148a7d6542SBram Moolenaar } 2158a7d6542SBram Moolenaar ga_clear(&si->sn_imports); 21620431c9dSBram Moolenaar ga_clear(&si->sn_var_vals); 21720431c9dSBram Moolenaar ga_clear(&si->sn_type_list); 2188a7d6542SBram Moolenaar } 2198a7d6542SBram Moolenaar 2208a7d6542SBram Moolenaar /* 2218a7d6542SBram Moolenaar * ":import Item from 'filename'" 2228a7d6542SBram Moolenaar * ":import Item as Alias from 'filename'" 2238a7d6542SBram Moolenaar * ":import {Item} from 'filename'". 2248a7d6542SBram Moolenaar * ":import {Item as Alias} from 'filename'" 2258a7d6542SBram Moolenaar * ":import {Item, Item} from 'filename'" 2268a7d6542SBram Moolenaar * ":import {Item, Item as Alias} from 'filename'" 2278a7d6542SBram Moolenaar * 2288a7d6542SBram Moolenaar * ":import * as Name from 'filename'" 2298a7d6542SBram Moolenaar */ 2308a7d6542SBram Moolenaar void 2318a7d6542SBram Moolenaar ex_import(exarg_T *eap) 2328a7d6542SBram Moolenaar { 2338a7d6542SBram Moolenaar if (current_sctx.sc_version != SCRIPT_VERSION_VIM9) 2348a7d6542SBram Moolenaar emsg(_(e_needs_vim9)); 2358a7d6542SBram Moolenaar else 2368a7d6542SBram Moolenaar { 2375269bd2aSBram Moolenaar char_u *cmd_end = handle_import(eap->arg, NULL, 2385269bd2aSBram Moolenaar current_sctx.sc_sid, NULL); 2398a7d6542SBram Moolenaar 2408a7d6542SBram Moolenaar if (cmd_end != NULL) 2418a7d6542SBram Moolenaar eap->nextcmd = check_nextcmd(cmd_end); 2428a7d6542SBram Moolenaar } 2438a7d6542SBram Moolenaar } 2448a7d6542SBram Moolenaar 2458a7d6542SBram Moolenaar /* 246f2d5c240SBram Moolenaar * Find an exported item in "sid" matching the name at "*argp". 247f2d5c240SBram Moolenaar * When it is a variable return the index. 248f2d5c240SBram Moolenaar * When it is a user function return "*ufunc". 249f2d5c240SBram Moolenaar * When not found returns -1 and "*ufunc" is NULL. 250f2d5c240SBram Moolenaar */ 251f2d5c240SBram Moolenaar int 252f2d5c240SBram Moolenaar find_exported( 253f2d5c240SBram Moolenaar int sid, 254f2d5c240SBram Moolenaar char_u **argp, 255f2d5c240SBram Moolenaar int *name_len, 256f2d5c240SBram Moolenaar ufunc_T **ufunc, 257f2d5c240SBram Moolenaar type_T **type) 258f2d5c240SBram Moolenaar { 259f2d5c240SBram Moolenaar char_u *name = *argp; 260f2d5c240SBram Moolenaar char_u *arg = *argp; 261f2d5c240SBram Moolenaar int cc; 262f2d5c240SBram Moolenaar int idx = -1; 263f2d5c240SBram Moolenaar svar_T *sv; 264f2d5c240SBram Moolenaar scriptitem_T *script = SCRIPT_ITEM(sid); 265f2d5c240SBram Moolenaar 266f2d5c240SBram Moolenaar // isolate one name 267fa29c8abSBram Moolenaar while (eval_isnamec(*arg)) 268f2d5c240SBram Moolenaar ++arg; 269f2d5c240SBram Moolenaar *name_len = (int)(arg - name); 270f2d5c240SBram Moolenaar 271f2d5c240SBram Moolenaar // find name in "script" 272f2d5c240SBram Moolenaar // TODO: also find script-local user function 273f2d5c240SBram Moolenaar cc = *arg; 274f2d5c240SBram Moolenaar *arg = NUL; 275f2d5c240SBram Moolenaar idx = get_script_item_idx(sid, name, FALSE); 276f2d5c240SBram Moolenaar if (idx >= 0) 277f2d5c240SBram Moolenaar { 278f2d5c240SBram Moolenaar sv = ((svar_T *)script->sn_var_vals.ga_data) + idx; 279f2d5c240SBram Moolenaar if (!sv->sv_export) 280f2d5c240SBram Moolenaar { 281f2d5c240SBram Moolenaar semsg(_("E1049: Item not exported in script: %s"), name); 282f2d5c240SBram Moolenaar *arg = cc; 283f2d5c240SBram Moolenaar return -1; 284f2d5c240SBram Moolenaar } 285f2d5c240SBram Moolenaar *type = sv->sv_type; 286f2d5c240SBram Moolenaar *ufunc = NULL; 287f2d5c240SBram Moolenaar } 288f2d5c240SBram Moolenaar else 289f2d5c240SBram Moolenaar { 290f2d5c240SBram Moolenaar char_u buffer[200]; 291f2d5c240SBram Moolenaar char_u *funcname; 292f2d5c240SBram Moolenaar 293f2d5c240SBram Moolenaar // it could be a user function. 294f2d5c240SBram Moolenaar if (STRLEN(name) < sizeof(buffer) - 10) 295f2d5c240SBram Moolenaar funcname = buffer; 296f2d5c240SBram Moolenaar else 297f2d5c240SBram Moolenaar { 298f2d5c240SBram Moolenaar funcname = alloc(STRLEN(name) + 10); 299f2d5c240SBram Moolenaar if (funcname == NULL) 300f2d5c240SBram Moolenaar { 301f2d5c240SBram Moolenaar *arg = cc; 302f2d5c240SBram Moolenaar return -1; 303f2d5c240SBram Moolenaar } 304f2d5c240SBram Moolenaar } 305f2d5c240SBram Moolenaar funcname[0] = K_SPECIAL; 306f2d5c240SBram Moolenaar funcname[1] = KS_EXTRA; 307f2d5c240SBram Moolenaar funcname[2] = (int)KE_SNR; 308f2d5c240SBram Moolenaar sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name); 3094c17ad94SBram Moolenaar *ufunc = find_func(funcname, FALSE, NULL); 310f2d5c240SBram Moolenaar if (funcname != buffer) 311f2d5c240SBram Moolenaar vim_free(funcname); 312f2d5c240SBram Moolenaar 313f2d5c240SBram Moolenaar if (*ufunc == NULL) 314f2d5c240SBram Moolenaar { 315f2d5c240SBram Moolenaar semsg(_("E1048: Item not found in script: %s"), name); 316f2d5c240SBram Moolenaar *arg = cc; 317f2d5c240SBram Moolenaar return -1; 318f2d5c240SBram Moolenaar } 319f2d5c240SBram Moolenaar } 320f2d5c240SBram Moolenaar *arg = cc; 321f2d5c240SBram Moolenaar arg = skipwhite(arg); 322f2d5c240SBram Moolenaar *argp = arg; 323f2d5c240SBram Moolenaar 324f2d5c240SBram Moolenaar return idx; 325f2d5c240SBram Moolenaar } 326f2d5c240SBram Moolenaar 327f2d5c240SBram Moolenaar /* 3288a7d6542SBram Moolenaar * Handle an ":import" command and add the resulting imported_T to "gap", when 3298a7d6542SBram Moolenaar * not NULL, or script "import_sid" sn_imports. 3308a7d6542SBram Moolenaar * Returns a pointer to after the command or NULL in case of failure 3318a7d6542SBram Moolenaar */ 3328a7d6542SBram Moolenaar char_u * 3335269bd2aSBram Moolenaar handle_import(char_u *arg_start, garray_T *gap, int import_sid, void *cctx) 3348a7d6542SBram Moolenaar { 3358a7d6542SBram Moolenaar char_u *arg = arg_start; 3368a7d6542SBram Moolenaar char_u *cmd_end; 3378a7d6542SBram Moolenaar char_u *as_ptr = NULL; 3388a7d6542SBram Moolenaar char_u *from_ptr; 3398a7d6542SBram Moolenaar int as_len = 0; 3408a7d6542SBram Moolenaar int ret = FAIL; 3418a7d6542SBram Moolenaar typval_T tv; 3428a7d6542SBram Moolenaar int sid = -1; 3438a7d6542SBram Moolenaar int res; 3448a7d6542SBram Moolenaar 3458a7d6542SBram Moolenaar if (*arg == '{') 3468a7d6542SBram Moolenaar { 3478a7d6542SBram Moolenaar // skip over {item} list 3488a7d6542SBram Moolenaar while (*arg != NUL && *arg != '}') 3498a7d6542SBram Moolenaar ++arg; 3508a7d6542SBram Moolenaar if (*arg == '}') 3518a7d6542SBram Moolenaar arg = skipwhite(arg + 1); 3528a7d6542SBram Moolenaar } 3538a7d6542SBram Moolenaar else 3548a7d6542SBram Moolenaar { 3558a7d6542SBram Moolenaar if (*arg == '*') 3568a7d6542SBram Moolenaar arg = skipwhite(arg + 1); 357fa29c8abSBram Moolenaar else if (eval_isnamec1(*arg)) 3588a7d6542SBram Moolenaar { 359fa29c8abSBram Moolenaar while (eval_isnamec(*arg)) 3608a7d6542SBram Moolenaar ++arg; 3618a7d6542SBram Moolenaar arg = skipwhite(arg); 3628a7d6542SBram Moolenaar } 3638a7d6542SBram Moolenaar if (STRNCMP("as", arg, 2) == 0 && VIM_ISWHITE(arg[2])) 3648a7d6542SBram Moolenaar { 3658a7d6542SBram Moolenaar // skip over "as Name " 3668a7d6542SBram Moolenaar arg = skipwhite(arg + 2); 3678a7d6542SBram Moolenaar as_ptr = arg; 368fa29c8abSBram Moolenaar if (eval_isnamec1(*arg)) 369fa29c8abSBram Moolenaar while (eval_isnamec(*arg)) 3708a7d6542SBram Moolenaar ++arg; 3718a7d6542SBram Moolenaar as_len = (int)(arg - as_ptr); 3728a7d6542SBram Moolenaar arg = skipwhite(arg); 3735269bd2aSBram Moolenaar if (check_defined(as_ptr, as_len, cctx) == FAIL) 3745269bd2aSBram Moolenaar return NULL; 3758a7d6542SBram Moolenaar } 3768a7d6542SBram Moolenaar else if (*arg_start == '*') 3778a7d6542SBram Moolenaar { 3788a7d6542SBram Moolenaar emsg(_("E1045: Missing \"as\" after *")); 3798a7d6542SBram Moolenaar return NULL; 3808a7d6542SBram Moolenaar } 3818a7d6542SBram Moolenaar } 3828a7d6542SBram Moolenaar if (STRNCMP("from", arg, 4) != 0 || !VIM_ISWHITE(arg[4])) 3838a7d6542SBram Moolenaar { 384fa29c8abSBram Moolenaar emsg(_("E1070: Missing \"from\"")); 3858a7d6542SBram Moolenaar return NULL; 3868a7d6542SBram Moolenaar } 3878a7d6542SBram Moolenaar from_ptr = arg; 3888a7d6542SBram Moolenaar arg = skipwhite(arg + 4); 3898a7d6542SBram Moolenaar tv.v_type = VAR_UNKNOWN; 3908a7d6542SBram Moolenaar // TODO: should we accept any expression? 3918a7d6542SBram Moolenaar if (*arg == '\'') 3928a7d6542SBram Moolenaar ret = get_lit_string_tv(&arg, &tv, TRUE); 3938a7d6542SBram Moolenaar else if (*arg == '"') 3948a7d6542SBram Moolenaar ret = get_string_tv(&arg, &tv, TRUE); 3958a7d6542SBram Moolenaar if (ret == FAIL || tv.vval.v_string == NULL || *tv.vval.v_string == NUL) 3968a7d6542SBram Moolenaar { 397fa29c8abSBram Moolenaar emsg(_("E1071: Invalid string after \"from\"")); 3988a7d6542SBram Moolenaar return NULL; 3998a7d6542SBram Moolenaar } 4008a7d6542SBram Moolenaar cmd_end = arg; 4018a7d6542SBram Moolenaar 4028a7d6542SBram Moolenaar // find script tv.vval.v_string 4038a7d6542SBram Moolenaar if (*tv.vval.v_string == '.') 4048a7d6542SBram Moolenaar { 4058a7d6542SBram Moolenaar size_t len; 40621b9e977SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); 4078a7d6542SBram Moolenaar char_u *tail = gettail(si->sn_name); 4088a7d6542SBram Moolenaar char_u *from_name; 4098a7d6542SBram Moolenaar 4108a7d6542SBram Moolenaar // Relative to current script: "./name.vim", "../../name.vim". 4118a7d6542SBram Moolenaar len = STRLEN(si->sn_name) - STRLEN(tail) + STRLEN(tv.vval.v_string) + 2; 4128a7d6542SBram Moolenaar from_name = alloc((int)len); 4138a7d6542SBram Moolenaar if (from_name == NULL) 4148a7d6542SBram Moolenaar { 4158a7d6542SBram Moolenaar clear_tv(&tv); 4168a7d6542SBram Moolenaar return NULL; 4178a7d6542SBram Moolenaar } 4188a7d6542SBram Moolenaar vim_strncpy(from_name, si->sn_name, tail - si->sn_name); 4198a7d6542SBram Moolenaar add_pathsep(from_name); 4208a7d6542SBram Moolenaar STRCAT(from_name, tv.vval.v_string); 4218a7d6542SBram Moolenaar simplify_filename(from_name); 4228a7d6542SBram Moolenaar 4238a7d6542SBram Moolenaar res = do_source(from_name, FALSE, DOSO_NONE, &sid); 4248a7d6542SBram Moolenaar vim_free(from_name); 4258a7d6542SBram Moolenaar } 4268a7d6542SBram Moolenaar else if (mch_isFullName(tv.vval.v_string)) 4278a7d6542SBram Moolenaar { 4288a7d6542SBram Moolenaar // Absolute path: "/tmp/name.vim" 4298a7d6542SBram Moolenaar res = do_source(tv.vval.v_string, FALSE, DOSO_NONE, &sid); 4308a7d6542SBram Moolenaar } 4318a7d6542SBram Moolenaar else 4328a7d6542SBram Moolenaar { 4338a7d6542SBram Moolenaar size_t len = 7 + STRLEN(tv.vval.v_string) + 1; 4348a7d6542SBram Moolenaar char_u *from_name; 4358a7d6542SBram Moolenaar 4368a7d6542SBram Moolenaar // Find file in "import" subdirs in 'runtimepath'. 4378a7d6542SBram Moolenaar from_name = alloc((int)len); 4388a7d6542SBram Moolenaar if (from_name == NULL) 4398a7d6542SBram Moolenaar { 4408a7d6542SBram Moolenaar clear_tv(&tv); 4418a7d6542SBram Moolenaar return NULL; 4428a7d6542SBram Moolenaar } 4438a7d6542SBram Moolenaar vim_snprintf((char *)from_name, len, "import/%s", tv.vval.v_string); 4448a7d6542SBram Moolenaar res = source_in_path(p_rtp, from_name, DIP_NOAFTER, &sid); 4458a7d6542SBram Moolenaar vim_free(from_name); 4468a7d6542SBram Moolenaar } 4478a7d6542SBram Moolenaar 4488a7d6542SBram Moolenaar if (res == FAIL || sid <= 0) 4498a7d6542SBram Moolenaar { 4508a7d6542SBram Moolenaar semsg(_("E1053: Could not import \"%s\""), tv.vval.v_string); 4518a7d6542SBram Moolenaar clear_tv(&tv); 4528a7d6542SBram Moolenaar return NULL; 4538a7d6542SBram Moolenaar } 4548a7d6542SBram Moolenaar clear_tv(&tv); 4558a7d6542SBram Moolenaar 4568a7d6542SBram Moolenaar if (*arg_start == '*') 4578a7d6542SBram Moolenaar { 4588a7d6542SBram Moolenaar imported_T *imported = new_imported(gap != NULL ? gap 45921b9e977SBram Moolenaar : &SCRIPT_ITEM(import_sid)->sn_imports); 4608a7d6542SBram Moolenaar 4618a7d6542SBram Moolenaar if (imported == NULL) 4628a7d6542SBram Moolenaar return NULL; 4638a7d6542SBram Moolenaar imported->imp_name = vim_strnsave(as_ptr, as_len); 4648a7d6542SBram Moolenaar imported->imp_sid = sid; 4658a7d6542SBram Moolenaar imported->imp_all = TRUE; 4668a7d6542SBram Moolenaar } 4678a7d6542SBram Moolenaar else 4688a7d6542SBram Moolenaar { 4698a7d6542SBram Moolenaar arg = arg_start; 4708a7d6542SBram Moolenaar if (*arg == '{') 4718a7d6542SBram Moolenaar arg = skipwhite(arg + 1); 4728a7d6542SBram Moolenaar for (;;) 4738a7d6542SBram Moolenaar { 4748a7d6542SBram Moolenaar char_u *name = arg; 4758a7d6542SBram Moolenaar int name_len; 4768a7d6542SBram Moolenaar int idx; 4778a7d6542SBram Moolenaar imported_T *imported; 478f2d5c240SBram Moolenaar ufunc_T *ufunc = NULL; 479f2d5c240SBram Moolenaar type_T *type; 4808a7d6542SBram Moolenaar 481f2d5c240SBram Moolenaar idx = find_exported(sid, &arg, &name_len, &ufunc, &type); 4828a7d6542SBram Moolenaar 483f2d5c240SBram Moolenaar if (idx < 0 && ufunc == NULL) 4848a7d6542SBram Moolenaar return NULL; 4858a7d6542SBram Moolenaar 4865269bd2aSBram Moolenaar if (check_defined(name, name_len, cctx) == FAIL) 4875269bd2aSBram Moolenaar return NULL; 4885269bd2aSBram Moolenaar 4898a7d6542SBram Moolenaar imported = new_imported(gap != NULL ? gap 49021b9e977SBram Moolenaar : &SCRIPT_ITEM(import_sid)->sn_imports); 4918a7d6542SBram Moolenaar if (imported == NULL) 4928a7d6542SBram Moolenaar return NULL; 4938a7d6542SBram Moolenaar 4948a7d6542SBram Moolenaar // TODO: check for "as" following 4958a7d6542SBram Moolenaar // imported->imp_name = vim_strnsave(as_ptr, as_len); 4968a7d6542SBram Moolenaar imported->imp_name = vim_strnsave(name, name_len); 4978a7d6542SBram Moolenaar imported->imp_sid = sid; 4988a7d6542SBram Moolenaar if (idx >= 0) 4998a7d6542SBram Moolenaar { 500f2d5c240SBram Moolenaar imported->imp_type = type; 5018a7d6542SBram Moolenaar imported->imp_var_vals_idx = idx; 5028a7d6542SBram Moolenaar } 5038a7d6542SBram Moolenaar else 5048a7d6542SBram Moolenaar imported->imp_funcname = ufunc->uf_name; 5058a7d6542SBram Moolenaar 5068a7d6542SBram Moolenaar arg = skipwhite(arg); 5078a7d6542SBram Moolenaar if (*arg_start != '{') 5088a7d6542SBram Moolenaar break; 5098a7d6542SBram Moolenaar if (*arg == '}') 5108a7d6542SBram Moolenaar { 5118a7d6542SBram Moolenaar arg = skipwhite(arg + 1); 5128a7d6542SBram Moolenaar break; 5138a7d6542SBram Moolenaar } 5148a7d6542SBram Moolenaar 5158a7d6542SBram Moolenaar if (*arg != ',') 5168a7d6542SBram Moolenaar { 5178a7d6542SBram Moolenaar emsg(_("E1046: Missing comma in import")); 5188a7d6542SBram Moolenaar return NULL; 5198a7d6542SBram Moolenaar } 5208a7d6542SBram Moolenaar arg = skipwhite(arg + 1); 5218a7d6542SBram Moolenaar } 5228a7d6542SBram Moolenaar if (arg != from_ptr) 5238a7d6542SBram Moolenaar { 524fa29c8abSBram Moolenaar // cannot happen, just in case the above has a flaw 5258a7d6542SBram Moolenaar emsg(_("E1047: syntax error in import")); 5268a7d6542SBram Moolenaar return NULL; 5278a7d6542SBram Moolenaar } 5288a7d6542SBram Moolenaar } 5298a7d6542SBram Moolenaar return cmd_end; 5308a7d6542SBram Moolenaar } 5318a7d6542SBram Moolenaar 5328a7d6542SBram Moolenaar #endif // FEAT_EVAL 533