|
|
073263 |
To: vim_dev@googlegroups.com
|
|
|
073263 |
Subject: Patch 7.4.609
|
|
|
073263 |
Fcc: outbox
|
|
|
073263 |
From: Bram Moolenaar <Bram@moolenaar.net>
|
|
|
073263 |
Mime-Version: 1.0
|
|
|
073263 |
Content-Type: text/plain; charset=UTF-8
|
|
|
073263 |
Content-Transfer-Encoding: 8bit
|
|
|
073263 |
------------
|
|
|
073263 |
|
|
|
073263 |
Patch 7.4.609
|
|
|
073263 |
Problem: For complicated list and dict use the garbage collector can run
|
|
|
073263 |
out of stack space.
|
|
|
073263 |
Solution: Use a stack of dicts and lists to be marked, thus making it
|
|
|
073263 |
iterative instead of recursive. (Ben Fritz)
|
|
|
073263 |
Files: src/eval.c, src/if_lua.c, src/if_py_both.h, src/if_python.c,
|
|
|
073263 |
src/if_python3.c, src/proto/eval.pro, src/proto/if_lua.pro,
|
|
|
073263 |
src/proto/if_python.pro, src/proto/if_python3.pro, src/structs.h
|
|
|
073263 |
|
|
|
073263 |
|
|
|
073263 |
*** ../vim-7.4.608/src/eval.c 2015-01-27 15:18:55.152333309 +0100
|
|
|
073263 |
--- src/eval.c 2015-02-03 12:41:59.468525906 +0100
|
|
|
073263 |
***************
|
|
|
073263 |
*** 93,99 ****
|
|
|
073263 |
char_u *ll_newkey; /* New key for Dict in alloc. mem or NULL. */
|
|
|
073263 |
} lval_T;
|
|
|
073263 |
|
|
|
073263 |
-
|
|
|
073263 |
static char *e_letunexp = N_("E18: Unexpected characters in :let");
|
|
|
073263 |
static char *e_listidx = N_("E684: list index out of range: %ld");
|
|
|
073263 |
static char *e_undefvar = N_("E121: Undefined variable: %s");
|
|
|
073263 |
--- 93,98 ----
|
|
|
073263 |
***************
|
|
|
073263 |
*** 6811,6816 ****
|
|
|
073263 |
--- 6810,6816 ----
|
|
|
073263 |
garbage_collect()
|
|
|
073263 |
{
|
|
|
073263 |
int copyID;
|
|
|
073263 |
+ int abort = FALSE;
|
|
|
073263 |
buf_T *buf;
|
|
|
073263 |
win_T *wp;
|
|
|
073263 |
int i;
|
|
|
073263 |
***************
|
|
|
073263 |
*** 6841,6922 ****
|
|
|
073263 |
* the item is referenced elsewhere the funccal must not be freed. */
|
|
|
073263 |
for (fc = previous_funccal; fc != NULL; fc = fc->caller)
|
|
|
073263 |
{
|
|
|
073263 |
! set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1);
|
|
|
073263 |
! set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1);
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
/* script-local variables */
|
|
|
073263 |
for (i = 1; i <= ga_scripts.ga_len; ++i)
|
|
|
073263 |
! set_ref_in_ht(&SCRIPT_VARS(i), copyID);
|
|
|
073263 |
|
|
|
073263 |
/* buffer-local variables */
|
|
|
073263 |
for (buf = firstbuf; buf != NULL; buf = buf->b_next)
|
|
|
073263 |
! set_ref_in_item(&buf->b_bufvar.di_tv, copyID);
|
|
|
073263 |
|
|
|
073263 |
/* window-local variables */
|
|
|
073263 |
FOR_ALL_TAB_WINDOWS(tp, wp)
|
|
|
073263 |
! set_ref_in_item(&wp->w_winvar.di_tv, copyID);
|
|
|
073263 |
#ifdef FEAT_AUTOCMD
|
|
|
073263 |
if (aucmd_win != NULL)
|
|
|
073263 |
! set_ref_in_item(&aucmd_win->w_winvar.di_tv, copyID);
|
|
|
073263 |
#endif
|
|
|
073263 |
|
|
|
073263 |
#ifdef FEAT_WINDOWS
|
|
|
073263 |
/* tabpage-local variables */
|
|
|
073263 |
for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
|
|
|
073263 |
! set_ref_in_item(&tp->tp_winvar.di_tv, copyID);
|
|
|
073263 |
#endif
|
|
|
073263 |
|
|
|
073263 |
/* global variables */
|
|
|
073263 |
! set_ref_in_ht(&globvarht, copyID);
|
|
|
073263 |
|
|
|
073263 |
/* function-local variables */
|
|
|
073263 |
for (fc = current_funccal; fc != NULL; fc = fc->caller)
|
|
|
073263 |
{
|
|
|
073263 |
! set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID);
|
|
|
073263 |
! set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID);
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
/* v: vars */
|
|
|
073263 |
! set_ref_in_ht(&vimvarht, copyID);
|
|
|
073263 |
|
|
|
073263 |
#ifdef FEAT_LUA
|
|
|
073263 |
! set_ref_in_lua(copyID);
|
|
|
073263 |
#endif
|
|
|
073263 |
|
|
|
073263 |
#ifdef FEAT_PYTHON
|
|
|
073263 |
! set_ref_in_python(copyID);
|
|
|
073263 |
#endif
|
|
|
073263 |
|
|
|
073263 |
#ifdef FEAT_PYTHON3
|
|
|
073263 |
! set_ref_in_python3(copyID);
|
|
|
073263 |
#endif
|
|
|
073263 |
|
|
|
073263 |
! /*
|
|
|
073263 |
! * 2. Free lists and dictionaries that are not referenced.
|
|
|
073263 |
! */
|
|
|
073263 |
! did_free = free_unref_items(copyID);
|
|
|
073263 |
!
|
|
|
073263 |
! /*
|
|
|
073263 |
! * 3. Check if any funccal can be freed now.
|
|
|
073263 |
! */
|
|
|
073263 |
! for (pfc = &previous_funccal; *pfc != NULL; )
|
|
|
073263 |
{
|
|
|
073263 |
! if (can_free_funccal(*pfc, copyID))
|
|
|
073263 |
{
|
|
|
073263 |
! fc = *pfc;
|
|
|
073263 |
! *pfc = fc->caller;
|
|
|
073263 |
! free_funccal(fc, TRUE);
|
|
|
073263 |
! did_free = TRUE;
|
|
|
073263 |
! did_free_funccal = TRUE;
|
|
|
073263 |
}
|
|
|
073263 |
! else
|
|
|
073263 |
! pfc = &(*pfc)->caller;
|
|
|
073263 |
}
|
|
|
073263 |
- if (did_free_funccal)
|
|
|
073263 |
- /* When a funccal was freed some more items might be garbage
|
|
|
073263 |
- * collected, so run again. */
|
|
|
073263 |
- (void)garbage_collect();
|
|
|
073263 |
|
|
|
073263 |
return did_free;
|
|
|
073263 |
}
|
|
|
073263 |
--- 6841,6935 ----
|
|
|
073263 |
* the item is referenced elsewhere the funccal must not be freed. */
|
|
|
073263 |
for (fc = previous_funccal; fc != NULL; fc = fc->caller)
|
|
|
073263 |
{
|
|
|
073263 |
! abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1,
|
|
|
073263 |
! NULL);
|
|
|
073263 |
! abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1,
|
|
|
073263 |
! NULL);
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
/* script-local variables */
|
|
|
073263 |
for (i = 1; i <= ga_scripts.ga_len; ++i)
|
|
|
073263 |
! abort = abort || set_ref_in_ht(&SCRIPT_VARS(i), copyID, NULL);
|
|
|
073263 |
|
|
|
073263 |
/* buffer-local variables */
|
|
|
073263 |
for (buf = firstbuf; buf != NULL; buf = buf->b_next)
|
|
|
073263 |
! abort = abort || set_ref_in_item(&buf->b_bufvar.di_tv, copyID,
|
|
|
073263 |
! NULL, NULL);
|
|
|
073263 |
|
|
|
073263 |
/* window-local variables */
|
|
|
073263 |
FOR_ALL_TAB_WINDOWS(tp, wp)
|
|
|
073263 |
! abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
|
|
|
073263 |
! NULL, NULL);
|
|
|
073263 |
#ifdef FEAT_AUTOCMD
|
|
|
073263 |
if (aucmd_win != NULL)
|
|
|
073263 |
! abort = abort || set_ref_in_item(&aucmd_win->w_winvar.di_tv, copyID,
|
|
|
073263 |
! NULL, NULL);
|
|
|
073263 |
#endif
|
|
|
073263 |
|
|
|
073263 |
#ifdef FEAT_WINDOWS
|
|
|
073263 |
/* tabpage-local variables */
|
|
|
073263 |
for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
|
|
|
073263 |
! abort = abort || set_ref_in_item(&tp->tp_winvar.di_tv, copyID,
|
|
|
073263 |
! NULL, NULL);
|
|
|
073263 |
#endif
|
|
|
073263 |
|
|
|
073263 |
/* global variables */
|
|
|
073263 |
! abort = abort || set_ref_in_ht(&globvarht, copyID, NULL);
|
|
|
073263 |
|
|
|
073263 |
/* function-local variables */
|
|
|
073263 |
for (fc = current_funccal; fc != NULL; fc = fc->caller)
|
|
|
073263 |
{
|
|
|
073263 |
! abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL);
|
|
|
073263 |
! abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL);
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
/* v: vars */
|
|
|
073263 |
! abort = abort || set_ref_in_ht(&vimvarht, copyID, NULL);
|
|
|
073263 |
|
|
|
073263 |
#ifdef FEAT_LUA
|
|
|
073263 |
! abort = abort || set_ref_in_lua(copyID);
|
|
|
073263 |
#endif
|
|
|
073263 |
|
|
|
073263 |
#ifdef FEAT_PYTHON
|
|
|
073263 |
! abort = abort || set_ref_in_python(copyID);
|
|
|
073263 |
#endif
|
|
|
073263 |
|
|
|
073263 |
#ifdef FEAT_PYTHON3
|
|
|
073263 |
! abort = abort || set_ref_in_python3(copyID);
|
|
|
073263 |
#endif
|
|
|
073263 |
|
|
|
073263 |
! if (!abort)
|
|
|
073263 |
{
|
|
|
073263 |
! /*
|
|
|
073263 |
! * 2. Free lists and dictionaries that are not referenced.
|
|
|
073263 |
! */
|
|
|
073263 |
! did_free = free_unref_items(copyID);
|
|
|
073263 |
!
|
|
|
073263 |
! /*
|
|
|
073263 |
! * 3. Check if any funccal can be freed now.
|
|
|
073263 |
! */
|
|
|
073263 |
! for (pfc = &previous_funccal; *pfc != NULL; )
|
|
|
073263 |
{
|
|
|
073263 |
! if (can_free_funccal(*pfc, copyID))
|
|
|
073263 |
! {
|
|
|
073263 |
! fc = *pfc;
|
|
|
073263 |
! *pfc = fc->caller;
|
|
|
073263 |
! free_funccal(fc, TRUE);
|
|
|
073263 |
! did_free = TRUE;
|
|
|
073263 |
! did_free_funccal = TRUE;
|
|
|
073263 |
! }
|
|
|
073263 |
! else
|
|
|
073263 |
! pfc = &(*pfc)->caller;
|
|
|
073263 |
}
|
|
|
073263 |
! if (did_free_funccal)
|
|
|
073263 |
! /* When a funccal was freed some more items might be garbage
|
|
|
073263 |
! * collected, so run again. */
|
|
|
073263 |
! (void)garbage_collect();
|
|
|
073263 |
! }
|
|
|
073263 |
! else if (p_verbose > 0)
|
|
|
073263 |
! {
|
|
|
073263 |
! verb_msg((char_u *)_("Not enough memory to set references, garbage collection aborted!"));
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
return did_free;
|
|
|
073263 |
}
|
|
|
073263 |
***************
|
|
|
073263 |
*** 6976,7023 ****
|
|
|
073263 |
|
|
|
073263 |
/*
|
|
|
073263 |
* Mark all lists and dicts referenced through hashtab "ht" with "copyID".
|
|
|
073263 |
*/
|
|
|
073263 |
! void
|
|
|
073263 |
! set_ref_in_ht(ht, copyID)
|
|
|
073263 |
! hashtab_T *ht;
|
|
|
073263 |
! int copyID;
|
|
|
073263 |
{
|
|
|
073263 |
int todo;
|
|
|
073263 |
hashitem_T *hi;
|
|
|
073263 |
|
|
|
073263 |
! todo = (int)ht->ht_used;
|
|
|
073263 |
! for (hi = ht->ht_array; todo > 0; ++hi)
|
|
|
073263 |
! if (!HASHITEM_EMPTY(hi))
|
|
|
073263 |
{
|
|
|
073263 |
! --todo;
|
|
|
073263 |
! set_ref_in_item(&HI2DI(hi)->di_tv, copyID);
|
|
|
073263 |
}
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
/*
|
|
|
073263 |
* Mark all lists and dicts referenced through list "l" with "copyID".
|
|
|
073263 |
*/
|
|
|
073263 |
! void
|
|
|
073263 |
! set_ref_in_list(l, copyID)
|
|
|
073263 |
list_T *l;
|
|
|
073263 |
int copyID;
|
|
|
073263 |
{
|
|
|
073263 |
! listitem_T *li;
|
|
|
073263 |
|
|
|
073263 |
! for (li = l->lv_first; li != NULL; li = li->li_next)
|
|
|
073263 |
! set_ref_in_item(&li->li_tv, copyID);
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
/*
|
|
|
073263 |
* Mark all lists and dicts referenced through typval "tv" with "copyID".
|
|
|
073263 |
*/
|
|
|
073263 |
! void
|
|
|
073263 |
! set_ref_in_item(tv, copyID)
|
|
|
073263 |
! typval_T *tv;
|
|
|
073263 |
! int copyID;
|
|
|
073263 |
{
|
|
|
073263 |
dict_T *dd;
|
|
|
073263 |
list_T *ll;
|
|
|
073263 |
|
|
|
073263 |
switch (tv->v_type)
|
|
|
073263 |
{
|
|
|
073263 |
--- 6989,7100 ----
|
|
|
073263 |
|
|
|
073263 |
/*
|
|
|
073263 |
* Mark all lists and dicts referenced through hashtab "ht" with "copyID".
|
|
|
073263 |
+ * "list_stack" is used to add lists to be marked. Can be NULL.
|
|
|
073263 |
+ *
|
|
|
073263 |
+ * Returns TRUE if setting references failed somehow.
|
|
|
073263 |
*/
|
|
|
073263 |
! int
|
|
|
073263 |
! set_ref_in_ht(ht, copyID, list_stack)
|
|
|
073263 |
! hashtab_T *ht;
|
|
|
073263 |
! int copyID;
|
|
|
073263 |
! list_stack_T **list_stack;
|
|
|
073263 |
{
|
|
|
073263 |
int todo;
|
|
|
073263 |
+ int abort = FALSE;
|
|
|
073263 |
hashitem_T *hi;
|
|
|
073263 |
+ hashtab_T *cur_ht;
|
|
|
073263 |
+ ht_stack_T *ht_stack = NULL;
|
|
|
073263 |
+ ht_stack_T *tempitem;
|
|
|
073263 |
|
|
|
073263 |
! cur_ht = ht;
|
|
|
073263 |
! for (;;)
|
|
|
073263 |
! {
|
|
|
073263 |
! if (!abort)
|
|
|
073263 |
{
|
|
|
073263 |
! /* Mark each item in the hashtab. If the item contains a hashtab
|
|
|
073263 |
! * it is added to ht_stack, if it contains a list it is added to
|
|
|
073263 |
! * list_stack. */
|
|
|
073263 |
! todo = (int)cur_ht->ht_used;
|
|
|
073263 |
! for (hi = cur_ht->ht_array; todo > 0; ++hi)
|
|
|
073263 |
! if (!HASHITEM_EMPTY(hi))
|
|
|
073263 |
! {
|
|
|
073263 |
! --todo;
|
|
|
073263 |
! abort = abort || set_ref_in_item(&HI2DI(hi)->di_tv, copyID,
|
|
|
073263 |
! &ht_stack, list_stack);
|
|
|
073263 |
! }
|
|
|
073263 |
}
|
|
|
073263 |
+
|
|
|
073263 |
+ if (ht_stack == NULL)
|
|
|
073263 |
+ break;
|
|
|
073263 |
+
|
|
|
073263 |
+ /* take an item from the stack */
|
|
|
073263 |
+ cur_ht = ht_stack->ht;
|
|
|
073263 |
+ tempitem = ht_stack;
|
|
|
073263 |
+ ht_stack = ht_stack->prev;
|
|
|
073263 |
+ free(tempitem);
|
|
|
073263 |
+ }
|
|
|
073263 |
+
|
|
|
073263 |
+ return abort;
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
/*
|
|
|
073263 |
* Mark all lists and dicts referenced through list "l" with "copyID".
|
|
|
073263 |
+ * "ht_stack" is used to add hashtabs to be marked. Can be NULL.
|
|
|
073263 |
+ *
|
|
|
073263 |
+ * Returns TRUE if setting references failed somehow.
|
|
|
073263 |
*/
|
|
|
073263 |
! int
|
|
|
073263 |
! set_ref_in_list(l, copyID, ht_stack)
|
|
|
073263 |
list_T *l;
|
|
|
073263 |
int copyID;
|
|
|
073263 |
+ ht_stack_T **ht_stack;
|
|
|
073263 |
{
|
|
|
073263 |
! listitem_T *li;
|
|
|
073263 |
! int abort = FALSE;
|
|
|
073263 |
! list_T *cur_l;
|
|
|
073263 |
! list_stack_T *list_stack = NULL;
|
|
|
073263 |
! list_stack_T *tempitem;
|
|
|
073263 |
!
|
|
|
073263 |
! cur_l = l;
|
|
|
073263 |
! for (;;)
|
|
|
073263 |
! {
|
|
|
073263 |
! if (!abort)
|
|
|
073263 |
! /* Mark each item in the list. If the item contains a hashtab
|
|
|
073263 |
! * it is added to ht_stack, if it contains a list it is added to
|
|
|
073263 |
! * list_stack. */
|
|
|
073263 |
! for (li = cur_l->lv_first; !abort && li != NULL; li = li->li_next)
|
|
|
073263 |
! abort = abort || set_ref_in_item(&li->li_tv, copyID,
|
|
|
073263 |
! ht_stack, &list_stack);
|
|
|
073263 |
! if (list_stack == NULL)
|
|
|
073263 |
! break;
|
|
|
073263 |
!
|
|
|
073263 |
! /* take an item from the stack */
|
|
|
073263 |
! cur_l = list_stack->list;
|
|
|
073263 |
! tempitem = list_stack;
|
|
|
073263 |
! list_stack = list_stack->prev;
|
|
|
073263 |
! free(tempitem);
|
|
|
073263 |
! }
|
|
|
073263 |
|
|
|
073263 |
! return abort;
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
/*
|
|
|
073263 |
* Mark all lists and dicts referenced through typval "tv" with "copyID".
|
|
|
073263 |
+ * "list_stack" is used to add lists to be marked. Can be NULL.
|
|
|
073263 |
+ * "ht_stack" is used to add hashtabs to be marked. Can be NULL.
|
|
|
073263 |
+ *
|
|
|
073263 |
+ * Returns TRUE if setting references failed somehow.
|
|
|
073263 |
*/
|
|
|
073263 |
! int
|
|
|
073263 |
! set_ref_in_item(tv, copyID, ht_stack, list_stack)
|
|
|
073263 |
! typval_T *tv;
|
|
|
073263 |
! int copyID;
|
|
|
073263 |
! ht_stack_T **ht_stack;
|
|
|
073263 |
! list_stack_T **list_stack;
|
|
|
073263 |
{
|
|
|
073263 |
dict_T *dd;
|
|
|
073263 |
list_T *ll;
|
|
|
073263 |
+ int abort = FALSE;
|
|
|
073263 |
|
|
|
073263 |
switch (tv->v_type)
|
|
|
073263 |
{
|
|
|
073263 |
***************
|
|
|
073263 |
*** 7027,7033 ****
|
|
|
073263 |
{
|
|
|
073263 |
/* Didn't see this dict yet. */
|
|
|
073263 |
dd->dv_copyID = copyID;
|
|
|
073263 |
! set_ref_in_ht(&dd->dv_hashtab, copyID);
|
|
|
073263 |
}
|
|
|
073263 |
break;
|
|
|
073263 |
|
|
|
073263 |
--- 7104,7126 ----
|
|
|
073263 |
{
|
|
|
073263 |
/* Didn't see this dict yet. */
|
|
|
073263 |
dd->dv_copyID = copyID;
|
|
|
073263 |
! if (ht_stack == NULL)
|
|
|
073263 |
! {
|
|
|
073263 |
! abort = set_ref_in_ht(&dd->dv_hashtab, copyID, list_stack);
|
|
|
073263 |
! }
|
|
|
073263 |
! else
|
|
|
073263 |
! {
|
|
|
073263 |
! ht_stack_T *newitem = (ht_stack_T*)malloc(
|
|
|
073263 |
! sizeof(ht_stack_T));
|
|
|
073263 |
! if (newitem == NULL)
|
|
|
073263 |
! abort = TRUE;
|
|
|
073263 |
! else
|
|
|
073263 |
! {
|
|
|
073263 |
! newitem->ht = &dd->dv_hashtab;
|
|
|
073263 |
! newitem->prev = *ht_stack;
|
|
|
073263 |
! *ht_stack = newitem;
|
|
|
073263 |
! }
|
|
|
073263 |
! }
|
|
|
073263 |
}
|
|
|
073263 |
break;
|
|
|
073263 |
|
|
|
073263 |
***************
|
|
|
073263 |
*** 7037,7047 ****
|
|
|
073263 |
{
|
|
|
073263 |
/* Didn't see this list yet. */
|
|
|
073263 |
ll->lv_copyID = copyID;
|
|
|
073263 |
! set_ref_in_list(ll, copyID);
|
|
|
073263 |
}
|
|
|
073263 |
break;
|
|
|
073263 |
}
|
|
|
073263 |
! return;
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
/*
|
|
|
073263 |
--- 7130,7156 ----
|
|
|
073263 |
{
|
|
|
073263 |
/* Didn't see this list yet. */
|
|
|
073263 |
ll->lv_copyID = copyID;
|
|
|
073263 |
! if (list_stack == NULL)
|
|
|
073263 |
! {
|
|
|
073263 |
! abort = set_ref_in_list(ll, copyID, ht_stack);
|
|
|
073263 |
! }
|
|
|
073263 |
! else
|
|
|
073263 |
! {
|
|
|
073263 |
! list_stack_T *newitem = (list_stack_T*)malloc(
|
|
|
073263 |
! sizeof(list_stack_T));
|
|
|
073263 |
! if (newitem == NULL)
|
|
|
073263 |
! abort = TRUE;
|
|
|
073263 |
! else
|
|
|
073263 |
! {
|
|
|
073263 |
! newitem->list = ll;
|
|
|
073263 |
! newitem->prev = *list_stack;
|
|
|
073263 |
! *list_stack = newitem;
|
|
|
073263 |
! }
|
|
|
073263 |
! }
|
|
|
073263 |
}
|
|
|
073263 |
break;
|
|
|
073263 |
}
|
|
|
073263 |
! return abort;
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
/*
|
|
|
073263 |
*** ../vim-7.4.608/src/if_lua.c 2014-05-07 17:31:32.473182497 +0200
|
|
|
073263 |
--- src/if_lua.c 2015-02-03 12:45:41.978204997 +0100
|
|
|
073263 |
***************
|
|
|
073263 |
*** 1523,1534 ****
|
|
|
073263 |
static int
|
|
|
073263 |
luaV_setref (lua_State *L)
|
|
|
073263 |
{
|
|
|
073263 |
! int copyID = lua_tointeger(L, 1);
|
|
|
073263 |
! typval_T tv;
|
|
|
073263 |
luaV_getfield(L, LUAVIM_LIST);
|
|
|
073263 |
luaV_getfield(L, LUAVIM_DICT);
|
|
|
073263 |
lua_pushnil(L);
|
|
|
073263 |
! while (lua_next(L, lua_upvalueindex(1)) != 0) /* traverse cache table */
|
|
|
073263 |
{
|
|
|
073263 |
lua_getmetatable(L, -1);
|
|
|
073263 |
if (lua_rawequal(L, -1, 2)) /* list? */
|
|
|
073263 |
--- 1523,1536 ----
|
|
|
073263 |
static int
|
|
|
073263 |
luaV_setref (lua_State *L)
|
|
|
073263 |
{
|
|
|
073263 |
! int copyID = lua_tointeger(L, 1);
|
|
|
073263 |
! int abort = FALSE;
|
|
|
073263 |
! typval_T tv;
|
|
|
073263 |
!
|
|
|
073263 |
luaV_getfield(L, LUAVIM_LIST);
|
|
|
073263 |
luaV_getfield(L, LUAVIM_DICT);
|
|
|
073263 |
lua_pushnil(L);
|
|
|
073263 |
! while (!abort && lua_next(L, lua_upvalueindex(1)) != 0) /* traverse cache table */
|
|
|
073263 |
{
|
|
|
073263 |
lua_getmetatable(L, -1);
|
|
|
073263 |
if (lua_rawequal(L, -1, 2)) /* list? */
|
|
|
073263 |
***************
|
|
|
073263 |
*** 1542,1550 ****
|
|
|
073263 |
tv.vval.v_dict = (dict_T *) lua_touserdata(L, 4); /* key */
|
|
|
073263 |
}
|
|
|
073263 |
lua_pop(L, 2); /* metatable and value */
|
|
|
073263 |
! set_ref_in_item(&tv, copyID);
|
|
|
073263 |
}
|
|
|
073263 |
! return 0;
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
static int
|
|
|
073263 |
--- 1544,1552 ----
|
|
|
073263 |
tv.vval.v_dict = (dict_T *) lua_touserdata(L, 4); /* key */
|
|
|
073263 |
}
|
|
|
073263 |
lua_pop(L, 2); /* metatable and value */
|
|
|
073263 |
! abort = set_ref_in_item(&tv, copyID, NULL, NULL);
|
|
|
073263 |
}
|
|
|
073263 |
! lua_pushinteger(L, abort);
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
static int
|
|
|
073263 |
***************
|
|
|
073263 |
*** 1770,1782 ****
|
|
|
073263 |
lua_call(L, 3, 0);
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
! void
|
|
|
073263 |
set_ref_in_lua (int copyID)
|
|
|
073263 |
{
|
|
|
073263 |
! if (!lua_isopen()) return;
|
|
|
073263 |
! luaV_getfield(L, LUAVIM_SETREF);
|
|
|
073263 |
! lua_pushinteger(L, copyID);
|
|
|
073263 |
! lua_call(L, 1, 0);
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
#endif
|
|
|
073263 |
--- 1772,1794 ----
|
|
|
073263 |
lua_call(L, 3, 0);
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
! int
|
|
|
073263 |
set_ref_in_lua (int copyID)
|
|
|
073263 |
{
|
|
|
073263 |
! int aborted = 0;
|
|
|
073263 |
!
|
|
|
073263 |
! if (lua_isopen())
|
|
|
073263 |
! {
|
|
|
073263 |
! luaV_getfield(L, LUAVIM_SETREF);
|
|
|
073263 |
! /* call the function with 1 arg, getting 1 result back */
|
|
|
073263 |
! lua_pushinteger(L, copyID);
|
|
|
073263 |
! lua_call(L, 1, 1);
|
|
|
073263 |
! /* get the result */
|
|
|
073263 |
! aborted = lua_tointeger(L, -1);
|
|
|
073263 |
! /* pop result off the stack */
|
|
|
073263 |
! lua_pop(L, 1);
|
|
|
073263 |
! }
|
|
|
073263 |
! return aborted;
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
#endif
|
|
|
073263 |
*** ../vim-7.4.608/src/if_py_both.h 2014-12-17 14:45:56.095854545 +0100
|
|
|
073263 |
--- src/if_py_both.h 2015-02-03 12:46:46.629530177 +0100
|
|
|
073263 |
***************
|
|
|
073263 |
*** 5502,5535 ****
|
|
|
073263 |
PyErr_Clear();
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
! static void
|
|
|
073263 |
set_ref_in_py(const int copyID)
|
|
|
073263 |
{
|
|
|
073263 |
pylinkedlist_T *cur;
|
|
|
073263 |
dict_T *dd;
|
|
|
073263 |
list_T *ll;
|
|
|
073263 |
|
|
|
073263 |
if (lastdict != NULL)
|
|
|
073263 |
! for(cur = lastdict ; cur != NULL ; cur = cur->pll_prev)
|
|
|
073263 |
{
|
|
|
073263 |
dd = ((DictionaryObject *) (cur->pll_obj))->dict;
|
|
|
073263 |
if (dd->dv_copyID != copyID)
|
|
|
073263 |
{
|
|
|
073263 |
dd->dv_copyID = copyID;
|
|
|
073263 |
! set_ref_in_ht(&dd->dv_hashtab, copyID);
|
|
|
073263 |
}
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
if (lastlist != NULL)
|
|
|
073263 |
! for(cur = lastlist ; cur != NULL ; cur = cur->pll_prev)
|
|
|
073263 |
{
|
|
|
073263 |
ll = ((ListObject *) (cur->pll_obj))->list;
|
|
|
073263 |
if (ll->lv_copyID != copyID)
|
|
|
073263 |
{
|
|
|
073263 |
ll->lv_copyID = copyID;
|
|
|
073263 |
! set_ref_in_list(ll, copyID);
|
|
|
073263 |
}
|
|
|
073263 |
}
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
static int
|
|
|
073263 |
--- 5502,5542 ----
|
|
|
073263 |
PyErr_Clear();
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
! static int
|
|
|
073263 |
set_ref_in_py(const int copyID)
|
|
|
073263 |
{
|
|
|
073263 |
pylinkedlist_T *cur;
|
|
|
073263 |
dict_T *dd;
|
|
|
073263 |
list_T *ll;
|
|
|
073263 |
+ int abort = FALSE;
|
|
|
073263 |
|
|
|
073263 |
if (lastdict != NULL)
|
|
|
073263 |
! {
|
|
|
073263 |
! for(cur = lastdict ; !abort && cur != NULL ; cur = cur->pll_prev)
|
|
|
073263 |
{
|
|
|
073263 |
dd = ((DictionaryObject *) (cur->pll_obj))->dict;
|
|
|
073263 |
if (dd->dv_copyID != copyID)
|
|
|
073263 |
{
|
|
|
073263 |
dd->dv_copyID = copyID;
|
|
|
073263 |
! abort = abort || set_ref_in_ht(&dd->dv_hashtab, copyID, NULL);
|
|
|
073263 |
}
|
|
|
073263 |
}
|
|
|
073263 |
+ }
|
|
|
073263 |
|
|
|
073263 |
if (lastlist != NULL)
|
|
|
073263 |
! {
|
|
|
073263 |
! for(cur = lastlist ; !abort && cur != NULL ; cur = cur->pll_prev)
|
|
|
073263 |
{
|
|
|
073263 |
ll = ((ListObject *) (cur->pll_obj))->list;
|
|
|
073263 |
if (ll->lv_copyID != copyID)
|
|
|
073263 |
{
|
|
|
073263 |
ll->lv_copyID = copyID;
|
|
|
073263 |
! abort = abort || set_ref_in_list(ll, copyID, NULL);
|
|
|
073263 |
}
|
|
|
073263 |
}
|
|
|
073263 |
+ }
|
|
|
073263 |
+
|
|
|
073263 |
+ return abort;
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
static int
|
|
|
073263 |
*** ../vim-7.4.608/src/if_python.c 2014-07-23 16:56:56.587876204 +0200
|
|
|
073263 |
--- src/if_python.c 2015-02-03 12:05:13.471422753 +0100
|
|
|
073263 |
***************
|
|
|
073263 |
*** 1567,1574 ****
|
|
|
073263 |
}
|
|
|
073263 |
#endif /* Python 1.4 */
|
|
|
073263 |
|
|
|
073263 |
! void
|
|
|
073263 |
set_ref_in_python (int copyID)
|
|
|
073263 |
{
|
|
|
073263 |
! set_ref_in_py(copyID);
|
|
|
073263 |
}
|
|
|
073263 |
--- 1567,1574 ----
|
|
|
073263 |
}
|
|
|
073263 |
#endif /* Python 1.4 */
|
|
|
073263 |
|
|
|
073263 |
! int
|
|
|
073263 |
set_ref_in_python (int copyID)
|
|
|
073263 |
{
|
|
|
073263 |
! return set_ref_in_py(copyID);
|
|
|
073263 |
}
|
|
|
073263 |
*** ../vim-7.4.608/src/if_python3.c 2014-03-30 16:11:37.180530823 +0200
|
|
|
073263 |
--- src/if_python3.c 2015-02-03 12:05:13.471422753 +0100
|
|
|
073263 |
***************
|
|
|
073263 |
*** 1649,1656 ****
|
|
|
073263 |
}
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
! void
|
|
|
073263 |
set_ref_in_python3 (int copyID)
|
|
|
073263 |
{
|
|
|
073263 |
! set_ref_in_py(copyID);
|
|
|
073263 |
}
|
|
|
073263 |
--- 1649,1656 ----
|
|
|
073263 |
}
|
|
|
073263 |
}
|
|
|
073263 |
|
|
|
073263 |
! int
|
|
|
073263 |
set_ref_in_python3 (int copyID)
|
|
|
073263 |
{
|
|
|
073263 |
! int set_ref_in_py(copyID);
|
|
|
073263 |
}
|
|
|
073263 |
*** ../vim-7.4.608/src/proto/eval.pro 2014-12-17 14:36:10.363090985 +0100
|
|
|
073263 |
--- src/proto/eval.pro 2015-02-03 12:47:58.472780049 +0100
|
|
|
073263 |
***************
|
|
|
073263 |
*** 62,70 ****
|
|
|
073263 |
void list_insert __ARGS((list_T *l, listitem_T *ni, listitem_T *item));
|
|
|
073263 |
void vimlist_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));
|
|
|
073263 |
int garbage_collect __ARGS((void));
|
|
|
073263 |
! void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID));
|
|
|
073263 |
! void set_ref_in_list __ARGS((list_T *l, int copyID));
|
|
|
073263 |
! void set_ref_in_item __ARGS((typval_T *tv, int copyID));
|
|
|
073263 |
dict_T *dict_alloc __ARGS((void));
|
|
|
073263 |
void dict_unref __ARGS((dict_T *d));
|
|
|
073263 |
void dict_free __ARGS((dict_T *d, int recurse));
|
|
|
073263 |
--- 62,70 ----
|
|
|
073263 |
void list_insert __ARGS((list_T *l, listitem_T *ni, listitem_T *item));
|
|
|
073263 |
void vimlist_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));
|
|
|
073263 |
int garbage_collect __ARGS((void));
|
|
|
073263 |
! int set_ref_in_ht __ARGS((hashtab_T *ht, int copyID, list_stack_T **list_stack));
|
|
|
073263 |
! int set_ref_in_list __ARGS((list_T *l, int copyID, ht_stack_T **ht_stack));
|
|
|
073263 |
! int set_ref_in_item __ARGS((typval_T *tv, int copyID, ht_stack_T **ht_stack, list_stack_T **list_stack));
|
|
|
073263 |
dict_T *dict_alloc __ARGS((void));
|
|
|
073263 |
void dict_unref __ARGS((dict_T *d));
|
|
|
073263 |
void dict_free __ARGS((dict_T *d, int recurse));
|
|
|
073263 |
*** ../vim-7.4.608/src/proto/if_lua.pro 2012-04-05 16:41:35.000000000 +0200
|
|
|
073263 |
--- src/proto/if_lua.pro 2015-02-03 12:05:13.475422711 +0100
|
|
|
073263 |
***************
|
|
|
073263 |
*** 7,11 ****
|
|
|
073263 |
void lua_buffer_free __ARGS((buf_T *buf));
|
|
|
073263 |
void lua_window_free __ARGS((win_T *win));
|
|
|
073263 |
void do_luaeval __ARGS((char_u *str, typval_T *arg, typval_T *rettv));
|
|
|
073263 |
! void set_ref_in_lua __ARGS((int copyID));
|
|
|
073263 |
/* vim: set ft=c : */
|
|
|
073263 |
--- 7,11 ----
|
|
|
073263 |
void lua_buffer_free __ARGS((buf_T *buf));
|
|
|
073263 |
void lua_window_free __ARGS((win_T *win));
|
|
|
073263 |
void do_luaeval __ARGS((char_u *str, typval_T *arg, typval_T *rettv));
|
|
|
073263 |
! int set_ref_in_lua __ARGS((int copyID));
|
|
|
073263 |
/* vim: set ft=c : */
|
|
|
073263 |
*** ../vim-7.4.608/src/proto/if_python.pro 2013-08-10 13:37:15.000000000 +0200
|
|
|
073263 |
--- src/proto/if_python.pro 2015-02-03 12:48:02.936733431 +0100
|
|
|
073263 |
***************
|
|
|
073263 |
*** 9,13 ****
|
|
|
073263 |
void python_window_free __ARGS((win_T *win));
|
|
|
073263 |
void python_tabpage_free __ARGS((tabpage_T *tab));
|
|
|
073263 |
void do_pyeval __ARGS((char_u *str, typval_T *rettv));
|
|
|
073263 |
! void set_ref_in_python __ARGS((int copyID));
|
|
|
073263 |
/* vim: set ft=c : */
|
|
|
073263 |
--- 9,13 ----
|
|
|
073263 |
void python_window_free __ARGS((win_T *win));
|
|
|
073263 |
void python_tabpage_free __ARGS((tabpage_T *tab));
|
|
|
073263 |
void do_pyeval __ARGS((char_u *str, typval_T *rettv));
|
|
|
073263 |
! int set_ref_in_python __ARGS((int copyID));
|
|
|
073263 |
/* vim: set ft=c : */
|
|
|
073263 |
*** ../vim-7.4.608/src/proto/if_python3.pro 2013-08-10 13:37:16.000000000 +0200
|
|
|
073263 |
--- src/proto/if_python3.pro 2015-02-03 12:48:03.292729714 +0100
|
|
|
073263 |
***************
|
|
|
073263 |
*** 9,13 ****
|
|
|
073263 |
void python3_window_free __ARGS((win_T *win));
|
|
|
073263 |
void python3_tabpage_free __ARGS((tabpage_T *tab));
|
|
|
073263 |
void do_py3eval __ARGS((char_u *str, typval_T *rettv));
|
|
|
073263 |
! void set_ref_in_python3 __ARGS((int copyID));
|
|
|
073263 |
/* vim: set ft=c : */
|
|
|
073263 |
--- 9,13 ----
|
|
|
073263 |
void python3_window_free __ARGS((win_T *win));
|
|
|
073263 |
void python3_tabpage_free __ARGS((tabpage_T *tab));
|
|
|
073263 |
void do_py3eval __ARGS((char_u *str, typval_T *rettv));
|
|
|
073263 |
! int set_ref_in_python3 __ARGS((int copyID));
|
|
|
073263 |
/* vim: set ft=c : */
|
|
|
073263 |
*** ../vim-7.4.608/src/structs.h 2015-01-14 12:44:38.407422077 +0100
|
|
|
073263 |
--- src/structs.h 2015-02-03 12:05:13.475422711 +0100
|
|
|
073263 |
***************
|
|
|
073263 |
*** 1223,1228 ****
|
|
|
073263 |
--- 1223,1242 ----
|
|
|
073263 |
dict_T *dv_used_prev; /* previous dict in used dicts list */
|
|
|
073263 |
};
|
|
|
073263 |
|
|
|
073263 |
+ /* structure used for explicit stack while garbage collecting hash tables */
|
|
|
073263 |
+ typedef struct ht_stack_S
|
|
|
073263 |
+ {
|
|
|
073263 |
+ hashtab_T *ht;
|
|
|
073263 |
+ struct ht_stack_S *prev;
|
|
|
073263 |
+ } ht_stack_T;
|
|
|
073263 |
+
|
|
|
073263 |
+ /* structure used for explicit stack while garbage collecting lists */
|
|
|
073263 |
+ typedef struct list_stack_S
|
|
|
073263 |
+ {
|
|
|
073263 |
+ list_T *list;
|
|
|
073263 |
+ struct list_stack_S *prev;
|
|
|
073263 |
+ } list_stack_T;
|
|
|
073263 |
+
|
|
|
073263 |
/* values for b_syn_spell: what to do with toplevel text */
|
|
|
073263 |
#define SYNSPL_DEFAULT 0 /* spell check if @Spell not defined */
|
|
|
073263 |
#define SYNSPL_TOP 1 /* spell check toplevel text */
|
|
|
073263 |
*** ../vim-7.4.608/src/version.c 2015-01-27 22:52:10.713524965 +0100
|
|
|
073263 |
--- src/version.c 2015-02-03 12:09:19.324876918 +0100
|
|
|
073263 |
***************
|
|
|
073263 |
*** 743,744 ****
|
|
|
073263 |
--- 743,746 ----
|
|
|
073263 |
{ /* Add new patch number below this line */
|
|
|
073263 |
+ /**/
|
|
|
073263 |
+ 609,
|
|
|
073263 |
/**/
|
|
|
073263 |
|
|
|
073263 |
--
|
|
|
073263 |
hundred-and-one symptoms of being an internet addict:
|
|
|
073263 |
167. You have more than 200 websites bookmarked.
|
|
|
073263 |
|
|
|
073263 |
/// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
|
|
|
073263 |
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
|
|
|
073263 |
\\\ an exciting new programming language -- http://www.Zimbu.org ///
|
|
|
073263 |
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
|