Patch 9.0.0398
Problem:    Members of funccall_T are inconsistently named.
Solution:   Use the "fc_" prefix for all members.
Files:      src/structs.h, src/profiler.c, src/userfunc.c, src/vim9execute.c,
            src/evalvars.c


*** ../vim-9.0.0397/src/structs.h       2022-09-06 18:31:09.074310277 +0100
--- src/structs.h       2022-09-06 18:53:35.296180233 +0100
***************
*** 1735,1774 ****
   */
  struct funccall_S
  {
!     ufunc_T   *func;          // function being called
!     int               linenr;         // next line to be executed
!     int               returned;       // ":return" used
      struct                    // fixed variables for arguments
      {
        dictitem_T      var;            // variable (without room for name)
        char_u  room[VAR_SHORT_LEN];    // room for the name
!     } fixvar[FIXVAR_CNT];
!     dict_T    l_vars;         // l: local function variables
!     dictitem_T        l_vars_var;     // variable for l: scope
!     dict_T    l_avars;        // a: argument variables
!     dictitem_T        l_avars_var;    // variable for a: scope
!     list_T    l_varlist;      // list for a:000
!     listitem_T        l_listitems[MAX_FUNC_ARGS];     // listitems for a:000
!     typval_T  *rettv;         // return value
!     linenr_T  breakpoint;     // next line with breakpoint or zero
!     int               dbg_tick;       // debug_tick when breakpoint was set
!     int               level;          // top nesting level of executed 
function
  
      garray_T  fc_defer;       // functions to be called on return
      ectx_T    *fc_ectx;       // execution context for :def function, NULL
                                // otherwise
  
  #ifdef FEAT_PROFILE
!     proftime_T        prof_child;     // time spent in a child
  #endif
!     funccall_T        *caller;        // calling function or NULL; or next 
funccal in
                                // list pointed to by previous_funccal.
  
      // for closure
      int               fc_refcount;    // number of user functions that 
reference this
                                // funccal
      int               fc_copyID;      // for garbage collection
!     garray_T  fc_funcs;       // list of ufunc_T* which keep a reference to
                                // "func"
  };
  
--- 1735,1774 ----
   */
  struct funccall_S
  {
!     ufunc_T   *fc_func;       // function being called
!     int               fc_linenr;      // next line to be executed
!     int               fc_returned;    // ":return" used
      struct                    // fixed variables for arguments
      {
        dictitem_T      var;            // variable (without room for name)
        char_u  room[VAR_SHORT_LEN];    // room for the name
!     } fc_fixvar[FIXVAR_CNT];
!     dict_T    fc_l_vars;      // l: local function variables
!     dictitem_T        fc_l_vars_var;  // variable for l: scope
!     dict_T    fc_l_avars;     // a: argument variables
!     dictitem_T        fc_l_avars_var; // variable for a: scope
!     list_T    fc_l_varlist;   // list for a:000
!     listitem_T        fc_l_listitems[MAX_FUNC_ARGS];  // listitems for a:000
!     typval_T  *fc_rettv;      // return value
!     linenr_T  fc_breakpoint;  // next line with breakpoint or zero
!     int               fc_dbg_tick;    // debug_tick when breakpoint was set
!     int               fc_level;       // top nesting level of executed 
function
  
      garray_T  fc_defer;       // functions to be called on return
      ectx_T    *fc_ectx;       // execution context for :def function, NULL
                                // otherwise
  
  #ifdef FEAT_PROFILE
!     proftime_T        fc_prof_child;  // time spent in a child
  #endif
!     funccall_T        *fc_caller;     // calling function or NULL; or next 
funccal in
                                // list pointed to by previous_funccal.
  
      // for closure
      int               fc_refcount;    // number of user functions that 
reference this
                                // funccal
      int               fc_copyID;      // for garbage collection
!     garray_T  fc_ufuncs;      // list of ufunc_T* which keep a reference to
                                // "func"
  };
  
*** ../vim-9.0.0397/src/profiler.c      2022-05-28 13:38:55.000000000 +0100
--- src/profiler.c      2022-09-06 18:46:14.653046563 +0100
***************
*** 718,725 ****
  {
      funccall_T *fc = get_current_funccal();
  
!     if (fc != NULL && fc->func->uf_profiling)
!       profile_start(&fc->prof_child);
      script_prof_save(tm);
  }
  
--- 718,725 ----
  {
      funccall_T *fc = get_current_funccal();
  
!     if (fc != NULL && fc->fc_func->uf_profiling)
!       profile_start(&fc->fc_prof_child);
      script_prof_save(tm);
  }
  
***************
*** 733,744 ****
  {
      funccall_T *fc = get_current_funccal();
  
!     if (fc != NULL && fc->func->uf_profiling)
      {
!       profile_end(&fc->prof_child);
!       profile_sub_wait(tm, &fc->prof_child); // don't count waiting time
!       profile_add(&fc->func->uf_tm_children, &fc->prof_child);
!       profile_add(&fc->func->uf_tml_children, &fc->prof_child);
      }
      script_prof_restore(tm);
  }
--- 733,744 ----
  {
      funccall_T *fc = get_current_funccal();
  
!     if (fc != NULL && fc->fc_func->uf_profiling)
      {
!       profile_end(&fc->fc_prof_child);
!       profile_sub_wait(tm, &fc->fc_prof_child); // don't count waiting time
!       profile_add(&fc->fc_func->uf_tm_children, &fc->fc_prof_child);
!       profile_add(&fc->fc_func->uf_tml_children, &fc->fc_prof_child);
      }
      script_prof_restore(tm);
  }
***************
*** 753,759 ****
  func_line_start(void *cookie, long lnum)
  {
      funccall_T        *fcp = (funccall_T *)cookie;
!     ufunc_T   *fp = fcp->func;
  
      if (fp->uf_profiling && lnum >= 1 && lnum <= fp->uf_lines.ga_len)
      {
--- 753,759 ----
  func_line_start(void *cookie, long lnum)
  {
      funccall_T        *fcp = (funccall_T *)cookie;
!     ufunc_T   *fp = fcp->fc_func;
  
      if (fp->uf_profiling && lnum >= 1 && lnum <= fp->uf_lines.ga_len)
      {
***************
*** 775,781 ****
  func_line_exec(void *cookie)
  {
      funccall_T        *fcp = (funccall_T *)cookie;
!     ufunc_T   *fp = fcp->func;
  
      if (fp->uf_profiling && fp->uf_tml_idx >= 0)
        fp->uf_tml_execed = TRUE;
--- 775,781 ----
  func_line_exec(void *cookie)
  {
      funccall_T        *fcp = (funccall_T *)cookie;
!     ufunc_T   *fp = fcp->fc_func;
  
      if (fp->uf_profiling && fp->uf_tml_idx >= 0)
        fp->uf_tml_execed = TRUE;
***************
*** 788,794 ****
  func_line_end(void *cookie)
  {
      funccall_T        *fcp = (funccall_T *)cookie;
!     ufunc_T   *fp = fcp->func;
  
      if (fp->uf_profiling && fp->uf_tml_idx >= 0)
      {
--- 788,794 ----
  func_line_end(void *cookie)
  {
      funccall_T        *fcp = (funccall_T *)cookie;
!     ufunc_T   *fp = fcp->fc_func;
  
      if (fp->uf_profiling && fp->uf_tml_idx >= 0)
      {
*** ../vim-9.0.0397/src/userfunc.c      2022-09-06 18:31:09.070310282 +0100
--- src/userfunc.c      2022-09-06 18:54:28.732071228 +0100
***************
*** 499,508 ****
      fp->uf_scoped = current_funccal;
      current_funccal->fc_refcount++;
  
!     if (ga_grow(&current_funccal->fc_funcs, 1) == FAIL)
        return FAIL;
!     ((ufunc_T **)current_funccal->fc_funcs.ga_data)
!       [current_funccal->fc_funcs.ga_len++] = fp;
      return OK;
  }
  
--- 499,508 ----
      fp->uf_scoped = current_funccal;
      current_funccal->fc_refcount++;
  
!     if (ga_grow(&current_funccal->fc_ufuncs, 1) == FAIL)
        return FAIL;
!     ((ufunc_T **)current_funccal->fc_ufuncs.ga_data)
!                                   [current_funccal->fc_ufuncs.ga_len++] = fp;
      return OK;
  }
  
***************
*** 2141,2149 ****
  {
      int       i;
  
!     for (i = 0; i < fc->fc_funcs.ga_len; ++i)
      {
!       ufunc_T *fp = ((ufunc_T **)(fc->fc_funcs.ga_data))[i];
  
        // When garbage collecting a funccall_T may be freed before the
        // function that references it, clear its uf_scoped field.
--- 2141,2149 ----
  {
      int       i;
  
!     for (i = 0; i < fc->fc_ufuncs.ga_len; ++i)
      {
!       ufunc_T *fp = ((ufunc_T **)(fc->fc_ufuncs.ga_data))[i];
  
        // When garbage collecting a funccall_T may be freed before the
        // function that references it, clear its uf_scoped field.
***************
*** 2152,2160 ****
        if (fp != NULL && fp->uf_scoped == fc)
            fp->uf_scoped = NULL;
      }
!     ga_clear(&fc->fc_funcs);
  
!     func_ptr_unref(fc->func);
      vim_free(fc);
  }
  
--- 2152,2160 ----
        if (fp != NULL && fp->uf_scoped == fc)
            fp->uf_scoped = NULL;
      }
!     ga_clear(&fc->fc_ufuncs);
  
!     func_ptr_unref(fc->fc_func);
      vim_free(fc);
  }
  
***************
*** 2169,2181 ****
      listitem_T        *li;
  
      // Free all l: variables.
!     vars_clear(&fc->l_vars.dv_hashtab);
  
      // Free all a: variables.
!     vars_clear(&fc->l_avars.dv_hashtab);
  
      // Free the a:000 variables.
!     FOR_ALL_LIST_ITEMS(&fc->l_varlist, li)
        clear_tv(&li->li_tv);
  
      free_funccal(fc);
--- 2169,2181 ----
      listitem_T        *li;
  
      // Free all l: variables.
!     vars_clear(&fc->fc_l_vars.dv_hashtab);
  
      // Free all a: variables.
!     vars_clear(&fc->fc_l_avars.dv_hashtab);
  
      // Free the a:000 variables.
!     FOR_ALL_LIST_ITEMS(&fc->fc_l_varlist, li)
        clear_tv(&li->li_tv);
  
      free_funccal(fc);
***************
*** 2191,2209 ****
      int       may_free_fc = fc->fc_refcount <= 0;
      int       free_fc = TRUE;
  
!     current_funccal = fc->caller;
  
      // Free all l: variables if not referred.
!     if (may_free_fc && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT)
!       vars_clear(&fc->l_vars.dv_hashtab);
      else
        free_fc = FALSE;
  
      // If the a:000 list and the l: and a: dicts are not referenced and
      // there is no closure using it, we can free the funccall_T and what's
      // in it.
!     if (may_free_fc && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT)
!       vars_clear_ext(&fc->l_avars.dv_hashtab, FALSE);
      else
      {
        int         todo;
--- 2191,2209 ----
      int       may_free_fc = fc->fc_refcount <= 0;
      int       free_fc = TRUE;
  
!     current_funccal = fc->fc_caller;
  
      // Free all l: variables if not referred.
!     if (may_free_fc && fc->fc_l_vars.dv_refcount == DO_NOT_FREE_CNT)
!       vars_clear(&fc->fc_l_vars.dv_hashtab);
      else
        free_fc = FALSE;
  
      // If the a:000 list and the l: and a: dicts are not referenced and
      // there is no closure using it, we can free the funccall_T and what's
      // in it.
!     if (may_free_fc && fc->fc_l_avars.dv_refcount == DO_NOT_FREE_CNT)
!       vars_clear_ext(&fc->fc_l_avars.dv_hashtab, FALSE);
      else
      {
        int         todo;
***************
*** 2213,2220 ****
        free_fc = FALSE;
  
        // Make a copy of the a: variables, since we didn't do that above.
!       todo = (int)fc->l_avars.dv_hashtab.ht_used;
!       for (hi = fc->l_avars.dv_hashtab.ht_array; todo > 0; ++hi)
        {
            if (!HASHITEM_EMPTY(hi))
            {
--- 2213,2220 ----
        free_fc = FALSE;
  
        // Make a copy of the a: variables, since we didn't do that above.
!       todo = (int)fc->fc_l_avars.dv_hashtab.ht_used;
!       for (hi = fc->fc_l_avars.dv_hashtab.ht_array; todo > 0; ++hi)
        {
            if (!HASHITEM_EMPTY(hi))
            {
***************
*** 2225,2232 ****
        }
      }
  
!     if (may_free_fc && fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT)
!       fc->l_varlist.lv_first = NULL;
      else
      {
        listitem_T *li;
--- 2225,2232 ----
        }
      }
  
!     if (may_free_fc && fc->fc_l_varlist.lv_refcount == DO_NOT_FREE_CNT)
!       fc->fc_l_varlist.lv_first = NULL;
      else
      {
        listitem_T *li;
***************
*** 2234,2240 ****
        free_fc = FALSE;
  
        // Make a copy of the a:000 items, since we didn't do that above.
!       FOR_ALL_LIST_ITEMS(&fc->l_varlist, li)
            copy_tv(&li->li_tv, &li->li_tv);
      }
  
--- 2234,2240 ----
        free_fc = FALSE;
  
        // Make a copy of the a:000 items, since we didn't do that above.
!       FOR_ALL_LIST_ITEMS(&fc->fc_l_varlist, li)
            copy_tv(&li->li_tv, &li->li_tv);
      }
  
***************
*** 2247,2253 ****
        // "fc" is still in use.  This can happen when returning "a:000",
        // assigning "l:" to a global variable or defining a closure.
        // Link "fc" in the list for garbage collection later.
!       fc->caller = previous_funccal;
        previous_funccal = fc;
  
        if (want_garbage_collect)
--- 2247,2253 ----
        // "fc" is still in use.  This can happen when returning "a:000",
        // assigning "l:" to a global variable or defining a closure.
        // Link "fc" in the list for garbage collection later.
!       fc->fc_caller = previous_funccal;
        previous_funccal = fc;
  
        if (want_garbage_collect)
***************
*** 2305,2325 ****
        return;
  
      if (--fc->fc_refcount <= 0 && (force || (
!               fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT
!               && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT
!               && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT)))
!       for (pfc = &previous_funccal; *pfc != NULL; pfc = &(*pfc)->caller)
        {
            if (fc == *pfc)
            {
!               *pfc = fc->caller;
                free_funccal_contents(fc);
                return;
            }
        }
!     for (i = 0; i < fc->fc_funcs.ga_len; ++i)
!       if (((ufunc_T **)(fc->fc_funcs.ga_data))[i] == fp)
!           ((ufunc_T **)(fc->fc_funcs.ga_data))[i] = NULL;
  }
  
  /*
--- 2305,2325 ----
        return;
  
      if (--fc->fc_refcount <= 0 && (force || (
!               fc->fc_l_varlist.lv_refcount == DO_NOT_FREE_CNT
!               && fc->fc_l_vars.dv_refcount == DO_NOT_FREE_CNT
!               && fc->fc_l_avars.dv_refcount == DO_NOT_FREE_CNT)))
!       for (pfc = &previous_funccal; *pfc != NULL; pfc = &(*pfc)->fc_caller)
        {
            if (fc == *pfc)
            {
!               *pfc = fc->fc_caller;
                free_funccal_contents(fc);
                return;
            }
        }
!     for (i = 0; i < fc->fc_ufuncs.ga_len; ++i)
!       if (((ufunc_T **)(fc->fc_ufuncs.ga_data))[i] == fp)
!           ((ufunc_T **)(fc->fc_ufuncs.ga_data))[i] = NULL;
  }
  
  /*
***************
*** 2599,2605 ****
      int               save_did_emsg;
      int               default_arg_err = FALSE;
      dictitem_T        *v;
!     int               fixvar_idx = 0; // index in fixvar[]
      int               i;
      int               ai;
      int               islambda = FALSE;
--- 2599,2605 ----
      int               save_did_emsg;
      int               default_arg_err = FALSE;
      dictitem_T        *v;
!     int               fixvar_idx = 0; // index in fc_fixvar[]
      int               i;
      int               ai;
      int               islambda = FALSE;
***************
*** 2629,2650 ****
      fc = ALLOC_CLEAR_ONE(funccall_T);
      if (fc == NULL)
        return;
!     fc->caller = current_funccal;
      current_funccal = fc;
!     fc->func = fp;
!     fc->rettv = rettv;
!     fc->level = ex_nesting_level;
      // Check if this function has a breakpoint.
!     fc->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0);
!     fc->dbg_tick = debug_tick;
      // Set up fields for closure.
!     ga_init2(&fc->fc_funcs, sizeof(ufunc_T *), 1);
      func_ptr_ref(fp);
  
      if (fp->uf_def_status != UF_NOT_COMPILED)
      {
  #ifdef FEAT_PROFILE
!       ufunc_T *caller = fc->caller == NULL ? NULL : fc->caller->func;
  #endif
        // Execute the function, possibly compiling it first.
  #ifdef FEAT_PROFILE
--- 2629,2650 ----
      fc = ALLOC_CLEAR_ONE(funccall_T);
      if (fc == NULL)
        return;
!     fc->fc_caller = current_funccal;
      current_funccal = fc;
!     fc->fc_func = fp;
!     fc->fc_rettv = rettv;
!     fc->fc_level = ex_nesting_level;
      // Check if this function has a breakpoint.
!     fc->fc_breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0);
!     fc->fc_dbg_tick = debug_tick;
      // Set up fields for closure.
!     ga_init2(&fc->fc_ufuncs, sizeof(ufunc_T *), 1);
      func_ptr_ref(fp);
  
      if (fp->uf_def_status != UF_NOT_COMPILED)
      {
  #ifdef FEAT_PROFILE
!       ufunc_T *caller = fc->fc_caller == NULL ? NULL : fc->fc_caller->fc_func;
  #endif
        // Execute the function, possibly compiling it first.
  #ifdef FEAT_PROFILE
***************
*** 2660,2666 ****
                                  || (caller != NULL && caller->uf_profiling)))
            profile_may_end_func(&profile_info, fp, caller);
  #endif
!       current_funccal = fc->caller;
        free_funccal(fc);
        sticky_cmdmod_flags = save_sticky_cmdmod_flags;
        return;
--- 2660,2666 ----
                                  || (caller != NULL && caller->uf_profiling)))
            profile_may_end_func(&profile_info, fp, caller);
  #endif
!       current_funccal = fc->fc_caller;
        free_funccal(fc);
        sticky_cmdmod_flags = save_sticky_cmdmod_flags;
        return;
***************
*** 2669,2691 ****
      islambda = fp->uf_flags & FC_LAMBDA;
  
      /*
!      * Note about using fc->fixvar[]: This is an array of FIXVAR_CNT variables
       * with names up to VAR_SHORT_LEN long.  This avoids having to alloc/free
       * each argument variable and saves a lot of time.
       */
      /*
       * Init l: variables.
       */
!     init_var_dict(&fc->l_vars, &fc->l_vars_var, VAR_DEF_SCOPE);
      if (selfdict != NULL)
      {
        // Set l:self to "selfdict".  Use "name" to avoid a warning from
        // some compiler that checks the destination size.
!       v = &fc->fixvar[fixvar_idx++].var;
        name = v->di_key;
        STRCPY(name, "self");
        v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
!       hash_add(&fc->l_vars.dv_hashtab, DI2HIKEY(v));
        v->di_tv.v_type = VAR_DICT;
        v->di_tv.v_lock = 0;
        v->di_tv.vval.v_dict = selfdict;
--- 2669,2691 ----
      islambda = fp->uf_flags & FC_LAMBDA;
  
      /*
!      * Note about using fc->fc_fixvar[]: This is an array of FIXVAR_CNT 
variables
       * with names up to VAR_SHORT_LEN long.  This avoids having to alloc/free
       * each argument variable and saves a lot of time.
       */
      /*
       * Init l: variables.
       */
!     init_var_dict(&fc->fc_l_vars, &fc->fc_l_vars_var, VAR_DEF_SCOPE);
      if (selfdict != NULL)
      {
        // Set l:self to "selfdict".  Use "name" to avoid a warning from
        // some compiler that checks the destination size.
!       v = &fc->fc_fixvar[fixvar_idx++].var;
        name = v->di_key;
        STRCPY(name, "self");
        v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
!       hash_add(&fc->fc_l_vars.dv_hashtab, DI2HIKEY(v));
        v->di_tv.v_type = VAR_DICT;
        v->di_tv.v_lock = 0;
        v->di_tv.vval.v_dict = selfdict;
***************
*** 2697,2724 ****
       * Set a:0 to "argcount" less number of named arguments, if >= 0.
       * Set a:000 to a list with room for the "..." arguments.
       */
!     init_var_dict(&fc->l_avars, &fc->l_avars_var, VAR_SCOPE);
      if ((fp->uf_flags & FC_NOARGS) == 0)
!       add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "0",
                                (varnumber_T)(argcount >= fp->uf_args.ga_len
                                    ? argcount - fp->uf_args.ga_len : 0));
!     fc->l_avars.dv_lock = VAR_FIXED;
      if ((fp->uf_flags & FC_NOARGS) == 0)
      {
        // Use "name" to avoid a warning from some compiler that checks the
        // destination size.
!       v = &fc->fixvar[fixvar_idx++].var;
        name = v->di_key;
        STRCPY(name, "000");
        v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
!       hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v));
        v->di_tv.v_type = VAR_LIST;
        v->di_tv.v_lock = VAR_FIXED;
!       v->di_tv.vval.v_list = &fc->l_varlist;
      }
!     CLEAR_FIELD(fc->l_varlist);
!     fc->l_varlist.lv_refcount = DO_NOT_FREE_CNT;
!     fc->l_varlist.lv_lock = VAR_FIXED;
  
      /*
       * Set a:firstline to "firstline" and a:lastline to "lastline".
--- 2697,2724 ----
       * Set a:0 to "argcount" less number of named arguments, if >= 0.
       * Set a:000 to a list with room for the "..." arguments.
       */
!     init_var_dict(&fc->fc_l_avars, &fc->fc_l_avars_var, VAR_SCOPE);
      if ((fp->uf_flags & FC_NOARGS) == 0)
!       add_nr_var(&fc->fc_l_avars, &fc->fc_fixvar[fixvar_idx++].var, "0",
                                (varnumber_T)(argcount >= fp->uf_args.ga_len
                                    ? argcount - fp->uf_args.ga_len : 0));
!     fc->fc_l_avars.dv_lock = VAR_FIXED;
      if ((fp->uf_flags & FC_NOARGS) == 0)
      {
        // Use "name" to avoid a warning from some compiler that checks the
        // destination size.
!       v = &fc->fc_fixvar[fixvar_idx++].var;
        name = v->di_key;
        STRCPY(name, "000");
        v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
!       hash_add(&fc->fc_l_avars.dv_hashtab, DI2HIKEY(v));
        v->di_tv.v_type = VAR_LIST;
        v->di_tv.v_lock = VAR_FIXED;
!       v->di_tv.vval.v_list = &fc->fc_l_varlist;
      }
!     CLEAR_FIELD(fc->fc_l_varlist);
!     fc->fc_l_varlist.lv_refcount = DO_NOT_FREE_CNT;
!     fc->fc_l_varlist.lv_lock = VAR_FIXED;
  
      /*
       * Set a:firstline to "firstline" and a:lastline to "lastline".
***************
*** 2728,2737 ****
       */
      if ((fp->uf_flags & FC_NOARGS) == 0)
      {
!       add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "firstline",
!                                          (varnumber_T)funcexe->fe_firstline);
!       add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "lastline",
!                                           (varnumber_T)funcexe->fe_lastline);
      }
      for (i = 0; i < argcount || i < fp->uf_args.ga_len; ++i)
      {
--- 2728,2737 ----
       */
      if ((fp->uf_flags & FC_NOARGS) == 0)
      {
!       add_nr_var(&fc->fc_l_avars, &fc->fc_fixvar[fixvar_idx++].var,
!                             "firstline", (varnumber_T)funcexe->fe_firstline);
!       add_nr_var(&fc->fc_l_avars, &fc->fc_fixvar[fixvar_idx++].var,
!                               "lastline", (varnumber_T)funcexe->fe_lastline);
      }
      for (i = 0; i < argcount || i < fp->uf_args.ga_len; ++i)
      {
***************
*** 2779,2785 ****
        }
        if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN)
        {
!           v = &fc->fixvar[fixvar_idx++].var;
            v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
            STRCPY(v->di_key, name);
        }
--- 2779,2785 ----
        }
        if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN)
        {
!           v = &fc->fc_fixvar[fixvar_idx++].var;
            v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
            STRCPY(v->di_key, name);
        }
***************
*** 2805,2822 ****
            // Named arguments should be accessed without the "a:" prefix in
            // lambda expressions.  Add to the l: dict.
            copy_tv(&v->di_tv, &v->di_tv);
!           hash_add(&fc->l_vars.dv_hashtab, DI2HIKEY(v));
        }
        else
!           hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v));
  
        if (ai >= 0 && ai < MAX_FUNC_ARGS)
        {
!           listitem_T *li = &fc->l_listitems[ai];
  
            li->li_tv = argvars[i];
            li->li_tv.v_lock = VAR_FIXED;
!           list_append(&fc->l_varlist, li);
        }
      }
  
--- 2805,2822 ----
            // Named arguments should be accessed without the "a:" prefix in
            // lambda expressions.  Add to the l: dict.
            copy_tv(&v->di_tv, &v->di_tv);
!           hash_add(&fc->fc_l_vars.dv_hashtab, DI2HIKEY(v));
        }
        else
!           hash_add(&fc->fc_l_avars.dv_hashtab, DI2HIKEY(v));
  
        if (ai >= 0 && ai < MAX_FUNC_ARGS)
        {
!           listitem_T *li = &fc->fc_l_listitems[ai];
  
            li->li_tv = argvars[i];
            li->li_tv.v_lock = VAR_FIXED;
!           list_append(&fc->fc_l_varlist, li);
        }
      }
  
***************
*** 2879,2885 ****
  #ifdef FEAT_PROFILE
      if (do_profiling == PROF_YES)
        profile_may_start_func(&profile_info, fp,
!                                fc->caller == NULL ? NULL : fc->caller->func);
  #endif
  
      // "legacy" does not apply to commands in the function
--- 2879,2885 ----
  #ifdef FEAT_PROFILE
      if (do_profiling == PROF_YES)
        profile_may_start_func(&profile_info, fp,
!                       fc->fc_caller == NULL ? NULL : fc->fc_caller->fc_func);
  #endif
  
      // "legacy" does not apply to commands in the function
***************
*** 2923,2929 ****
  #ifdef FEAT_PROFILE
      if (do_profiling == PROF_YES)
      {
!       ufunc_T *caller = fc->caller == NULL ? NULL : fc->caller->func;
  
        if (fp->uf_profiling || (caller != NULL && caller->uf_profiling))
            profile_may_end_func(&profile_info, fp, caller);
--- 2923,2929 ----
  #ifdef FEAT_PROFILE
      if (do_profiling == PROF_YES)
      {
!       ufunc_T *caller = fc->fc_caller == NULL ? NULL : fc->fc_caller->fc_func;
  
        if (fp->uf_profiling || (caller != NULL && caller->uf_profiling))
            profile_may_end_func(&profile_info, fp, caller);
***************
*** 2938,2946 ****
  
        if (aborting())
            smsg(_("%s aborted"), SOURCING_NAME);
!       else if (fc->rettv->v_type == VAR_NUMBER)
            smsg(_("%s returning #%ld"), SOURCING_NAME,
!                                              (long)fc->rettv->vval.v_number);
        else
        {
            char_u      buf[MSG_BUF_LEN];
--- 2938,2946 ----
  
        if (aborting())
            smsg(_("%s aborted"), SOURCING_NAME);
!       else if (fc->fc_rettv->v_type == VAR_NUMBER)
            smsg(_("%s returning #%ld"), SOURCING_NAME,
!                                           (long)fc->fc_rettv->vval.v_number);
        else
        {
            char_u      buf[MSG_BUF_LEN];
***************
*** 2952,2958 ****
            // have some idea how it starts and ends. smsg() would always
            // truncate it at the end. Don't want errors such as E724 here.
            ++emsg_off;
!           s = tv2string(fc->rettv, &tofree, numbuf2, 0);
            --emsg_off;
            if (s != NULL)
            {
--- 2952,2958 ----
            // have some idea how it starts and ends. smsg() would always
            // truncate it at the end. Don't want errors such as E724 here.
            ++emsg_off;
!           s = tv2string(fc->fc_rettv, &tofree, numbuf2, 0);
            --emsg_off;
            if (s != NULL)
            {
***************
*** 3188,3194 ****
      // Clean up the current_funccal chain and the funccal stack.
      while (current_funccal != NULL)
      {
!       clear_tv(current_funccal->rettv);
        cleanup_function_call(current_funccal);
        if (current_funccal == NULL && funccal_stack != NULL)
            restore_funccal();
--- 3188,3194 ----
      // Clean up the current_funccal chain and the funccal stack.
      while (current_funccal != NULL)
      {
!       clear_tv(current_funccal->fc_rettv);
        cleanup_function_call(current_funccal);
        if (current_funccal == NULL && funccal_stack != NULL)
            restore_funccal();
***************
*** 5418,5426 ****
      static int
  can_free_funccal(funccall_T *fc, int copyID)
  {
!     return (fc->l_varlist.lv_copyID != copyID
!           && fc->l_vars.dv_copyID != copyID
!           && fc->l_avars.dv_copyID != copyID
            && fc->fc_copyID != copyID);
  }
  
--- 5418,5426 ----
      static int
  can_free_funccal(funccall_T *fc, int copyID)
  {
!     return (fc->fc_l_varlist.lv_copyID != copyID
!           && fc->fc_l_vars.dv_copyID != copyID
!           && fc->fc_l_avars.dv_copyID != copyID
            && fc->fc_copyID != copyID);
  }
  
***************
*** 5696,5702 ****
  {
      funccall_T *funccal;
  
!     for (funccal = current_funccal; funccal != NULL; funccal = 
funccal->caller)
        if (funccal->fc_ectx != NULL)
        {
            // :def function
--- 5696,5703 ----
  {
      funccall_T *funccal;
  
!     for (funccal = current_funccal; funccal != NULL;
!                                                 funccal = funccal->fc_caller)
        if (funccal->fc_ectx != NULL)
        {
            // :def function
***************
*** 5849,5855 ****
  
      if (reanimate)
        // Undo the return.
!       current_funccal->returned = FALSE;
  
      /*
       * Cleanup (and inactivate) conditionals, but stop when a try conditional
--- 5850,5856 ----
  
      if (reanimate)
        // Undo the return.
!       current_funccal->fc_returned = FALSE;
  
      /*
       * Cleanup (and inactivate) conditionals, but stop when a try conditional
***************
*** 5872,5878 ****
            // When undoing a return in order to make it pending, get the stored
            // return rettv.
            if (reanimate)
!               rettv = current_funccal->rettv;
  
            if (rettv != NULL)
            {
--- 5873,5879 ----
            // When undoing a return in order to make it pending, get the stored
            // return rettv.
            if (reanimate)
!               rettv = current_funccal->fc_rettv;
  
            if (rettv != NULL)
            {
***************
*** 5890,5912 ****
                // The pending return value could be overwritten by a ":return"
                // without argument in a finally clause; reset the default
                // return value.
!               current_funccal->rettv->v_type = VAR_NUMBER;
!               current_funccal->rettv->vval.v_number = 0;
            }
        }
        report_make_pending(CSTP_RETURN, rettv);
      }
      else
      {
!       current_funccal->returned = TRUE;
  
        // If the return is carried out now, store the return value.  For
        // a return immediately after reanimation, the value is already
        // there.
        if (!reanimate && rettv != NULL)
        {
!           clear_tv(current_funccal->rettv);
!           *current_funccal->rettv = *(typval_T *)rettv;
            if (!is_cmd)
                vim_free(rettv);
        }
--- 5891,5913 ----
                // The pending return value could be overwritten by a ":return"
                // without argument in a finally clause; reset the default
                // return value.
!               current_funccal->fc_rettv->v_type = VAR_NUMBER;
!               current_funccal->fc_rettv->vval.v_number = 0;
            }
        }
        report_make_pending(CSTP_RETURN, rettv);
      }
      else
      {
!       current_funccal->fc_returned = TRUE;
  
        // If the return is carried out now, store the return value.  For
        // a return immediately after reanimation, the value is already
        // there.
        if (!reanimate && rettv != NULL)
        {
!           clear_tv(current_funccal->fc_rettv);
!           *current_funccal->fc_rettv = *(typval_T *)rettv;
            if (!is_cmd)
                vim_free(rettv);
        }
***************
*** 5961,5976 ****
      getline_opt_T options UNUSED)
  {
      funccall_T        *fcp = (funccall_T *)cookie;
!     ufunc_T   *fp = fcp->func;
      char_u    *retval;
      garray_T  *gap;  // growarray with function lines
  
      // If breakpoints have been added/deleted need to check for it.
!     if (fcp->dbg_tick != debug_tick)
      {
!       fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
                                                               SOURCING_LNUM);
!       fcp->dbg_tick = debug_tick;
      }
  #ifdef FEAT_PROFILE
      if (do_profiling == PROF_YES)
--- 5962,5977 ----
      getline_opt_T options UNUSED)
  {
      funccall_T        *fcp = (funccall_T *)cookie;
!     ufunc_T   *fp = fcp->fc_func;
      char_u    *retval;
      garray_T  *gap;  // growarray with function lines
  
      // If breakpoints have been added/deleted need to check for it.
!     if (fcp->fc_dbg_tick != debug_tick)
      {
!       fcp->fc_breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
                                                               SOURCING_LNUM);
!       fcp->fc_dbg_tick = debug_tick;
      }
  #ifdef FEAT_PROFILE
      if (do_profiling == PROF_YES)
***************
*** 5979,5998 ****
  
      gap = &fp->uf_lines;
      if (((fp->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
!           || fcp->returned)
        retval = NULL;
      else
      {
        // Skip NULL lines (continuation lines).
!       while (fcp->linenr < gap->ga_len
!                         && ((char_u **)(gap->ga_data))[fcp->linenr] == NULL)
!           ++fcp->linenr;
!       if (fcp->linenr >= gap->ga_len)
            retval = NULL;
        else
        {
!           retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]);
!           SOURCING_LNUM = fcp->linenr;
  #ifdef FEAT_PROFILE
            if (do_profiling == PROF_YES)
                func_line_start(cookie, SOURCING_LNUM);
--- 5980,5999 ----
  
      gap = &fp->uf_lines;
      if (((fp->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
!           || fcp->fc_returned)
        retval = NULL;
      else
      {
        // Skip NULL lines (continuation lines).
!       while (fcp->fc_linenr < gap->ga_len
!                       && ((char_u **)(gap->ga_data))[fcp->fc_linenr] == NULL)
!           ++fcp->fc_linenr;
!       if (fcp->fc_linenr >= gap->ga_len)
            retval = NULL;
        else
        {
!           retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->fc_linenr++]);
!           SOURCING_LNUM = fcp->fc_linenr;
  #ifdef FEAT_PROFILE
            if (do_profiling == PROF_YES)
                func_line_start(cookie, SOURCING_LNUM);
***************
*** 6001,6013 ****
      }
  
      // Did we encounter a breakpoint?
!     if (fcp->breakpoint != 0 && fcp->breakpoint <= SOURCING_LNUM)
      {
        dbg_breakpoint(fp->uf_name, SOURCING_LNUM);
        // Find next breakpoint.
!       fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
                                                               SOURCING_LNUM);
!       fcp->dbg_tick = debug_tick;
      }
  
      return retval;
--- 6002,6014 ----
      }
  
      // Did we encounter a breakpoint?
!     if (fcp->fc_breakpoint != 0 && fcp->fc_breakpoint <= SOURCING_LNUM)
      {
        dbg_breakpoint(fp->uf_name, SOURCING_LNUM);
        // Find next breakpoint.
!       fcp->fc_breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
                                                               SOURCING_LNUM);
!       fcp->fc_dbg_tick = debug_tick;
      }
  
      return retval;
***************
*** 6024,6031 ****
  
      // Ignore the "abort" flag if the abortion behavior has been changed due 
to
      // an error inside a try conditional.
!     return (((fcp->func->uf_flags & FC_ABORT) && did_emsg && 
!aborted_in_try())
!           || fcp->returned);
  }
  
  /*
--- 6025,6033 ----
  
      // Ignore the "abort" flag if the abortion behavior has been changed due 
to
      // an error inside a try conditional.
!     return (((fcp->fc_func->uf_flags & FC_ABORT)
!                                             && did_emsg && !aborted_in_try())
!           || fcp->fc_returned);
  }
  
  /*
***************
*** 6035,6041 ****
  func_has_abort(
      void    *cookie)
  {
!     return ((funccall_T *)cookie)->func->uf_flags & FC_ABORT;
  }
  
  
--- 6037,6043 ----
  func_has_abort(
      void    *cookie)
  {
!     return ((funccall_T *)cookie)->fc_func->uf_flags & FC_ABORT;
  }
  
  
***************
*** 6143,6149 ****
      char_u *
  func_name(void *cookie)
  {
!     return ((funccall_T *)cookie)->func->uf_name;
  }
  
  /*
--- 6145,6151 ----
      char_u *
  func_name(void *cookie)
  {
!     return ((funccall_T *)cookie)->fc_func->uf_name;
  }
  
  /*
***************
*** 6152,6158 ****
      linenr_T *
  func_breakpoint(void *cookie)
  {
!     return &((funccall_T *)cookie)->breakpoint;
  }
  
  /*
--- 6154,6160 ----
      linenr_T *
  func_breakpoint(void *cookie)
  {
!     return &((funccall_T *)cookie)->fc_breakpoint;
  }
  
  /*
***************
*** 6161,6167 ****
      int *
  func_dbg_tick(void *cookie)
  {
!     return &((funccall_T *)cookie)->dbg_tick;
  }
  
  /*
--- 6163,6169 ----
      int *
  func_dbg_tick(void *cookie)
  {
!     return &((funccall_T *)cookie)->fc_dbg_tick;
  }
  
  /*
***************
*** 6170,6176 ****
      int
  func_level(void *cookie)
  {
!     return ((funccall_T *)cookie)->level;
  }
  
  /*
--- 6172,6178 ----
      int
  func_level(void *cookie)
  {
!     return ((funccall_T *)cookie)->fc_level;
  }
  
  /*
***************
*** 6179,6185 ****
      int
  current_func_returned(void)
  {
!     return current_funccal->returned;
  }
  
      int
--- 6181,6187 ----
      int
  current_func_returned(void)
  {
!     return current_funccal->fc_returned;
  }
  
      int
***************
*** 6194,6206 ****
        if (can_free_funccal(*pfc, copyID))
        {
            fc = *pfc;
!           *pfc = fc->caller;
            free_funccal_contents(fc);
            did_free = TRUE;
            did_free_funccal = TRUE;
        }
        else
!           pfc = &(*pfc)->caller;
      }
      if (did_free_funccal)
        // When a funccal was freed some more items might be garbage
--- 6196,6208 ----
        if (can_free_funccal(*pfc, copyID))
        {
            fc = *pfc;
!           *pfc = fc->fc_caller;
            free_funccal_contents(fc);
            did_free = TRUE;
            did_free_funccal = TRUE;
        }
        else
!           pfc = &(*pfc)->fc_caller;
      }
      if (did_free_funccal)
        // When a funccal was freed some more items might be garbage
***************
*** 6225,6231 ****
      {
        for (i = 0; i < debug_backtrace_level; i++)
        {
!           temp_funccal = funccal->caller;
            if (temp_funccal)
                funccal = temp_funccal;
            else
--- 6227,6233 ----
      {
        for (i = 0; i < debug_backtrace_level; i++)
        {
!           temp_funccal = funccal->fc_caller;
            if (temp_funccal)
                funccal = temp_funccal;
            else
***************
*** 6243,6251 ****
      hashtab_T *
  get_funccal_local_ht()
  {
!     if (current_funccal == NULL || current_funccal->l_vars.dv_refcount == 0)
        return NULL;
!     return &get_funccal()->l_vars.dv_hashtab;
  }
  
  /*
--- 6245,6253 ----
      hashtab_T *
  get_funccal_local_ht()
  {
!     if (current_funccal == NULL || current_funccal->fc_l_vars.dv_refcount == 
0)
        return NULL;
!     return &get_funccal()->fc_l_vars.dv_hashtab;
  }
  
  /*
***************
*** 6255,6263 ****
      dictitem_T *
  get_funccal_local_var()
  {
!     if (current_funccal == NULL || current_funccal->l_vars.dv_refcount == 0)
        return NULL;
!     return &get_funccal()->l_vars_var;
  }
  
  /*
--- 6257,6265 ----
      dictitem_T *
  get_funccal_local_var()
  {
!     if (current_funccal == NULL || current_funccal->fc_l_vars.dv_refcount == 
0)
        return NULL;
!     return &get_funccal()->fc_l_vars_var;
  }
  
  /*
***************
*** 6267,6275 ****
      hashtab_T *
  get_funccal_args_ht()
  {
!     if (current_funccal == NULL || current_funccal->l_vars.dv_refcount == 0)
        return NULL;
!     return &get_funccal()->l_avars.dv_hashtab;
  }
  
  /*
--- 6269,6277 ----
      hashtab_T *
  get_funccal_args_ht()
  {
!     if (current_funccal == NULL || current_funccal->fc_l_vars.dv_refcount == 
0)
        return NULL;
!     return &get_funccal()->fc_l_avars.dv_hashtab;
  }
  
  /*
***************
*** 6279,6287 ****
      dictitem_T *
  get_funccal_args_var()
  {
!     if (current_funccal == NULL || current_funccal->l_vars.dv_refcount == 0)
        return NULL;
!     return &get_funccal()->l_avars_var;
  }
  
  /*
--- 6281,6289 ----
      dictitem_T *
  get_funccal_args_var()
  {
!     if (current_funccal == NULL || current_funccal->fc_l_vars.dv_refcount == 
0)
        return NULL;
!     return &get_funccal()->fc_l_avars_var;
  }
  
  /*
***************
*** 6290,6297 ****
      void
  list_func_vars(int *first)
  {
!     if (current_funccal != NULL && current_funccal->l_vars.dv_refcount > 0)
!       list_hashtable_vars(&current_funccal->l_vars.dv_hashtab,
                                                           "l:", FALSE, first);
  }
  
--- 6292,6299 ----
      void
  list_func_vars(int *first)
  {
!     if (current_funccal != NULL && current_funccal->fc_l_vars.dv_refcount > 0)
!       list_hashtable_vars(&current_funccal->fc_l_vars.dv_hashtab,
                                                           "l:", FALSE, first);
  }
  
***************
*** 6304,6311 ****
  get_current_funccal_dict(hashtab_T *ht)
  {
      if (current_funccal != NULL
!           && ht == &current_funccal->l_vars.dv_hashtab)
!       return &current_funccal->l_vars;
      return NULL;
  }
  
--- 6306,6313 ----
  get_current_funccal_dict(hashtab_T *ht)
  {
      if (current_funccal != NULL
!           && ht == &current_funccal->fc_l_vars.dv_hashtab)
!       return &current_funccal->fc_l_vars;
      return NULL;
  }
  
***************
*** 6320,6330 ****
      hashitem_T        *hi = NULL;
      char_u    *varname;
  
!     if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL)
        return NULL;
  
      // Search in parent scope, which can be referenced from a lambda.
!     current_funccal = current_funccal->func->uf_scoped;
      while (current_funccal != NULL)
      {
        ht = find_var_ht(name, &varname);
--- 6322,6332 ----
      hashitem_T        *hi = NULL;
      char_u    *varname;
  
!     if (current_funccal == NULL || current_funccal->fc_func->uf_scoped == 
NULL)
        return NULL;
  
      // Search in parent scope, which can be referenced from a lambda.
!     current_funccal = current_funccal->fc_func->uf_scoped;
      while (current_funccal != NULL)
      {
        ht = find_var_ht(name, &varname);
***************
*** 6337,6345 ****
                break;
            }
        }
!       if (current_funccal == current_funccal->func->uf_scoped)
            break;
!       current_funccal = current_funccal->func->uf_scoped;
      }
      current_funccal = old_current_funccal;
  
--- 6339,6347 ----
                break;
            }
        }
!       if (current_funccal == current_funccal->fc_func->uf_scoped)
            break;
!       current_funccal = current_funccal->fc_func->uf_scoped;
      }
      current_funccal = old_current_funccal;
  
***************
*** 6357,6367 ****
      hashtab_T *ht;
      char_u    *varname;
  
!     if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL)
        return NULL;
  
      // Search in parent scope which is possible to reference from lambda
!     current_funccal = current_funccal->func->uf_scoped;
      while (current_funccal)
      {
        ht = find_var_ht(name, &varname);
--- 6359,6369 ----
      hashtab_T *ht;
      char_u    *varname;
  
!     if (current_funccal == NULL || current_funccal->fc_func->uf_scoped == 
NULL)
        return NULL;
  
      // Search in parent scope which is possible to reference from lambda
!     current_funccal = current_funccal->fc_func->uf_scoped;
      while (current_funccal)
      {
        ht = find_var_ht(name, &varname);
***************
*** 6371,6379 ****
            if (v != NULL)
                break;
        }
!       if (current_funccal == current_funccal->func->uf_scoped)
            break;
!       current_funccal = current_funccal->func->uf_scoped;
      }
      current_funccal = old_current_funccal;
  
--- 6373,6381 ----
            if (v != NULL)
                break;
        }
!       if (current_funccal == current_funccal->fc_func->uf_scoped)
            break;
!       current_funccal = current_funccal->fc_func->uf_scoped;
      }
      current_funccal = old_current_funccal;
  
***************
*** 6388,6399 ****
  {
      funccall_T        *fc;
  
!     for (fc = previous_funccal; fc != NULL; fc = fc->caller)
      {
        fc->fc_copyID = copyID + 1;
!       if (set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1, NULL)
!               || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1, NULL)
!               || set_ref_in_list_items(&fc->l_varlist, copyID + 1, NULL))
            return TRUE;
      }
      return FALSE;
--- 6390,6401 ----
  {
      funccall_T        *fc;
  
!     for (fc = previous_funccal; fc != NULL; fc = fc->fc_caller)
      {
        fc->fc_copyID = copyID + 1;
!       if (set_ref_in_ht(&fc->fc_l_vars.dv_hashtab, copyID + 1, NULL)
!               || set_ref_in_ht(&fc->fc_l_avars.dv_hashtab, copyID + 1, NULL)
!               || set_ref_in_list_items(&fc->fc_l_varlist, copyID + 1, NULL))
            return TRUE;
      }
      return FALSE;
***************
*** 6405,6414 ****
      if (fc->fc_copyID != copyID)
      {
        fc->fc_copyID = copyID;
!       if (set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL)
!               || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL)
!               || set_ref_in_list_items(&fc->l_varlist, copyID, NULL)
!               || set_ref_in_func(NULL, fc->func, copyID))
            return TRUE;
      }
      return FALSE;
--- 6407,6416 ----
      if (fc->fc_copyID != copyID)
      {
        fc->fc_copyID = copyID;
!       if (set_ref_in_ht(&fc->fc_l_vars.dv_hashtab, copyID, NULL)
!               || set_ref_in_ht(&fc->fc_l_avars.dv_hashtab, copyID, NULL)
!               || set_ref_in_list_items(&fc->fc_l_varlist, copyID, NULL)
!               || set_ref_in_func(NULL, fc->fc_func, copyID))
            return TRUE;
      }
      return FALSE;
***************
*** 6423,6435 ****
      funccall_T                *fc;
      funccal_entry_T   *entry;
  
!     for (fc = current_funccal; fc != NULL; fc = fc->caller)
        if (set_ref_in_funccal(fc, copyID))
            return TRUE;
  
      // Also go through the funccal_stack.
      for (entry = funccal_stack; entry != NULL; entry = entry->next)
!       for (fc = entry->top_funccal; fc != NULL; fc = fc->caller)
            if (set_ref_in_funccal(fc, copyID))
                return TRUE;
      return FALSE;
--- 6425,6437 ----
      funccall_T                *fc;
      funccal_entry_T   *entry;
  
!     for (fc = current_funccal; fc != NULL; fc = fc->fc_caller)
        if (set_ref_in_funccal(fc, copyID))
            return TRUE;
  
      // Also go through the funccal_stack.
      for (entry = funccal_stack; entry != NULL; entry = entry->next)
!       for (fc = entry->top_funccal; fc != NULL; fc = fc->fc_caller)
            if (set_ref_in_funccal(fc, copyID))
                return TRUE;
      return FALSE;
***************
*** 6500,6506 ****
      }
      if (fp != NULL)
      {
!       for (fc = fp->uf_scoped; fc != NULL; fc = fc->func->uf_scoped)
            abort = abort || set_ref_in_funccal(fc, copyID);
      }
  
--- 6502,6508 ----
      }
      if (fp != NULL)
      {
!       for (fc = fp->uf_scoped; fc != NULL; fc = fc->fc_func->uf_scoped)
            abort = abort || set_ref_in_funccal(fc, copyID);
      }
  
*** ../vim-9.0.0397/src/vim9execute.c   2022-09-06 18:31:09.070310282 +0100
--- src/vim9execute.c   2022-09-06 18:39:30.633746431 +0100
***************
*** 5080,5091 ****
            case ISN_PROF_END:
                {
  #ifdef FEAT_PROFILE
!                   funccall_T cookie;
!                   ufunc_T         *cur_ufunc =
                                    (((dfunc_T *)def_functions.ga_data)
                                               + ectx->ec_dfunc_idx)->df_ufunc;
  
!                   cookie.func = cur_ufunc;
                    if (iptr->isn_type == ISN_PROF_START)
                    {
                        func_line_start(&cookie, iptr->isn_lnum);
--- 5080,5091 ----
            case ISN_PROF_END:
                {
  #ifdef FEAT_PROFILE
!                   funccall_T  cookie;
!                   ufunc_T     *cur_ufunc =
                                    (((dfunc_T *)def_functions.ga_data)
                                               + ectx->ec_dfunc_idx)->df_ufunc;
  
!                   cookie.fc_func = cur_ufunc;
                    if (iptr->isn_type == ISN_PROF_START)
                    {
                        func_line_start(&cookie, iptr->isn_lnum);
*** ../vim-9.0.0397/src/evalvars.c      2022-09-03 10:52:18.395075356 +0100
--- src/evalvars.c      2022-09-06 18:51:55.628381740 +0100
***************
*** 3391,3397 ****
      if (*name == 'v')                         // v: variable
        return &vimvarht;
      if (get_current_funccal() != NULL
!              && get_current_funccal()->func->uf_def_status == UF_NOT_COMPILED)
      {
        // a: and l: are only used in functions defined with ":function"
        if (*name == 'a')                       // a: function argument
--- 3391,3398 ----
      if (*name == 'v')                         // v: variable
        return &vimvarht;
      if (get_current_funccal() != NULL
!              && get_current_funccal()->fc_func->uf_def_status
!                                                           == UF_NOT_COMPILED)
      {
        // a: and l: are only used in functions defined with ":function"
        if (*name == 'a')                       // a: function argument
*** ../vim-9.0.0397/src/version.c       2022-09-06 18:31:09.074310277 +0100
--- src/version.c       2022-09-06 18:56:08.119866967 +0100
***************
*** 705,706 ****
--- 705,708 ----
  {   /* Add new patch number below this line */
+ /**/
+     398,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
18. Your wife drapes a blond wig over your monitor to remind you of what she
    looks like.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20220906175822.289371C0CE4%40moolenaar.net.

Raspunde prin e-mail lui