mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
updated for version 7.0051
This commit is contained in:
540
src/eval.c
540
src/eval.c
@@ -148,17 +148,17 @@ typedef struct ufunc ufunc_T;
|
||||
|
||||
struct ufunc
|
||||
{
|
||||
ufunc_T *next; /* next function in list */
|
||||
char_u *name; /* name of function; can start with <SNR>123_
|
||||
(<SNR> is K_SPECIAL KS_EXTRA KE_SNR) */
|
||||
int varargs; /* variable nr of arguments */
|
||||
int flags;
|
||||
int calls; /* nr of active calls */
|
||||
garray_T args; /* arguments */
|
||||
garray_T lines; /* function lines */
|
||||
scid_T script_ID; /* ID of script where function was defined,
|
||||
int uf_varargs; /* variable nr of arguments */
|
||||
int uf_flags;
|
||||
int uf_calls; /* nr of active calls */
|
||||
garray_T uf_args; /* arguments */
|
||||
garray_T uf_lines; /* function lines */
|
||||
scid_T uf_script_ID; /* ID of script where function was defined,
|
||||
used for s: variables */
|
||||
int refcount; /* for numbered function: reference count */
|
||||
int uf_refcount; /* for numbered function: reference count */
|
||||
char_u uf_name[1]; /* name of function (actually longer); can
|
||||
start with <SNR>123_ (<SNR> is K_SPECIAL
|
||||
KS_EXTRA KE_SNR) */
|
||||
};
|
||||
|
||||
/* function flags */
|
||||
@@ -167,13 +167,18 @@ struct ufunc
|
||||
#define FC_DICT 4 /* Dict function, uses "self" */
|
||||
|
||||
/*
|
||||
* All user-defined functions are found in the forward-linked function list.
|
||||
* The first function is pointed at by firstfunc.
|
||||
* All user-defined functions are found in this hash table.
|
||||
*/
|
||||
ufunc_T *firstfunc = NULL;
|
||||
hashtab_T func_hashtab;
|
||||
|
||||
#define FUNCARG(fp, j) ((char_u **)(fp->args.ga_data))[j]
|
||||
#define FUNCLINE(fp, j) ((char_u **)(fp->lines.ga_data))[j]
|
||||
/* From user function to hashitem and back. */
|
||||
static ufunc_T dumuf;
|
||||
#define UF2HIKEY(fp) ((fp)->uf_name)
|
||||
#define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf)))
|
||||
#define HI2UF(hi) HIKEY2UF((hi)->hi_key)
|
||||
|
||||
#define FUNCARG(fp, j) ((char_u **)(fp->uf_args.ga_data))[j]
|
||||
#define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j]
|
||||
|
||||
#define MAX_FUNC_ARGS 20 /* maximum number of function arguments */
|
||||
#define VAR_SHORT_LEN 20 /* short variable name length */
|
||||
@@ -475,6 +480,9 @@ static void f_matchlist __ARGS((typval_T *argvars, typval_T *rettv));
|
||||
static void f_matchstr __ARGS((typval_T *argvars, typval_T *rettv));
|
||||
static void f_max __ARGS((typval_T *argvars, typval_T *rettv));
|
||||
static void f_min __ARGS((typval_T *argvars, typval_T *rettv));
|
||||
#ifdef vim_mkdir
|
||||
static void f_mkdir __ARGS((typval_T *argvars, typval_T *rettv));
|
||||
#endif
|
||||
static void f_mode __ARGS((typval_T *argvars, typval_T *rettv));
|
||||
static void f_nextnonblank __ARGS((typval_T *argvars, typval_T *rettv));
|
||||
static void f_nr2char __ARGS((typval_T *argvars, typval_T *rettv));
|
||||
@@ -554,7 +562,7 @@ static linenr_T get_tv_lnum __ARGS((typval_T *argvars));
|
||||
static char_u *get_tv_string __ARGS((typval_T *varp));
|
||||
static char_u *get_tv_string_buf __ARGS((typval_T *varp, char_u *buf));
|
||||
static dictitem_T *find_var __ARGS((char_u *name, hashtab_T **htp));
|
||||
static dictitem_T *find_var_in_ht __ARGS((hashtab_T *ht, char_u *varname));
|
||||
static dictitem_T *find_var_in_ht __ARGS((hashtab_T *ht, char_u *varname, int writing));
|
||||
static hashtab_T *find_var_ht __ARGS((char_u *name, char_u **varname));
|
||||
static void vars_clear_ext __ARGS((hashtab_T *ht, int free_val));
|
||||
static void delete_var __ARGS((hashtab_T *ht, hashitem_T *hi));
|
||||
@@ -574,7 +582,8 @@ static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp));
|
||||
static ufunc_T *find_func __ARGS((char_u *name));
|
||||
static int function_exists __ARGS((char_u *name));
|
||||
static int builtin_function __ARGS((char_u *name));
|
||||
static int func_autoload __ARGS((char_u *name));
|
||||
static int script_autoload __ARGS((char_u *name));
|
||||
static char_u *autoload_name __ARGS((char_u *name));
|
||||
static void func_free __ARGS((ufunc_T *fp));
|
||||
static void func_unref __ARGS((char_u *name));
|
||||
static void func_ref __ARGS((char_u *name));
|
||||
@@ -605,6 +614,7 @@ static void ex_unletlock __ARGS((exarg_T *eap, char_u *argstart, int deep));
|
||||
static int do_unlet_var __ARGS((lval_T *lp, char_u *name_end, int forceit));
|
||||
static int do_lock_var __ARGS((lval_T *lp, char_u *name_end, int deep, int lock));
|
||||
static void item_lock __ARGS((typval_T *tv, int deep, int lock));
|
||||
static int tv_islocked __ARGS((typval_T *tv));
|
||||
|
||||
/*
|
||||
* Initialize the global and v: variables.
|
||||
@@ -618,6 +628,7 @@ eval_init()
|
||||
init_var_dict(&globvardict, &globvars_var);
|
||||
init_var_dict(&vimvardict, &vimvars_var);
|
||||
hash_init(&compat_hashtab);
|
||||
hash_init(&func_hashtab);
|
||||
|
||||
for (i = 0; i < VV_LEN; ++i)
|
||||
{
|
||||
@@ -646,7 +657,7 @@ eval_init()
|
||||
func_name(cookie)
|
||||
void *cookie;
|
||||
{
|
||||
return ((funccall_T *)cookie)->func->name;
|
||||
return ((funccall_T *)cookie)->func->uf_name;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -716,6 +727,136 @@ set_internal_string_var(name, value)
|
||||
}
|
||||
}
|
||||
|
||||
static lval_T *redir_lval = NULL;
|
||||
static char_u *redir_endp = NULL;
|
||||
static char_u *redir_varname = NULL;
|
||||
|
||||
/*
|
||||
* Start recording command output to a variable
|
||||
* Returns OK if successfully completed the setup. FAIL otherwise.
|
||||
*/
|
||||
int
|
||||
var_redir_start(name, append)
|
||||
char_u *name;
|
||||
int append; /* append to an existing variable */
|
||||
{
|
||||
int save_emsg;
|
||||
int err;
|
||||
typval_T tv;
|
||||
|
||||
/* Make sure a valid variable name is specified */
|
||||
if (!eval_isnamec(*name) || VIM_ISDIGIT(*name))
|
||||
{
|
||||
EMSG(_(e_invarg));
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
redir_varname = vim_strsave(name);
|
||||
if (redir_varname == NULL)
|
||||
return FAIL;
|
||||
|
||||
redir_lval = (lval_T *)alloc_clear((unsigned)sizeof(lval_T));
|
||||
if (redir_lval == NULL)
|
||||
{
|
||||
var_redir_stop();
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
/* Parse the variable name (can be a dict or list entry). */
|
||||
redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, FALSE);
|
||||
if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != NUL)
|
||||
{
|
||||
if (redir_endp != NULL && *redir_endp != NUL)
|
||||
/* Trailing characters are present after the variable name */
|
||||
EMSG(_(e_trailing));
|
||||
else
|
||||
EMSG(_(e_invarg));
|
||||
var_redir_stop();
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
/* check if we can write to the variable: set it to or append an empty
|
||||
* string */
|
||||
save_emsg = did_emsg;
|
||||
did_emsg = FALSE;
|
||||
tv.v_type = VAR_STRING;
|
||||
tv.vval.v_string = (char_u *)"";
|
||||
if (append)
|
||||
set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)".");
|
||||
else
|
||||
set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)"=");
|
||||
err = did_emsg;
|
||||
did_emsg += save_emsg;
|
||||
if (err)
|
||||
{
|
||||
var_redir_stop();
|
||||
return FAIL;
|
||||
}
|
||||
if (redir_lval->ll_newkey != NULL)
|
||||
{
|
||||
/* Dictionary item was created, don't do it again. */
|
||||
vim_free(redir_lval->ll_newkey);
|
||||
redir_lval->ll_newkey = NULL;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append "value[len]" to the variable set by var_redir_start().
|
||||
*/
|
||||
void
|
||||
var_redir_str(value, len)
|
||||
char_u *value;
|
||||
int len;
|
||||
{
|
||||
char_u *val;
|
||||
typval_T tv;
|
||||
int save_emsg;
|
||||
int err;
|
||||
|
||||
if (redir_lval == NULL)
|
||||
return;
|
||||
|
||||
if (len == -1)
|
||||
/* Append the entire string */
|
||||
val = vim_strsave(value);
|
||||
else
|
||||
/* Append only the specified number of characters */
|
||||
val = vim_strnsave(value, len);
|
||||
if (val == NULL)
|
||||
return;
|
||||
|
||||
tv.v_type = VAR_STRING;
|
||||
tv.vval.v_string = val;
|
||||
|
||||
save_emsg = did_emsg;
|
||||
did_emsg = FALSE;
|
||||
set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)".");
|
||||
err = did_emsg;
|
||||
did_emsg += save_emsg;
|
||||
if (err)
|
||||
var_redir_stop();
|
||||
|
||||
vim_free(tv.vval.v_string);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop redirecting command output to a variable.
|
||||
*/
|
||||
void
|
||||
var_redir_stop()
|
||||
{
|
||||
if (redir_lval != NULL)
|
||||
{
|
||||
clear_lval(redir_lval);
|
||||
vim_free(redir_lval);
|
||||
redir_lval = NULL;
|
||||
}
|
||||
vim_free(redir_varname);
|
||||
redir_varname = NULL;
|
||||
}
|
||||
|
||||
# if defined(FEAT_MBYTE) || defined(PROTO)
|
||||
int
|
||||
eval_charconvert(enc_from, enc_to, fname_from, fname_to)
|
||||
@@ -5866,12 +6007,15 @@ static struct fst
|
||||
{"matchstr", 2, 4, f_matchstr},
|
||||
{"max", 1, 1, f_max},
|
||||
{"min", 1, 1, f_min},
|
||||
#ifdef vim_mkdir
|
||||
{"mkdir", 1, 3, f_mkdir},
|
||||
#endif
|
||||
{"mode", 0, 0, f_mode},
|
||||
{"nextnonblank", 1, 1, f_nextnonblank},
|
||||
{"nr2char", 1, 1, f_nr2char},
|
||||
{"prevnonblank", 1, 1, f_prevnonblank},
|
||||
{"range", 1, 3, f_range},
|
||||
{"readfile", 1, 2, f_readfile},
|
||||
{"readfile", 1, 3, f_readfile},
|
||||
{"remote_expr", 2, 3, f_remote_expr},
|
||||
{"remote_foreground", 1, 1, f_remote_foreground},
|
||||
{"remote_peek", 1, 2, f_remote_peek},
|
||||
@@ -6218,7 +6362,7 @@ call_func(name, len, rettv, argcount, argvars, firstline, lastline,
|
||||
}
|
||||
#endif
|
||||
/* Try loading a package. */
|
||||
if (fp == NULL && func_autoload(fname) && !aborting())
|
||||
if (fp == NULL && script_autoload(fname) && !aborting())
|
||||
{
|
||||
/* loaded a package, search for the function again */
|
||||
fp = find_func(fname);
|
||||
@@ -6226,13 +6370,13 @@ call_func(name, len, rettv, argcount, argvars, firstline, lastline,
|
||||
|
||||
if (fp != NULL)
|
||||
{
|
||||
if (fp->flags & FC_RANGE)
|
||||
if (fp->uf_flags & FC_RANGE)
|
||||
*doesrange = TRUE;
|
||||
if (argcount < fp->args.ga_len)
|
||||
if (argcount < fp->uf_args.ga_len)
|
||||
error = ERROR_TOOFEW;
|
||||
else if (!fp->varargs && argcount > fp->args.ga_len)
|
||||
else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len)
|
||||
error = ERROR_TOOMANY;
|
||||
else if ((fp->flags & FC_DICT) && selfdict == NULL)
|
||||
else if ((fp->uf_flags & FC_DICT) && selfdict == NULL)
|
||||
error = ERROR_DICT;
|
||||
else
|
||||
{
|
||||
@@ -6243,12 +6387,12 @@ call_func(name, len, rettv, argcount, argvars, firstline, lastline,
|
||||
*/
|
||||
save_search_patterns();
|
||||
saveRedobuff();
|
||||
++fp->calls;
|
||||
++fp->uf_calls;
|
||||
call_user_func(fp, argcount, argvars, rettv,
|
||||
firstline, lastline,
|
||||
(fp->flags & FC_DICT) ? selfdict : NULL);
|
||||
if (--fp->calls <= 0 && isdigit(*fp->name)
|
||||
&& fp->refcount <= 0)
|
||||
(fp->uf_flags & FC_DICT) ? selfdict : NULL);
|
||||
if (--fp->uf_calls <= 0 && isdigit(*fp->uf_name)
|
||||
&& fp->uf_refcount <= 0)
|
||||
/* Function was unreferenced while being used, free it
|
||||
* now. */
|
||||
func_free(fp);
|
||||
@@ -8198,7 +8342,7 @@ f_getbufvar(argvars, rettv)
|
||||
else
|
||||
{
|
||||
/* look up the variable */
|
||||
v = find_var_in_ht(&buf->b_vars.dv_hashtab, varname);
|
||||
v = find_var_in_ht(&buf->b_vars.dv_hashtab, varname, FALSE);
|
||||
if (v != NULL)
|
||||
copy_tv(&v->di_tv, rettv);
|
||||
}
|
||||
@@ -8723,7 +8867,7 @@ f_getwinvar(argvars, rettv)
|
||||
else
|
||||
{
|
||||
/* look up the variable */
|
||||
v = find_var_in_ht(&win->w_vars.dv_hashtab, varname);
|
||||
v = find_var_in_ht(&win->w_vars.dv_hashtab, varname, FALSE);
|
||||
if (v != NULL)
|
||||
copy_tv(&v->di_tv, rettv);
|
||||
}
|
||||
@@ -8909,6 +9053,9 @@ f_has(argvars, rettv)
|
||||
#ifdef FEAT_SEARCHPATH
|
||||
"file_in_path",
|
||||
#endif
|
||||
#if defined(UNIX) && !defined(USE_SYSTEM)
|
||||
"filterpipe",
|
||||
#endif
|
||||
#ifdef FEAT_FIND_ID
|
||||
"find_in_path",
|
||||
#endif
|
||||
@@ -9772,8 +9919,6 @@ f_isdirectory(argvars, rettv)
|
||||
rettv->vval.v_number = mch_isdir(get_tv_string(&argvars[0]));
|
||||
}
|
||||
|
||||
static int tv_islocked __ARGS((typval_T *tv));
|
||||
|
||||
/*
|
||||
* Return TRUE if typeval "tv" is locked: Either tha value is locked itself or
|
||||
* it refers to a List or Dictionary that is locked.
|
||||
@@ -10569,6 +10714,68 @@ f_min(argvars, rettv)
|
||||
max_min(argvars, rettv, FALSE);
|
||||
}
|
||||
|
||||
static int mkdir_recurse __ARGS((char_u *dir, int prot));
|
||||
|
||||
/*
|
||||
* Create the directory in which "dir" is located, and higher levels when
|
||||
* needed.
|
||||
*/
|
||||
static int
|
||||
mkdir_recurse(dir, prot)
|
||||
char_u *dir;
|
||||
int prot;
|
||||
{
|
||||
char_u *p;
|
||||
char_u *updir;
|
||||
int r = FAIL;
|
||||
|
||||
/* Get end of directory name in "dir".
|
||||
* We're done when it's "/" or "c:/". */
|
||||
p = gettail_sep(dir);
|
||||
if (p <= get_past_head(dir))
|
||||
return OK;
|
||||
|
||||
/* If the directory exists we're done. Otherwise: create it.*/
|
||||
updir = vim_strnsave(dir, (int)(p - dir));
|
||||
if (updir == NULL)
|
||||
return FAIL;
|
||||
if (mch_isdir(updir))
|
||||
r = OK;
|
||||
else if (mkdir_recurse(updir, prot) == OK)
|
||||
r = vim_mkdir_emsg(updir, prot);
|
||||
vim_free(updir);
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef vim_mkdir
|
||||
/*
|
||||
* "mkdir()" function
|
||||
*/
|
||||
static void
|
||||
f_mkdir(argvars, rettv)
|
||||
typval_T *argvars;
|
||||
typval_T *rettv;
|
||||
{
|
||||
char_u *dir;
|
||||
char_u buf[NUMBUFLEN];
|
||||
int prot = 0755;
|
||||
|
||||
rettv->vval.v_number = FAIL;
|
||||
if (check_restricted() || check_secure())
|
||||
return;
|
||||
|
||||
dir = get_tv_string_buf(&argvars[0], buf);
|
||||
if (argvars[1].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
prot = get_tv_number(&argvars[2]);
|
||||
if (STRCMP(get_tv_string(&argvars[1]), "p") == 0)
|
||||
mkdir_recurse(dir, prot);
|
||||
}
|
||||
rettv->vval.v_number = vim_mkdir_emsg(dir, prot);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* "mode()" function
|
||||
*/
|
||||
@@ -10754,10 +10961,16 @@ f_readfile(argvars, rettv)
|
||||
int prevlen = 0; /* length of "prev" if not NULL */
|
||||
char_u *s;
|
||||
int len;
|
||||
long maxline = MAXLNUM;
|
||||
long cnt = 0;
|
||||
|
||||
if (argvars[1].v_type != VAR_UNKNOWN
|
||||
&& STRCMP(get_tv_string(&argvars[1]), "b") == 0)
|
||||
binary = TRUE;
|
||||
if (argvars[1].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
if (STRCMP(get_tv_string(&argvars[1]), "b") == 0)
|
||||
binary = TRUE;
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
maxline = get_tv_number(&argvars[2]);
|
||||
}
|
||||
|
||||
l = list_alloc();
|
||||
if (l == NULL)
|
||||
@@ -10776,7 +10989,7 @@ f_readfile(argvars, rettv)
|
||||
}
|
||||
|
||||
filtd = 0;
|
||||
for (;;)
|
||||
while (cnt < maxline)
|
||||
{
|
||||
readlen = fread(buf + filtd, 1, FREAD_SIZE - filtd, fd);
|
||||
buflen = filtd + readlen;
|
||||
@@ -10825,6 +11038,8 @@ f_readfile(argvars, rettv)
|
||||
li->li_tv.vval.v_string = s;
|
||||
list_append(l, li);
|
||||
|
||||
if (++cnt >= maxline)
|
||||
break;
|
||||
if (readlen <= 0)
|
||||
break;
|
||||
}
|
||||
@@ -10863,6 +11078,7 @@ f_readfile(argvars, rettv)
|
||||
}
|
||||
}
|
||||
|
||||
vim_free(prev);
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
@@ -14132,7 +14348,7 @@ find_var(name, htp)
|
||||
*htp = ht;
|
||||
if (ht == NULL)
|
||||
return NULL;
|
||||
return find_var_in_ht(ht, varname);
|
||||
return find_var_in_ht(ht, varname, htp != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -14140,9 +14356,10 @@ find_var(name, htp)
|
||||
* Returns NULL if not found.
|
||||
*/
|
||||
static dictitem_T *
|
||||
find_var_in_ht(ht, varname)
|
||||
find_var_in_ht(ht, varname, writing)
|
||||
hashtab_T *ht;
|
||||
char_u *varname;
|
||||
int writing;
|
||||
{
|
||||
hashitem_T *hi;
|
||||
|
||||
@@ -14164,7 +14381,15 @@ find_var_in_ht(ht, varname)
|
||||
|
||||
hi = hash_find(ht, varname);
|
||||
if (HASHITEM_EMPTY(hi))
|
||||
return NULL;
|
||||
{
|
||||
/* For global variables we may try auto-loading the script. If it
|
||||
* worked find the variable again. */
|
||||
if (ht == &globvarht && !writing
|
||||
&& script_autoload(varname) && !aborting())
|
||||
hi = hash_find(ht, varname);
|
||||
if (HASHITEM_EMPTY(hi))
|
||||
return NULL;
|
||||
}
|
||||
return HI2DI(hi);
|
||||
}
|
||||
|
||||
@@ -14179,8 +14404,8 @@ find_var_ht(name, varname)
|
||||
{
|
||||
if (name[1] != ':')
|
||||
{
|
||||
/* If not "x:name" there must not be any ":" in the name. */
|
||||
if (vim_strchr(name, ':') != NULL)
|
||||
/* The name must not start with a colon. */
|
||||
if (name[0] == ':')
|
||||
return NULL;
|
||||
*varname = name;
|
||||
|
||||
@@ -14193,12 +14418,15 @@ find_var_ht(name, varname)
|
||||
return ¤t_funccal->l_vars.dv_hashtab; /* l: variable */
|
||||
}
|
||||
*varname = name + 2;
|
||||
if (*name == 'g') /* global variable */
|
||||
return &globvarht;
|
||||
/* There must be no ':' in the rest of the name, unless g: is used */
|
||||
if (vim_strchr(name + 2, ':') != NULL)
|
||||
return NULL;
|
||||
if (*name == 'b') /* buffer variable */
|
||||
return &curbuf->b_vars.dv_hashtab;
|
||||
if (*name == 'w') /* window variable */
|
||||
return &curwin->w_vars.dv_hashtab;
|
||||
if (*name == 'g') /* global variable */
|
||||
return &globvarht;
|
||||
if (*name == 'v') /* v: variable */
|
||||
return &vimvarht;
|
||||
if (*name == 'a' && current_funccal != NULL) /* function argument */
|
||||
@@ -14435,7 +14663,7 @@ set_var(name, tv, copy)
|
||||
return;
|
||||
}
|
||||
|
||||
v = find_var_in_ht(ht, varname);
|
||||
v = find_var_in_ht(ht, varname, TRUE);
|
||||
if (v != NULL)
|
||||
{
|
||||
/* existing variable, need to clear the value */
|
||||
@@ -14932,6 +15160,9 @@ ex_function(eap)
|
||||
funcdict_T fudi;
|
||||
static int func_nr = 0; /* number for nameless function */
|
||||
int paren;
|
||||
hashtab_T *ht;
|
||||
int todo;
|
||||
hashitem_T *hi;
|
||||
|
||||
/*
|
||||
* ":function" without argument: list functions.
|
||||
@@ -14939,9 +15170,19 @@ ex_function(eap)
|
||||
if (ends_excmd(*eap->arg))
|
||||
{
|
||||
if (!eap->skip)
|
||||
for (fp = firstfunc; fp != NULL && !got_int; fp = fp->next)
|
||||
if (!isdigit(*fp->name))
|
||||
list_func_head(fp, FALSE);
|
||||
{
|
||||
todo = globvarht.ht_used;
|
||||
for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi)
|
||||
{
|
||||
if (!HASHITEM_EMPTY(hi))
|
||||
{
|
||||
--todo;
|
||||
fp = HI2UF(hi);
|
||||
if (!isdigit(*fp->uf_name))
|
||||
list_func_head(fp, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
eap->nextcmd = check_nextcmd(eap->arg);
|
||||
return;
|
||||
}
|
||||
@@ -15004,7 +15245,7 @@ ex_function(eap)
|
||||
if (fp != NULL)
|
||||
{
|
||||
list_func_head(fp, TRUE);
|
||||
for (j = 0; j < fp->lines.ga_len && !got_int; ++j)
|
||||
for (j = 0; j < fp->uf_lines.ga_len && !got_int; ++j)
|
||||
{
|
||||
msg_putchar('\n');
|
||||
msg_outnum((long)(j + 1));
|
||||
@@ -15012,7 +15253,7 @@ ex_function(eap)
|
||||
msg_putchar(' ');
|
||||
if (j < 99)
|
||||
msg_putchar(' ');
|
||||
msg_prt_line(FUNCLINE(fp, j));
|
||||
msg_prt_line(FUNCLINE(fp, j), FALSE);
|
||||
out_flush(); /* show a line at a time */
|
||||
ui_breakcheck();
|
||||
}
|
||||
@@ -15260,7 +15501,7 @@ ex_function(eap)
|
||||
*/
|
||||
if (fudi.fd_dict == NULL)
|
||||
{
|
||||
v = find_var(name, NULL);
|
||||
v = find_var(name, &ht);
|
||||
if (v != NULL && v->di_tv.v_type == VAR_FUNC)
|
||||
{
|
||||
emsg_funcname("E707: Function name conflicts with variable: %s",
|
||||
@@ -15276,15 +15517,15 @@ ex_function(eap)
|
||||
emsg_funcname(e_funcexts, name);
|
||||
goto erret;
|
||||
}
|
||||
if (fp->calls > 0)
|
||||
if (fp->uf_calls > 0)
|
||||
{
|
||||
emsg_funcname("E127: Cannot redefine function %s: It is in use",
|
||||
name);
|
||||
goto erret;
|
||||
}
|
||||
/* redefine existing function */
|
||||
ga_clear_strings(&(fp->args));
|
||||
ga_clear_strings(&(fp->lines));
|
||||
ga_clear_strings(&(fp->uf_args));
|
||||
ga_clear_strings(&(fp->uf_lines));
|
||||
vim_free(name);
|
||||
name = NULL;
|
||||
}
|
||||
@@ -15320,7 +15561,35 @@ ex_function(eap)
|
||||
|
||||
if (fp == NULL)
|
||||
{
|
||||
fp = (ufunc_T *)alloc((unsigned)sizeof(ufunc_T));
|
||||
if (fudi.fd_dict == NULL && vim_strchr(name, ':') != NULL)
|
||||
{
|
||||
int slen, plen;
|
||||
char_u *scriptname;
|
||||
|
||||
/* Check that the autoload name matches the script name. */
|
||||
j = FAIL;
|
||||
if (sourcing_name != NULL)
|
||||
{
|
||||
scriptname = autoload_name(name);
|
||||
if (scriptname != NULL)
|
||||
{
|
||||
p = vim_strchr(scriptname, '/');
|
||||
plen = STRLEN(p);
|
||||
slen = STRLEN(sourcing_name);
|
||||
if (slen > plen && fnamecmp(p,
|
||||
sourcing_name + slen - plen) == 0)
|
||||
j = OK;
|
||||
vim_free(scriptname);
|
||||
}
|
||||
}
|
||||
if (j == FAIL)
|
||||
{
|
||||
EMSG2(_("E746: Function name does not match script file name: %s"), name);
|
||||
goto erret;
|
||||
}
|
||||
}
|
||||
|
||||
fp = (ufunc_T *)alloc((unsigned)(sizeof(ufunc_T) + STRLEN(name)));
|
||||
if (fp == NULL)
|
||||
goto erret;
|
||||
|
||||
@@ -15347,21 +15616,19 @@ ex_function(eap)
|
||||
fudi.fd_di->di_tv.v_type = VAR_FUNC;
|
||||
fudi.fd_di->di_tv.v_lock = 0;
|
||||
fudi.fd_di->di_tv.vval.v_string = vim_strsave(name);
|
||||
fp->refcount = 1;
|
||||
fp->uf_refcount = 1;
|
||||
}
|
||||
|
||||
/* insert the new function in the function list */
|
||||
fp->name = name;
|
||||
name = NULL;
|
||||
fp->next = firstfunc;
|
||||
firstfunc = fp;
|
||||
STRCPY(fp->uf_name, name);
|
||||
hash_add(&func_hashtab, UF2HIKEY(fp));
|
||||
}
|
||||
fp->args = newargs;
|
||||
fp->lines = newlines;
|
||||
fp->varargs = varargs;
|
||||
fp->flags = flags;
|
||||
fp->calls = 0;
|
||||
fp->script_ID = current_SID;
|
||||
fp->uf_args = newargs;
|
||||
fp->uf_lines = newlines;
|
||||
fp->uf_varargs = varargs;
|
||||
fp->uf_flags = flags;
|
||||
fp->uf_calls = 0;
|
||||
fp->uf_script_ID = current_SID;
|
||||
goto ret_free;
|
||||
|
||||
erret:
|
||||
@@ -15573,21 +15840,21 @@ list_func_head(fp, indent)
|
||||
if (indent)
|
||||
MSG_PUTS(" ");
|
||||
MSG_PUTS("function ");
|
||||
if (fp->name[0] == K_SPECIAL)
|
||||
if (fp->uf_name[0] == K_SPECIAL)
|
||||
{
|
||||
MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8));
|
||||
msg_puts(fp->name + 3);
|
||||
msg_puts(fp->uf_name + 3);
|
||||
}
|
||||
else
|
||||
msg_puts(fp->name);
|
||||
msg_puts(fp->uf_name);
|
||||
msg_putchar('(');
|
||||
for (j = 0; j < fp->args.ga_len; ++j)
|
||||
for (j = 0; j < fp->uf_args.ga_len; ++j)
|
||||
{
|
||||
if (j)
|
||||
MSG_PUTS(", ");
|
||||
msg_puts(FUNCARG(fp, j));
|
||||
}
|
||||
if (fp->varargs)
|
||||
if (fp->uf_varargs)
|
||||
{
|
||||
if (j)
|
||||
MSG_PUTS(", ");
|
||||
@@ -15604,12 +15871,12 @@ list_func_head(fp, indent)
|
||||
find_func(name)
|
||||
char_u *name;
|
||||
{
|
||||
ufunc_T *fp;
|
||||
hashitem_T *hi;
|
||||
|
||||
for (fp = firstfunc; fp != NULL; fp = fp->next)
|
||||
if (STRCMP(name, fp->name) == 0)
|
||||
break;
|
||||
return fp;
|
||||
hi = hash_find(&func_hashtab, name);
|
||||
if (!HASHITEM_EMPTY(hi))
|
||||
return HI2UF(hi);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -15646,11 +15913,11 @@ builtin_function(name)
|
||||
}
|
||||
|
||||
/*
|
||||
* If "name" has a package name try autoloading the script.
|
||||
* If "name" has a package name try autoloading the script for it.
|
||||
* Return TRUE if a package was loaded.
|
||||
*/
|
||||
static int
|
||||
func_autoload(name)
|
||||
script_autoload(name)
|
||||
char_u *name;
|
||||
{
|
||||
char_u *p;
|
||||
@@ -15662,6 +15929,26 @@ func_autoload(name)
|
||||
if (p == NULL || p <= name + 2)
|
||||
return FALSE;
|
||||
|
||||
/* Try loading the package from $VIMRUNTIME/autoload/<name>.vim */
|
||||
scriptname = autoload_name(name);
|
||||
if (cmd_runtime(scriptname, FALSE) == OK)
|
||||
ret = TRUE;
|
||||
|
||||
vim_free(scriptname);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the autoload script name for a function or variable name.
|
||||
* Returns NULL when out of memory.
|
||||
*/
|
||||
static char_u *
|
||||
autoload_name(name)
|
||||
char_u *name;
|
||||
{
|
||||
char_u *p;
|
||||
char_u *scriptname;
|
||||
|
||||
/* Get the script file name: replace ':' with '/', append ".vim". */
|
||||
scriptname = alloc((unsigned)(STRLEN(name) + 14));
|
||||
if (scriptname == NULL)
|
||||
@@ -15672,13 +15959,7 @@ func_autoload(name)
|
||||
STRCAT(scriptname, ".vim");
|
||||
while ((p = vim_strchr(scriptname, ':')) != NULL)
|
||||
*p = '/';
|
||||
|
||||
/* Try loading the package from $VIMRUNTIME/autoload/<name>.vim */
|
||||
if (cmd_runtime(scriptname, FALSE) == OK)
|
||||
ret = TRUE;
|
||||
|
||||
vim_free(scriptname);
|
||||
return ret;
|
||||
return scriptname;
|
||||
}
|
||||
|
||||
#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
|
||||
@@ -15692,24 +15973,33 @@ get_user_func_name(xp, idx)
|
||||
expand_T *xp;
|
||||
int idx;
|
||||
{
|
||||
static ufunc_T *fp = NULL;
|
||||
static long_u done;
|
||||
static hashitem_T *hi;
|
||||
ufunc_T *fp;
|
||||
|
||||
if (idx == 0)
|
||||
fp = firstfunc;
|
||||
if (fp != NULL)
|
||||
{
|
||||
if (STRLEN(fp->name) + 4 >= IOSIZE)
|
||||
return fp->name; /* prevents overflow */
|
||||
done = 0;
|
||||
hi = func_hashtab.ht_array;
|
||||
}
|
||||
if (done < func_hashtab.ht_used)
|
||||
{
|
||||
if (done++ > 0)
|
||||
++hi;
|
||||
while (HASHITEM_EMPTY(hi))
|
||||
++hi;
|
||||
fp = HI2UF(hi);
|
||||
|
||||
if (STRLEN(fp->uf_name) + 4 >= IOSIZE)
|
||||
return fp->uf_name; /* prevents overflow */
|
||||
|
||||
cat_func_name(IObuff, fp);
|
||||
if (xp->xp_context != EXPAND_USER_FUNC)
|
||||
{
|
||||
STRCAT(IObuff, "(");
|
||||
if (!fp->varargs && fp->args.ga_len == 0)
|
||||
if (!fp->uf_varargs && fp->uf_args.ga_len == 0)
|
||||
STRCAT(IObuff, ")");
|
||||
}
|
||||
|
||||
fp = fp->next;
|
||||
return IObuff;
|
||||
}
|
||||
return NULL;
|
||||
@@ -15727,13 +16017,13 @@ cat_func_name(buf, fp)
|
||||
char_u *buf;
|
||||
ufunc_T *fp;
|
||||
{
|
||||
if (fp->name[0] == K_SPECIAL)
|
||||
if (fp->uf_name[0] == K_SPECIAL)
|
||||
{
|
||||
STRCPY(buf, "<SNR>");
|
||||
STRCAT(buf, fp->name + 3);
|
||||
STRCAT(buf, fp->uf_name + 3);
|
||||
}
|
||||
else
|
||||
STRCPY(buf, fp->name);
|
||||
STRCPY(buf, fp->uf_name);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -15778,7 +16068,7 @@ ex_delfunction(eap)
|
||||
EMSG2(_("E130: Undefined function: %s"), eap->arg);
|
||||
return;
|
||||
}
|
||||
if (fp->calls > 0)
|
||||
if (fp->uf_calls > 0)
|
||||
{
|
||||
EMSG2(_("E131: Cannot delete function %s: It is in use"), eap->arg);
|
||||
return;
|
||||
@@ -15802,25 +16092,19 @@ ex_delfunction(eap)
|
||||
func_free(fp)
|
||||
ufunc_T *fp;
|
||||
{
|
||||
ufunc_T *pfp;
|
||||
hashitem_T *hi;
|
||||
|
||||
/* clear this function */
|
||||
vim_free(fp->name);
|
||||
ga_clear_strings(&(fp->args));
|
||||
ga_clear_strings(&(fp->lines));
|
||||
ga_clear_strings(&(fp->uf_args));
|
||||
ga_clear_strings(&(fp->uf_lines));
|
||||
|
||||
/* remove the function from the function list */
|
||||
if (firstfunc == fp)
|
||||
firstfunc = fp->next;
|
||||
/* remove the function from the function hashtable */
|
||||
hi = hash_find(&func_hashtab, UF2HIKEY(fp));
|
||||
if (HASHITEM_EMPTY(hi))
|
||||
EMSG2(_(e_intern2), "func_free()");
|
||||
else
|
||||
{
|
||||
for (pfp = firstfunc; pfp != NULL; pfp = pfp->next)
|
||||
if (pfp->next == fp)
|
||||
{
|
||||
pfp->next = fp->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
hash_remove(&func_hashtab, hi);
|
||||
|
||||
vim_free(fp);
|
||||
}
|
||||
|
||||
@@ -15839,11 +16123,11 @@ func_unref(name)
|
||||
fp = find_func(name);
|
||||
if (fp == NULL)
|
||||
EMSG2(_(e_intern2), "func_unref()");
|
||||
else if (--fp->refcount <= 0)
|
||||
else if (--fp->uf_refcount <= 0)
|
||||
{
|
||||
/* Only delete it when it's not being used. Otherwise it's done
|
||||
* when "calls" becomes zero. */
|
||||
if (fp->calls == 0)
|
||||
* when "uf_calls" becomes zero. */
|
||||
if (fp->uf_calls == 0)
|
||||
func_free(fp);
|
||||
}
|
||||
}
|
||||
@@ -15864,7 +16148,7 @@ func_ref(name)
|
||||
if (fp == NULL)
|
||||
EMSG2(_(e_intern2), "func_ref()");
|
||||
else
|
||||
++fp->refcount;
|
||||
++fp->uf_refcount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15915,7 +16199,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
|
||||
fc.returned = FALSE;
|
||||
fc.level = ex_nesting_level;
|
||||
/* Check if this function has a breakpoint. */
|
||||
fc.breakpoint = dbg_find_breakpoint(FALSE, fp->name, (linenr_T)0);
|
||||
fc.breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0);
|
||||
fc.dbg_tick = debug_tick;
|
||||
|
||||
/*
|
||||
@@ -15947,7 +16231,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
|
||||
*/
|
||||
init_var_dict(&fc.l_avars, &fc.l_avars_var);
|
||||
add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "0",
|
||||
(varnumber_T)(argcount - fp->args.ga_len));
|
||||
(varnumber_T)(argcount - fp->uf_args.ga_len));
|
||||
v = &fc.fixvar[fixvar_idx++].var;
|
||||
STRCPY(v->di_key, "000");
|
||||
v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
|
||||
@@ -15969,7 +16253,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
|
||||
(varnumber_T)lastline);
|
||||
for (i = 0; i < argcount; ++i)
|
||||
{
|
||||
ai = i - fp->args.ga_len;
|
||||
ai = i - fp->uf_args.ga_len;
|
||||
if (ai < 0)
|
||||
/* named argument a:name */
|
||||
name = FUNCARG(fp, i);
|
||||
@@ -16014,7 +16298,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
|
||||
save_sourcing_lnum = sourcing_lnum;
|
||||
sourcing_lnum = 1;
|
||||
sourcing_name = alloc((unsigned)((save_sourcing_name == NULL ? 0
|
||||
: STRLEN(save_sourcing_name)) + STRLEN(fp->name) + 13));
|
||||
: STRLEN(save_sourcing_name)) + STRLEN(fp->uf_name) + 13));
|
||||
if (sourcing_name != NULL)
|
||||
{
|
||||
if (save_sourcing_name != NULL
|
||||
@@ -16058,7 +16342,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
|
||||
}
|
||||
}
|
||||
save_current_SID = current_SID;
|
||||
current_SID = fp->script_ID;
|
||||
current_SID = fp->uf_script_ID;
|
||||
save_did_emsg = did_emsg;
|
||||
did_emsg = FALSE;
|
||||
|
||||
@@ -16069,7 +16353,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
|
||||
--RedrawingDisabled;
|
||||
|
||||
/* when the function was aborted because of an error, return -1 */
|
||||
if ((did_emsg && (fp->flags & FC_ABORT)) || rettv->v_type == VAR_UNKNOWN)
|
||||
if ((did_emsg && (fp->uf_flags & FC_ABORT)) || rettv->v_type == VAR_UNKNOWN)
|
||||
{
|
||||
clear_tv(rettv);
|
||||
rettv->v_type = VAR_NUMBER;
|
||||
@@ -16346,13 +16630,13 @@ get_func_line(c, cookie, indent)
|
||||
/* If breakpoints have been added/deleted need to check for it. */
|
||||
if (fcp->dbg_tick != debug_tick)
|
||||
{
|
||||
fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->name,
|
||||
fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->uf_name,
|
||||
sourcing_lnum);
|
||||
fcp->dbg_tick = debug_tick;
|
||||
}
|
||||
|
||||
gap = &fcp->func->lines;
|
||||
if ((fcp->func->flags & FC_ABORT) && did_emsg && !aborted_in_try())
|
||||
gap = &fcp->func->uf_lines;
|
||||
if ((fcp->func->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
|
||||
retval = NULL;
|
||||
else if (fcp->returned || fcp->linenr >= gap->ga_len)
|
||||
retval = NULL;
|
||||
@@ -16365,9 +16649,9 @@ get_func_line(c, cookie, indent)
|
||||
/* Did we encounter a breakpoint? */
|
||||
if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum)
|
||||
{
|
||||
dbg_breakpoint(fcp->func->name, sourcing_lnum);
|
||||
dbg_breakpoint(fcp->func->uf_name, sourcing_lnum);
|
||||
/* Find next breakpoint. */
|
||||
fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->name,
|
||||
fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->uf_name,
|
||||
sourcing_lnum);
|
||||
fcp->dbg_tick = debug_tick;
|
||||
}
|
||||
@@ -16387,7 +16671,7 @@ func_has_ended(cookie)
|
||||
|
||||
/* Ignore the "abort" flag if the abortion behavior has been changed due to
|
||||
* an error inside a try conditional. */
|
||||
return (((fcp->func->flags & FC_ABORT) && did_emsg && !aborted_in_try())
|
||||
return (((fcp->func->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
|
||||
|| fcp->returned);
|
||||
}
|
||||
|
||||
@@ -16398,7 +16682,7 @@ func_has_ended(cookie)
|
||||
func_has_abort(cookie)
|
||||
void *cookie;
|
||||
{
|
||||
return ((funccall_T *)cookie)->func->flags & FC_ABORT;
|
||||
return ((funccall_T *)cookie)->func->uf_flags & FC_ABORT;
|
||||
}
|
||||
|
||||
#if defined(FEAT_VIMINFO) || defined(FEAT_SESSION)
|
||||
|
Reference in New Issue
Block a user