0
0
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:
Bram Moolenaar 2005-06-27 22:48:21 +00:00
parent 39a58ca3d4
commit 9a50b1bf21
8 changed files with 2634 additions and 1747 deletions

View File

@ -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*

View File

@ -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?

View File

@ -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 &current_funccal->l_vars_var; case 'l': return current_funccal == NULL
case 'a': return &current_funccal->l_avars_var; ? NULL : &current_funccal->l_vars_var;
case 'a': return current_funccal == NULL
? NULL : &current_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. */

View File

@ -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;

View File

@ -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

View File

@ -148,7 +148,7 @@ mch_inchar(buf, maxlen, time, tb_change_cnt)
return 3; return 3;
} }
#endif #endif
updatescript(0); before_blocking();
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -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));