Mercurial > vim
comparison src/eval.c @ 371:4b9fef49d7ff v7.0095
updated for version 7.0095
author | vimboss |
---|---|
date | Mon, 27 Jun 2005 22:48:21 +0000 |
parents | 5332dd13733c |
children | 575dacb554d8 |
comparison
equal
deleted
inserted
replaced
370:3a21825ad207 | 371:4b9fef49d7ff |
---|---|
192 #define FC_DICT 4 /* Dict function, uses "self" */ | 192 #define FC_DICT 4 /* Dict function, uses "self" */ |
193 | 193 |
194 #define DEL_REFCOUNT 999999 /* list/dict is being deleted */ | 194 #define DEL_REFCOUNT 999999 /* list/dict is being deleted */ |
195 | 195 |
196 /* | 196 /* |
197 * All user-defined functions are found in this hash table. | 197 * All user-defined functions are found in this hashtable. |
198 */ | 198 */ |
199 static hashtab_T func_hashtab; | 199 static hashtab_T func_hashtab; |
200 | |
201 /* list heads for garbage collection */ | |
202 static dict_T *first_dict = NULL; /* list of all dicts */ | |
203 static list_T *first_list = NULL; /* list of all lists */ | |
200 | 204 |
201 /* From user function to hashitem and back. */ | 205 /* From user function to hashitem and back. */ |
202 static ufunc_T dumuf; | 206 static ufunc_T dumuf; |
203 #define UF2HIKEY(fp) ((fp)->uf_name) | 207 #define UF2HIKEY(fp) ((fp)->uf_name) |
204 #define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf))) | 208 #define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf))) |
210 #define MAX_FUNC_ARGS 20 /* maximum number of function arguments */ | 214 #define MAX_FUNC_ARGS 20 /* maximum number of function arguments */ |
211 #define VAR_SHORT_LEN 20 /* short variable name length */ | 215 #define VAR_SHORT_LEN 20 /* short variable name length */ |
212 #define FIXVAR_CNT 12 /* number of fixed variables */ | 216 #define FIXVAR_CNT 12 /* number of fixed variables */ |
213 | 217 |
214 /* structure to hold info for a function that is currently being executed. */ | 218 /* structure to hold info for a function that is currently being executed. */ |
215 typedef struct funccall_S | 219 typedef struct funccall_S funccall_T; |
220 | |
221 struct funccall_S | |
216 { | 222 { |
217 ufunc_T *func; /* function being called */ | 223 ufunc_T *func; /* function being called */ |
218 int linenr; /* next line to be executed */ | 224 int linenr; /* next line to be executed */ |
219 int returned; /* ":return" used */ | 225 int returned; /* ":return" used */ |
220 struct /* fixed variables for arguments */ | 226 struct /* fixed variables for arguments */ |
233 int dbg_tick; /* debug_tick when breakpoint was set */ | 239 int dbg_tick; /* debug_tick when breakpoint was set */ |
234 int level; /* top nesting level of executed function */ | 240 int level; /* top nesting level of executed function */ |
235 #ifdef FEAT_PROFILE | 241 #ifdef FEAT_PROFILE |
236 proftime_T prof_child; /* time spent in a child */ | 242 proftime_T prof_child; /* time spent in a child */ |
237 #endif | 243 #endif |
238 } funccall_T; | 244 funccall_T *caller; /* calling function or NULL */ |
245 }; | |
239 | 246 |
240 /* | 247 /* |
241 * Info used by a ":for" loop. | 248 * Info used by a ":for" loop. |
242 */ | 249 */ |
243 typedef struct | 250 typedef struct |
380 static list_T *list_copy __ARGS((list_T *orig, int deep, int copyID)); | 387 static list_T *list_copy __ARGS((list_T *orig, int deep, int copyID)); |
381 static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2)); | 388 static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2)); |
382 static char_u *list2string __ARGS((typval_T *tv)); | 389 static char_u *list2string __ARGS((typval_T *tv)); |
383 static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo)); | 390 static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo)); |
384 | 391 |
385 static int count_self_ref __ARGS((void *p, int type)); | 392 static void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID)); |
386 static int count_ref_in_dict __ARGS((dict_T *d, void *rp, int copyID, garray_T *gap)); | 393 static void set_ref_in_list __ARGS((list_T *l, int copyID)); |
387 static int count_ref_in_list __ARGS((list_T *l, void *rp, int copyID, garray_T *gap)); | 394 static void set_ref_in_item __ARGS((typval_T *tv, int copyID)); |
388 static int count_ref_item __ARGS((typval_T *tv, void *rp, int copyID, garray_T *gap)); | |
389 | 395 |
390 static void dict_unref __ARGS((dict_T *d)); | 396 static void dict_unref __ARGS((dict_T *d)); |
391 static void dict_free __ARGS((dict_T *d)); | 397 static void dict_free __ARGS((dict_T *d)); |
392 static dictitem_T *dictitem_alloc __ARGS((char_u *key)); | 398 static dictitem_T *dictitem_alloc __ARGS((char_u *key)); |
393 static dictitem_T *dictitem_copy __ARGS((dictitem_T *org)); | 399 static dictitem_T *dictitem_copy __ARGS((dictitem_T *org)); |
458 static void f_foldlevel __ARGS((typval_T *argvars, typval_T *rettv)); | 464 static void f_foldlevel __ARGS((typval_T *argvars, typval_T *rettv)); |
459 static void f_foldtext __ARGS((typval_T *argvars, typval_T *rettv)); | 465 static void f_foldtext __ARGS((typval_T *argvars, typval_T *rettv)); |
460 static void f_foldtextresult __ARGS((typval_T *argvars, typval_T *rettv)); | 466 static void f_foldtextresult __ARGS((typval_T *argvars, typval_T *rettv)); |
461 static void f_foreground __ARGS((typval_T *argvars, typval_T *rettv)); | 467 static void f_foreground __ARGS((typval_T *argvars, typval_T *rettv)); |
462 static void f_function __ARGS((typval_T *argvars, typval_T *rettv)); | 468 static void f_function __ARGS((typval_T *argvars, typval_T *rettv)); |
469 static void f_garbagecollect __ARGS((typval_T *argvars, typval_T *rettv)); | |
463 static void f_get __ARGS((typval_T *argvars, typval_T *rettv)); | 470 static void f_get __ARGS((typval_T *argvars, typval_T *rettv)); |
464 static void f_getbufvar __ARGS((typval_T *argvars, typval_T *rettv)); | 471 static void f_getbufvar __ARGS((typval_T *argvars, typval_T *rettv)); |
465 static void f_getchar __ARGS((typval_T *argvars, typval_T *rettv)); | 472 static void f_getchar __ARGS((typval_T *argvars, typval_T *rettv)); |
466 static void f_getcharmod __ARGS((typval_T *argvars, typval_T *rettv)); | 473 static void f_getcharmod __ARGS((typval_T *argvars, typval_T *rettv)); |
467 static void f_getcmdline __ARGS((typval_T *argvars, typval_T *rettv)); | 474 static void f_getcmdline __ARGS((typval_T *argvars, typval_T *rettv)); |
747 free_scriptnames(); | 754 free_scriptnames(); |
748 | 755 |
749 /* global variables */ | 756 /* global variables */ |
750 vars_clear(&globvarht); | 757 vars_clear(&globvarht); |
751 | 758 |
759 /* functions */ | |
752 free_all_functions(); | 760 free_all_functions(); |
761 hash_clear(&func_hashtab); | |
762 | |
763 /* unreferenced lists and dicts */ | |
764 (void)garbage_collect(); | |
753 } | 765 } |
754 #endif | 766 #endif |
755 | 767 |
756 /* | 768 /* |
757 * Return the name of the executed function. | 769 * Return the name of the executed function. |
4943 * Allocate an empty header for a list. | 4955 * Allocate an empty header for a list. |
4944 */ | 4956 */ |
4945 static list_T * | 4957 static list_T * |
4946 list_alloc() | 4958 list_alloc() |
4947 { | 4959 { |
4948 return (list_T *)alloc_clear(sizeof(list_T)); | 4960 list_T *l; |
4961 | |
4962 l = (list_T *)alloc_clear(sizeof(list_T)); | |
4963 if (l != NULL) | |
4964 { | |
4965 /* Prepend the list to the list of lists for garbage collection. */ | |
4966 if (first_list != NULL) | |
4967 first_list->lv_used_prev = l; | |
4968 l->lv_used_prev = NULL; | |
4969 l->lv_used_next = first_list; | |
4970 first_list = l; | |
4971 } | |
4972 return l; | |
4949 } | 4973 } |
4950 | 4974 |
4951 /* | 4975 /* |
4952 * Unreference a list: decrement the reference count and free it when it | 4976 * Unreference a list: decrement the reference count and free it when it |
4953 * becomes zero. | 4977 * becomes zero. |
4954 */ | 4978 */ |
4955 static void | 4979 static void |
4956 list_unref(l) | 4980 list_unref(l) |
4957 list_T *l; | 4981 list_T *l; |
4958 { | 4982 { |
4959 int selfref; | 4983 if (l != NULL && l->lv_refcount != DEL_REFCOUNT && --l->lv_refcount <= 0) |
4960 | 4984 list_free(l); |
4961 if (l != NULL && l->lv_refcount != DEL_REFCOUNT) | |
4962 { | |
4963 if (--l->lv_refcount > 0) | |
4964 { | |
4965 /* Check if the dict contains references to itself. These need to | |
4966 * be subtracted from the reference count to find out if we can | |
4967 * delete the dict. */ | |
4968 selfref = count_self_ref(l, VAR_LIST); | |
4969 } | |
4970 else | |
4971 selfref = 0; | |
4972 if (l->lv_refcount - selfref == 0) | |
4973 /* No references to the list now, free it. */ | |
4974 list_free(l); | |
4975 } | |
4976 } | 4985 } |
4977 | 4986 |
4978 /* | 4987 /* |
4979 * Free a list, including all items it points to. | 4988 * Free a list, including all items it points to. |
4980 * Ignores the reference count. | 4989 * Ignores the reference count. |
4985 { | 4994 { |
4986 listitem_T *item; | 4995 listitem_T *item; |
4987 | 4996 |
4988 /* Avoid that recursive reference to the list frees us again. */ | 4997 /* Avoid that recursive reference to the list frees us again. */ |
4989 l->lv_refcount = DEL_REFCOUNT; | 4998 l->lv_refcount = DEL_REFCOUNT; |
4999 | |
5000 /* Remove the list from the list of lists for garbage collection. */ | |
5001 if (l->lv_used_prev == NULL) | |
5002 first_list = l->lv_used_next; | |
5003 else | |
5004 l->lv_used_prev->lv_used_next = l->lv_used_next; | |
5005 if (l->lv_used_next != NULL) | |
5006 l->lv_used_next->lv_used_prev = l->lv_used_prev; | |
4990 | 5007 |
4991 for (item = l->lv_first; item != NULL; item = l->lv_first) | 5008 for (item = l->lv_first; item != NULL; item = l->lv_first) |
4992 { | 5009 { |
4993 /* Remove the item before deleting it. */ | 5010 /* Remove the item before deleting it. */ |
4994 l->lv_first = item->li_next; | 5011 l->lv_first = item->li_next; |
5566 } | 5583 } |
5567 return OK; | 5584 return OK; |
5568 } | 5585 } |
5569 | 5586 |
5570 /* | 5587 /* |
5571 * Count the number of references for list/dict "p" inside itself. | 5588 * Garbage collection for lists and dictionaries. |
5572 * This is used to find out if there are no more references elsewhere. | 5589 * |
5573 * The tricky bit is that we must not count references in lists/dicts that are | 5590 * We use reference counts to be able to free most items right away when they |
5574 * used elsewhere, but we can only know by counting their references... | 5591 * are no longer used. But for composite items it's possible that it becomes |
5575 * This is a bit slow, but required to avoid leaking memory. | 5592 * unused while the reference count is > 0: When there is a recursive |
5576 */ | 5593 * reference. Example: |
5577 static int | 5594 * :let l = [1, 2, 3] |
5578 count_self_ref(p, type) | 5595 * :let d = {9: l} |
5579 void *p; | 5596 * :let l[1] = d |
5580 int type; | 5597 * |
5581 { | 5598 * Since this is quite unusual we handle this with garbage collection: every |
5582 garray_T ga; | 5599 * once in a while find out which lists and dicts are not referenced from any |
5583 typval_T *tv; | 5600 * variable. |
5584 int selfref; | 5601 * |
5602 * Here is a good reference text about garbage collection (refers to Python | |
5603 * but it applies to all reference-counting mechanisms): | |
5604 * http://python.ca/nas/python/gc/ | |
5605 */ | |
5606 | |
5607 /* | |
5608 * Do garbage collection for lists and dicts. | |
5609 * Return TRUE if some memory was freed. | |
5610 */ | |
5611 int | |
5612 garbage_collect() | |
5613 { | |
5614 dict_T *dd; | |
5615 list_T *ll; | |
5616 int copyID = ++current_copyID; | |
5617 buf_T *buf; | |
5618 win_T *wp; | |
5585 int i; | 5619 int i; |
5586 int n; | 5620 funccall_T *fc; |
5587 | 5621 int did_free = FALSE; |
5588 ga_init2(&ga, sizeof(typval_T *), 10); | 5622 |
5589 if (type == VAR_DICT) | 5623 /* |
5590 selfref = count_ref_in_dict(p, p, ++current_copyID, &ga); | 5624 * 1. Go through all accessible variables and mark all lists and dicts |
5591 else | 5625 * with copyID. |
5592 selfref = count_ref_in_list(p, p, ++current_copyID, &ga); | 5626 */ |
5593 for (i = 0; i < ga.ga_len; ++i) | 5627 /* script-local variables */ |
5594 { | 5628 for (i = 1; i <= ga_scripts.ga_len; ++i) |
5595 tv = ((typval_T **)ga.ga_data)[i]; | 5629 set_ref_in_ht(&SCRIPT_VARS(i), copyID); |
5596 if (tv->v_type == VAR_DICT) | 5630 |
5597 { | 5631 /* buffer-local variables */ |
5598 n = count_ref_in_dict(tv->vval.v_dict, tv->vval.v_dict, | 5632 for (buf = firstbuf; buf != NULL; buf = buf->b_next) |
5599 ++current_copyID, NULL); | 5633 set_ref_in_ht(&buf->b_vars.dv_hashtab, copyID); |
5600 if (n < tv->vval.v_dict->dv_refcount) | 5634 |
5601 { | 5635 /* window-local variables */ |
5602 selfref = 0; | 5636 FOR_ALL_WINDOWS(wp) |
5603 break; | 5637 set_ref_in_ht(&wp->w_vars.dv_hashtab, copyID); |
5604 } | 5638 |
5639 /* global variables */ | |
5640 set_ref_in_ht(&globvarht, copyID); | |
5641 | |
5642 /* function-local variables */ | |
5643 for (fc = current_funccal; fc != NULL; fc = fc->caller) | |
5644 { | |
5645 set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID); | |
5646 set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID); | |
5647 } | |
5648 | |
5649 /* | |
5650 * 2. Go through the list of dicts and free items without the copyID. | |
5651 */ | |
5652 for (dd = first_dict; dd != NULL; ) | |
5653 if (dd->dv_copyID != copyID) | |
5654 { | |
5655 dict_free(dd); | |
5656 did_free = TRUE; | |
5657 | |
5658 /* restart, next dict may also have been freed */ | |
5659 dd = first_dict; | |
5605 } | 5660 } |
5606 else | 5661 else |
5607 { | 5662 dd = dd->dv_used_next; |
5608 n = count_ref_in_list(tv->vval.v_list, tv->vval.v_list, | 5663 |
5609 ++current_copyID, NULL); | 5664 /* |
5610 if (n < tv->vval.v_list->lv_refcount) | 5665 * 3. Go through the list of lists and free items without the copyID. |
5611 { | 5666 */ |
5612 selfref = 0; | 5667 for (ll = first_list; ll != NULL; ) |
5613 break; | 5668 if (ll->lv_copyID != copyID) |
5614 } | 5669 { |
5615 } | 5670 list_free(ll); |
5616 } | 5671 did_free = TRUE; |
5617 | 5672 |
5618 ga_clear(&ga); | 5673 /* restart, next dict may also have been freed */ |
5619 return selfref; | 5674 ll = first_list; |
5620 } | 5675 } |
5621 | 5676 else |
5622 /* | 5677 ll = ll->lv_used_next; |
5623 * Count number of references to "rp" in dictionary "d" and its members. | 5678 |
5624 * We use "copyID" to avoid recursing into the same list/dict twice. | 5679 return did_free; |
5625 */ | 5680 } |
5626 static int | 5681 |
5627 count_ref_in_dict(d, rp, copyID, gap) | 5682 /* |
5628 dict_T *d; | 5683 * Mark all lists and dicts referenced through hashtab "ht" with "copyID". |
5629 void *rp; | 5684 */ |
5685 static void | |
5686 set_ref_in_ht(ht, copyID) | |
5687 hashtab_T *ht; | |
5630 int copyID; | 5688 int copyID; |
5631 garray_T *gap; | |
5632 { | 5689 { |
5633 int todo; | 5690 int todo; |
5634 hashitem_T *hi; | 5691 hashitem_T *hi; |
5635 int n = 0; | 5692 |
5636 | 5693 todo = ht->ht_used; |
5637 todo = d->dv_hashtab.ht_used; | 5694 for (hi = ht->ht_array; todo > 0; ++hi) |
5638 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) | |
5639 if (!HASHITEM_EMPTY(hi)) | 5695 if (!HASHITEM_EMPTY(hi)) |
5640 { | 5696 { |
5641 --todo; | 5697 --todo; |
5642 n += count_ref_item(&HI2DI(hi)->di_tv, rp, copyID, gap); | 5698 set_ref_in_item(&HI2DI(hi)->di_tv, copyID); |
5643 } | 5699 } |
5644 return n; | 5700 } |
5645 } | 5701 |
5646 | 5702 /* |
5647 /* | 5703 * Mark all lists and dicts referenced through list "l" with "copyID". |
5648 * Count number of references to "rp" in list "l" and its members. | 5704 */ |
5649 * We use "copyID" to avoid recursing into the same list/dict twice. | 5705 static void |
5650 */ | 5706 set_ref_in_list(l, copyID) |
5651 static int | |
5652 count_ref_in_list(l, rp, copyID, gap) | |
5653 list_T *l; | 5707 list_T *l; |
5654 void *rp; | |
5655 int copyID; | 5708 int copyID; |
5656 garray_T *gap; | |
5657 { | 5709 { |
5658 listitem_T *li; | 5710 listitem_T *li; |
5659 int n = 0; | |
5660 | 5711 |
5661 for (li = l->lv_first; li != NULL; li = li->li_next) | 5712 for (li = l->lv_first; li != NULL; li = li->li_next) |
5662 n += count_ref_item(&li->li_tv, rp, copyID, gap); | 5713 set_ref_in_item(&li->li_tv, copyID); |
5663 return n; | 5714 } |
5664 } | 5715 |
5665 | 5716 /* |
5666 /* | 5717 * Mark all lists and dicts referenced through typval "tv" with "copyID". |
5667 * Count number of references to "rp" in item "tv" and any members. | 5718 */ |
5668 * We use "copyID" to avoid recursing into the same list/dict twice. | 5719 static void |
5669 * When "gap" is not NULL store items that require checking for only | 5720 set_ref_in_item(tv, copyID) |
5670 * references inside the structure. | |
5671 */ | |
5672 static int | |
5673 count_ref_item(tv, rp, copyID, gap) | |
5674 typval_T *tv; | 5721 typval_T *tv; |
5675 void *rp; | |
5676 int copyID; | 5722 int copyID; |
5677 garray_T *gap; | |
5678 { | 5723 { |
5679 dict_T *dd; | 5724 dict_T *dd; |
5680 list_T *ll; | 5725 list_T *ll; |
5681 int n; | |
5682 | 5726 |
5683 switch (tv->v_type) | 5727 switch (tv->v_type) |
5684 { | 5728 { |
5685 case VAR_DICT: | 5729 case VAR_DICT: |
5686 dd = tv->vval.v_dict; | 5730 dd = tv->vval.v_dict; |
5687 if (dd == rp) | 5731 if (dd->dv_copyID != copyID) |
5688 return 1; /* match, count it */ | |
5689 if (dd->dv_copyID == copyID) | |
5690 return 0; /* already inspected this dict */ | |
5691 dd->dv_copyID = copyID; | |
5692 n = count_ref_in_dict(dd, rp, copyID, gap); | |
5693 if (n > 0 && gap != NULL && dd->dv_refcount > 1) | |
5694 { | 5732 { |
5695 /* We must later check that the references to this dict are | 5733 /* Didn't see this dict yet. */ |
5696 * all in the structure we are freeing. */ | 5734 dd->dv_copyID = copyID; |
5697 if (ga_grow(gap, 1) == FAIL) | 5735 set_ref_in_ht(&dd->dv_hashtab, copyID); |
5698 return 0; | |
5699 ((typval_T **)gap->ga_data)[gap->ga_len++] = tv; | |
5700 } | 5736 } |
5701 return n; | 5737 break; |
5702 | 5738 |
5703 case VAR_LIST: | 5739 case VAR_LIST: |
5704 ll = tv->vval.v_list; | 5740 ll = tv->vval.v_list; |
5705 if (ll == rp) | 5741 if (ll->lv_copyID != copyID) |
5706 return 1; /* match, count it */ | |
5707 if (ll->lv_copyID == copyID) | |
5708 return 0; /* already inspected this list */ | |
5709 ll->lv_copyID = copyID; | |
5710 n = count_ref_in_list(ll, rp, copyID, gap); | |
5711 if (n > 0 && gap != NULL && ll->lv_refcount > 1) | |
5712 { | 5742 { |
5713 /* We must later check that the references to this list are | 5743 /* Didn't see this list yet. */ |
5714 * all in the structure we are freeing. */ | 5744 ll->lv_copyID = copyID; |
5715 if (ga_grow(gap, 1) == FAIL) | 5745 set_ref_in_list(ll, copyID); |
5716 return 0; | |
5717 ((typval_T **)gap->ga_data)[gap->ga_len++] = tv; | |
5718 } | 5746 } |
5719 return n; | 5747 break; |
5720 } | 5748 } |
5721 return 0; | 5749 return; |
5722 } | 5750 } |
5723 | 5751 |
5724 /* | 5752 /* |
5725 * Allocate an empty header for a dictionary. | 5753 * Allocate an empty header for a dictionary. |
5726 */ | 5754 */ |
5730 dict_T *d; | 5758 dict_T *d; |
5731 | 5759 |
5732 d = (dict_T *)alloc(sizeof(dict_T)); | 5760 d = (dict_T *)alloc(sizeof(dict_T)); |
5733 if (d != NULL) | 5761 if (d != NULL) |
5734 { | 5762 { |
5763 /* Add the list to the hashtable for garbage collection. */ | |
5764 if (first_dict != NULL) | |
5765 first_dict->dv_used_prev = d; | |
5766 d->dv_used_next = first_dict; | |
5767 d->dv_used_prev = NULL; | |
5768 | |
5735 hash_init(&d->dv_hashtab); | 5769 hash_init(&d->dv_hashtab); |
5736 d->dv_lock = 0; | 5770 d->dv_lock = 0; |
5737 d->dv_refcount = 0; | 5771 d->dv_refcount = 0; |
5738 d->dv_copyID = 0; | 5772 d->dv_copyID = 0; |
5739 } | 5773 } |
5746 */ | 5780 */ |
5747 static void | 5781 static void |
5748 dict_unref(d) | 5782 dict_unref(d) |
5749 dict_T *d; | 5783 dict_T *d; |
5750 { | 5784 { |
5751 int selfref; | 5785 if (d != NULL && d->dv_refcount != DEL_REFCOUNT && --d->dv_refcount <= 0) |
5752 | 5786 dict_free(d); |
5753 if (d != NULL && d->dv_refcount != DEL_REFCOUNT) | |
5754 { | |
5755 if (--d->dv_refcount > 0) | |
5756 { | |
5757 /* Check if the dict contains references to itself. These need to | |
5758 * be subtracted from the reference count to find out if we can | |
5759 * delete the dict. */ | |
5760 selfref = count_self_ref(d, VAR_DICT); | |
5761 } | |
5762 else | |
5763 selfref = 0; | |
5764 if (d->dv_refcount - selfref == 0) | |
5765 /* No references to the dict now, free it. */ | |
5766 dict_free(d); | |
5767 } | |
5768 } | 5787 } |
5769 | 5788 |
5770 /* | 5789 /* |
5771 * Free a Dictionary, including all items it contains. | 5790 * Free a Dictionary, including all items it contains. |
5772 * Ignores the reference count. | 5791 * Ignores the reference count. |
5780 dictitem_T *di; | 5799 dictitem_T *di; |
5781 | 5800 |
5782 /* Avoid that recursive reference to the dict frees us again. */ | 5801 /* Avoid that recursive reference to the dict frees us again. */ |
5783 d->dv_refcount = DEL_REFCOUNT; | 5802 d->dv_refcount = DEL_REFCOUNT; |
5784 | 5803 |
5785 /* Lock the hashtab, we don't want it to resize while looping through it. | 5804 /* Remove the dict from the list of dicts for garbage collection. */ |
5786 * */ | 5805 if (d->dv_used_prev == NULL) |
5806 first_dict = d->dv_used_next; | |
5807 else | |
5808 d->dv_used_prev->dv_used_next = d->dv_used_next; | |
5809 if (d->dv_used_next != NULL) | |
5810 d->dv_used_next->dv_used_prev = d->dv_used_prev; | |
5811 | |
5812 /* Lock the hashtab, we don't want it to resize while freeing items. */ | |
5787 hash_lock(&d->dv_hashtab); | 5813 hash_lock(&d->dv_hashtab); |
5788 todo = d->dv_hashtab.ht_used; | 5814 todo = d->dv_hashtab.ht_used; |
5789 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) | 5815 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) |
5790 { | 5816 { |
5791 if (!HASHITEM_EMPTY(hi)) | 5817 if (!HASHITEM_EMPTY(hi)) |
6503 {"foldlevel", 1, 1, f_foldlevel}, | 6529 {"foldlevel", 1, 1, f_foldlevel}, |
6504 {"foldtext", 0, 0, f_foldtext}, | 6530 {"foldtext", 0, 0, f_foldtext}, |
6505 {"foldtextresult", 1, 1, f_foldtextresult}, | 6531 {"foldtextresult", 1, 1, f_foldtextresult}, |
6506 {"foreground", 0, 0, f_foreground}, | 6532 {"foreground", 0, 0, f_foreground}, |
6507 {"function", 1, 1, f_function}, | 6533 {"function", 1, 1, f_function}, |
6534 {"garbagecollect", 0, 0, f_garbagecollect}, | |
6508 {"get", 2, 3, f_get}, | 6535 {"get", 2, 3, f_get}, |
6509 {"getbufvar", 2, 2, f_getbufvar}, | 6536 {"getbufvar", 2, 2, f_getbufvar}, |
6510 {"getchar", 0, 1, f_getchar}, | 6537 {"getchar", 0, 1, f_getchar}, |
6511 {"getcharmod", 0, 0, f_getcharmod}, | 6538 {"getcharmod", 0, 0, f_getcharmod}, |
6512 {"getcmdline", 0, 0, f_getcmdline}, | 6539 {"getcmdline", 0, 0, f_getcmdline}, |
8884 rettv->v_type = VAR_FUNC; | 8911 rettv->v_type = VAR_FUNC; |
8885 } | 8912 } |
8886 } | 8913 } |
8887 | 8914 |
8888 /* | 8915 /* |
8916 * "garbagecollect()" function | |
8917 */ | |
8918 /*ARGSUSED*/ | |
8919 static void | |
8920 f_garbagecollect(argvars, rettv) | |
8921 typval_T *argvars; | |
8922 typval_T *rettv; | |
8923 { | |
8924 garbage_collect(); | |
8925 } | |
8926 | |
8927 /* | |
8889 * "get()" function | 8928 * "get()" function |
8890 */ | 8929 */ |
8891 static void | 8930 static void |
8892 f_get(argvars, rettv) | 8931 f_get(argvars, rettv) |
8893 typval_T *argvars; | 8932 typval_T *argvars; |
15504 case 's': return &SCRIPT_SV(current_SID).sv_var; | 15543 case 's': return &SCRIPT_SV(current_SID).sv_var; |
15505 case 'g': return &globvars_var; | 15544 case 'g': return &globvars_var; |
15506 case 'v': return &vimvars_var; | 15545 case 'v': return &vimvars_var; |
15507 case 'b': return &curbuf->b_bufvar; | 15546 case 'b': return &curbuf->b_bufvar; |
15508 case 'w': return &curwin->w_winvar; | 15547 case 'w': return &curwin->w_winvar; |
15509 case 'l': return ¤t_funccal->l_vars_var; | 15548 case 'l': return current_funccal == NULL |
15510 case 'a': return ¤t_funccal->l_avars_var; | 15549 ? NULL : ¤t_funccal->l_vars_var; |
15550 case 'a': return current_funccal == NULL | |
15551 ? NULL : ¤t_funccal->l_avars_var; | |
15511 } | 15552 } |
15512 return NULL; | 15553 return NULL; |
15513 } | 15554 } |
15514 | 15555 |
15515 hi = hash_find(ht, varname); | 15556 hi = hash_find(ht, varname); |
15687 if ((v->di_flags & DI_FLAGS_FIX) == 0) | 15728 if ((v->di_flags & DI_FLAGS_FIX) == 0) |
15688 vim_free(v); | 15729 vim_free(v); |
15689 } | 15730 } |
15690 } | 15731 } |
15691 hash_clear(ht); | 15732 hash_clear(ht); |
15733 ht->ht_used = 0; | |
15692 } | 15734 } |
15693 | 15735 |
15694 /* | 15736 /* |
15695 * Delete a variable from hashtab "ht" at item "hi". | 15737 * Delete a variable from hashtab "ht" at item "hi". |
15696 * Clear the variable value and free the dictitem. | 15738 * Clear the variable value and free the dictitem. |
15787 EMSG2(_("E704: Funcref variable name must start with a capital: %s"), name); | 15829 EMSG2(_("E704: Funcref variable name must start with a capital: %s"), name); |
15788 return; | 15830 return; |
15789 } | 15831 } |
15790 if (function_exists(name)) | 15832 if (function_exists(name)) |
15791 { | 15833 { |
15792 EMSG2(_("705: Variable name conflicts with existing function: %s"), | 15834 EMSG2(_("E705: Variable name conflicts with existing function: %s"), |
15793 name); | 15835 name); |
15794 return; | 15836 return; |
15795 } | 15837 } |
15796 } | 15838 } |
15797 | 15839 |
17567 { | 17609 { |
17568 char_u *save_sourcing_name; | 17610 char_u *save_sourcing_name; |
17569 linenr_T save_sourcing_lnum; | 17611 linenr_T save_sourcing_lnum; |
17570 scid_T save_current_SID; | 17612 scid_T save_current_SID; |
17571 funccall_T fc; | 17613 funccall_T fc; |
17572 funccall_T *save_fcp = current_funccal; | |
17573 int save_did_emsg; | 17614 int save_did_emsg; |
17574 static int depth = 0; | 17615 static int depth = 0; |
17575 dictitem_T *v; | 17616 dictitem_T *v; |
17576 int fixvar_idx = 0; /* index in fixvar[] */ | 17617 int fixvar_idx = 0; /* index in fixvar[] */ |
17577 int i; | 17618 int i; |
17592 } | 17633 } |
17593 ++depth; | 17634 ++depth; |
17594 | 17635 |
17595 line_breakcheck(); /* check for CTRL-C hit */ | 17636 line_breakcheck(); /* check for CTRL-C hit */ |
17596 | 17637 |
17638 fc.caller = current_funccal; | |
17597 current_funccal = &fc; | 17639 current_funccal = &fc; |
17598 fc.func = fp; | 17640 fc.func = fp; |
17599 fc.rettv = rettv; | 17641 fc.rettv = rettv; |
17600 rettv->vval.v_number = 0; | 17642 rettv->vval.v_number = 0; |
17601 fc.linenr = 0; | 17643 fc.linenr = 0; |
17750 if (do_profiling) | 17792 if (do_profiling) |
17751 { | 17793 { |
17752 if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL)) | 17794 if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL)) |
17753 func_do_profile(fp); | 17795 func_do_profile(fp); |
17754 if (fp->uf_profiling | 17796 if (fp->uf_profiling |
17755 || (save_fcp != NULL && &save_fcp->func->uf_profiling)) | 17797 || (fc.caller != NULL && &fc.caller->func->uf_profiling)) |
17756 { | 17798 { |
17757 ++fp->uf_tm_count; | 17799 ++fp->uf_tm_count; |
17758 profile_start(&fp->uf_tm_start); | 17800 profile_start(&fp->uf_tm_start); |
17759 profile_zero(&fp->uf_tm_children); | 17801 profile_zero(&fp->uf_tm_children); |
17760 } | 17802 } |
17780 rettv->v_type = VAR_NUMBER; | 17822 rettv->v_type = VAR_NUMBER; |
17781 rettv->vval.v_number = -1; | 17823 rettv->vval.v_number = -1; |
17782 } | 17824 } |
17783 | 17825 |
17784 #ifdef FEAT_PROFILE | 17826 #ifdef FEAT_PROFILE |
17785 if (fp->uf_profiling || (save_fcp != NULL && &save_fcp->func->uf_profiling)) | 17827 if (fp->uf_profiling || (fc.caller != NULL && &fc.caller->func->uf_profiling)) |
17786 { | 17828 { |
17787 profile_end(&fp->uf_tm_start); | 17829 profile_end(&fp->uf_tm_start); |
17788 profile_sub_wait(&wait_start, &fp->uf_tm_start); | 17830 profile_sub_wait(&wait_start, &fp->uf_tm_start); |
17789 profile_add(&fp->uf_tm_total, &fp->uf_tm_start); | 17831 profile_add(&fp->uf_tm_total, &fp->uf_tm_start); |
17790 profile_add(&fp->uf_tm_self, &fp->uf_tm_start); | 17832 profile_add(&fp->uf_tm_self, &fp->uf_tm_start); |
17791 profile_sub(&fp->uf_tm_self, &fp->uf_tm_children); | 17833 profile_sub(&fp->uf_tm_self, &fp->uf_tm_children); |
17792 if (save_fcp != NULL && &save_fcp->func->uf_profiling) | 17834 if (fc.caller != NULL && &fc.caller->func->uf_profiling) |
17793 { | 17835 { |
17794 profile_add(&save_fcp->func->uf_tm_children, &fp->uf_tm_start); | 17836 profile_add(&fc.caller->func->uf_tm_children, &fp->uf_tm_start); |
17795 profile_add(&save_fcp->func->uf_tml_children, &fp->uf_tm_start); | 17837 profile_add(&fc.caller->func->uf_tml_children, &fp->uf_tm_start); |
17796 } | 17838 } |
17797 } | 17839 } |
17798 #endif | 17840 #endif |
17799 | 17841 |
17800 /* when being verbose, mention the return value */ | 17842 /* when being verbose, mention the return value */ |
17848 verbose_leave_scroll(); | 17890 verbose_leave_scroll(); |
17849 --no_wait_return; | 17891 --no_wait_return; |
17850 } | 17892 } |
17851 | 17893 |
17852 did_emsg |= save_did_emsg; | 17894 did_emsg |= save_did_emsg; |
17853 current_funccal = save_fcp; | 17895 current_funccal = fc.caller; |
17854 | 17896 |
17855 /* The a: variables typevals were not alloced, only free the allocated | 17897 /* The a: variables typevals were not alloced, only free the allocated |
17856 * variables. */ | 17898 * variables. */ |
17857 vars_clear_ext(&fc.l_avars.dv_hashtab, FALSE); | 17899 vars_clear_ext(&fc.l_avars.dv_hashtab, FALSE); |
17858 | 17900 |