patch 8.2.0114: info about sourced scripts is scattered
Problem: Info about sourced scripts is scattered.
Solution: Use scriptitem_T for info about a script, including s: variables.
Drop ga_scripts.
diff --git a/src/eval.c b/src/eval.c
index 48357d4..fe6dee1 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -149,8 +149,7 @@
eval_clear(void)
{
evalvars_clear();
-
- free_scriptnames();
+ free_scriptnames(); // must come after evalvars_clear().
free_locales();
// autoloaded script names
diff --git a/src/evalvars.c b/src/evalvars.c
index fbe23c4..d359c7f 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -163,18 +163,7 @@
// for VIM_VERSION_ defines
#include "version.h"
-/*
- * Array to hold the hashtab with variables local to each sourced script.
- * Each item holds a variable (nameless) that points to the dict_T.
- */
-typedef struct
-{
- dictitem_T sv_var;
- dict_T sv_dict;
-} scriptvar_T;
-
-static garray_T ga_scripts = {0, 0, sizeof(scriptvar_T *), 4, NULL};
-#define SCRIPT_SV(id) (((scriptvar_T **)ga_scripts.ga_data)[(id) - 1])
+#define SCRIPT_SV(id) (SCRIPT_ITEM(id).sn_vars)
#define SCRIPT_VARS(id) (SCRIPT_SV(id)->sv_dict.dv_hashtab)
static void ex_let_const(exarg_T *eap, int is_const);
@@ -289,14 +278,12 @@
// global variables
vars_clear(&globvarht);
- // Script-local variables. First clear all the variables and in a second
- // loop free the scriptvar_T, because a variable in one script might hold
- // a reference to the whole scope of another script.
- for (i = 1; i <= ga_scripts.ga_len; ++i)
+ // Script-local variables. Clear all the variables here.
+ // The scriptvar_T is cleared later in free_scriptnames(), because a
+ // variable in one script might hold a reference to the whole scope of
+ // another script.
+ for (i = 1; i <= script_items.ga_len; ++i)
vars_clear(&SCRIPT_VARS(i));
- for (i = 1; i <= ga_scripts.ga_len; ++i)
- vim_free(SCRIPT_SV(i));
- ga_clear(&ga_scripts);
}
#endif
@@ -318,7 +305,7 @@
int i;
int abort = FALSE;
- for (i = 1; i <= ga_scripts.ga_len; ++i)
+ for (i = 1; i <= script_items.ga_len; ++i)
abort = abort || set_ref_in_ht(&SCRIPT_VARS(i), copyID, NULL);
return abort;
@@ -538,7 +525,7 @@
static void
list_script_vars(int *first)
{
- if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= ga_scripts.ga_len)
+ if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len)
list_hashtable_vars(&SCRIPT_VARS(current_sctx.sc_sid),
"s:", FALSE, first);
}
@@ -2433,7 +2420,7 @@
return get_funccal_local_ht();
if (*name == 's' // script variable
&& current_sctx.sc_sid > 0
- && current_sctx.sc_sid <= ga_scripts.ga_len)
+ && current_sctx.sc_sid <= script_items.ga_len)
return &SCRIPT_VARS(current_sctx.sc_sid);
return NULL;
}
@@ -2461,32 +2448,13 @@
void
new_script_vars(scid_T id)
{
- int i;
- hashtab_T *ht;
scriptvar_T *sv;
- if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
- {
- // Re-allocating ga_data means that an ht_array pointing to
- // ht_smallarray becomes invalid. We can recognize this: ht_mask is
- // at its init value. Also reset "v_dict", it's always the same.
- for (i = 1; i <= ga_scripts.ga_len; ++i)
- {
- ht = &SCRIPT_VARS(i);
- if (ht->ht_mask == HT_INIT_SIZE - 1)
- ht->ht_array = ht->ht_smallarray;
- sv = SCRIPT_SV(i);
- sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict;
- }
-
- while (ga_scripts.ga_len < id)
- {
- sv = SCRIPT_SV(ga_scripts.ga_len + 1) =
- ALLOC_CLEAR_ONE(scriptvar_T);
- init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE);
- ++ga_scripts.ga_len;
- }
- }
+ sv = ALLOC_CLEAR_ONE(scriptvar_T);
+ if (sv == NULL)
+ return;
+ init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE);
+ SCRIPT_ITEM(id).sn_vars = sv;
}
/*
diff --git a/src/scriptfile.c b/src/scriptfile.c
index a175541..a574bf6 100644
--- a/src/scriptfile.c
+++ b/src/scriptfile.c
@@ -1236,7 +1236,7 @@
save_current_sctx = current_sctx;
current_sctx.sc_lnum = 0;
- current_sctx.sc_version = 1;
+ 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.
@@ -1272,6 +1272,10 @@
{
++script_items.ga_len;
SCRIPT_ITEM(script_items.ga_len).sn_name = NULL;
+ SCRIPT_ITEM(script_items.ga_len).sn_version = 1;
+
+ // Allocate the local script variables to use for this script.
+ new_script_vars(script_items.ga_len);
# ifdef FEAT_PROFILE
SCRIPT_ITEM(script_items.ga_len).sn_prof_on = FALSE;
# endif
@@ -1289,9 +1293,6 @@
else
si->sn_dev_valid = FALSE;
# endif
-
- // Allocate the local script variables to use for this script.
- new_script_vars(current_sctx.sc_sid);
}
# ifdef FEAT_PROFILE
@@ -1483,6 +1484,8 @@
for (i = script_items.ga_len; i > 0; --i)
{
+ // the variables themselves are cleared in evalvars_clear()
+ vim_free(SCRIPT_ITEM(i).sn_vars);
vim_free(SCRIPT_ITEM(i).sn_name);
# ifdef FEAT_PROFILE
ga_clear(&SCRIPT_ITEM(i).sn_prl_ga);
@@ -1791,7 +1794,10 @@
else if (nr > 4)
semsg(_("E999: scriptversion not supported: %d"), nr);
else
+ {
current_sctx.sc_version = nr;
+ SCRIPT_ITEM(current_sctx.sc_sid).sn_version = nr;
+ }
#endif
}
diff --git a/src/structs.h b/src/structs.h
index ffd6734..7e1508e 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -74,6 +74,8 @@
* function was defined, "sourcing_lnum" is the line number inside the
* function. When stored with a function, mapping, option, etc. "sc_lnum" is
* the line number in the script "sc_sid".
+ *
+ * sc_version is also here, for convenience.
*/
typedef struct {
scid_T sc_sid; // script ID
@@ -1566,13 +1568,28 @@
#define HI2UF(hi) HIKEY2UF((hi)->hi_key)
/*
+ * Holds the hashtab with variables local to each sourced script.
+ * Each item holds a variable (nameless) that points to the dict_T.
+ */
+typedef struct
+{
+ dictitem_T sv_var;
+ dict_T sv_dict;
+} scriptvar_T;
+
+/*
* Growarray to store info about already sourced scripts.
* For Unix also store the dev/ino, so that we don't have to stat() each
* script when going through the list.
*/
-typedef struct scriptitem_S
+typedef struct
{
+ scriptvar_T *sn_vars; // stores s: variables for this script
+
char_u *sn_name;
+
+ int sn_version; // :scriptversion
+
# ifdef UNIX
int sn_dev_valid;
dev_t sn_dev;
diff --git a/src/version.c b/src/version.c
index ba4fa7f..0dac41e 100644
--- a/src/version.c
+++ b/src/version.c
@@ -743,6 +743,8 @@
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 114,
+/**/
113,
/**/
112,