Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
V
Vim
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Someone-Else
Vim
Commits
d9fba318
Commit
d9fba318
authored
19 years ago
by
Bram Moolenaar
Browse files
Options
Downloads
Patches
Plain Diff
updated for version 7.0094
parent
80b29f27
No related branches found
Branches containing commit
Tags
v7.0094
Tags containing commit
No related merge requests found
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
runtime/doc/repeat.txt
+6
-1
6 additions, 1 deletion
runtime/doc/repeat.txt
runtime/doc/todo.txt
+5
-2
5 additions, 2 deletions
runtime/doc/todo.txt
src/eval.c
+237
-18
237 additions, 18 deletions
src/eval.c
src/ex_cmds.h
+2
-0
2 additions, 0 deletions
src/ex_cmds.h
src/ex_cmds2.c
+31
-15
31 additions, 15 deletions
src/ex_cmds2.c
with
281 additions
and
36 deletions
runtime/doc/repeat.txt
+
6
−
1
View file @
d9fba318
*repeat.txt* For Vim version 7.0aa. Last change: 2005 Jun 2
5
*repeat.txt* For Vim version 7.0aa. Last change: 2005 Jun 2
6
VIM REFERENCE MANUAL by Bram Moolenaar
...
...
@@ -579,6 +579,11 @@ It is only included when Vim was compiled with "huge" features.
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
file is written when Vim exits. Here is an example of the output, with line
numbers prepended for the explanation:
...
...
This diff is collapsed.
Click to expand it.
runtime/doc/todo.txt
+
5
−
2
View file @
d9fba318
*todo.txt* For Vim version 7.0aa. Last change: 2005 Jun 2
5
*todo.txt* For Vim version 7.0aa. Last change: 2005 Jun 2
6
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 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:
: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
vowel as first char: *
remove other vowels
-
C
leanup spell help.
-
Proofread and c
leanup spell help.
- Use "engspchk" from Charles Campbell for ideas (commands, rare words).
- Make "en-rare" spell file? Ask Charles Campbell.
- References: MySpell library (in OpenOffice.org).
...
...
This diff is collapsed.
Click to expand it.
src/eval.c
+
237
−
18
View file @
d9fba318
...
...
@@ -122,6 +122,12 @@ static dictitem_T globvars_var;
*/
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.
* 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_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.
*/
...
...
@@ -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 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_free __ARGS((dict_T *d));
static dictitem_T *dictitem_alloc __ARGS((char_u *key));
...
...
@@ -719,7 +732,10 @@ eval_clear()
{
p = &vimvars[i];
if (p->vv_di.di_tv.v_type == VAR_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(&compat_hashtab);
...
...
@@ -728,9 +744,12 @@ eval_clear()
for (i = 1; i <= ga_scripts.ga_len; ++i)
vars_clear(&SCRIPT_VARS(i));
ga_clear(&ga_scripts);
free_scriptnames();
/* global variables */
vars_clear(&globvarht);
free_all_functions();
}
#endif
...
...
@@ -4937,8 +4956,23 @@ list_alloc()
list_unref(l)
list_T *l;
{
if (l != NULL && --l->lv_refcount <= 0)
list_free(l);
int selfref;
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;
{
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);
}
vim_free(l);
...
...
@@ -5530,6 +5567,160 @@ list_join(gap, l, sep, echo)
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.
*/
...
...
@@ -5557,8 +5748,23 @@ dict_alloc()
dict_unref(d)
dict_T *d;
{
if (d != NULL && --d->dv_refcount <= 0)
dict_free(d);
int selfref;
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;
hashitem_T *hi;
dictitem_T *di;
/* Careful: we free the dictitems while they still appear in the
* hashtab. Must not try to resize the hashtab! */
/* Avoid that recursive reference to the dict frees us again. */
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;
for (hi = d->dv_hashtab.ht_array; todo > 0; ++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;
}
}
...
...
@@ -7663,7 +7878,6 @@ f_deepcopy(argvars, rettv)
typval_T *argvars;
typval_T *rettv;
{
static int copyID = 0;
int noref = 0;
if (argvars[1].v_type != VAR_UNKNOWN)
...
...
@@ -7671,7 +7885,7 @@ f_deepcopy(argvars, rettv)
if (noref < 0 || noref > 1)
EMSG(_(e_invarg));
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;
list_extend(l1, l2, item);
++l1->lv_refcount;
copy_tv(&argvars[0], rettv);
}
}
...
...
@@ -8106,7 +8319,6 @@ f_extend(argvars, rettv)
}
}
++d1->dv_refcount;
copy_tv(&argvars[0], rettv);
}
}
...
...
@@ -10421,7 +10633,6 @@ f_insert(argvars, rettv)
if (l != NULL)
{
list_insert_tv(l, &argvars[1], item);
++l->lv_refcount;
copy_tv(&argvars[0], rettv);
}
}
...
...
@@ -14934,6 +15145,7 @@ handle_subscript(arg, rettv, evaluate, verbose)
dict_T *selfdict = NULL;
char_u *s;
int len;
typval_T functv;
while (ret == OK
&& (**arg == '['
...
...
@@ -14943,12 +15155,19 @@ handle_subscript(arg, rettv, evaluate, verbose)
{
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! */
s = functv.vval.v_string;
ret = get_func_tv(s, STRLEN(s), rettv, arg,
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
&len, evaluate, selfdict);
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
&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
* error, or when an interrupt occurred or an exception was thrown
...
...
This diff is collapsed.
Click to expand it.
src/ex_cmds.h
+
2
−
0
View file @
d9fba318
...
...
@@ -613,6 +613,8 @@ EX(CMD_promptrepl, "promptrepl", gui_mch_replace_dialog,
EXTRA
|
NOTRLCOM
|
CMDWIN
),
EX
(
CMD_profile
,
"profile"
,
ex_profile
,
BANG
|
EXTRA
|
TRLBAR
|
CMDWIN
),
EX
(
CMD_profdel
,
"profdel"
,
ex_breakdel
,
EXTRA
|
TRLBAR
|
CMDWIN
),
EX
(
CMD_psearch
,
"psearch"
,
ex_psearch
,
BANG
|
RANGE
|
WHOLEFOLD
|
DFLALL
|
EXTRA
),
EX
(
CMD_ptag
,
"ptag"
,
ex_ptag
,
...
...
This diff is collapsed.
Click to expand it.
src/ex_cmds2.c
+
31
−
15
View file @
d9fba318
...
...
@@ -591,7 +591,7 @@ ex_debuggreedy(eap)
}
/*
* ":breakdel".
* ":breakdel"
and ":profdel"
.
*/
void
ex_breakdel
(
eap
)
...
...
@@ -603,13 +603,20 @@ ex_breakdel(eap)
int
del_all
=
FALSE
;
int
i
;
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
))
{
/* ":breakdel {nr}" */
nr
=
atol
((
char
*
)
eap
->
arg
);
for
(
i
=
0
;
i
<
dbg_breakp
.
ga_len
;
++
i
)
if
(
BREAKP
(
i
).
dbg_nr
==
nr
)
for
(
i
=
0
;
i
<
gap
->
ga_len
;
++
i
)
if
(
DEBUGGY
(
gap
,
i
).
dbg_nr
==
nr
)
{
todel
=
i
;
break
;
...
...
@@ -623,12 +630,12 @@ ex_breakdel(eap)
else
{
/* ":breakdel {func|file} [lnum] {name}" */
if
(
dbg_parsearg
(
eap
->
arg
,
&
dbg_break
p
)
==
FAIL
)
if
(
dbg_parsearg
(
eap
->
arg
,
ga
p
)
==
FAIL
)
return
;
bp
=
&
BREAKP
(
dbg_breakp
.
ga_len
);
for
(
i
=
0
;
i
<
dbg_breakp
.
ga_len
;
++
i
)
bp
=
&
DEBUGGY
(
gap
,
gap
->
ga_len
);
for
(
i
=
0
;
i
<
gap
->
ga_len
;
++
i
)
{
bpi
=
&
BREAKP
(
i
);
bpi
=
&
DEBUGGY
(
gap
,
i
);
if
(
bp
->
dbg_type
==
bpi
->
dbg_type
&&
STRCMP
(
bp
->
dbg_name
,
bpi
->
dbg_name
)
==
0
&&
(
bp
->
dbg_lnum
==
bpi
->
dbg_lnum
...
...
@@ -646,18 +653,27 @@ ex_breakdel(eap)
if
(
todel
<
0
)
EMSG2
(
_
(
"E161: Breakpoint not found: %s"
),
eap
->
arg
);
else
while
(
dbg_breakp
.
ga_len
>
0
)
{
while
(
gap
->
ga_len
>
0
)
{
vim_free
(
BREAKP
(
todel
).
dbg_name
);
vim_free
(
BREAKP
(
todel
).
dbg_prog
);
--
dbg_breakp
.
ga_len
;
if
(
todel
<
dbg_breakp
.
ga_len
)
mch_memmove
(
&
BREAKP
(
todel
),
&
BREAKP
(
todel
+
1
),
(
dbg_breakp
.
ga_len
-
todel
)
*
sizeof
(
struct
debuggy
));
++
debug_tick
;
vim_free
(
DEBUGGY
(
gap
,
todel
).
dbg_name
);
vim_free
(
DEBUGGY
(
gap
,
todel
).
dbg_prog
);
--
gap
->
ga_len
;
if
(
todel
<
gap
->
ga_len
)
mch_memmove
(
&
DEBUGGY
(
gap
,
todel
),
&
DEBUGGY
(
gap
,
todel
+
1
),
(
gap
->
ga_len
-
todel
)
*
sizeof
(
struct
debuggy
));
#ifdef FEAT_PROFILE
if
(
eap
->
cmdidx
==
CMD_breakdel
)
#endif
++
debug_tick
;
if
(
!
del_all
)
break
;
}
/* If all breakpoints were removed clear the array. */
if
(
gap
->
ga_len
==
0
)
ga_clear
(
gap
);
}
}
/*
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment