mirror of
https://github.com/vim/vim.git
synced 2025-08-29 20:33:37 -04:00
updated for version 7.0094
This commit is contained in:
parent
80b29f273d
commit
d9fba318b8
@ -1,4 +1,4 @@
|
|||||||
*repeat.txt* For Vim version 7.0aa. Last change: 2005 Jun 25
|
*repeat.txt* For Vim version 7.0aa. Last change: 2005 Jun 26
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@ -579,6 +579,11 @@ It is only included when Vim was compiled with "huge" features.
|
|||||||
this command.
|
this command.
|
||||||
|
|
||||||
|
|
||||||
|
:profd[el] ... *:profd* *:profdel*
|
||||||
|
Stop profiling for the arguments specified. See |:breakdel|
|
||||||
|
for the arguments.
|
||||||
|
|
||||||
|
|
||||||
You must always start with a ":profile start fname" command. The resulting
|
You must always start with a ":profile start fname" command. The resulting
|
||||||
file is written when Vim exits. Here is an example of the output, with line
|
file is written when Vim exits. Here is an example of the output, with line
|
||||||
numbers prepended for the explanation:
|
numbers prepended for the explanation:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
*todo.txt* For Vim version 7.0aa. Last change: 2005 Jun 25
|
*todo.txt* For Vim version 7.0aa. Last change: 2005 Jun 26
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@ -30,6 +30,9 @@ be worked on, but only if you sponsor Vim development. See |sponsor|.
|
|||||||
*known-bugs*
|
*known-bugs*
|
||||||
-------------------- Known bugs and current work -----------------------
|
-------------------- Known bugs and current work -----------------------
|
||||||
|
|
||||||
|
Is the fix for memory leaks in unreferencing dict/list correct? Is there a
|
||||||
|
situation where a reference from outside of the structure is not counted?
|
||||||
|
|
||||||
Add extra list of file locations. Can be used with:
|
Add extra list of file locations. Can be used with:
|
||||||
:ltag list of matching tags, like :tselect
|
:ltag list of matching tags, like :tselect
|
||||||
|
|
||||||
@ -116,7 +119,7 @@ PLANNED FOR VERSION 7.0:
|
|||||||
- Simple and fast sound-a-like: mapping list for first char and rest
|
- Simple and fast sound-a-like: mapping list for first char and rest
|
||||||
vowel as first char: *
|
vowel as first char: *
|
||||||
remove other vowels
|
remove other vowels
|
||||||
- Cleanup spell help.
|
- Proofread and cleanup spell help.
|
||||||
- Use "engspchk" from Charles Campbell for ideas (commands, rare words).
|
- Use "engspchk" from Charles Campbell for ideas (commands, rare words).
|
||||||
- Make "en-rare" spell file? Ask Charles Campbell.
|
- Make "en-rare" spell file? Ask Charles Campbell.
|
||||||
- References: MySpell library (in OpenOffice.org).
|
- References: MySpell library (in OpenOffice.org).
|
||||||
|
255
src/eval.c
255
src/eval.c
@ -122,6 +122,12 @@ static dictitem_T globvars_var;
|
|||||||
*/
|
*/
|
||||||
static hashtab_T compat_hashtab;
|
static hashtab_T compat_hashtab;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When recursively copying lists and dicts we need to remember which ones we
|
||||||
|
* have done to avoid endless recursiveness. This unique ID is used for that.
|
||||||
|
*/
|
||||||
|
static int current_copyID = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Array to hold the hashtab with variables local to each sourced script.
|
* Array to hold the hashtab with variables local to each sourced script.
|
||||||
* Each item holds a variable (nameless) that points to the dict_T.
|
* Each item holds a variable (nameless) that points to the dict_T.
|
||||||
@ -185,6 +191,8 @@ struct ufunc
|
|||||||
#define FC_RANGE 2 /* function accepts range */
|
#define FC_RANGE 2 /* function accepts range */
|
||||||
#define FC_DICT 4 /* Dict function, uses "self" */
|
#define FC_DICT 4 /* Dict function, uses "self" */
|
||||||
|
|
||||||
|
#define DEL_REFCOUNT 999999 /* list/dict is being deleted */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All user-defined functions are found in this hash table.
|
* All user-defined functions are found in this hash table.
|
||||||
*/
|
*/
|
||||||
@ -374,6 +382,11 @@ static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2))
|
|||||||
static char_u *list2string __ARGS((typval_T *tv));
|
static char_u *list2string __ARGS((typval_T *tv));
|
||||||
static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo));
|
static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo));
|
||||||
|
|
||||||
|
static int count_self_ref __ARGS((void *p, int type));
|
||||||
|
static int count_ref_in_dict __ARGS((dict_T *d, void *rp, int copyID, garray_T *gap));
|
||||||
|
static int count_ref_in_list __ARGS((list_T *l, void *rp, int copyID, garray_T *gap));
|
||||||
|
static int count_ref_item __ARGS((typval_T *tv, void *rp, int copyID, garray_T *gap));
|
||||||
|
|
||||||
static void dict_unref __ARGS((dict_T *d));
|
static void dict_unref __ARGS((dict_T *d));
|
||||||
static void dict_free __ARGS((dict_T *d));
|
static void dict_free __ARGS((dict_T *d));
|
||||||
static dictitem_T *dictitem_alloc __ARGS((char_u *key));
|
static dictitem_T *dictitem_alloc __ARGS((char_u *key));
|
||||||
@ -719,7 +732,10 @@ eval_clear()
|
|||||||
{
|
{
|
||||||
p = &vimvars[i];
|
p = &vimvars[i];
|
||||||
if (p->vv_di.di_tv.v_type == VAR_STRING)
|
if (p->vv_di.di_tv.v_type == VAR_STRING)
|
||||||
|
{
|
||||||
vim_free(p->vv_di.di_tv.vval.v_string);
|
vim_free(p->vv_di.di_tv.vval.v_string);
|
||||||
|
p->vv_di.di_tv.vval.v_string = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
hash_clear(&vimvarht);
|
hash_clear(&vimvarht);
|
||||||
hash_clear(&compat_hashtab);
|
hash_clear(&compat_hashtab);
|
||||||
@ -728,9 +744,12 @@ eval_clear()
|
|||||||
for (i = 1; i <= ga_scripts.ga_len; ++i)
|
for (i = 1; i <= ga_scripts.ga_len; ++i)
|
||||||
vars_clear(&SCRIPT_VARS(i));
|
vars_clear(&SCRIPT_VARS(i));
|
||||||
ga_clear(&ga_scripts);
|
ga_clear(&ga_scripts);
|
||||||
|
free_scriptnames();
|
||||||
|
|
||||||
/* global variables */
|
/* global variables */
|
||||||
vars_clear(&globvarht);
|
vars_clear(&globvarht);
|
||||||
|
|
||||||
|
free_all_functions();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -4937,8 +4956,23 @@ list_alloc()
|
|||||||
list_unref(l)
|
list_unref(l)
|
||||||
list_T *l;
|
list_T *l;
|
||||||
{
|
{
|
||||||
if (l != NULL && --l->lv_refcount <= 0)
|
int selfref;
|
||||||
list_free(l);
|
|
||||||
|
if (l != NULL && l->lv_refcount != DEL_REFCOUNT)
|
||||||
|
{
|
||||||
|
if (--l->lv_refcount > 0)
|
||||||
|
{
|
||||||
|
/* Check if the dict contains references to itself. These need to
|
||||||
|
* be subtracted from the reference count to find out if we can
|
||||||
|
* delete the dict. */
|
||||||
|
selfref = count_self_ref(l, VAR_LIST);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
selfref = 0;
|
||||||
|
if (l->lv_refcount - selfref == 0)
|
||||||
|
/* No references to the list now, free it. */
|
||||||
|
list_free(l);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4950,11 +4984,14 @@ list_free(l)
|
|||||||
list_T *l;
|
list_T *l;
|
||||||
{
|
{
|
||||||
listitem_T *item;
|
listitem_T *item;
|
||||||
listitem_T *next;
|
|
||||||
|
|
||||||
for (item = l->lv_first; item != NULL; item = next)
|
/* Avoid that recursive reference to the list frees us again. */
|
||||||
|
l->lv_refcount = DEL_REFCOUNT;
|
||||||
|
|
||||||
|
for (item = l->lv_first; item != NULL; item = l->lv_first)
|
||||||
{
|
{
|
||||||
next = item->li_next;
|
/* Remove the item before deleting it. */
|
||||||
|
l->lv_first = item->li_next;
|
||||||
listitem_free(item);
|
listitem_free(item);
|
||||||
}
|
}
|
||||||
vim_free(l);
|
vim_free(l);
|
||||||
@ -5530,6 +5567,160 @@ list_join(gap, l, sep, echo)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Count the number of references for list/dict "p" inside itself.
|
||||||
|
* This is used to find out if there are no more references elsewhere.
|
||||||
|
* The tricky bit is that we must not count references in lists/dicts that are
|
||||||
|
* used elsewhere, but we can only know by counting their references...
|
||||||
|
* This is a bit slow, but required to avoid leaking memory.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
count_self_ref(p, type)
|
||||||
|
void *p;
|
||||||
|
int type;
|
||||||
|
{
|
||||||
|
garray_T ga;
|
||||||
|
typval_T *tv;
|
||||||
|
int selfref;
|
||||||
|
int i;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
ga_init2(&ga, sizeof(typval_T *), 10);
|
||||||
|
if (type == VAR_DICT)
|
||||||
|
selfref = count_ref_in_dict(p, p, ++current_copyID, &ga);
|
||||||
|
else
|
||||||
|
selfref = count_ref_in_list(p, p, ++current_copyID, &ga);
|
||||||
|
for (i = 0; i < ga.ga_len; ++i)
|
||||||
|
{
|
||||||
|
tv = ((typval_T **)ga.ga_data)[i];
|
||||||
|
if (tv->v_type == VAR_DICT)
|
||||||
|
{
|
||||||
|
n = count_ref_in_dict(tv->vval.v_dict, tv->vval.v_dict,
|
||||||
|
++current_copyID, NULL);
|
||||||
|
if (n < tv->vval.v_dict->dv_refcount)
|
||||||
|
{
|
||||||
|
selfref = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
n = count_ref_in_list(tv->vval.v_list, tv->vval.v_list,
|
||||||
|
++current_copyID, NULL);
|
||||||
|
if (n < tv->vval.v_list->lv_refcount)
|
||||||
|
{
|
||||||
|
selfref = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ga_clear(&ga);
|
||||||
|
return selfref;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Count number of references to "rp" in dictionary "d" and its members.
|
||||||
|
* We use "copyID" to avoid recursing into the same list/dict twice.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
count_ref_in_dict(d, rp, copyID, gap)
|
||||||
|
dict_T *d;
|
||||||
|
void *rp;
|
||||||
|
int copyID;
|
||||||
|
garray_T *gap;
|
||||||
|
{
|
||||||
|
int todo;
|
||||||
|
hashitem_T *hi;
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
todo = d->dv_hashtab.ht_used;
|
||||||
|
for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
|
||||||
|
if (!HASHITEM_EMPTY(hi))
|
||||||
|
{
|
||||||
|
--todo;
|
||||||
|
n += count_ref_item(&HI2DI(hi)->di_tv, rp, copyID, gap);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Count number of references to "rp" in list "l" and its members.
|
||||||
|
* We use "copyID" to avoid recursing into the same list/dict twice.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
count_ref_in_list(l, rp, copyID, gap)
|
||||||
|
list_T *l;
|
||||||
|
void *rp;
|
||||||
|
int copyID;
|
||||||
|
garray_T *gap;
|
||||||
|
{
|
||||||
|
listitem_T *li;
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
for (li = l->lv_first; li != NULL; li = li->li_next)
|
||||||
|
n += count_ref_item(&li->li_tv, rp, copyID, gap);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Count number of references to "rp" in item "tv" and any members.
|
||||||
|
* We use "copyID" to avoid recursing into the same list/dict twice.
|
||||||
|
* When "gap" is not NULL store items that require checking for only
|
||||||
|
* references inside the structure.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
count_ref_item(tv, rp, copyID, gap)
|
||||||
|
typval_T *tv;
|
||||||
|
void *rp;
|
||||||
|
int copyID;
|
||||||
|
garray_T *gap;
|
||||||
|
{
|
||||||
|
dict_T *dd;
|
||||||
|
list_T *ll;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
switch (tv->v_type)
|
||||||
|
{
|
||||||
|
case VAR_DICT:
|
||||||
|
dd = tv->vval.v_dict;
|
||||||
|
if (dd == rp)
|
||||||
|
return 1; /* match, count it */
|
||||||
|
if (dd->dv_copyID == copyID)
|
||||||
|
return 0; /* already inspected this dict */
|
||||||
|
dd->dv_copyID = copyID;
|
||||||
|
n = count_ref_in_dict(dd, rp, copyID, gap);
|
||||||
|
if (n > 0 && gap != NULL && dd->dv_refcount > 1)
|
||||||
|
{
|
||||||
|
/* We must later check that the references to this dict are
|
||||||
|
* all in the structure we are freeing. */
|
||||||
|
if (ga_grow(gap, 1) == FAIL)
|
||||||
|
return 0;
|
||||||
|
((typval_T **)gap->ga_data)[gap->ga_len++] = tv;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
|
||||||
|
case VAR_LIST:
|
||||||
|
ll = tv->vval.v_list;
|
||||||
|
if (ll == rp)
|
||||||
|
return 1; /* match, count it */
|
||||||
|
if (ll->lv_copyID == copyID)
|
||||||
|
return 0; /* already inspected this list */
|
||||||
|
ll->lv_copyID = copyID;
|
||||||
|
n = count_ref_in_list(ll, rp, copyID, gap);
|
||||||
|
if (n > 0 && gap != NULL && ll->lv_refcount > 1)
|
||||||
|
{
|
||||||
|
/* We must later check that the references to this list are
|
||||||
|
* all in the structure we are freeing. */
|
||||||
|
if (ga_grow(gap, 1) == FAIL)
|
||||||
|
return 0;
|
||||||
|
((typval_T **)gap->ga_data)[gap->ga_len++] = tv;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate an empty header for a dictionary.
|
* Allocate an empty header for a dictionary.
|
||||||
*/
|
*/
|
||||||
@ -5557,8 +5748,23 @@ dict_alloc()
|
|||||||
dict_unref(d)
|
dict_unref(d)
|
||||||
dict_T *d;
|
dict_T *d;
|
||||||
{
|
{
|
||||||
if (d != NULL && --d->dv_refcount <= 0)
|
int selfref;
|
||||||
dict_free(d);
|
|
||||||
|
if (d != NULL && d->dv_refcount != DEL_REFCOUNT)
|
||||||
|
{
|
||||||
|
if (--d->dv_refcount > 0)
|
||||||
|
{
|
||||||
|
/* Check if the dict contains references to itself. These need to
|
||||||
|
* be subtracted from the reference count to find out if we can
|
||||||
|
* delete the dict. */
|
||||||
|
selfref = count_self_ref(d, VAR_DICT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
selfref = 0;
|
||||||
|
if (d->dv_refcount - selfref == 0)
|
||||||
|
/* No references to the dict now, free it. */
|
||||||
|
dict_free(d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -5571,15 +5777,24 @@ dict_free(d)
|
|||||||
{
|
{
|
||||||
int todo;
|
int todo;
|
||||||
hashitem_T *hi;
|
hashitem_T *hi;
|
||||||
|
dictitem_T *di;
|
||||||
|
|
||||||
/* Careful: we free the dictitems while they still appear in the
|
/* Avoid that recursive reference to the dict frees us again. */
|
||||||
* hashtab. Must not try to resize the hashtab! */
|
d->dv_refcount = DEL_REFCOUNT;
|
||||||
|
|
||||||
|
/* Lock the hashtab, we don't want it to resize while looping through it.
|
||||||
|
* */
|
||||||
|
hash_lock(&d->dv_hashtab);
|
||||||
todo = d->dv_hashtab.ht_used;
|
todo = d->dv_hashtab.ht_used;
|
||||||
for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
|
for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
|
||||||
{
|
{
|
||||||
if (!HASHITEM_EMPTY(hi))
|
if (!HASHITEM_EMPTY(hi))
|
||||||
{
|
{
|
||||||
dictitem_free(HI2DI(hi));
|
/* Remove the item before deleting it, just in case there is
|
||||||
|
* something recursive causing trouble. */
|
||||||
|
di = HI2DI(hi);
|
||||||
|
hash_remove(&d->dv_hashtab, hi);
|
||||||
|
dictitem_free(di);
|
||||||
--todo;
|
--todo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7663,7 +7878,6 @@ f_deepcopy(argvars, rettv)
|
|||||||
typval_T *argvars;
|
typval_T *argvars;
|
||||||
typval_T *rettv;
|
typval_T *rettv;
|
||||||
{
|
{
|
||||||
static int copyID = 0;
|
|
||||||
int noref = 0;
|
int noref = 0;
|
||||||
|
|
||||||
if (argvars[1].v_type != VAR_UNKNOWN)
|
if (argvars[1].v_type != VAR_UNKNOWN)
|
||||||
@ -7671,7 +7885,7 @@ f_deepcopy(argvars, rettv)
|
|||||||
if (noref < 0 || noref > 1)
|
if (noref < 0 || noref > 1)
|
||||||
EMSG(_(e_invarg));
|
EMSG(_(e_invarg));
|
||||||
else
|
else
|
||||||
item_copy(&argvars[0], rettv, TRUE, noref == 0 ? ++copyID : 0);
|
item_copy(&argvars[0], rettv, TRUE, noref == 0 ? ++current_copyID : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -8040,7 +8254,6 @@ f_extend(argvars, rettv)
|
|||||||
item = NULL;
|
item = NULL;
|
||||||
list_extend(l1, l2, item);
|
list_extend(l1, l2, item);
|
||||||
|
|
||||||
++l1->lv_refcount;
|
|
||||||
copy_tv(&argvars[0], rettv);
|
copy_tv(&argvars[0], rettv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8106,7 +8319,6 @@ f_extend(argvars, rettv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
++d1->dv_refcount;
|
|
||||||
copy_tv(&argvars[0], rettv);
|
copy_tv(&argvars[0], rettv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -10421,7 +10633,6 @@ f_insert(argvars, rettv)
|
|||||||
if (l != NULL)
|
if (l != NULL)
|
||||||
{
|
{
|
||||||
list_insert_tv(l, &argvars[1], item);
|
list_insert_tv(l, &argvars[1], item);
|
||||||
++l->lv_refcount;
|
|
||||||
copy_tv(&argvars[0], rettv);
|
copy_tv(&argvars[0], rettv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -14934,6 +15145,7 @@ handle_subscript(arg, rettv, evaluate, verbose)
|
|||||||
dict_T *selfdict = NULL;
|
dict_T *selfdict = NULL;
|
||||||
char_u *s;
|
char_u *s;
|
||||||
int len;
|
int len;
|
||||||
|
typval_T functv;
|
||||||
|
|
||||||
while (ret == OK
|
while (ret == OK
|
||||||
&& (**arg == '['
|
&& (**arg == '['
|
||||||
@ -14943,12 +15155,19 @@ handle_subscript(arg, rettv, evaluate, verbose)
|
|||||||
{
|
{
|
||||||
if (**arg == '(')
|
if (**arg == '(')
|
||||||
{
|
{
|
||||||
s = rettv->vval.v_string;
|
/* need to copy the funcref so that we can clear rettv */
|
||||||
|
functv = *rettv;
|
||||||
|
rettv->v_type = VAR_UNKNOWN;
|
||||||
|
|
||||||
/* Invoke the function. Recursive! */
|
/* Invoke the function. Recursive! */
|
||||||
|
s = functv.vval.v_string;
|
||||||
ret = get_func_tv(s, STRLEN(s), rettv, arg,
|
ret = get_func_tv(s, STRLEN(s), rettv, arg,
|
||||||
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
||||||
&len, evaluate, selfdict);
|
&len, evaluate, selfdict);
|
||||||
|
|
||||||
|
/* Clear the funcref afterwards, so that deleting it while
|
||||||
|
* evaluating the arguments is possible (see test55). */
|
||||||
|
clear_tv(&functv);
|
||||||
|
|
||||||
/* Stop the expression evaluation when immediately aborting on
|
/* Stop the expression evaluation when immediately aborting on
|
||||||
* error, or when an interrupt occurred or an exception was thrown
|
* error, or when an interrupt occurred or an exception was thrown
|
||||||
|
@ -613,6 +613,8 @@ EX(CMD_promptrepl, "promptrepl", gui_mch_replace_dialog,
|
|||||||
EXTRA|NOTRLCOM|CMDWIN),
|
EXTRA|NOTRLCOM|CMDWIN),
|
||||||
EX(CMD_profile, "profile", ex_profile,
|
EX(CMD_profile, "profile", ex_profile,
|
||||||
BANG|EXTRA|TRLBAR|CMDWIN),
|
BANG|EXTRA|TRLBAR|CMDWIN),
|
||||||
|
EX(CMD_profdel, "profdel", ex_breakdel,
|
||||||
|
EXTRA|TRLBAR|CMDWIN),
|
||||||
EX(CMD_psearch, "psearch", ex_psearch,
|
EX(CMD_psearch, "psearch", ex_psearch,
|
||||||
BANG|RANGE|WHOLEFOLD|DFLALL|EXTRA),
|
BANG|RANGE|WHOLEFOLD|DFLALL|EXTRA),
|
||||||
EX(CMD_ptag, "ptag", ex_ptag,
|
EX(CMD_ptag, "ptag", ex_ptag,
|
||||||
|
@ -591,7 +591,7 @@ ex_debuggreedy(eap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ":breakdel".
|
* ":breakdel" and ":profdel".
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ex_breakdel(eap)
|
ex_breakdel(eap)
|
||||||
@ -603,13 +603,20 @@ ex_breakdel(eap)
|
|||||||
int del_all = FALSE;
|
int del_all = FALSE;
|
||||||
int i;
|
int i;
|
||||||
linenr_T best_lnum = 0;
|
linenr_T best_lnum = 0;
|
||||||
|
garray_T *gap;
|
||||||
|
|
||||||
|
gap = &dbg_breakp;
|
||||||
|
#ifdef FEAT_PROFILE
|
||||||
|
if (eap->cmdidx == CMD_profdel)
|
||||||
|
gap = &prof_ga;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (vim_isdigit(*eap->arg))
|
if (vim_isdigit(*eap->arg))
|
||||||
{
|
{
|
||||||
/* ":breakdel {nr}" */
|
/* ":breakdel {nr}" */
|
||||||
nr = atol((char *)eap->arg);
|
nr = atol((char *)eap->arg);
|
||||||
for (i = 0; i < dbg_breakp.ga_len; ++i)
|
for (i = 0; i < gap->ga_len; ++i)
|
||||||
if (BREAKP(i).dbg_nr == nr)
|
if (DEBUGGY(gap, i).dbg_nr == nr)
|
||||||
{
|
{
|
||||||
todel = i;
|
todel = i;
|
||||||
break;
|
break;
|
||||||
@ -623,12 +630,12 @@ ex_breakdel(eap)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* ":breakdel {func|file} [lnum] {name}" */
|
/* ":breakdel {func|file} [lnum] {name}" */
|
||||||
if (dbg_parsearg(eap->arg, &dbg_breakp) == FAIL)
|
if (dbg_parsearg(eap->arg, gap) == FAIL)
|
||||||
return;
|
return;
|
||||||
bp = &BREAKP(dbg_breakp.ga_len);
|
bp = &DEBUGGY(gap, gap->ga_len);
|
||||||
for (i = 0; i < dbg_breakp.ga_len; ++i)
|
for (i = 0; i < gap->ga_len; ++i)
|
||||||
{
|
{
|
||||||
bpi = &BREAKP(i);
|
bpi = &DEBUGGY(gap, i);
|
||||||
if (bp->dbg_type == bpi->dbg_type
|
if (bp->dbg_type == bpi->dbg_type
|
||||||
&& STRCMP(bp->dbg_name, bpi->dbg_name) == 0
|
&& STRCMP(bp->dbg_name, bpi->dbg_name) == 0
|
||||||
&& (bp->dbg_lnum == bpi->dbg_lnum
|
&& (bp->dbg_lnum == bpi->dbg_lnum
|
||||||
@ -646,18 +653,27 @@ ex_breakdel(eap)
|
|||||||
if (todel < 0)
|
if (todel < 0)
|
||||||
EMSG2(_("E161: Breakpoint not found: %s"), eap->arg);
|
EMSG2(_("E161: Breakpoint not found: %s"), eap->arg);
|
||||||
else
|
else
|
||||||
while (dbg_breakp.ga_len > 0)
|
{
|
||||||
|
while (gap->ga_len > 0)
|
||||||
{
|
{
|
||||||
vim_free(BREAKP(todel).dbg_name);
|
vim_free(DEBUGGY(gap, todel).dbg_name);
|
||||||
vim_free(BREAKP(todel).dbg_prog);
|
vim_free(DEBUGGY(gap, todel).dbg_prog);
|
||||||
--dbg_breakp.ga_len;
|
--gap->ga_len;
|
||||||
if (todel < dbg_breakp.ga_len)
|
if (todel < gap->ga_len)
|
||||||
mch_memmove(&BREAKP(todel), &BREAKP(todel + 1),
|
mch_memmove(&DEBUGGY(gap, todel), &DEBUGGY(gap, todel + 1),
|
||||||
(dbg_breakp.ga_len - todel) * sizeof(struct debuggy));
|
(gap->ga_len - todel) * sizeof(struct debuggy));
|
||||||
++debug_tick;
|
#ifdef FEAT_PROFILE
|
||||||
|
if (eap->cmdidx == CMD_breakdel)
|
||||||
|
#endif
|
||||||
|
++debug_tick;
|
||||||
if (!del_all)
|
if (!del_all)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If all breakpoints were removed clear the array. */
|
||||||
|
if (gap->ga_len == 0)
|
||||||
|
ga_clear(gap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user