/* vi:set ts=8 sts=4 sw=4: * * VIM - Vi IMproved by Bram Moolenaar * * Do ":help uganda" in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. * See README.txt for an overview of the Vim source code. */ /* * eval.c: Expression evaluation. */#if defined(MSDOS) || defined(MSWIN)# include "vimio.h" /* for mch_open(), must be before vim.h */#endif #include "vim.h" #ifdef AMIGA# include <time.h> /* for strftime() */#endif #ifdef MACOS# include <time.h> /* for time_t */#endif #ifdef HAVE_FCNTL_H# include <fcntl.h>#endif #if defined(FEAT_EVAL) || defined(PROTO) #define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */ /* * In a hashtab item "hi_key" points to "di_key" in a dictitem. * This avoids adding a pointer to the hashtab item. * DI2HIKEY() converts a dictitem pointer to a hashitem key pointer. * HIKEY2DI() converts a hashitem key pointer to a dictitem pointer. * HI2DI() converts a hashitem pointer to a dictitem pointer. */static dictitem_T dumdi;#define DI2HIKEY(di) ((di)->di_key)#define HIKEY2DI(p) ((dictitem_T *)(p - (dumdi.di_key - (char_u *)&dumdi)))#define HI2DI(hi) HIKEY2DI((hi)->hi_key) /* * Structure returned by get_lval() and used by set_var_lval(). * For a plain name: * "name" points to the variable name. * "exp_name" is NULL. * "tv" is NULL * For a magic braces name: * "name" points to the expanded variable name. * "exp_name" is non-NULL, to be freed later. * "tv" is NULL * For an index in a list: * "name" points to the (expanded) variable name. * "exp_name" NULL or non-NULL, to be freed later. * "tv" points to the (first) list item value * "li" points to the (first) list item * "range", "n1", "n2" and "empty2" indicate what items are used. * For an existing Dict item: * "name" points to the (expanded) variable name. * "exp_name" NULL or non-NULL, to be freed later. * "tv" points to the dict item value * "newkey" is NULL * For a non-existing Dict item: * "name" points to the (expanded) variable name. * "exp_name" NULL or non-NULL, to be freed later. * "tv" points to the Dictionary typval_T * "newkey" is the key for the new item. */typedef struct lval_S{ char_u *ll_name; /* start of variable name (can be NULL) */ char_u *ll_exp_name; /* NULL or expanded name in allocated memory. */ typval_T *ll_tv; /* Typeval of item being used. If "newkey" isn't NULL it's the Dict to which to add the item. */ listitem_T *ll_li; /* The list item or NULL. */ list_T *ll_list; /* The list or NULL. */ int ll_range; /* TRUE when a [i:j] range was used */ long ll_n1; /* First index for list */ long ll_n2; /* Second index for list range */ int ll_empty2; /* Second index is empty: [i:] */ dict_T *ll_dict; /* The Dictionary or NULL */ dictitem_T *ll_di; /* The dictitem or NULL */ char_u *ll_newkey; /* New key for Dict in alloc. mem or NULL. */} lval_T; static char *e_letunexp = N_("E18: Unexpected characters in :let");static char *e_listidx = N_("E684: list index out of range: %ld");static char *e_undefvar = N_("E121: Undefined variable: %s");static char *e_missbrac = N_("E111: Missing ']'");static char *e_listarg = N_("E686: Argument of %s must be a List");static char *e_listdictarg = N_("E712: Argument of %s must be a List or Dictionary");static char *e_emptykey = N_("E713: Cannot use empty key for Dictionary");static char *e_listreq = N_("E714: List required");static char *e_dictreq = N_("E715: Dictionary required");static char *e_toomanyarg = N_("E118: Too many arguments for function: %s");static char *e_dictkey = N_("E716: Key not present in Dictionary: %s");static char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it");static char *e_funcdict = N_("E717: Dictionary entry already exists");static char *e_funcref = N_("E718: Funcref required");static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary");static char *e_letwrong = N_("E734: Wrong variable type for %s=");static char *e_nofunc = N_("E130: Unknown function: %s");static char *e_illvar = N_("E461: Illegal variable name: %s");/* * All user-defined global variables are stored in dictionary "globvardict". * "globvars_var" is the variable that is used for "g:". */static dict_T globvardict;static dictitem_T globvars_var;#define globvarht globvardict.dv_hashtab /* * Old Vim variables such as "v:version" are also available without the "v:". * Also in functions. We need a special hashtable for them. */static hashtab_T compat_hashtab; /* * When recursively copying lists and dicts we need to remember which ones we * have done to avoid endless recursiveness. This unique ID is used for that. */static int current_copyID = 0; /* * Array to hold the hashtab with variables local to each sourced script. * Each item holds a variable (nameless) that points to the dict_T. */typedef struct{ dictitem_T sv_var; dict_T sv_dict;} scriptvar_T; static garray_T ga_scripts = {0, 0, sizeof(scriptvar_T), 4, NULL};#define SCRIPT_SV(id) (((scriptvar_T *)ga_scripts.ga_data)[(id) - 1])#define SCRIPT_VARS(id) (SCRIPT_SV(id).sv_dict.dv_hashtab) static int echo_attr = 0; /* attributes used for ":echo" */ /* Values for trans_function_name() argument: */#define TFN_INT 1 /* internal function name OK */#define TFN_QUIET 2 /* no error messages */ /* * Structure to hold info for a user function. */typedef struct ufunc ufunc_T; struct ufunc{ 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 */#ifdef FEAT_PROFILE int uf_profiling; /* TRUE when func is being profiled */ /* profiling the function as a whole */ int uf_tm_count; /* nr of calls */ proftime_T uf_tm_total; /* time spend in function + children */ proftime_T uf_tm_self; /* time spend in function itself */ proftime_T uf_tm_children; /* time spent in children this call */ /* profiling the function per line */ int *uf_tml_count; /* nr of times line was executed */ proftime_T *uf_tml_total; /* time spend in a line + children */ proftime_T *uf_tml_self; /* time spend in a line itself */ proftime_T uf_tml_start; /* start time for current line */ proftime_T uf_tml_children; /* time spent in children for this line */ proftime_T uf_tml_wait; /* start wait time for current line */ int uf_tml_idx; /* index of line being timed; -1 if none */ int uf_tml_execed; /* line being timed was executed */#endif scid_T uf_script_ID; /* ID of script where function was defined, used for s: variables */ 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 */#define FC_ABORT 1 /* abort function on error */#define FC_RANGE 2 /* function accepts range */#define FC_DICT 4 /* Dict function, uses "self" */ /* * All user-defined functions are found in this hashtable. */static hashtab_T func_hashtab; /* The names of packages that once were loaded are remembered. */static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL}; /* 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. */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 */#define FIXVAR_CNT 12 /* number of fixed variables */ /* structure to hold info for a function that is currently being executed. */typedef struct funccall_S funccall_T; struct funccall_S{ ufunc_T *func; /* function being called */ int linenr; /* next line to be executed */ int returned; /* ":return" used */ struct /* fixed variables for arguments */ { dictitem_T var; /* variable (without room for name) */ char_u room[VAR_SHORT_LEN]; /* room for the name */ } fixvar[FIXVAR_CNT]; dict_T l_vars; /* l: local function variables */ dictitem_T l_vars_var; /* variable for l: scope */ dict_T l_avars; /* a: argument variables */ dictitem_T l_avars_var; /* variable for a: scope */ list_T l_varlist; /* list for a:000 */ listitem_T l_listitems[MAX_FUNC_ARGS]; /* listitems for a:000 */ typval_T *rettv; /* return value */ linenr_T breakpoint; /* next line with breakpoint or zero */ int dbg_tick; /* debug_tick when breakpoint was set */ int level; /* top nesting level of executed function */#ifdef FEAT_PROFILE proftime_T prof_child; /* time spent in a child */#endif funccall_T *caller; /* calling function or NULL */}; /* * Info used by a ":for" loop. */typedef struct{ int fi_semicolon; /* TRUE if ending in '; var]' */ int fi_varcount; /* nr of variables in the list */ listwatch_T fi_lw; /* keep an eye on the item used. */ list_T *fi_list; /* list being used */} forinfo_T; /* * Struct used by trans_function_name() */typedef struct{ dict_T *fd_dict; /* Dictionary used */ char_u *fd_newkey; /* new key in "dict" in allocated memory */ dictitem_T *fd_di; /* Dictionary item used */} funcdict_T; /* * Array to hold the value of v: variables. * The value is in a dictitem, so that it can also be used in the v: scope. * The reason to use this table anyway is for very quick access to the * variables with the VV_ defines. */#include "version.h" /* values for vv_flags: */#define VV_COMPAT 1 /* compatible, also used without "v:" */#define VV_RO 2 /* read-only */#define VV_RO_SBX 4 /* read-only in the sandbox */ #define VV_NAME(s, t) s, {{t}}, {0} static struct vimvar{ char *vv_name; /* name of variable, without v: */ dictitem_T vv_di; /* value and name for key */ char vv_filler[16]; /* space for LONGEST name below!!! */ char vv_flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */} vimvars[VV_LEN] ={ /* * The order here must match the VV_ defines in vim.h! * Initializing a union does not work, leave tv.vval empty to get zero's. */ {VV_NAME("count", VAR_NUMBER), VV_COMPAT+VV_RO}, {VV_NAME("count1", VAR_NUMBER), VV_RO}, {VV_NAME("prevcount", VAR_NUMBER), VV_RO}, {VV_NAME("errmsg", VAR_STRING), VV_COMPAT}, {VV_NAME("warningmsg", VAR_STRING), 0}, {VV_NAME("statusmsg", VAR_STRING), 0}, {VV_NAME("shell_error", VAR_NUMBER), VV_COMPAT+VV_RO}, {VV_NAME("this_session", VAR_STRING), VV_COMPAT}, {VV_NAME("version", VAR_NUMBER), VV_COMPAT+VV_RO}, {VV_NAME("lnum", VAR_NUMBER), VV_RO_SBX}, {VV_NAME("termresponse", VAR_STRING), VV_RO}, {VV_NAME("fname", VAR_STRING), VV_RO}, {VV_NAME("lang", VAR_STRING), VV_RO}, {VV_NAME("lc_time", VAR_STRING), VV_RO}, {VV_NAME("ctype", VAR_STRING), VV_RO}, {VV_NAME("charconvert_from", VAR_STRING), VV_RO}, {VV_NAME("charconvert_to", VAR_STRING), VV_RO}, {VV_NAME("fname_in", VAR_STRING), VV_RO}, {VV_NAME("fname_out", VAR_STRING), VV_RO}, {VV_NAME("fname_new", VAR_STRING), VV_RO}, {VV_NAME("fname_diff", VAR_STRING), VV_RO}, {VV_NAME("cmdarg", VAR_STRING), VV_RO}, {VV_NAME("foldstart", VAR_NUMBER), VV_RO_SBX}, {VV_NAME("foldend", VAR_NUMBER), VV_RO_SBX}, {VV_NAME("folddashes", VAR_STRING), VV_RO_SBX}, {VV_NAME("foldlevel", VAR_NUMBER), VV_RO_SBX}, {VV_NAME("progname", VAR_STRING), VV_RO}, {VV_NAME("servername", VAR_STRING), VV_RO}, {VV_NAME("dying", VAR_NUMBER), VV_RO}, {VV_NAME("exception", VAR_STRING), VV_RO}, {VV_NAME("throwpoint", VAR_STRING), VV_RO}, {VV_NAME("register", VAR_STRING), VV_RO}, {VV_NAME("cmdbang", VAR_NUMBER), VV_RO}, {VV_NAME("insertmode", VAR_STRING), VV_RO}, {VV_NAME("val", VAR_UNKNOWN), VV_RO}, {VV_NAME("key", VAR_UNKNOWN), VV_RO}, {VV_NAME("profiling", VAR_NUMBER), VV_RO}, {VV_NAME("fcs_reason", VAR_STRING), VV_RO}, {VV_NAME("fcs_choice", VAR_STRING), 0}, {VV_NAME("beval_bufnr", VAR_NUMBER), VV_RO}, {VV_NAME("beval_winnr", VAR_NUMBER), VV_RO}, {VV_NAME("beval_lnum", VAR_NUMBER), VV_RO}, {VV_NAME("beval_col", VAR_NUMBER), VV_RO}, {VV_NAME("beval_text", VAR_STRING), VV_RO}, {VV_NAME("scrollstart", VAR_STRING), 0}, {VV_NAME("swapname", VAR_STRING), VV_RO}, {VV_NAME("swapchoice", VAR_STRING), 0}, {VV_NAME("swapcommand", VAR_STRING), VV_RO}, {VV_NAME("char", VAR_STRING), VV_RO}, {VV_NAME("mouse_win", VAR_NUMBER), 0}, {VV_NAME("mouse_lnum", VAR_NUMBER), 0}, {VV_NAME("mouse_col", VAR_NUMBER), 0},}; /* shorthand */#define vv_type vv_di.di_tv.v_type#define vv_nr vv_di.di_tv.vval.v_number#define vv_str vv_di.di_tv.vval.v_string#define vv_tv vv_di.di_tv /* * The v: variables are stored in dictionary "vimvardict". * "vimvars_var" is the variable that is used for the "l:" scope. */static dict_T vimvardict;static dictitem_T vimvars_var;#define vimvarht vimvardict.dv_hashtab static void prepare_vimvar __ARGS((int idx, typval_T *save_tv));static void restore_vimvar __ARGS((int idx, typval_T *save_tv));#if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)static int call_vim_function __ARGS((char_u *func, int argc, char_u **argv, int safe, typval_T *rettv));#endifstatic int ex_let_vars __ARGS((char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, char_u *nextchars));static char_u *skip_var_list __ARGS((char_u *arg, int *var_count, int *semicolon));static char_u *skip_var_one __ARGS((char_u *arg));static void list_hashtable_vars __ARGS((hashtab_T *ht, char_u *prefix, int empty));static void list_glob_vars __ARGS((void));static void list_buf_vars __ARGS((void));static void list_win_vars __ARGS((void));#ifdef FEAT_WINDOWSstatic void list_tab_vars __ARGS((void));#endifstatic void list_vim_vars __ARGS((void));static void list_script_vars __ARGS((void));static void list_func_vars __ARGS((void));static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg));static char_u *ex_let_one __ARGS((char_u *arg, typval_T *tv, int copy, char_u *endchars, char_u *op));static int check_changedtick __ARGS((char_u *arg));static char_u *get_lval __ARGS((char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int quiet, int fne_flags));static void clear_lval __ARGS((lval_T *lp));static void set_var_lval __ARGS((lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op));static int tv_op __ARGS((typval_T *tv1, typval_T *tv2, char_u *op));static void list_add_watch __ARGS((list_T *l, listwatch_T *lw));static void list_rem_watch __ARGS((list_T *l, listwatch_T *lwrem));static void list_fix_watch __ARGS((list_T *l, listitem_T *item));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)); static int eval0 __ARGS((char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate));static int eval1 __ARGS((char_u **arg, typval_T *rettv, int evaluate));static int eval2 __ARGS((char_u **arg, typval_T *rettv, int evaluate));static int eval3 __ARGS((char_u **arg, typval_T *rettv, int evaluate));static int eval4 __ARGS((char_u **arg, typval_T *rettv, int evaluate));static int eval5 __ARGS((char_u **arg, typval_T *rettv, int evaluate));static int eval6 __ARGS((char_u **arg, typval_T *rettv, int evaluate));static int eval7 __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static int eval_index __ARGS((char_u **arg, typval_T *rettv, int evaluate, int verbose));static int get_option_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));static int get_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));static int get_lit_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));static int get_list_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));static int rettv_list_alloc __ARGS((typval_T *rettv));static listitem_T *listitem_alloc __ARGS((void));static void listitem_free __ARGS((listitem_T *item));static void listitem_remove __ARGS((list_T *l, listitem_T *item));static long list_len __ARGS((list_T *l));static int list_equal __ARGS((list_T *l1, list_T *l2, int ic));static int dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic));static int tv_equal __ARGS((typval_T *tv1, typval_T *tv2, int ic));static listitem_T *list_find __ARGS((list_T *l, long n));static long list_find_nr __ARGS((list_T *l, long idx, int *errorp));static long list_idx_of_item __ARGS((list_T *l, listitem_T *item));static void list_append __ARGS((list_T *l, listitem_T *item));static int list_append_tv __ARGS((list_T *l, typval_T *tv));static int list_append_string __ARGS((list_T *l, char_u *str, int len));static int list_append_number __ARGS((list_T *l, varnumber_T n));static int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item));static int list_extend __ARGS((list_T *l1, list_T *l2, listitem_T *bef));static int list_concat __ARGS((list_T *l1, list_T *l2, typval_T *tv));static list_T *list_copy __ARGS((list_T *orig, int deep, int copyID));static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));static char_u *list2string __ARGS((typval_T *tv, int copyID));static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo, int copyID));static void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID));static void set_ref_in_list __ARGS((list_T *l, int copyID));static void set_ref_in_item __ARGS((typval_T *tv, int copyID));static void dict_unref __ARGS((dict_T *d));static void dict_free __ARGS((dict_T *d, int recurse));static dictitem_T *dictitem_alloc __ARGS((char_u *key));static dictitem_T *dictitem_copy __ARGS((dictitem_T *org));static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item));static void dictitem_free __ARGS((dictitem_T *item));static dict_T *dict_copy __ARGS((dict_T *orig, int deep, int copyID));static int dict_add __ARGS((dict_T *d, dictitem_T *item));static long dict_len __ARGS((dict_T *d));static dictitem_T *dict_find __ARGS((dict_T *d, char_u *key, int len));static char_u *dict2string __ARGS((typval_T *tv, int copyID));static int get_dict_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));static char_u *echo_string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID));static char_u *tv2string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID));static char_u *string_quote __ARGS((char_u *str, int function));static int get_env_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));static int find_internal_func __ARGS((char_u *name));static char_u *deref_func_name __ARGS((char_u *name, int *lenp));static int get_func_tv __ARGS((char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));static int call_func __ARGS((char_u *name, int len, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));static void emsg_funcname __ARGS((char *ermsg, char_u *name)); static void f_add __ARGS((typval_T *argvars, typval_T *rettv));static void f_append __ARGS((typval_T *argvars, typval_T *rettv));static void f_argc __ARGS((typval_T *argvars, typval_T *rettv));static void f_argidx __ARGS((typval_T *argvars, typval_T *rettv));static void f_argv __ARGS((typval_T *argvars, typval_T *rettv));static void f_browse __ARGS((typval_T *argvars, typval_T *rettv));static void f_browsedir __ARGS((typval_T *argvars, typval_T *rettv));static void f_bufexists __ARGS((typval_T *argvars, typval_T *rettv));static void f_buflisted __ARGS((typval_T *argvars, typval_T *rettv));static void f_bufloaded __ARGS((typval_T *argvars, typval_T *rettv));static void f_bufname __ARGS((typval_T *argvars, typval_T *rettv));static void f_bufnr __ARGS((typval_T *argvars, typval_T *rettv));static void f_bufwinnr __ARGS((typval_T *argvars, typval_T *rettv));static void f_byte2line __ARGS((typval_T *argvars, typval_T *rettv));static void f_byteidx __ARGS((typval_T *argvars, typval_T *rettv));static void f_call __ARGS((typval_T *argvars, typval_T *rettv));static void f_changenr __ARGS((typval_T *argvars, typval_T *rettv));static void f_char2nr __ARGS((typval_T *argvars, typval_T *rettv));static void f_cindent __ARGS((typval_T *argvars, typval_T *rettv));static void f_col __ARGS((typval_T *argvars, typval_T *rettv));#if defined(FEAT_INS_EXPAND)static void f_complete __ARGS((typval_T *argvars, typval_T *rettv));static void f_complete_add __ARGS((typval_T *argvars, typval_T *rettv));static void f_complete_check __ARGS((typval_T *argvars, typval_T *rettv));#endifstatic void f_confirm __ARGS((typval_T *argvars, typval_T *rettv));static void f_copy __ARGS((typval_T *argvars, typval_T *rettv));static void f_count __ARGS((typval_T *argvars, typval_T *rettv));static void f_cscope_connection __ARGS((typval_T *argvars, typval_T *rettv));static void f_cursor __ARGS((typval_T *argsvars, typval_T *rettv));static void f_deepcopy __ARGS((typval_T *argvars, typval_T *rettv));static void f_delete __ARGS((typval_T *argvars, typval_T *rettv));static void f_did_filetype __ARGS((typval_T *argvars, typval_T *rettv));static void f_diff_filler __ARGS((typval_T *argvars, typval_T *rettv));static void f_diff_hlID __ARGS((typval_T *argvars, typval_T *rettv));static void f_empty __ARGS((typval_T *argvars, typval_T *rettv));static void f_escape __ARGS((typval_T *argvars, typval_T *rettv));static void f_eval __ARGS((typval_T *argvars, typval_T *rettv));static void f_eventhandler __ARGS((typval_T *argvars, typval_T *rettv));static void f_executable __ARGS((typval_T *argvars, typval_T *rettv));static void f_exists __ARGS((typval_T *argvars, typval_T *rettv));static void f_expand __ARGS((typval_T *argvars, typval_T *rettv));Lines 1–500 of 21312. Load more
/* vi:set ts=8 sts=4 sw=4: * * VIM - Vi IMproved by Bram Moolenaar * * Do ":help uganda" in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. * See README.txt for an overview of the Vim source code. */ /* * eval.c: Expression evaluation. */ #if defined(MSDOS) || defined(MSWIN) # include "vimio.h" /* for mch_open(), must be before vim.h */ #endif #include "vim.h" #ifdef AMIGA # include <time.h> /* for strftime() */ #endif #ifdef MACOS # include <time.h> /* for time_t */ #endif #ifdef HAVE_FCNTL_H # include <fcntl.h> #endif #if defined(FEAT_EVAL) || defined(PROTO) #define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */ /* * In a hashtab item "hi_key" points to "di_key" in a dictitem. * This avoids adding a pointer to the hashtab item. * DI2HIKEY() converts a dictitem pointer to a hashitem key pointer. * HIKEY2DI() converts a hashitem key pointer to a dictitem pointer. * HI2DI() converts a hashitem pointer to a dictitem pointer. */ static dictitem_T dumdi; #define DI2HIKEY(di) ((di)->di_key) #define HIKEY2DI(p) ((dictitem_T *)(p - (dumdi.di_key - (char_u *)&dumdi))) #define HI2DI(hi) HIKEY2DI((hi)->hi_key) /* * Structure returned by get_lval() and used by set_var_lval(). * For a plain name: * "name" points to the variable name. * "exp_name" is NULL. * "tv" is NULL * For a magic braces name: * "name" points to the expanded variable name. * "exp_name" is non-NULL, to be freed later. * "tv" is NULL * For an index in a list: * "name" points to the (expanded) variable name. * "exp_name" NULL or non-NULL, to be freed later. * "tv" points to the (first) list item value * "li" points to the (first) list item * "range", "n1", "n2" and "empty2" indicate what items are used. * For an existing Dict item: * "name" points to the (expanded) variable name. * "exp_name" NULL or non-NULL, to be freed later. * "tv" points to the dict item value * "newkey" is NULL * For a non-existing Dict item: * "name" points to the (expanded) variable name. * "exp_name" NULL or non-NULL, to be freed later. * "tv" points to the Dictionary typval_T * "newkey" is the key for the new item. */ typedef struct lval_S { char_u *ll_name; /* start of variable name (can be NULL) */ char_u *ll_exp_name; /* NULL or expanded name in allocated memory. */ typval_T *ll_tv; /* Typeval of item being used. If "newkey" isn't NULL it's the Dict to which to add the item. */ listitem_T *ll_li; /* The list item or NULL. */ list_T *ll_list; /* The list or NULL. */ int ll_range; /* TRUE when a [i:j] range was used */ long ll_n1; /* First index for list */ long ll_n2; /* Second index for list range */ int ll_empty2; /* Second index is empty: [i:] */ dict_T *ll_dict; /* The Dictionary or NULL */ dictitem_T *ll_di; /* The dictitem or NULL */ char_u *ll_newkey; /* New key for Dict in alloc. mem or NULL. */ } lval_T; static char *e_letunexp = N_("E18: Unexpected characters in :let"); static char *e_listidx = N_("E684: list index out of range: %ld"); static char *e_undefvar = N_("E121: Undefined variable: %s"); static char *e_missbrac = N_("E111: Missing ']'"); static char *e_listarg = N_("E686: Argument of %s must be a List"); static char *e_listdictarg = N_("E712: Argument of %s must be a List or Dictionary"); static char *e_emptykey = N_("E713: Cannot use empty key for Dictionary"); static char *e_listreq = N_("E714: List required"); static char *e_dictreq = N_("E715: Dictionary required"); static char *e_toomanyarg = N_("E118: Too many arguments for function: %s"); static char *e_dictkey = N_("E716: Key not present in Dictionary: %s"); static char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it"); static char *e_funcdict = N_("E717: Dictionary entry already exists"); static char *e_funcref = N_("E718: Funcref required"); static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary"); static char *e_letwrong = N_("E734: Wrong variable type for %s="); static char *e_nofunc = N_("E130: Unknown function: %s"); static char *e_illvar = N_("E461: Illegal variable name: %s"); /* * All user-defined global variables are stored in dictionary "globvardict". * "globvars_var" is the variable that is used for "g:". */ static dict_T globvardict; static dictitem_T globvars_var; #define globvarht globvardict.dv_hashtab /* * Old Vim variables such as "v:version" are also available without the "v:". * Also in functions. We need a special hashtable for them. */ static hashtab_T compat_hashtab; /* * When recursively copying lists and dicts we need to remember which ones we * have done to avoid endless recursiveness. This unique ID is used for that. */ static int current_copyID = 0; /* * Array to hold the hashtab with variables local to each sourced script. * Each item holds a variable (nameless) that points to the dict_T. */ typedef struct { dictitem_T sv_var; dict_T sv_dict; } scriptvar_T; static garray_T ga_scripts = {0, 0, sizeof(scriptvar_T), 4, NULL}; #define SCRIPT_SV(id) (((scriptvar_T *)ga_scripts.ga_data)[(id) - 1]) #define SCRIPT_VARS(id) (SCRIPT_SV(id).sv_dict.dv_hashtab) static int echo_attr = 0; /* attributes used for ":echo" */ /* Values for trans_function_name() argument: */ #define TFN_INT 1 /* internal function name OK */ #define TFN_QUIET 2 /* no error messages */ /* * Structure to hold info for a user function. */ typedef struct ufunc ufunc_T; struct ufunc { 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 */ #ifdef FEAT_PROFILE int uf_profiling; /* TRUE when func is being profiled */ /* profiling the function as a whole */ int uf_tm_count; /* nr of calls */ proftime_T uf_tm_total; /* time spend in function + children */ proftime_T uf_tm_self; /* time spend in function itself */ proftime_T uf_tm_children; /* time spent in children this call */ /* profiling the function per line */ int *uf_tml_count; /* nr of times line was executed */ proftime_T *uf_tml_total; /* time spend in a line + children */ proftime_T *uf_tml_self; /* time spend in a line itself */ proftime_T uf_tml_start; /* start time for current line */ proftime_T uf_tml_children; /* time spent in children for this line */ proftime_T uf_tml_wait; /* start wait time for current line */ int uf_tml_idx; /* index of line being timed; -1 if none */ int uf_tml_execed; /* line being timed was executed */ #endif scid_T uf_script_ID; /* ID of script where function was defined, used for s: variables */ 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 */ #define FC_ABORT 1 /* abort function on error */ #define FC_RANGE 2 /* function accepts range */ #define FC_DICT 4 /* Dict function, uses "self" */ /* * All user-defined functions are found in this hashtable. */ static hashtab_T func_hashtab; /* The names of packages that once were loaded are remembered. */ static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL}; /* 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. */ 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 */ #define FIXVAR_CNT 12 /* number of fixed variables */ /* structure to hold info for a function that is currently being executed. */ typedef struct funccall_S funccall_T; struct funccall_S { ufunc_T *func; /* function being called */ int linenr; /* next line to be executed */ int returned; /* ":return" used */ struct /* fixed variables for arguments */ { dictitem_T var; /* variable (without room for name) */ char_u room[VAR_SHORT_LEN]; /* room for the name */ } fixvar[FIXVAR_CNT]; dict_T l_vars; /* l: local function variables */ dictitem_T l_vars_var; /* variable for l: scope */ dict_T l_avars; /* a: argument variables */ dictitem_T l_avars_var; /* variable for a: scope */ list_T l_varlist; /* list for a:000 */ listitem_T l_listitems[MAX_FUNC_ARGS]; /* listitems for a:000 */ typval_T *rettv; /* return value */ linenr_T breakpoint; /* next line with breakpoint or zero */ int dbg_tick; /* debug_tick when breakpoint was set */ int level; /* top nesting level of executed function */ #ifdef FEAT_PROFILE proftime_T prof_child; /* time spent in a child */ #endif funccall_T *caller; /* calling function or NULL */ }; /* * Info used by a ":for" loop. */ typedef struct { int fi_semicolon; /* TRUE if ending in '; var]' */ int fi_varcount; /* nr of variables in the list */ listwatch_T fi_lw; /* keep an eye on the item used. */ list_T *fi_list; /* list being used */ } forinfo_T; /* * Struct used by trans_function_name() */ typedef struct { dict_T *fd_dict; /* Dictionary used */ char_u *fd_newkey; /* new key in "dict" in allocated memory */ dictitem_T *fd_di; /* Dictionary item used */ } funcdict_T; /* * Array to hold the value of v: variables. * The value is in a dictitem, so that it can also be used in the v: scope. * The reason to use this table anyway is for very quick access to the * variables with the VV_ defines. */ #include "version.h" /* values for vv_flags: */ #define VV_COMPAT 1 /* compatible, also used without "v:" */ #define VV_RO 2 /* read-only */ #define VV_RO_SBX 4 /* read-only in the sandbox */ #define VV_NAME(s, t) s, {{t}}, {0} static struct vimvar { char *vv_name; /* name of variable, without v: */ dictitem_T vv_di; /* value and name for key */ char vv_filler[16]; /* space for LONGEST name below!!! */ char vv_flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */ } vimvars[VV_LEN] = { /* * The order here must match the VV_ defines in vim.h! * Initializing a union does not work, leave tv.vval empty to get zero's. */ {VV_NAME("count", VAR_NUMBER), VV_COMPAT+VV_RO}, {VV_NAME("count1", VAR_NUMBER), VV_RO}, {VV_NAME("prevcount", VAR_NUMBER), VV_RO}, {VV_NAME("errmsg", VAR_STRING), VV_COMPAT}, {VV_NAME("warningmsg", VAR_STRING), 0}, {VV_NAME("statusmsg", VAR_STRING), 0}, {VV_NAME("shell_error", VAR_NUMBER), VV_COMPAT+VV_RO}, {VV_NAME("this_session", VAR_STRING), VV_COMPAT}, {VV_NAME("version", VAR_NUMBER), VV_COMPAT+VV_RO}, {VV_NAME("lnum", VAR_NUMBER), VV_RO_SBX}, {VV_NAME("termresponse", VAR_STRING), VV_RO}, {VV_NAME("fname", VAR_STRING), VV_RO}, {VV_NAME("lang", VAR_STRING), VV_RO}, {VV_NAME("lc_time", VAR_STRING), VV_RO}, {VV_NAME("ctype", VAR_STRING), VV_RO}, {VV_NAME("charconvert_from", VAR_STRING), VV_RO}, {VV_NAME("charconvert_to", VAR_STRING), VV_RO}, {VV_NAME("fname_in", VAR_STRING), VV_RO}, {VV_NAME("fname_out", VAR_STRING), VV_RO}, {VV_NAME("fname_new", VAR_STRING), VV_RO}, {VV_NAME("fname_diff", VAR_STRING), VV_RO}, {VV_NAME("cmdarg", VAR_STRING), VV_RO}, {VV_NAME("foldstart", VAR_NUMBER), VV_RO_SBX}, {VV_NAME("foldend", VAR_NUMBER), VV_RO_SBX}, {VV_NAME("folddashes", VAR_STRING), VV_RO_SBX}, {VV_NAME("foldlevel", VAR_NUMBER), VV_RO_SBX}, {VV_NAME("progname", VAR_STRING), VV_RO}, {VV_NAME("servername", VAR_STRING), VV_RO}, {VV_NAME("dying", VAR_NUMBER), VV_RO}, {VV_NAME("exception", VAR_STRING), VV_RO}, {VV_NAME("throwpoint", VAR_STRING), VV_RO}, {VV_NAME("register", VAR_STRING), VV_RO}, {VV_NAME("cmdbang", VAR_NUMBER), VV_RO}, {VV_NAME("insertmode", VAR_STRING), VV_RO}, {VV_NAME("val", VAR_UNKNOWN), VV_RO}, {VV_NAME("key", VAR_UNKNOWN), VV_RO}, {VV_NAME("profiling", VAR_NUMBER), VV_RO}, {VV_NAME("fcs_reason", VAR_STRING), VV_RO}, {VV_NAME("fcs_choice", VAR_STRING), 0}, {VV_NAME("beval_bufnr", VAR_NUMBER), VV_RO}, {VV_NAME("beval_winnr", VAR_NUMBER), VV_RO}, {VV_NAME("beval_lnum", VAR_NUMBER), VV_RO}, {VV_NAME("beval_col", VAR_NUMBER), VV_RO}, {VV_NAME("beval_text", VAR_STRING), VV_RO}, {VV_NAME("scrollstart", VAR_STRING), 0}, {VV_NAME("swapname", VAR_STRING), VV_RO}, {VV_NAME("swapchoice", VAR_STRING), 0}, {VV_NAME("swapcommand", VAR_STRING), VV_RO}, {VV_NAME("char", VAR_STRING), VV_RO}, {VV_NAME("mouse_win", VAR_NUMBER), 0}, {VV_NAME("mouse_lnum", VAR_NUMBER), 0}, {VV_NAME("mouse_col", VAR_NUMBER), 0}, }; /* shorthand */ #define vv_type vv_di.di_tv.v_type #define vv_nr vv_di.di_tv.vval.v_number #define vv_str vv_di.di_tv.vval.v_string #define vv_tv vv_di.di_tv /* * The v: variables are stored in dictionary "vimvardict". * "vimvars_var" is the variable that is used for the "l:" scope. */ static dict_T vimvardict; static dictitem_T vimvars_var; #define vimvarht vimvardict.dv_hashtab static void prepare_vimvar __ARGS((int idx, typval_T *save_tv)); static void restore_vimvar __ARGS((int idx, typval_T *save_tv)); #if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL) static int call_vim_function __ARGS((char_u *func, int argc, char_u **argv, int safe, typval_T *rettv)); #endif static int ex_let_vars __ARGS((char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, char_u *nextchars)); static char_u *skip_var_list __ARGS((char_u *arg, int *var_count, int *semicolon)); static char_u *skip_var_one __ARGS((char_u *arg)); static void list_hashtable_vars __ARGS((hashtab_T *ht, char_u *prefix, int empty)); static void list_glob_vars __ARGS((void)); static void list_buf_vars __ARGS((void)); static void list_win_vars __ARGS((void)); #ifdef FEAT_WINDOWS static void list_tab_vars __ARGS((void)); #endif static void list_vim_vars __ARGS((void)); static void list_script_vars __ARGS((void)); static void list_func_vars __ARGS((void)); static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg)); static char_u *ex_let_one __ARGS((char_u *arg, typval_T *tv, int copy, char_u *endchars, char_u *op)); static int check_changedtick __ARGS((char_u *arg)); static char_u *get_lval __ARGS((char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int quiet, int fne_flags)); static void clear_lval __ARGS((lval_T *lp)); static void set_var_lval __ARGS((lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op)); static int tv_op __ARGS((typval_T *tv1, typval_T *tv2, char_u *op)); static void list_add_watch __ARGS((list_T *l, listwatch_T *lw)); static void list_rem_watch __ARGS((list_T *l, listwatch_T *lwrem)); static void list_fix_watch __ARGS((list_T *l, listitem_T *item)); 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)); static int eval0 __ARGS((char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate)); static int eval1 __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static int eval2 __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static int eval3 __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static int eval4 __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static int eval5 __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static int eval6 __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static int eval7 __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static int eval_index __ARGS((char_u **arg, typval_T *rettv, int evaluate, int verbose)); static int get_option_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static int get_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static int get_lit_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static int get_list_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static int rettv_list_alloc __ARGS((typval_T *rettv)); static listitem_T *listitem_alloc __ARGS((void)); static void listitem_free __ARGS((listitem_T *item)); static void listitem_remove __ARGS((list_T *l, listitem_T *item)); static long list_len __ARGS((list_T *l)); static int list_equal __ARGS((list_T *l1, list_T *l2, int ic)); static int dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic)); static int tv_equal __ARGS((typval_T *tv1, typval_T *tv2, int ic)); static listitem_T *list_find __ARGS((list_T *l, long n)); static long list_find_nr __ARGS((list_T *l, long idx, int *errorp)); static long list_idx_of_item __ARGS((list_T *l, listitem_T *item)); static void list_append __ARGS((list_T *l, listitem_T *item)); static int list_append_tv __ARGS((list_T *l, typval_T *tv)); static int list_append_string __ARGS((list_T *l, char_u *str, int len)); static int list_append_number __ARGS((list_T *l, varnumber_T n)); static int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item)); static int list_extend __ARGS((list_T *l1, list_T *l2, listitem_T *bef)); static int list_concat __ARGS((list_T *l1, list_T *l2, typval_T *tv)); static list_T *list_copy __ARGS((list_T *orig, int deep, int copyID)); static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2)); static char_u *list2string __ARGS((typval_T *tv, int copyID)); static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo, int copyID)); static void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID)); static void set_ref_in_list __ARGS((list_T *l, int copyID)); static void set_ref_in_item __ARGS((typval_T *tv, int copyID)); static void dict_unref __ARGS((dict_T *d)); static void dict_free __ARGS((dict_T *d, int recurse)); static dictitem_T *dictitem_alloc __ARGS((char_u *key)); static dictitem_T *dictitem_copy __ARGS((dictitem_T *org)); static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item)); static void dictitem_free __ARGS((dictitem_T *item)); static dict_T *dict_copy __ARGS((dict_T *orig, int deep, int copyID)); static int dict_add __ARGS((dict_T *d, dictitem_T *item)); static long dict_len __ARGS((dict_T *d)); static dictitem_T *dict_find __ARGS((dict_T *d, char_u *key, int len)); static char_u *dict2string __ARGS((typval_T *tv, int copyID)); static int get_dict_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static char_u *echo_string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID)); static char_u *tv2string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID)); static char_u *string_quote __ARGS((char_u *str, int function)); static int get_env_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static int find_internal_func __ARGS((char_u *name)); static char_u *deref_func_name __ARGS((char_u *name, int *lenp)); static int get_func_tv __ARGS((char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict)); static int call_func __ARGS((char_u *name, int len, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict)); static void emsg_funcname __ARGS((char *ermsg, char_u *name)); static void f_add __ARGS((typval_T *argvars, typval_T *rettv)); static void f_append __ARGS((typval_T *argvars, typval_T *rettv)); static void f_argc __ARGS((typval_T *argvars, typval_T *rettv)); static void f_argidx __ARGS((typval_T *argvars, typval_T *rettv)); static void f_argv __ARGS((typval_T *argvars, typval_T *rettv)); static void f_browse __ARGS((typval_T *argvars, typval_T *rettv)); static void f_browsedir __ARGS((typval_T *argvars, typval_T *rettv)); static void f_bufexists __ARGS((typval_T *argvars, typval_T *rettv)); static void f_buflisted __ARGS((typval_T *argvars, typval_T *rettv)); static void f_bufloaded __ARGS((typval_T *argvars, typval_T *rettv)); static void f_bufname __ARGS((typval_T *argvars, typval_T *rettv)); static void f_bufnr __ARGS((typval_T *argvars, typval_T *rettv)); static void f_bufwinnr __ARGS((typval_T *argvars, typval_T *rettv)); static void f_byte2line __ARGS((typval_T *argvars, typval_T *rettv)); static void f_byteidx __ARGS((typval_T *argvars, typval_T *rettv)); static void f_call __ARGS((typval_T *argvars, typval_T *rettv)); static void f_changenr __ARGS((typval_T *argvars, typval_T *rettv)); static void f_char2nr __ARGS((typval_T *argvars, typval_T *rettv)); static void f_cindent __ARGS((typval_T *argvars, typval_T *rettv)); static void f_col __ARGS((typval_T *argvars, typval_T *rettv)); #if defined(FEAT_INS_EXPAND) static void f_complete __ARGS((typval_T *argvars, typval_T *rettv)); static void f_complete_add __ARGS((typval_T *argvars, typval_T *rettv)); static void f_complete_check __ARGS((typval_T *argvars, typval_T *rettv)); #endif static void f_confirm __ARGS((typval_T *argvars, typval_T *rettv)); static void f_copy __ARGS((typval_T *argvars, typval_T *rettv)); static void f_count __ARGS((typval_T *argvars, typval_T *rettv)); static void f_cscope_connection __ARGS((typval_T *argvars, typval_T *rettv)); static void f_cursor __ARGS((typval_T *argsvars, typval_T *rettv)); static void f_deepcopy __ARGS((typval_T *argvars, typval_T *rettv)); static void f_delete __ARGS((typval_T *argvars, typval_T *rettv)); static void f_did_filetype __ARGS((typval_T *argvars, typval_T *rettv)); static void f_diff_filler __ARGS((typval_T *argvars, typval_T *rettv)); static void f_diff_hlID __ARGS((typval_T *argvars, typval_T *rettv)); static void f_empty __ARGS((typval_T *argvars, typval_T *rettv)); static void f_escape __ARGS((typval_T *argvars, typval_T *rettv)); static void f_eval __ARGS((typval_T *argvars, typval_T *rettv)); static void f_eventhandler __ARGS((typval_T *argvars, typval_T *rettv)); static void f_executable __ARGS((typval_T *argvars, typval_T *rettv)); static void f_exists __ARGS((typval_T *argvars, typval_T *rettv)); static void f_expand __ARGS((typval_T *argvars, typval_T *rettv));