mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.2.4650: "import autoload" only works with using 'runtimepath'
Problem: "import autoload" only works with using 'runtimepath'. Solution: Also support a relative and absolute file name.
This commit is contained in:
@@ -6,6 +6,8 @@ int estack_top_is_ufunc(ufunc_T *ufunc, long lnum);
|
||||
estack_T *estack_pop(void);
|
||||
char_u *estack_sfile(estack_arg_T which);
|
||||
void ex_runtime(exarg_T *eap);
|
||||
int find_script_by_name(char_u *name);
|
||||
int get_new_scriptitem_for_fname(int *error, char_u *fname);
|
||||
int do_in_path(char_u *path, char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie);
|
||||
int do_in_runtimepath(char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie);
|
||||
int source_runtime(char_u *name, int flags);
|
||||
|
@@ -8,6 +8,7 @@ char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, type_T **
|
||||
void emsg_funcname(char *ermsg, char_u *name);
|
||||
int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, evalarg_T *evalarg, funcexe_T *funcexe);
|
||||
char_u *fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error);
|
||||
void func_name_with_sid(char_u *name, int sid, char_u *buffer);
|
||||
ufunc_T *find_func_even_dead(char_u *name, int flags);
|
||||
ufunc_T *find_func(char_u *name, int is_global);
|
||||
int func_is_global(ufunc_T *ufunc);
|
||||
|
@@ -54,6 +54,7 @@ int generate_PCALL(cctx_T *cctx, int argcount, char_u *name, type_T *type, int a
|
||||
int generate_STRINGMEMBER(cctx_T *cctx, char_u *name, size_t len);
|
||||
int generate_ECHO(cctx_T *cctx, int with_white, int count);
|
||||
int generate_MULT_EXPR(cctx_T *cctx, isntype_T isn_type, int count);
|
||||
int generate_SOURCE(cctx_T *cctx, int sid);
|
||||
int generate_PUT(cctx_T *cctx, int regname, linenr_T lnum);
|
||||
int generate_EXEC_copy(cctx_T *cctx, isntype_T isntype, char_u *line);
|
||||
int generate_EXEC(cctx_T *cctx, isntype_T isntype, char_u *str);
|
||||
|
@@ -251,7 +251,7 @@ source_callback(char_u *fname, void *cookie)
|
||||
* Find an already loaded script "name".
|
||||
* If found returns its script ID. If not found returns -1.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
find_script_by_name(char_u *name)
|
||||
{
|
||||
int sid;
|
||||
@@ -320,6 +320,21 @@ get_new_scriptitem(int *error)
|
||||
return sid;
|
||||
}
|
||||
|
||||
int
|
||||
get_new_scriptitem_for_fname(int *error, char_u *fname)
|
||||
{
|
||||
int sid = get_new_scriptitem(error);
|
||||
|
||||
if (*error == OK)
|
||||
{
|
||||
scriptitem_T *si = SCRIPT_ITEM(sid);
|
||||
|
||||
si->sn_name = vim_strsave(fname);
|
||||
si->sn_state = SN_STATE_NOT_LOADED;
|
||||
}
|
||||
return sid;
|
||||
}
|
||||
|
||||
static void
|
||||
find_script_callback(char_u *fname, void *cookie)
|
||||
{
|
||||
@@ -329,17 +344,8 @@ find_script_callback(char_u *fname, void *cookie)
|
||||
|
||||
sid = find_script_by_name(fname);
|
||||
if (sid < 0)
|
||||
{
|
||||
// script does not exist yet, create a new scriptitem
|
||||
sid = get_new_scriptitem(&error);
|
||||
if (error == OK)
|
||||
{
|
||||
scriptitem_T *si = SCRIPT_ITEM(sid);
|
||||
|
||||
si->sn_name = vim_strsave(fname);
|
||||
si->sn_state = SN_STATE_NOT_LOADED;
|
||||
}
|
||||
}
|
||||
sid = get_new_scriptitem_for_fname(&error, fname);
|
||||
*ret_sid = sid;
|
||||
}
|
||||
#endif
|
||||
|
@@ -1833,7 +1833,7 @@ typedef struct {
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char_u *sn_name;
|
||||
char_u *sn_name; // full path of script file
|
||||
int sn_script_seq; // latest sctx_T sc_seq value
|
||||
|
||||
// "sn_vars" stores the s: variables currently valid. When leaving a block
|
||||
@@ -1864,9 +1864,12 @@ typedef struct
|
||||
char_u *sn_save_cpo; // 'cpo' value when :vim9script found
|
||||
char sn_is_vimrc; // .vimrc file, do not restore 'cpo'
|
||||
|
||||
// for "vim9script autoload" this is "dir#scriptname#"
|
||||
// for a Vim9 script under "rtp/autoload/" this is "dir#scriptname#"
|
||||
char_u *sn_autoload_prefix;
|
||||
|
||||
// TRUE for a script used with "import autoload './dirname/script.vim'"
|
||||
int sn_import_autoload;
|
||||
|
||||
# ifdef FEAT_PROFILE
|
||||
int sn_prof_on; // TRUE when script is/was profiled
|
||||
int sn_pr_force; // forceit: profile functions in this script
|
||||
|
@@ -318,6 +318,46 @@ def Test_disassemble_push()
|
||||
&rtp = save_rtp
|
||||
enddef
|
||||
|
||||
def Test_disassemble_import_autoload()
|
||||
writefile(['vim9script'], 'XimportAL.vim')
|
||||
|
||||
var lines =<< trim END
|
||||
vim9script
|
||||
import autoload './XimportAL.vim'
|
||||
|
||||
def AutoloadFunc()
|
||||
echo XimportAL.SomeFunc()
|
||||
echo XimportAL.someVar
|
||||
XimportAL.someVar = "yes"
|
||||
enddef
|
||||
|
||||
var res = execute('disass AutoloadFunc')
|
||||
assert_match('<SNR>\d*_AutoloadFunc.*' ..
|
||||
'echo XimportAL.SomeFunc()\_s*' ..
|
||||
'\d SOURCE /home/mool/vim/vim82/src/testdir/XimportAL.vim\_s*' ..
|
||||
'\d PUSHFUNC "<80><fd>R\d\+_SomeFunc"\_s*' ..
|
||||
'\d PCALL top (argc 0)\_s*' ..
|
||||
'\d PCALL end\_s*' ..
|
||||
'\d ECHO 1\_s*' ..
|
||||
|
||||
'echo XimportAL.someVar\_s*' ..
|
||||
'\d SOURCE .*/testdir/XimportAL.vim\_s*' ..
|
||||
'\d LOADEXPORT s:someVar from .*/testdir/XimportAL.vim\_s*' ..
|
||||
'\d ECHO 1\_s*' ..
|
||||
|
||||
'XimportAL.someVar = "yes"\_s*' ..
|
||||
'\d\+ PUSHS "yes"\_s*' ..
|
||||
'\d\+ SOURCE .*/testdir/XimportAL.vim\_s*' ..
|
||||
'\d\+ STOREEXPORT someVar in .*/testdir/XimportAL.vim\_s*' ..
|
||||
|
||||
'\d\+ RETURN void',
|
||||
res)
|
||||
END
|
||||
v9.CheckScriptSuccess(lines)
|
||||
|
||||
delete('XimportAL.vim')
|
||||
enddef
|
||||
|
||||
def s:ScriptFuncStore()
|
||||
var localnr = 1
|
||||
localnr = 2
|
||||
|
@@ -840,6 +840,135 @@ def Test_use_autoload_import_in_fold_expression()
|
||||
&rtp = save_rtp
|
||||
enddef
|
||||
|
||||
def Test_autoload_import_relative()
|
||||
var lines =<< trim END
|
||||
vim9script
|
||||
|
||||
g:loaded = 'yes'
|
||||
export def RelFunc(): string
|
||||
return 'relfunc'
|
||||
enddef
|
||||
def NotExported()
|
||||
echo 'not'
|
||||
enddef
|
||||
|
||||
export var someText = 'some text'
|
||||
var notexp = 'bad'
|
||||
END
|
||||
writefile(lines, 'XimportRel.vim')
|
||||
writefile(lines, 'XimportRel2.vim')
|
||||
writefile(lines, 'XimportRel3.vim')
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
g:loaded = 'no'
|
||||
import autoload './XimportRel.vim'
|
||||
assert_equal('no', g:loaded)
|
||||
|
||||
def AFunc(): string
|
||||
var res = ''
|
||||
res ..= XimportRel.RelFunc()
|
||||
res ..= '/'
|
||||
res ..= XimportRel.someText
|
||||
XimportRel.someText = 'from AFunc'
|
||||
return res
|
||||
enddef
|
||||
# script not loaded when compiling
|
||||
defcompile
|
||||
assert_equal('no', g:loaded)
|
||||
|
||||
assert_equal('relfunc/some text', AFunc())
|
||||
assert_equal('yes', g:loaded)
|
||||
unlet g:loaded
|
||||
|
||||
assert_equal('from AFunc', XimportRel.someText)
|
||||
XimportRel.someText = 'from script'
|
||||
assert_equal('from script', XimportRel.someText)
|
||||
END
|
||||
v9.CheckScriptSuccess(lines)
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
import autoload './XimportRel.vim'
|
||||
echo XimportRel.NotExported()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1049: Item not exported in script: NotExported', 3)
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
import autoload './XimportRel.vim'
|
||||
echo XimportRel.notexp
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1049: Item not exported in script: notexp', 3)
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
import autoload './XimportRel.vim'
|
||||
XimportRel.notexp = 'bad'
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1049: Item not exported in script: notexp', 3)
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
import autoload './XimportRel.vim'
|
||||
def Func()
|
||||
echo XimportRel.NotExported()
|
||||
enddef
|
||||
Func()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1049: Item not exported in script: NotExported', 1)
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
import autoload './XimportRel.vim'
|
||||
def Func()
|
||||
echo XimportRel.notexp
|
||||
enddef
|
||||
Func()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1049: Item not exported in script: notexp', 1)
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
import autoload './XimportRel.vim'
|
||||
def Func()
|
||||
XimportRel.notexp = 'bad'
|
||||
enddef
|
||||
Func()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1049: Item not exported in script: notexp', 1)
|
||||
|
||||
# does not fail if the script wasn't loaded yet
|
||||
g:loaded = 'no'
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
import autoload './XimportRel2.vim'
|
||||
def Func()
|
||||
echo XimportRel2.notexp
|
||||
enddef
|
||||
defcompile
|
||||
END
|
||||
v9.CheckScriptSuccess(lines)
|
||||
assert_equal('no', g:loaded)
|
||||
|
||||
# fails with a not loaded import
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
import autoload './XimportRel3.vim'
|
||||
def Func()
|
||||
XimportRel3.notexp = 'bad'
|
||||
enddef
|
||||
Func()
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1049: Item not exported in script: notexp', 1)
|
||||
assert_equal('yes', g:loaded)
|
||||
unlet g:loaded
|
||||
|
||||
delete('XimportRel.vim')
|
||||
delete('XimportRel2.vim')
|
||||
delete('XimportRel3.vim')
|
||||
enddef
|
||||
|
||||
func Test_import_in_diffexpr()
|
||||
CheckExecutable diff
|
||||
|
||||
@@ -2379,13 +2508,13 @@ def Test_import_autoload_fails()
|
||||
vim9script
|
||||
import autoload './doesNotExist.vim'
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1264:')
|
||||
v9.CheckScriptSuccess(lines)
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
import autoload '/dir/doesNotExist.vim'
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E1264:')
|
||||
v9.CheckScriptSuccess(lines)
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
|
@@ -1883,6 +1883,21 @@ fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error)
|
||||
return fname;
|
||||
}
|
||||
|
||||
/*
|
||||
* Concatenate the script ID and function name into "<SNR>99_name".
|
||||
* "buffer" must have size MAX_FUNC_NAME_LEN.
|
||||
*/
|
||||
void
|
||||
func_name_with_sid(char_u *name, int sid, char_u *buffer)
|
||||
{
|
||||
// A script-local function is stored as "<SNR>99_name".
|
||||
buffer[0] = K_SPECIAL;
|
||||
buffer[1] = KS_EXTRA;
|
||||
buffer[2] = (int)KE_SNR;
|
||||
vim_snprintf((char *)buffer + 3, MAX_FUNC_NAME_LEN - 3, "%ld_%s",
|
||||
(long)sid, name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a function "name" in script "sid".
|
||||
*/
|
||||
@@ -1890,17 +1905,12 @@ fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error)
|
||||
find_func_with_sid(char_u *name, int sid)
|
||||
{
|
||||
hashitem_T *hi;
|
||||
char_u buffer[200];
|
||||
char_u buffer[MAX_FUNC_NAME_LEN];
|
||||
|
||||
if (!SCRIPT_ID_VALID(sid))
|
||||
return NULL; // not in a script
|
||||
|
||||
// A script-local function is stored as "<SNR>99_name".
|
||||
buffer[0] = K_SPECIAL;
|
||||
buffer[1] = KS_EXTRA;
|
||||
buffer[2] = (int)KE_SNR;
|
||||
vim_snprintf((char *)buffer + 3, sizeof(buffer) - 3, "%ld_%s",
|
||||
(long)sid, name);
|
||||
func_name_with_sid(name, sid, buffer);
|
||||
hi = hash_find(&func_hashtab, buffer);
|
||||
if (!HASHITEM_EMPTY(hi))
|
||||
return HI2UF(hi);
|
||||
@@ -1914,7 +1924,7 @@ find_func_with_sid(char_u *name, int sid)
|
||||
find_func_with_prefix(char_u *name, int sid)
|
||||
{
|
||||
hashitem_T *hi;
|
||||
char_u buffer[200];
|
||||
char_u buffer[MAX_FUNC_NAME_LEN];
|
||||
scriptitem_T *si;
|
||||
|
||||
if (vim_strchr(name, AUTOLOAD_CHAR) != NULL)
|
||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
4650,
|
||||
/**/
|
||||
4649,
|
||||
/**/
|
||||
|
@@ -1571,6 +1571,9 @@ typedef UINT32_TYPEDEF UINT32_T;
|
||||
*/
|
||||
#define MAXMAPLEN 50
|
||||
|
||||
// maximum length of a function name, including SID and NUL
|
||||
#define MAX_FUNC_NAME_LEN 200
|
||||
|
||||
// Size in bytes of the hash used in the undo file.
|
||||
#define UNDO_HASH_SIZE 32
|
||||
|
||||
|
@@ -28,6 +28,8 @@ typedef enum {
|
||||
ISN_ECHOERR, // :echoerr with isn_arg.number items on top of stack
|
||||
ISN_RANGE, // compute range from isn_arg.string, push to stack
|
||||
ISN_SUBSTITUTE, // :s command with expression
|
||||
|
||||
ISN_SOURCE, // source autoload script, isn_arg.number is the script ID
|
||||
ISN_INSTR, // instructions compiled from expression
|
||||
|
||||
// get and set variables
|
||||
@@ -43,6 +45,7 @@ typedef enum {
|
||||
ISN_LOADWDICT, // push w: dict
|
||||
ISN_LOADTDICT, // push t: dict
|
||||
ISN_LOADS, // push s: variable isn_arg.loadstore
|
||||
ISN_LOADEXPORT, // push exported variable isn_arg.loadstore
|
||||
ISN_LOADOUTER, // push variable from outer scope isn_arg.outer
|
||||
ISN_LOADSCRIPT, // push script-local variable isn_arg.script.
|
||||
ISN_LOADOPT, // push option isn_arg.string
|
||||
@@ -57,6 +60,7 @@ typedef enum {
|
||||
ISN_STOREW, // pop into window-local variable isn_arg.string
|
||||
ISN_STORET, // pop into tab-local variable isn_arg.string
|
||||
ISN_STORES, // pop into script variable isn_arg.loadstore
|
||||
ISN_STOREEXPORT, // pop into exported script variable isn_arg.loadstore
|
||||
ISN_STOREOUTER, // pop variable into outer scope isn_arg.outer
|
||||
ISN_STORESCRIPT, // pop into script variable isn_arg.script
|
||||
ISN_STOREOPT, // pop into option isn_arg.storeopt
|
||||
|
@@ -1510,6 +1510,13 @@ get_script_svar(scriptref_T *sref, int dfunc_idx)
|
||||
emsg(_(e_script_variable_type_changed));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!sv->sv_export && sref->sref_sid != current_sctx.sc_sid)
|
||||
{
|
||||
if (dfunc != NULL)
|
||||
semsg(_(e_item_not_exported_in_script_str), sv->sv_name);
|
||||
return NULL;
|
||||
}
|
||||
return sv;
|
||||
}
|
||||
|
||||
@@ -2623,6 +2630,20 @@ exec_instructions(ectx_T *ectx)
|
||||
}
|
||||
break;
|
||||
|
||||
case ISN_SOURCE:
|
||||
{
|
||||
scriptitem_T *si = SCRIPT_ITEM(iptr->isn_arg.number);
|
||||
|
||||
if (si->sn_state == SN_STATE_NOT_LOADED)
|
||||
{
|
||||
SOURCING_LNUM = iptr->isn_lnum;
|
||||
if (do_source(si->sn_name, FALSE, DOSO_NONE, NULL)
|
||||
== FAIL)
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// execute :substitute with an expression
|
||||
case ISN_SUBSTITUTE:
|
||||
{
|
||||
@@ -2902,11 +2923,12 @@ exec_instructions(ectx_T *ectx)
|
||||
}
|
||||
break;
|
||||
|
||||
// load s: variable in old script
|
||||
// load s: variable in old script or autoload import
|
||||
case ISN_LOADS:
|
||||
case ISN_LOADEXPORT:
|
||||
{
|
||||
hashtab_T *ht = &SCRIPT_VARS(
|
||||
iptr->isn_arg.loadstore.ls_sid);
|
||||
int sid = iptr->isn_arg.loadstore.ls_sid;
|
||||
hashtab_T *ht = &SCRIPT_VARS(sid);
|
||||
char_u *name = iptr->isn_arg.loadstore.ls_name;
|
||||
dictitem_T *di = find_var_in_ht(ht, 0, name, TRUE);
|
||||
|
||||
@@ -2918,6 +2940,25 @@ exec_instructions(ectx_T *ectx)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (iptr->isn_type == ISN_LOADEXPORT)
|
||||
{
|
||||
int idx = get_script_item_idx(sid, name, 0,
|
||||
NULL, NULL);
|
||||
svar_T *sv;
|
||||
|
||||
if (idx >= 0)
|
||||
{
|
||||
sv = ((svar_T *)SCRIPT_ITEM(sid)
|
||||
->sn_var_vals.ga_data) + idx;
|
||||
if (!sv->sv_export)
|
||||
{
|
||||
SOURCING_LNUM = iptr->isn_lnum;
|
||||
semsg(_(e_item_not_exported_in_script_str),
|
||||
name);
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (GA_GROW_FAILS(&ectx->ec_stack, 1))
|
||||
goto theend;
|
||||
copy_tv(&di->di_tv, STACK_TV_BOT(0));
|
||||
@@ -3039,20 +3080,48 @@ exec_instructions(ectx_T *ectx)
|
||||
*tv = *STACK_TV_BOT(0);
|
||||
break;
|
||||
|
||||
// store s: variable in old script
|
||||
// store s: variable in old script or autoload import
|
||||
case ISN_STORES:
|
||||
case ISN_STOREEXPORT:
|
||||
{
|
||||
hashtab_T *ht = &SCRIPT_VARS(
|
||||
iptr->isn_arg.loadstore.ls_sid);
|
||||
int sid = iptr->isn_arg.loadstore.ls_sid;
|
||||
hashtab_T *ht = &SCRIPT_VARS(sid);
|
||||
char_u *name = iptr->isn_arg.loadstore.ls_name;
|
||||
dictitem_T *di = find_var_in_ht(ht, 0, name + 2, TRUE);
|
||||
dictitem_T *di = find_var_in_ht(ht, 0,
|
||||
iptr->isn_type == ISN_STORES
|
||||
? name + 2 : name, TRUE);
|
||||
|
||||
--ectx->ec_stack.ga_len;
|
||||
SOURCING_LNUM = iptr->isn_lnum;
|
||||
if (di == NULL)
|
||||
{
|
||||
if (iptr->isn_type == ISN_STOREEXPORT)
|
||||
{
|
||||
semsg(_(e_undefined_variable_str), name);
|
||||
goto on_error;
|
||||
}
|
||||
store_var(name, STACK_TV_BOT(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
SOURCING_LNUM = iptr->isn_lnum;
|
||||
if (iptr->isn_type == ISN_STOREEXPORT)
|
||||
{
|
||||
int idx = get_script_item_idx(sid, name, 0,
|
||||
NULL, NULL);
|
||||
|
||||
if (idx >= 0)
|
||||
{
|
||||
svar_T *sv = ((svar_T *)SCRIPT_ITEM(sid)
|
||||
->sn_var_vals.ga_data) + idx;
|
||||
|
||||
if (!sv->sv_export)
|
||||
{
|
||||
semsg(_(e_item_not_exported_in_script_str),
|
||||
name);
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (var_check_permission(di, name) == FAIL)
|
||||
{
|
||||
clear_tv(STACK_TV_BOT(0));
|
||||
@@ -5409,11 +5478,15 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
|
||||
#endif
|
||||
break;
|
||||
case ISN_INSTR:
|
||||
smsg("%s%4d INSTR", pfx, current);
|
||||
list_instructions(" ", iptr->isn_arg.instr, INT_MAX, NULL);
|
||||
msg(" -------------");
|
||||
break;
|
||||
case ISN_SOURCE:
|
||||
{
|
||||
smsg("%s%4d INSTR", pfx, current);
|
||||
list_instructions(" ", iptr->isn_arg.instr,
|
||||
INT_MAX, NULL);
|
||||
msg(" -------------");
|
||||
scriptitem_T *si = SCRIPT_ITEM(iptr->isn_arg.number);
|
||||
|
||||
smsg("%s%4d SOURCE %s", pfx, current, si->sn_name);
|
||||
}
|
||||
break;
|
||||
case ISN_SUBSTITUTE:
|
||||
@@ -5500,12 +5573,15 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
|
||||
}
|
||||
break;
|
||||
case ISN_LOADS:
|
||||
case ISN_LOADEXPORT:
|
||||
{
|
||||
scriptitem_T *si = SCRIPT_ITEM(
|
||||
iptr->isn_arg.loadstore.ls_sid);
|
||||
|
||||
smsg("%s%4d LOADS s:%s from %s", pfx, current,
|
||||
iptr->isn_arg.loadstore.ls_name, si->sn_name);
|
||||
smsg("%s%4d %s s:%s from %s", pfx, current,
|
||||
iptr->isn_type == ISN_LOADS ? "LOADS"
|
||||
: "LOADEXPORT",
|
||||
iptr->isn_arg.loadstore.ls_name, si->sn_name);
|
||||
}
|
||||
break;
|
||||
case ISN_LOADAUTO:
|
||||
@@ -5586,11 +5662,14 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
|
||||
smsg("%s%4d STORET %s", pfx, current, iptr->isn_arg.string);
|
||||
break;
|
||||
case ISN_STORES:
|
||||
case ISN_STOREEXPORT:
|
||||
{
|
||||
scriptitem_T *si = SCRIPT_ITEM(
|
||||
iptr->isn_arg.loadstore.ls_sid);
|
||||
|
||||
smsg("%s%4d STORES %s in %s", pfx, current,
|
||||
smsg("%s%4d %s %s in %s", pfx, current,
|
||||
iptr->isn_type == ISN_STORES
|
||||
? "STORES" : "STOREEXPORT",
|
||||
iptr->isn_arg.loadstore.ls_name, si->sn_name);
|
||||
}
|
||||
break;
|
||||
|
@@ -313,6 +313,27 @@ compile_load_scriptvar(
|
||||
vim_free(auto_name);
|
||||
done = TRUE;
|
||||
}
|
||||
else if (si->sn_import_autoload && si->sn_state == SN_STATE_NOT_LOADED)
|
||||
{
|
||||
// "import autoload './dir/script.vim'" - load script first
|
||||
res = generate_SOURCE(cctx, import->imp_sid);
|
||||
if (res == OK)
|
||||
{
|
||||
// If a '(' follows it must be a function. Otherwise we don't
|
||||
// know, it can be "script.Func".
|
||||
if (cc == '(' || paren_follows_after_expr)
|
||||
{
|
||||
char_u sid_name[MAX_FUNC_NAME_LEN];
|
||||
|
||||
func_name_with_sid(exp_name, import->imp_sid, sid_name);
|
||||
res = generate_PUSHFUNC(cctx, sid_name, &t_func_any);
|
||||
}
|
||||
else
|
||||
res = generate_OLDSCRIPT(cctx, ISN_LOADEXPORT, exp_name,
|
||||
import->imp_sid, &t_any);
|
||||
}
|
||||
done = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx = find_exported(import->imp_sid, exp_name, &ufunc, &type,
|
||||
|
@@ -1066,7 +1066,7 @@ generate_OLDSCRIPT(
|
||||
isn_T *isn;
|
||||
|
||||
RETURN_OK_IF_SKIP(cctx);
|
||||
if (isn_type == ISN_LOADS)
|
||||
if (isn_type == ISN_LOADS || isn_type == ISN_LOADEXPORT)
|
||||
isn = generate_instr_type(cctx, isn_type, type);
|
||||
else
|
||||
isn = generate_instr_drop(cctx, isn_type, 1);
|
||||
@@ -1727,6 +1727,21 @@ generate_MULT_EXPR(cctx_T *cctx, isntype_T isn_type, int count)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate an ISN_SOURCE instruction.
|
||||
*/
|
||||
int
|
||||
generate_SOURCE(cctx_T *cctx, int sid)
|
||||
{
|
||||
isn_T *isn;
|
||||
|
||||
if ((isn = generate_instr(cctx, ISN_SOURCE)) == NULL)
|
||||
return FAIL;
|
||||
isn->isn_arg.number = sid;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate an ISN_PUT instruction.
|
||||
*/
|
||||
@@ -1913,9 +1928,22 @@ generate_store_var(
|
||||
return generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
|
||||
case dest_script:
|
||||
if (scriptvar_idx < 0)
|
||||
{
|
||||
isntype_T isn_type = ISN_STORES;
|
||||
|
||||
if (SCRIPT_ID_VALID(scriptvar_sid)
|
||||
&& SCRIPT_ITEM(scriptvar_sid)->sn_import_autoload)
|
||||
{
|
||||
// "import autoload './dir/script.vim'" - load script first
|
||||
if (generate_SOURCE(cctx, scriptvar_sid) == FAIL)
|
||||
return FAIL;
|
||||
isn_type = ISN_STOREEXPORT;
|
||||
}
|
||||
|
||||
// "s:" may be included in the name.
|
||||
return generate_OLDSCRIPT(cctx, ISN_STORES, name,
|
||||
scriptvar_sid, type);
|
||||
return generate_OLDSCRIPT(cctx, isn_type, name,
|
||||
scriptvar_sid, type);
|
||||
}
|
||||
return generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
|
||||
scriptvar_sid, scriptvar_idx, type);
|
||||
case dest_local:
|
||||
@@ -2062,7 +2090,9 @@ delete_instr(isn_T *isn)
|
||||
break;
|
||||
|
||||
case ISN_LOADS:
|
||||
case ISN_LOADEXPORT:
|
||||
case ISN_STORES:
|
||||
case ISN_STOREEXPORT:
|
||||
vim_free(isn->isn_arg.loadstore.ls_name);
|
||||
break;
|
||||
|
||||
@@ -2089,7 +2119,7 @@ delete_instr(isn_T *isn)
|
||||
if (isn->isn_arg.funcref.fr_func_name == NULL)
|
||||
{
|
||||
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
||||
+ isn->isn_arg.funcref.fr_dfunc_idx;
|
||||
+ isn->isn_arg.funcref.fr_dfunc_idx;
|
||||
ufunc_T *ufunc = dfunc->df_ufunc;
|
||||
|
||||
if (ufunc != NULL && func_name_refcount(ufunc->uf_name))
|
||||
@@ -2109,10 +2139,10 @@ delete_instr(isn_T *isn)
|
||||
case ISN_DCALL:
|
||||
{
|
||||
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
||||
+ isn->isn_arg.dfunc.cdf_idx;
|
||||
+ isn->isn_arg.dfunc.cdf_idx;
|
||||
|
||||
if (dfunc->df_ufunc != NULL
|
||||
&& func_name_refcount(dfunc->df_ufunc->uf_name))
|
||||
&& func_name_refcount(dfunc->df_ufunc->uf_name))
|
||||
func_ptr_unref(dfunc->df_ufunc);
|
||||
}
|
||||
break;
|
||||
@@ -2140,7 +2170,7 @@ delete_instr(isn_T *isn)
|
||||
|
||||
case ISN_CMDMOD:
|
||||
vim_regfree(isn->isn_arg.cmdmod.cf_cmdmod
|
||||
->cmod_filter_regmatch.regprog);
|
||||
->cmod_filter_regmatch.regprog);
|
||||
vim_free(isn->isn_arg.cmdmod.cf_cmdmod);
|
||||
break;
|
||||
|
||||
@@ -2243,21 +2273,22 @@ delete_instr(isn_T *isn)
|
||||
case ISN_STORE:
|
||||
case ISN_STOREINDEX:
|
||||
case ISN_STORENR:
|
||||
case ISN_STOREOUTER:
|
||||
case ISN_STORERANGE:
|
||||
case ISN_STOREREG:
|
||||
case ISN_STOREV:
|
||||
case ISN_STRINDEX:
|
||||
case ISN_STRSLICE:
|
||||
case ISN_THROW:
|
||||
case ISN_TRYCONT:
|
||||
case ISN_UNLETINDEX:
|
||||
case ISN_UNLETRANGE:
|
||||
case ISN_UNPACK:
|
||||
case ISN_USEDICT:
|
||||
// nothing allocated
|
||||
break;
|
||||
}
|
||||
case ISN_SOURCE:
|
||||
case ISN_STOREOUTER:
|
||||
case ISN_STORERANGE:
|
||||
case ISN_STOREREG:
|
||||
case ISN_STOREV:
|
||||
case ISN_STRINDEX:
|
||||
case ISN_STRSLICE:
|
||||
case ISN_THROW:
|
||||
case ISN_TRYCONT:
|
||||
case ISN_UNLETINDEX:
|
||||
case ISN_UNLETRANGE:
|
||||
case ISN_UNPACK:
|
||||
case ISN_USEDICT:
|
||||
// nothing allocated
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@@ -383,6 +383,38 @@ mark_imports_for_reload(int sid)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Part of "import" that handles a relative or absolute file name/
|
||||
* Returns OK or FAIL.
|
||||
*/
|
||||
static int
|
||||
handle_import_fname(char_u *fname, int is_autoload, int *sid)
|
||||
{
|
||||
if (is_autoload)
|
||||
{
|
||||
scriptitem_T *si;
|
||||
|
||||
*sid = find_script_by_name(fname);
|
||||
if (*sid < 0)
|
||||
{
|
||||
int error = OK;
|
||||
|
||||
// script does not exist yet, create a new scriptitem
|
||||
*sid = get_new_scriptitem_for_fname(&error, fname);
|
||||
if (error == FAIL)
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
si = SCRIPT_ITEM(*sid);
|
||||
si->sn_import_autoload = TRUE;
|
||||
|
||||
// with testing override: load autoload script right away
|
||||
if (!override_autoload || si->sn_state != SN_STATE_NOT_LOADED)
|
||||
return OK;
|
||||
}
|
||||
return do_source(fname, FALSE, DOSO_NONE, sid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle an ":import" command and add the resulting imported_T to "gap", when
|
||||
* not NULL, or script "import_sid" sn_imports.
|
||||
@@ -442,25 +474,18 @@ handle_import(
|
||||
char_u *tail = gettail(si->sn_name);
|
||||
char_u *from_name;
|
||||
|
||||
if (is_autoload)
|
||||
res = FAIL;
|
||||
else
|
||||
{
|
||||
// Relative to current script: "./name.vim", "../../name.vim".
|
||||
len = STRLEN(si->sn_name) - STRLEN(tail) + STRLEN(tv.vval.v_string) + 2;
|
||||
from_name = alloc((int)len);
|
||||
if (from_name == NULL)
|
||||
goto erret;
|
||||
vim_strncpy(from_name, si->sn_name, tail - si->sn_name);
|
||||
add_pathsep(from_name);
|
||||
STRCAT(from_name, tv.vval.v_string);
|
||||
simplify_filename(from_name);
|
||||
|
||||
// Relative to current script: "./name.vim", "../../name.vim".
|
||||
len = STRLEN(si->sn_name) - STRLEN(tail)
|
||||
+ STRLEN(tv.vval.v_string) + 2;
|
||||
from_name = alloc((int)len);
|
||||
if (from_name == NULL)
|
||||
goto erret;
|
||||
vim_strncpy(from_name, si->sn_name, tail - si->sn_name);
|
||||
add_pathsep(from_name);
|
||||
STRCAT(from_name, tv.vval.v_string);
|
||||
simplify_filename(from_name);
|
||||
|
||||
res = do_source(from_name, FALSE, DOSO_NONE, &sid);
|
||||
vim_free(from_name);
|
||||
}
|
||||
res = handle_import_fname(from_name, is_autoload, &sid);
|
||||
vim_free(from_name);
|
||||
}
|
||||
else if (mch_isFullName(tv.vval.v_string)
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
@@ -471,10 +496,7 @@ handle_import(
|
||||
)
|
||||
{
|
||||
// Absolute path: "/tmp/name.vim"
|
||||
if (is_autoload)
|
||||
res = FAIL;
|
||||
else
|
||||
res = do_source(tv.vval.v_string, FALSE, DOSO_NONE, &sid);
|
||||
res = handle_import_fname(tv.vval.v_string, is_autoload, &sid);
|
||||
}
|
||||
else if (is_autoload)
|
||||
{
|
||||
@@ -677,6 +699,12 @@ find_exported(
|
||||
svar_T *sv;
|
||||
scriptitem_T *script = SCRIPT_ITEM(sid);
|
||||
|
||||
if (script->sn_import_autoload && script->sn_state == SN_STATE_NOT_LOADED)
|
||||
{
|
||||
if (do_source(script->sn_name, FALSE, DOSO_NONE, NULL) == FAIL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Find name in "script".
|
||||
idx = get_script_item_idx(sid, name, 0, cctx, cstack);
|
||||
if (idx >= 0)
|
||||
|
Reference in New Issue
Block a user