mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
updated for version 7.0095
This commit is contained in:
parent
39a58ca3d4
commit
9a50b1bf21
@ -1,4 +1,4 @@
|
|||||||
*spell.txt* For Vim version 7.0aa. Last change: 2005 Jun 25
|
*spell.txt* For Vim version 7.0aa. Last change: 2005 Jun 27
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@ -266,7 +266,7 @@ find these functions useful:
|
|||||||
|
|
||||||
Vim uses a binary file format for spelling. This greatly speeds up loading
|
Vim uses a binary file format for spelling. This greatly speeds up loading
|
||||||
the word list and keeps it small.
|
the word list and keeps it small.
|
||||||
|
*.aff* *.dic* *Myspell*
|
||||||
You can create a Vim spell file from the .aff and .dic files that Myspell
|
You can create a Vim spell file from the .aff and .dic files that Myspell
|
||||||
uses. Myspell is used by OpenOffice.org and Mozilla. You should be able to
|
uses. Myspell is used by OpenOffice.org and Mozilla. You should be able to
|
||||||
find them here:
|
find them here:
|
||||||
@ -321,9 +321,14 @@ then Vim will try to guess.
|
|||||||
When the spell file was written all currently used
|
When the spell file was written all currently used
|
||||||
spell files will be reloaded.
|
spell files will be reloaded.
|
||||||
|
|
||||||
:mksp[ell] [-ascii] {add-name}
|
:mksp[ell] [-ascii] {name}.{enc}.add
|
||||||
Like ":mkspell" above, using {add-name} as the input
|
Like ":mkspell" above, using {name}.{enc}.add as the
|
||||||
file and producing an output file that has ".spl"
|
input file and producing an output file that has
|
||||||
|
".spl" appended.
|
||||||
|
|
||||||
|
:mksp[ell] [-ascii] {name}
|
||||||
|
Like ":mkspell" above, using {name} as the input file
|
||||||
|
and producing an output file that has ".{enc}.spl"
|
||||||
appended.
|
appended.
|
||||||
|
|
||||||
Since you might want to change a Myspell word list for use with Vim the
|
Since you might want to change a Myspell word list for use with Vim the
|
||||||
@ -557,14 +562,43 @@ contain the table with characters, so that it can be combine with spell files
|
|||||||
for any encoding. The .add.spl files also do not contain the table.
|
for any encoding. The .add.spl files also do not contain the table.
|
||||||
|
|
||||||
|
|
||||||
|
MID-WORD CHARACTERS
|
||||||
|
*spell-midword*
|
||||||
|
Some characters are only to be considered word characters if they are used in
|
||||||
|
between two ordinary word characters. An example is the single quote: It is
|
||||||
|
often used to put text in quotes, thus it can't be recognized as a word
|
||||||
|
character, but when it appears in between word characters it must be part of
|
||||||
|
the word. This is needed to detect a spelling error such as they'are. That
|
||||||
|
should be they're, but since "they" and "are" are words themselves that would
|
||||||
|
go unnoticed.
|
||||||
|
|
||||||
|
These characters are defined with MIDWORD in the .aff file:
|
||||||
|
|
||||||
|
MIDWORD '- ~
|
||||||
|
|
||||||
|
|
||||||
AFFIXES
|
AFFIXES
|
||||||
*spell-affix-PFX* *spell-affix-SFX*
|
*spell-affix-PFX* *spell-affix-SFX*
|
||||||
The usual PFX (prefix) and SFX (suffix) lines are supported (see the Myspell
|
The usual PFX (prefix) and SFX (suffix) lines are supported (see the Myspell
|
||||||
documentation). Note that Myspell ignores any extra text after the relevant
|
documentation or the Aspell manual:
|
||||||
info. Vim requires this text to start with a "#" so that mistakes don't go
|
http://aspell.net/man-html/Affix-Compression.html).
|
||||||
unnoticed. Example:
|
|
||||||
|
|
||||||
SFX F 0 in [^i]n # Spion > Spionin ~
|
Note that Myspell ignores any extra text after the relevant info. Vim
|
||||||
|
requires this text to start with a "#" so that mistakes don't go unnoticed.
|
||||||
|
Example:
|
||||||
|
|
||||||
|
SFX F 0 in [^i]n # Spion > Spionin ~
|
||||||
|
SFX F 0 nen in # Bauerin > Bauerinnen ~
|
||||||
|
|
||||||
|
An extra item for Vim is the "rare" flag. It must come after the other
|
||||||
|
fields, before a comment. When used then all words that use the affix will be
|
||||||
|
marked as rare words. Example:
|
||||||
|
|
||||||
|
PFX F 0 nene . rare ~
|
||||||
|
SFX F 0 oin n rare # hardly ever used ~
|
||||||
|
|
||||||
|
However, if the word also appears as a good word in another way it won't be
|
||||||
|
marked as rare.
|
||||||
|
|
||||||
*spell-affix-PFXPOSTPONE*
|
*spell-affix-PFXPOSTPONE*
|
||||||
When an affix file has very many prefixes that apply to many words it's not
|
When an affix file has very many prefixes that apply to many words it's not
|
||||||
@ -610,8 +644,12 @@ bad words. Example:
|
|||||||
BAD ! ~
|
BAD ! ~
|
||||||
|
|
||||||
This can be used to exclude words that would otherwise be good. For example
|
This can be used to exclude words that would otherwise be good. For example
|
||||||
"the the". Once a word has been marked as bad it won't be undone by
|
"the the" in the .dic file:
|
||||||
encountering the same word as good.
|
|
||||||
|
the the/! ~
|
||||||
|
|
||||||
|
Once a word has been marked as bad it won't be undone by encountering the same
|
||||||
|
word as good.
|
||||||
|
|
||||||
|
|
||||||
REPLACEMENTS *spell-affix-REP*
|
REPLACEMENTS *spell-affix-REP*
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
*todo.txt* For Vim version 7.0aa. Last change: 2005 Jun 26
|
*todo.txt* For Vim version 7.0aa. Last change: 2005 Jun 27
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@ -30,8 +30,7 @@ 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
|
send fixes for ccmalloc port to FreeBSD.
|
||||||
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
|
||||||
@ -101,8 +100,6 @@ PLANNED FOR VERSION 7.0:
|
|||||||
|
|
||||||
- Add SPELLCHECKER, with support for many languages.
|
- Add SPELLCHECKER, with support for many languages.
|
||||||
- Spell checking code todo's:
|
- Spell checking code todo's:
|
||||||
- Special handling of ' and -: define in the .aff file.
|
|
||||||
Aspell does this with "special".
|
|
||||||
- Support user function to make suggestions:
|
- Support user function to make suggestions:
|
||||||
:set spellsuggest=MySuggest,fast
|
:set spellsuggest=MySuggest,fast
|
||||||
Also support a list with common mistakes?
|
Also support a list with common mistakes?
|
||||||
|
412
src/eval.c
412
src/eval.c
@ -194,10 +194,14 @@ struct ufunc
|
|||||||
#define DEL_REFCOUNT 999999 /* list/dict is being deleted */
|
#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 hashtable.
|
||||||
*/
|
*/
|
||||||
static hashtab_T func_hashtab;
|
static hashtab_T func_hashtab;
|
||||||
|
|
||||||
|
/* list heads for garbage collection */
|
||||||
|
static dict_T *first_dict = NULL; /* list of all dicts */
|
||||||
|
static list_T *first_list = NULL; /* list of all lists */
|
||||||
|
|
||||||
/* From user function to hashitem and back. */
|
/* From user function to hashitem and back. */
|
||||||
static ufunc_T dumuf;
|
static ufunc_T dumuf;
|
||||||
#define UF2HIKEY(fp) ((fp)->uf_name)
|
#define UF2HIKEY(fp) ((fp)->uf_name)
|
||||||
@ -212,7 +216,9 @@ static ufunc_T dumuf;
|
|||||||
#define FIXVAR_CNT 12 /* number of fixed variables */
|
#define FIXVAR_CNT 12 /* number of fixed variables */
|
||||||
|
|
||||||
/* structure to hold info for a function that is currently being executed. */
|
/* structure to hold info for a function that is currently being executed. */
|
||||||
typedef struct funccall_S
|
typedef struct funccall_S funccall_T;
|
||||||
|
|
||||||
|
struct funccall_S
|
||||||
{
|
{
|
||||||
ufunc_T *func; /* function being called */
|
ufunc_T *func; /* function being called */
|
||||||
int linenr; /* next line to be executed */
|
int linenr; /* next line to be executed */
|
||||||
@ -235,7 +241,8 @@ typedef struct funccall_S
|
|||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
proftime_T prof_child; /* time spent in a child */
|
proftime_T prof_child; /* time spent in a child */
|
||||||
#endif
|
#endif
|
||||||
} funccall_T;
|
funccall_T *caller; /* calling function or NULL */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Info used by a ":for" loop.
|
* Info used by a ":for" loop.
|
||||||
@ -382,10 +389,9 @@ 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 void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID));
|
||||||
static int count_ref_in_dict __ARGS((dict_T *d, void *rp, int copyID, garray_T *gap));
|
static void set_ref_in_list __ARGS((list_T *l, int copyID));
|
||||||
static int count_ref_in_list __ARGS((list_T *l, void *rp, int copyID, garray_T *gap));
|
static void set_ref_in_item __ARGS((typval_T *tv, int copyID));
|
||||||
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));
|
||||||
@ -460,6 +466,7 @@ static void f_foldtext __ARGS((typval_T *argvars, typval_T *rettv));
|
|||||||
static void f_foldtextresult __ARGS((typval_T *argvars, typval_T *rettv));
|
static void f_foldtextresult __ARGS((typval_T *argvars, typval_T *rettv));
|
||||||
static void f_foreground __ARGS((typval_T *argvars, typval_T *rettv));
|
static void f_foreground __ARGS((typval_T *argvars, typval_T *rettv));
|
||||||
static void f_function __ARGS((typval_T *argvars, typval_T *rettv));
|
static void f_function __ARGS((typval_T *argvars, typval_T *rettv));
|
||||||
|
static void f_garbagecollect __ARGS((typval_T *argvars, typval_T *rettv));
|
||||||
static void f_get __ARGS((typval_T *argvars, typval_T *rettv));
|
static void f_get __ARGS((typval_T *argvars, typval_T *rettv));
|
||||||
static void f_getbufvar __ARGS((typval_T *argvars, typval_T *rettv));
|
static void f_getbufvar __ARGS((typval_T *argvars, typval_T *rettv));
|
||||||
static void f_getchar __ARGS((typval_T *argvars, typval_T *rettv));
|
static void f_getchar __ARGS((typval_T *argvars, typval_T *rettv));
|
||||||
@ -749,7 +756,12 @@ eval_clear()
|
|||||||
/* global variables */
|
/* global variables */
|
||||||
vars_clear(&globvarht);
|
vars_clear(&globvarht);
|
||||||
|
|
||||||
|
/* functions */
|
||||||
free_all_functions();
|
free_all_functions();
|
||||||
|
hash_clear(&func_hashtab);
|
||||||
|
|
||||||
|
/* unreferenced lists and dicts */
|
||||||
|
(void)garbage_collect();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -4945,7 +4957,19 @@ failret:
|
|||||||
static list_T *
|
static list_T *
|
||||||
list_alloc()
|
list_alloc()
|
||||||
{
|
{
|
||||||
return (list_T *)alloc_clear(sizeof(list_T));
|
list_T *l;
|
||||||
|
|
||||||
|
l = (list_T *)alloc_clear(sizeof(list_T));
|
||||||
|
if (l != NULL)
|
||||||
|
{
|
||||||
|
/* Prepend the list to the list of lists for garbage collection. */
|
||||||
|
if (first_list != NULL)
|
||||||
|
first_list->lv_used_prev = l;
|
||||||
|
l->lv_used_prev = NULL;
|
||||||
|
l->lv_used_next = first_list;
|
||||||
|
first_list = l;
|
||||||
|
}
|
||||||
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4956,23 +4980,8 @@ list_alloc()
|
|||||||
list_unref(l)
|
list_unref(l)
|
||||||
list_T *l;
|
list_T *l;
|
||||||
{
|
{
|
||||||
int selfref;
|
if (l != NULL && l->lv_refcount != DEL_REFCOUNT && --l->lv_refcount <= 0)
|
||||||
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4988,6 +4997,14 @@ list_free(l)
|
|||||||
/* Avoid that recursive reference to the list frees us again. */
|
/* Avoid that recursive reference to the list frees us again. */
|
||||||
l->lv_refcount = DEL_REFCOUNT;
|
l->lv_refcount = DEL_REFCOUNT;
|
||||||
|
|
||||||
|
/* Remove the list from the list of lists for garbage collection. */
|
||||||
|
if (l->lv_used_prev == NULL)
|
||||||
|
first_list = l->lv_used_next;
|
||||||
|
else
|
||||||
|
l->lv_used_prev->lv_used_next = l->lv_used_next;
|
||||||
|
if (l->lv_used_next != NULL)
|
||||||
|
l->lv_used_next->lv_used_prev = l->lv_used_prev;
|
||||||
|
|
||||||
for (item = l->lv_first; item != NULL; item = l->lv_first)
|
for (item = l->lv_first; item != NULL; item = l->lv_first)
|
||||||
{
|
{
|
||||||
/* Remove the item before deleting it. */
|
/* Remove the item before deleting it. */
|
||||||
@ -5568,157 +5585,168 @@ list_join(gap, l, sep, echo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Count the number of references for list/dict "p" inside itself.
|
* Garbage collection for lists and dictionaries.
|
||||||
* 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
|
* We use reference counts to be able to free most items right away when they
|
||||||
* used elsewhere, but we can only know by counting their references...
|
* are no longer used. But for composite items it's possible that it becomes
|
||||||
* This is a bit slow, but required to avoid leaking memory.
|
* unused while the reference count is > 0: When there is a recursive
|
||||||
|
* reference. Example:
|
||||||
|
* :let l = [1, 2, 3]
|
||||||
|
* :let d = {9: l}
|
||||||
|
* :let l[1] = d
|
||||||
|
*
|
||||||
|
* Since this is quite unusual we handle this with garbage collection: every
|
||||||
|
* once in a while find out which lists and dicts are not referenced from any
|
||||||
|
* variable.
|
||||||
|
*
|
||||||
|
* Here is a good reference text about garbage collection (refers to Python
|
||||||
|
* but it applies to all reference-counting mechanisms):
|
||||||
|
* http://python.ca/nas/python/gc/
|
||||||
*/
|
*/
|
||||||
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.
|
* Do garbage collection for lists and dicts.
|
||||||
* We use "copyID" to avoid recursing into the same list/dict twice.
|
* Return TRUE if some memory was freed.
|
||||||
*/
|
*/
|
||||||
static int
|
int
|
||||||
count_ref_in_dict(d, rp, copyID, gap)
|
garbage_collect()
|
||||||
dict_T *d;
|
{
|
||||||
void *rp;
|
dict_T *dd;
|
||||||
int copyID;
|
list_T *ll;
|
||||||
garray_T *gap;
|
int copyID = ++current_copyID;
|
||||||
{
|
buf_T *buf;
|
||||||
int todo;
|
win_T *wp;
|
||||||
hashitem_T *hi;
|
int i;
|
||||||
int n = 0;
|
funccall_T *fc;
|
||||||
|
int did_free = FALSE;
|
||||||
todo = d->dv_hashtab.ht_used;
|
|
||||||
for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
|
/*
|
||||||
if (!HASHITEM_EMPTY(hi))
|
* 1. Go through all accessible variables and mark all lists and dicts
|
||||||
{
|
* with copyID.
|
||||||
--todo;
|
*/
|
||||||
n += count_ref_item(&HI2DI(hi)->di_tv, rp, copyID, gap);
|
/* script-local variables */
|
||||||
}
|
for (i = 1; i <= ga_scripts.ga_len; ++i)
|
||||||
return n;
|
set_ref_in_ht(&SCRIPT_VARS(i), copyID);
|
||||||
}
|
|
||||||
|
/* buffer-local variables */
|
||||||
/*
|
for (buf = firstbuf; buf != NULL; buf = buf->b_next)
|
||||||
* Count number of references to "rp" in list "l" and its members.
|
set_ref_in_ht(&buf->b_vars.dv_hashtab, copyID);
|
||||||
* We use "copyID" to avoid recursing into the same list/dict twice.
|
|
||||||
*/
|
/* window-local variables */
|
||||||
static int
|
FOR_ALL_WINDOWS(wp)
|
||||||
count_ref_in_list(l, rp, copyID, gap)
|
set_ref_in_ht(&wp->w_vars.dv_hashtab, copyID);
|
||||||
list_T *l;
|
|
||||||
void *rp;
|
/* global variables */
|
||||||
int copyID;
|
set_ref_in_ht(&globvarht, copyID);
|
||||||
garray_T *gap;
|
|
||||||
{
|
/* function-local variables */
|
||||||
listitem_T *li;
|
for (fc = current_funccal; fc != NULL; fc = fc->caller)
|
||||||
int n = 0;
|
{
|
||||||
|
set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID);
|
||||||
for (li = l->lv_first; li != NULL; li = li->li_next)
|
set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID);
|
||||||
n += count_ref_item(&li->li_tv, rp, copyID, gap);
|
}
|
||||||
return n;
|
|
||||||
}
|
/*
|
||||||
|
* 2. Go through the list of dicts and free items without the copyID.
|
||||||
/*
|
*/
|
||||||
* Count number of references to "rp" in item "tv" and any members.
|
for (dd = first_dict; dd != NULL; )
|
||||||
* We use "copyID" to avoid recursing into the same list/dict twice.
|
if (dd->dv_copyID != copyID)
|
||||||
* When "gap" is not NULL store items that require checking for only
|
{
|
||||||
* references inside the structure.
|
dict_free(dd);
|
||||||
*/
|
did_free = TRUE;
|
||||||
static int
|
|
||||||
count_ref_item(tv, rp, copyID, gap)
|
/* restart, next dict may also have been freed */
|
||||||
typval_T *tv;
|
dd = first_dict;
|
||||||
void *rp;
|
}
|
||||||
int copyID;
|
else
|
||||||
garray_T *gap;
|
dd = dd->dv_used_next;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 3. Go through the list of lists and free items without the copyID.
|
||||||
|
*/
|
||||||
|
for (ll = first_list; ll != NULL; )
|
||||||
|
if (ll->lv_copyID != copyID)
|
||||||
|
{
|
||||||
|
list_free(ll);
|
||||||
|
did_free = TRUE;
|
||||||
|
|
||||||
|
/* restart, next dict may also have been freed */
|
||||||
|
ll = first_list;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ll = ll->lv_used_next;
|
||||||
|
|
||||||
|
return did_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark all lists and dicts referenced through hashtab "ht" with "copyID".
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
set_ref_in_ht(ht, copyID)
|
||||||
|
hashtab_T *ht;
|
||||||
|
int copyID;
|
||||||
|
{
|
||||||
|
int todo;
|
||||||
|
hashitem_T *hi;
|
||||||
|
|
||||||
|
todo = ht->ht_used;
|
||||||
|
for (hi = ht->ht_array; todo > 0; ++hi)
|
||||||
|
if (!HASHITEM_EMPTY(hi))
|
||||||
|
{
|
||||||
|
--todo;
|
||||||
|
set_ref_in_item(&HI2DI(hi)->di_tv, copyID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark all lists and dicts referenced through list "l" with "copyID".
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
set_ref_in_list(l, copyID)
|
||||||
|
list_T *l;
|
||||||
|
int copyID;
|
||||||
|
{
|
||||||
|
listitem_T *li;
|
||||||
|
|
||||||
|
for (li = l->lv_first; li != NULL; li = li->li_next)
|
||||||
|
set_ref_in_item(&li->li_tv, copyID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark all lists and dicts referenced through typval "tv" with "copyID".
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
set_ref_in_item(tv, copyID)
|
||||||
|
typval_T *tv;
|
||||||
|
int copyID;
|
||||||
{
|
{
|
||||||
dict_T *dd;
|
dict_T *dd;
|
||||||
list_T *ll;
|
list_T *ll;
|
||||||
int n;
|
|
||||||
|
|
||||||
switch (tv->v_type)
|
switch (tv->v_type)
|
||||||
{
|
{
|
||||||
case VAR_DICT:
|
case VAR_DICT:
|
||||||
dd = tv->vval.v_dict;
|
dd = tv->vval.v_dict;
|
||||||
if (dd == rp)
|
if (dd->dv_copyID != copyID)
|
||||||
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
|
/* Didn't see this dict yet. */
|
||||||
* all in the structure we are freeing. */
|
dd->dv_copyID = copyID;
|
||||||
if (ga_grow(gap, 1) == FAIL)
|
set_ref_in_ht(&dd->dv_hashtab, copyID);
|
||||||
return 0;
|
|
||||||
((typval_T **)gap->ga_data)[gap->ga_len++] = tv;
|
|
||||||
}
|
}
|
||||||
return n;
|
break;
|
||||||
|
|
||||||
case VAR_LIST:
|
case VAR_LIST:
|
||||||
ll = tv->vval.v_list;
|
ll = tv->vval.v_list;
|
||||||
if (ll == rp)
|
if (ll->lv_copyID != copyID)
|
||||||
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
|
/* Didn't see this list yet. */
|
||||||
* all in the structure we are freeing. */
|
ll->lv_copyID = copyID;
|
||||||
if (ga_grow(gap, 1) == FAIL)
|
set_ref_in_list(ll, copyID);
|
||||||
return 0;
|
|
||||||
((typval_T **)gap->ga_data)[gap->ga_len++] = tv;
|
|
||||||
}
|
}
|
||||||
return n;
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -5732,6 +5760,12 @@ dict_alloc()
|
|||||||
d = (dict_T *)alloc(sizeof(dict_T));
|
d = (dict_T *)alloc(sizeof(dict_T));
|
||||||
if (d != NULL)
|
if (d != NULL)
|
||||||
{
|
{
|
||||||
|
/* Add the list to the hashtable for garbage collection. */
|
||||||
|
if (first_dict != NULL)
|
||||||
|
first_dict->dv_used_prev = d;
|
||||||
|
d->dv_used_next = first_dict;
|
||||||
|
d->dv_used_prev = NULL;
|
||||||
|
|
||||||
hash_init(&d->dv_hashtab);
|
hash_init(&d->dv_hashtab);
|
||||||
d->dv_lock = 0;
|
d->dv_lock = 0;
|
||||||
d->dv_refcount = 0;
|
d->dv_refcount = 0;
|
||||||
@ -5748,23 +5782,8 @@ dict_alloc()
|
|||||||
dict_unref(d)
|
dict_unref(d)
|
||||||
dict_T *d;
|
dict_T *d;
|
||||||
{
|
{
|
||||||
int selfref;
|
if (d != NULL && d->dv_refcount != DEL_REFCOUNT && --d->dv_refcount <= 0)
|
||||||
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -5782,8 +5801,15 @@ dict_free(d)
|
|||||||
/* Avoid that recursive reference to the dict frees us again. */
|
/* Avoid that recursive reference to the dict frees us again. */
|
||||||
d->dv_refcount = DEL_REFCOUNT;
|
d->dv_refcount = DEL_REFCOUNT;
|
||||||
|
|
||||||
/* Lock the hashtab, we don't want it to resize while looping through it.
|
/* Remove the dict from the list of dicts for garbage collection. */
|
||||||
* */
|
if (d->dv_used_prev == NULL)
|
||||||
|
first_dict = d->dv_used_next;
|
||||||
|
else
|
||||||
|
d->dv_used_prev->dv_used_next = d->dv_used_next;
|
||||||
|
if (d->dv_used_next != NULL)
|
||||||
|
d->dv_used_next->dv_used_prev = d->dv_used_prev;
|
||||||
|
|
||||||
|
/* Lock the hashtab, we don't want it to resize while freeing items. */
|
||||||
hash_lock(&d->dv_hashtab);
|
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)
|
||||||
@ -6505,6 +6531,7 @@ static struct fst
|
|||||||
{"foldtextresult", 1, 1, f_foldtextresult},
|
{"foldtextresult", 1, 1, f_foldtextresult},
|
||||||
{"foreground", 0, 0, f_foreground},
|
{"foreground", 0, 0, f_foreground},
|
||||||
{"function", 1, 1, f_function},
|
{"function", 1, 1, f_function},
|
||||||
|
{"garbagecollect", 0, 0, f_garbagecollect},
|
||||||
{"get", 2, 3, f_get},
|
{"get", 2, 3, f_get},
|
||||||
{"getbufvar", 2, 2, f_getbufvar},
|
{"getbufvar", 2, 2, f_getbufvar},
|
||||||
{"getchar", 0, 1, f_getchar},
|
{"getchar", 0, 1, f_getchar},
|
||||||
@ -8885,6 +8912,18 @@ f_function(argvars, rettv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "garbagecollect()" function
|
||||||
|
*/
|
||||||
|
/*ARGSUSED*/
|
||||||
|
static void
|
||||||
|
f_garbagecollect(argvars, rettv)
|
||||||
|
typval_T *argvars;
|
||||||
|
typval_T *rettv;
|
||||||
|
{
|
||||||
|
garbage_collect();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "get()" function
|
* "get()" function
|
||||||
*/
|
*/
|
||||||
@ -15506,8 +15545,10 @@ find_var_in_ht(ht, varname, writing)
|
|||||||
case 'v': return &vimvars_var;
|
case 'v': return &vimvars_var;
|
||||||
case 'b': return &curbuf->b_bufvar;
|
case 'b': return &curbuf->b_bufvar;
|
||||||
case 'w': return &curwin->w_winvar;
|
case 'w': return &curwin->w_winvar;
|
||||||
case 'l': return ¤t_funccal->l_vars_var;
|
case 'l': return current_funccal == NULL
|
||||||
case 'a': return ¤t_funccal->l_avars_var;
|
? NULL : ¤t_funccal->l_vars_var;
|
||||||
|
case 'a': return current_funccal == NULL
|
||||||
|
? NULL : ¤t_funccal->l_avars_var;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -15689,6 +15730,7 @@ vars_clear_ext(ht, free_val)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
hash_clear(ht);
|
hash_clear(ht);
|
||||||
|
ht->ht_used = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -15789,7 +15831,7 @@ set_var(name, tv, copy)
|
|||||||
}
|
}
|
||||||
if (function_exists(name))
|
if (function_exists(name))
|
||||||
{
|
{
|
||||||
EMSG2(_("705: Variable name conflicts with existing function: %s"),
|
EMSG2(_("E705: Variable name conflicts with existing function: %s"),
|
||||||
name);
|
name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -17569,7 +17611,6 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
|
|||||||
linenr_T save_sourcing_lnum;
|
linenr_T save_sourcing_lnum;
|
||||||
scid_T save_current_SID;
|
scid_T save_current_SID;
|
||||||
funccall_T fc;
|
funccall_T fc;
|
||||||
funccall_T *save_fcp = current_funccal;
|
|
||||||
int save_did_emsg;
|
int save_did_emsg;
|
||||||
static int depth = 0;
|
static int depth = 0;
|
||||||
dictitem_T *v;
|
dictitem_T *v;
|
||||||
@ -17594,6 +17635,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
|
|||||||
|
|
||||||
line_breakcheck(); /* check for CTRL-C hit */
|
line_breakcheck(); /* check for CTRL-C hit */
|
||||||
|
|
||||||
|
fc.caller = current_funccal;
|
||||||
current_funccal = &fc;
|
current_funccal = &fc;
|
||||||
fc.func = fp;
|
fc.func = fp;
|
||||||
fc.rettv = rettv;
|
fc.rettv = rettv;
|
||||||
@ -17752,7 +17794,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
|
|||||||
if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL))
|
if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL))
|
||||||
func_do_profile(fp);
|
func_do_profile(fp);
|
||||||
if (fp->uf_profiling
|
if (fp->uf_profiling
|
||||||
|| (save_fcp != NULL && &save_fcp->func->uf_profiling))
|
|| (fc.caller != NULL && &fc.caller->func->uf_profiling))
|
||||||
{
|
{
|
||||||
++fp->uf_tm_count;
|
++fp->uf_tm_count;
|
||||||
profile_start(&fp->uf_tm_start);
|
profile_start(&fp->uf_tm_start);
|
||||||
@ -17782,17 +17824,17 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
if (fp->uf_profiling || (save_fcp != NULL && &save_fcp->func->uf_profiling))
|
if (fp->uf_profiling || (fc.caller != NULL && &fc.caller->func->uf_profiling))
|
||||||
{
|
{
|
||||||
profile_end(&fp->uf_tm_start);
|
profile_end(&fp->uf_tm_start);
|
||||||
profile_sub_wait(&wait_start, &fp->uf_tm_start);
|
profile_sub_wait(&wait_start, &fp->uf_tm_start);
|
||||||
profile_add(&fp->uf_tm_total, &fp->uf_tm_start);
|
profile_add(&fp->uf_tm_total, &fp->uf_tm_start);
|
||||||
profile_add(&fp->uf_tm_self, &fp->uf_tm_start);
|
profile_add(&fp->uf_tm_self, &fp->uf_tm_start);
|
||||||
profile_sub(&fp->uf_tm_self, &fp->uf_tm_children);
|
profile_sub(&fp->uf_tm_self, &fp->uf_tm_children);
|
||||||
if (save_fcp != NULL && &save_fcp->func->uf_profiling)
|
if (fc.caller != NULL && &fc.caller->func->uf_profiling)
|
||||||
{
|
{
|
||||||
profile_add(&save_fcp->func->uf_tm_children, &fp->uf_tm_start);
|
profile_add(&fc.caller->func->uf_tm_children, &fp->uf_tm_start);
|
||||||
profile_add(&save_fcp->func->uf_tml_children, &fp->uf_tm_start);
|
profile_add(&fc.caller->func->uf_tml_children, &fp->uf_tm_start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -17850,7 +17892,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
|
|||||||
}
|
}
|
||||||
|
|
||||||
did_emsg |= save_did_emsg;
|
did_emsg |= save_did_emsg;
|
||||||
current_funccal = save_fcp;
|
current_funccal = fc.caller;
|
||||||
|
|
||||||
/* The a: variables typevals were not alloced, only free the allocated
|
/* The a: variables typevals were not alloced, only free the allocated
|
||||||
* variables. */
|
* variables. */
|
||||||
|
@ -3199,6 +3199,9 @@ do_ecmd(fnum, ffname, sfname, eap, newlnum, flags)
|
|||||||
#ifdef FEAT_DIFF
|
#ifdef FEAT_DIFF
|
||||||
curwin->w_p_diff = FALSE; /* No 'diff' */
|
curwin->w_p_diff = FALSE; /* No 'diff' */
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef FEAT_SYN_HL
|
||||||
|
curwin->w_p_spell = FALSE; /* No spell checking */
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef FEAT_AUTOCMD
|
#ifdef FEAT_AUTOCMD
|
||||||
buf = curbuf;
|
buf = curbuf;
|
||||||
|
@ -250,7 +250,7 @@ hash_set(hi, key)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove item "hi" from hashtable "ht". "hi" must have been obtained with
|
* Remove item "hi" from hashtable "ht". "hi" must have been obtained with
|
||||||
* hash_lookup() and point to an empty item.
|
* hash_lookup().
|
||||||
* The caller must take care of freeing the item itself.
|
* The caller must take care of freeing the item itself.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
|
@ -148,7 +148,7 @@ mch_inchar(buf, maxlen, time, tb_change_cnt)
|
|||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
updatescript(0);
|
before_blocking();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3894
src/po/pl.po
3894
src/po/pl.po
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,7 @@ void hash_debug_results __ARGS((void));
|
|||||||
int hash_add __ARGS((hashtab_T *ht, char_u *key));
|
int hash_add __ARGS((hashtab_T *ht, char_u *key));
|
||||||
int hash_add_item __ARGS((hashtab_T *ht, hashitem_T *hi, char_u *key, hash_T hash));
|
int hash_add_item __ARGS((hashtab_T *ht, hashitem_T *hi, char_u *key, hash_T hash));
|
||||||
void hash_remove __ARGS((hashtab_T *ht, hashitem_T *hi));
|
void hash_remove __ARGS((hashtab_T *ht, hashitem_T *hi));
|
||||||
|
int hash_delete __ARGS((hashtab_T *ht, char_u *key));
|
||||||
void hash_lock __ARGS((hashtab_T *ht));
|
void hash_lock __ARGS((hashtab_T *ht));
|
||||||
void hash_unlock __ARGS((hashtab_T *ht));
|
void hash_unlock __ARGS((hashtab_T *ht));
|
||||||
hash_T hash_hash __ARGS((char_u *key));
|
hash_T hash_hash __ARGS((char_u *key));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user