diff options
Diffstat (limited to 'src/scriptfile.c')
-rw-r--r-- | src/scriptfile.c | 125 |
1 files changed, 91 insertions, 34 deletions
diff --git a/src/scriptfile.c b/src/scriptfile.c index 78a80d02bc..120c64351e 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) |