summaryrefslogtreecommitdiff
path: root/src/scriptfile.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-01-26 15:56:19 +0100
committerBram Moolenaar <Bram@vim.org>2020-01-26 15:56:19 +0100
commit8a7d6542b33e5d2b352262305c3bfdb2d14e1cf8 (patch)
tree8e5f241129a1c690ea81d697a72fb4c1704c0cb6 /src/scriptfile.c
parent1d9215b9aaa120b9d78fee49488556f73007ce78 (diff)
downloadvim-git-8a7d6542b33e5d2b352262305c3bfdb2d14e1cf8.tar.gz
patch 8.2.0149: maintaining a Vim9 branch separately is more workv8.2.0149
Problem: Maintaining a Vim9 branch separately is more work. Solution: Merge the Vim9 script changes.
Diffstat (limited to 'src/scriptfile.c')
-rw-r--r--src/scriptfile.c125
1 files changed, 91 insertions, 34 deletions
diff --git a/src/scriptfile.c b/src/scriptfile.c
index 78a80d02b..120c64351 100644
--- a/src/scriptfile.c
+++ b/src/scriptfile.c
@@ -182,9 +182,9 @@ ex_runtime(exarg_T *eap)
}
static void
-source_callback(char_u *fname, void *cookie UNUSED)
+source_callback(char_u *fname, void *cookie)
{
- (void)do_source(fname, FALSE, DOSO_NONE);
+ (void)do_source(fname, FALSE, DOSO_NONE, cookie);
}
/*
@@ -399,16 +399,16 @@ do_in_runtimepath(
int
source_runtime(char_u *name, int flags)
{
- return source_in_path(p_rtp, name, flags);
+ return source_in_path(p_rtp, name, flags, NULL);
}
/*
* Just like source_runtime(), but use "path" instead of 'runtimepath'.
*/
int
-source_in_path(char_u *path, char_u *name, int flags)
+source_in_path(char_u *path, char_u *name, int flags, int *ret_sid)
{
- return do_in_path_and_pp(path, name, flags, source_callback, NULL);
+ return do_in_path_and_pp(path, name, flags, source_callback, ret_sid);
}
@@ -427,7 +427,7 @@ source_all_matches(char_u *pat)
if (gen_expand_wildcards(1, &pat, &num_files, &files, EW_FILE) == OK)
{
for (i = 0; i < num_files; ++i)
- (void)do_source(files[i], FALSE, DOSO_NONE);
+ (void)do_source(files[i], FALSE, DOSO_NONE, NULL);
FreeWild(num_files, files);
}
}
@@ -930,7 +930,7 @@ cmd_source(char_u *fname, exarg_T *eap)
);
// ":source" read ex commands
- else if (do_source(fname, FALSE, DOSO_NONE) == FAIL)
+ else if (do_source(fname, FALSE, DOSO_NONE, NULL) == FAIL)
semsg(_(e_notopen), fname);
}
@@ -1063,16 +1063,20 @@ fopen_noinh_readbin(char *filename)
/*
* do_source: Read the file "fname" and execute its lines as EX commands.
+ * When "ret_sid" is not NULL and we loaded the script before, don't load it
+ * again.
*
* This function may be called recursively!
*
- * return FAIL if file could not be opened, OK otherwise
+ * Return FAIL if file could not be opened, OK otherwise.
+ * If a scriptitem_T was found or created "*ret_sid" is set to the SID.
*/
int
do_source(
char_u *fname,
int check_other, // check for .vimrc and _vimrc
- int is_vimrc) // DOSO_ value
+ int is_vimrc, // DOSO_ value
+ int *ret_sid UNUSED)
{
struct source_cookie cookie;
char_u *p;
@@ -1085,6 +1089,7 @@ do_source(
static int last_current_SID_seq = 0;
funccal_entry_T funccalp_entry;
int save_debug_break_level = debug_break_level;
+ int sid;
scriptitem_T *si = NULL;
# ifdef UNIX
stat_T st;
@@ -1114,6 +1119,37 @@ do_source(
goto theend;
}
+#ifdef FEAT_EVAL
+ // See if we loaded this script before.
+# ifdef UNIX
+ stat_ok = (mch_stat((char *)fname_exp, &st) >= 0);
+# endif
+ for (sid = script_items.ga_len; sid > 0; --sid)
+ {
+ si = &SCRIPT_ITEM(sid);
+ if (si->sn_name != NULL)
+ {
+# ifdef UNIX
+ // Compare dev/ino when possible, it catches symbolic links. Also
+ // compare file names, the inode may change when the file was
+ // edited or it may be re-used for another script (esp. in tests).
+ if ((stat_ok && si->sn_dev_valid)
+ && (si->sn_dev != st.st_dev || si->sn_ino != st.st_ino))
+ continue;
+# endif
+ if (fnamecmp(si->sn_name, fname_exp) == 0)
+ // Found it!
+ break;
+ }
+ }
+ if (sid > 0 && ret_sid != NULL)
+ {
+ // Already loaded and no need to load again, return here.
+ *ret_sid = sid;
+ return OK;
+ }
+#endif
+
// Apply SourceCmd autocommands, they should get the file and source it.
if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL)
&& apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp,
@@ -1239,33 +1275,32 @@ do_source(
current_sctx.sc_version = 1; // default script version
// Check if this script was sourced before to finds its SID.
- // If it's new, generate a new SID.
// Always use a new sequence number.
current_sctx.sc_seq = ++last_current_SID_seq;
-# ifdef UNIX
- stat_ok = (mch_stat((char *)fname_exp, &st) >= 0);
-# endif
- for (current_sctx.sc_sid = script_items.ga_len; current_sctx.sc_sid > 0;
- --current_sctx.sc_sid)
+ if (sid > 0)
{
- si = &SCRIPT_ITEM(current_sctx.sc_sid);
- if (si->sn_name != NULL)
- {
-# ifdef UNIX
- // Compare dev/ino when possible, it catches symbolic links. Also
- // compare file names, the inode may change when the file was
- // edited or it may be re-used for another script (esp. in tests).
- if ((stat_ok && si->sn_dev_valid)
- && (si->sn_dev != st.st_dev || si->sn_ino != st.st_ino))
- continue;
-# endif
- if (fnamecmp(si->sn_name, fname_exp) == 0)
- // Found it!
- break;
- }
+ hashtab_T *ht;
+ hashitem_T *hi;
+ dictitem_T *di;
+ int todo;
+
+ // loading the same script again
+ si->sn_had_command = FALSE;
+ current_sctx.sc_sid = sid;
+
+ ht = &SCRIPT_VARS(sid);
+ todo = (int)ht->ht_used;
+ for (hi = ht->ht_array; todo > 0; ++hi)
+ if (!HASHITEM_EMPTY(hi))
+ {
+ --todo;
+ di = HI2DI(hi);
+ di->di_flags |= DI_FLAGS_RELOAD;
+ }
}
- if (current_sctx.sc_sid == 0)
+ else
{
+ // It's new, generate a new SID.
current_sctx.sc_sid = ++last_current_SID;
if (ga_grow(&script_items,
(int)(current_sctx.sc_sid - script_items.ga_len)) == FAIL)
@@ -1273,13 +1308,17 @@ do_source(
while (script_items.ga_len < current_sctx.sc_sid)
{
++script_items.ga_len;
- SCRIPT_ITEM(script_items.ga_len).sn_name = NULL;
- SCRIPT_ITEM(script_items.ga_len).sn_version = 1;
+ si = &SCRIPT_ITEM(script_items.ga_len);
+ si->sn_name = NULL;
+ si->sn_version = 1;
// Allocate the local script variables to use for this script.
new_script_vars(script_items.ga_len);
+ ga_init2(&si->sn_var_vals, sizeof(typval_T), 10);
+ ga_init2(&si->sn_imports, sizeof(imported_T), 10);
+ ga_init2(&si->sn_type_list, sizeof(type_T), 10);
# ifdef FEAT_PROFILE
- SCRIPT_ITEM(script_items.ga_len).sn_prof_on = FALSE;
+ si->sn_prof_on = FALSE;
# endif
}
si = &SCRIPT_ITEM(current_sctx.sc_sid);
@@ -1295,6 +1334,8 @@ do_source(
else
si->sn_dev_valid = FALSE;
# endif
+ if (ret_sid != NULL)
+ *ret_sid = current_sctx.sc_sid;
}
# ifdef FEAT_PROFILE
@@ -1392,6 +1433,15 @@ do_source(
#ifdef FEAT_EVAL
almosttheend:
+ // Get "si" again, "script_items" may have been reallocated.
+ si = &SCRIPT_ITEM(current_sctx.sc_sid);
+ if (si->sn_save_cpo != NULL)
+ {
+ free_string_option(p_cpo);
+ p_cpo = si->sn_save_cpo;
+ si->sn_save_cpo = NULL;
+ }
+
current_sctx = save_current_sctx;
restore_funccal();
# ifdef FEAT_PROFILE
@@ -1488,7 +1538,9 @@ free_scriptnames(void)
{
// the variables themselves are cleared in evalvars_clear()
vim_free(SCRIPT_ITEM(i).sn_vars);
+
vim_free(SCRIPT_ITEM(i).sn_name);
+ free_string_option(SCRIPT_ITEM(i).sn_save_cpo);
# ifdef FEAT_PROFILE
ga_clear(&SCRIPT_ITEM(i).sn_prl_ga);
# endif
@@ -1789,6 +1841,11 @@ ex_scriptversion(exarg_T *eap UNUSED)
emsg(_("E984: :scriptversion used outside of a sourced file"));
return;
}
+ if (current_sctx.sc_version == SCRIPT_VERSION_VIM9)
+ {
+ emsg(_("E1040: Cannot use :scriptversion after :vim9script"));
+ return;
+ }
nr = getdigits(&eap->arg);
if (nr == 0 || *eap->arg != NUL)