]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.2.0114: info about sourced scripts is scattered v8.2.0114
authorBram Moolenaar <Bram@vim.org>
Sun, 12 Jan 2020 16:42:55 +0000 (17:42 +0100)
committerBram Moolenaar <Bram@vim.org>
Sun, 12 Jan 2020 16:42:55 +0000 (17:42 +0100)
Problem:    Info about sourced scripts is scattered.
Solution:   Use scriptitem_T for info about a script, including s: variables.
            Drop ga_scripts.

src/eval.c
src/evalvars.c
src/scriptfile.c
src/structs.h
src/version.c

index 48357d441d991d951584b8ef8cc637a871a77c50..fe6dee1f1b355d1dde9a2f4ad40c1f33bef790ed 100644 (file)
@@ -149,8 +149,7 @@ eval_init(void)
 eval_clear(void)
 {
     evalvars_clear();
-
-    free_scriptnames();
+    free_scriptnames();  // must come after evalvars_clear().
     free_locales();
 
     // autoloaded script names
index fbe23c4f16fb92198faba8ea5fbbc432ab36fc48..d359c7f44cc332cc5deaf3bd7fcbdc6c4ad37f13 100644 (file)
@@ -163,18 +163,7 @@ static dict_T              vimvardict;             // Dictionary with v: variables
 // 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 @@ evalvars_clear(void)
     // 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 @@ garbage_collect_scriptvars(int copyID)
     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 @@ list_vim_vars(int *first)
     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 @@ find_var_ht(char_u *name, char_u **varname)
        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 @@ get_var_value(char_u *name)
     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;
 }
 
 /*
index a1755416b42b364a806e1281d79c81034e7b6895..a574bf665bb8a75d627a2bc9a4dc0c97a27aa82b 100644 (file)
@@ -1236,7 +1236,7 @@ do_source(
 
     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 @@ do_source(
        {
            ++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 @@ do_source(
        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 @@ free_scriptnames(void)
 
     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 @@ ex_scriptversion(exarg_T *eap UNUSED)
     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
 }
 
index ffd6734e42bf62ac3e9709567f1b5d85ce207156..7e1508eb9c486ac17b92ca0c4fd616550ca7bae5 100644 (file)
@@ -74,6 +74,8 @@ typedef struct VimMenu vimmenu_T;
  * 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
@@ -1565,14 +1567,29 @@ struct funccal_entry {
 #define HIKEY2UF(p)  ((ufunc_T *)((p) - offsetof(ufunc_T, uf_name)))
 #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;
index ba4fa7f7e4a16efe31a204a0beb0463f7a73423e..0dac41e7cf8db4cac1873a47204672e13944a583 100644 (file)
@@ -742,6 +742,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    114,
 /**/
     113,
 /**/