summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/eval.c3167
-rw-r--r--src/gui_beval.c2
-rw-r--r--src/if_mzsch.c323
-rwxr-xr-xsrc/link.sh2
-rw-r--r--src/testdir/test.ok32
5 files changed, 1904 insertions, 1622 deletions
diff --git a/src/eval.c b/src/eval.c
index 50298e9f4b..1ef824b152 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -30,131 +30,21 @@
#if defined(FEAT_EVAL) || defined(PROTO)
-#if SIZEOF_INT <= 3 /* use long if int is smaller than 32 bits */
-typedef long varnumber_T;
-#else
-typedef int varnumber_T;
-#endif
-
-/*
- * Structure to hold an internal variable without a name.
- */
-typedef struct
-{
- char v_type; /* see below: VAR_NUMBER, VAR_STRING, etc. */
- union
- {
- varnumber_T v_number; /* number value */
- char_u *v_string; /* string value (can be NULL!) */
- struct listvar_S *v_list; /* list value (can be NULL!) */
- struct dictvar_S *v_dict; /* dict value (can be NULL!) */
- } vval;
-} typeval;
-
-/* Values for "v_type". */
-#define VAR_UNKNOWN 0
-#define VAR_NUMBER 1 /* "v_number" is used */
-#define VAR_STRING 2 /* "v_string" is used */
-#define VAR_FUNC 3 /* "v_string" is function name */
-#define VAR_LIST 4 /* "v_list" is used */
-#define VAR_DICT 5 /* "v_dict" is used */
-
-/*
- * Structure to hold an internal variable with a name.
- * The "tv" must come first, so that this can be used as a "typeval" as well.
- */
-typedef struct
-{
- typeval tv; /* type and value of the variable */
- char_u v_name[1]; /* name of variable (actually longer) */
-} var;
-
-typedef var * VAR;
-
-/*
- * In a hashtable item "hi_key" points to "v_name" in a variable.
- * This avoids adding a pointer to the hashtable item.
- * VAR2HIKEY() converts a var pointer to a hashitem key pointer.
- * HIKEY2VAR() converts a hashitem key pointer to a var pointer.
- * HI2VAR() converts a hashitem pointer to a var pointer.
- */
-static var dumvar;
-#define VAR2HIKEY(v) ((v)->v_name)
-#define HIKEY2VAR(p) ((VAR)(p - (dumvar.v_name - (char_u *)&dumvar.tv)))
-#define HI2VAR(hi) HIKEY2VAR((hi)->hi_key)
-
-/*
- * Structure to hold an item of a list: an internal variable without a name.
- */
-struct listitem_S
-{
- struct listitem_S *li_next; /* next item in list */
- struct listitem_S *li_prev; /* previous item in list */
- typeval li_tv; /* type and value of the variable */
-};
-
-typedef struct listitem_S listitem;
+#define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */
/*
- * Struct used by those that are using an item in a list.
- */
-typedef struct listwatch_S
-{
- listitem *lw_item; /* item being watched */
- struct listwatch_S *lw_next; /* next watcher */
-} listwatch;
-
-/*
- * Structure to hold info about a list.
- */
-struct listvar_S
-{
- int lv_refcount; /* reference count */
- listitem *lv_first; /* first item, NULL if none */
- listitem *lv_last; /* last item, NULL if none */
- listwatch *lv_watch; /* first watcher, NULL if none */
-};
-
-typedef struct listvar_S listvar;
-
-#define VAR_MAXNEST 100 /* maximum nesting of lists and dicts */
-
-/*
- * Structure to hold an item of a Dictionary.
- * The key is copied into "di_key" to avoid an extra alloc/free for it.
- */
-struct dictitem_S
-{
- typeval di_tv; /* type and value of the variable */
- char_u di_key[1]; /* key (actually longer!) */
-};
-
-typedef struct dictitem_S dictitem;
-
-/*
- * In a hashtable item "hi_key" points to "di_key" in a dictitem.
- * This avoids adding a pointer to the hashtable item.
+ * 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 dumdi;
+static dictitem_T dumdi;
#define DI2HIKEY(di) ((di)->di_key)
-#define HIKEY2DI(p) ((dictitem *)(p - (dumdi.di_key - (char_u *)&dumdi.di_tv)))
+#define HIKEY2DI(p) ((dictitem_T *)(p - (dumdi.di_key - (char_u *)&dumdi)))
#define HI2DI(hi) HIKEY2DI((hi)->hi_key)
/*
- * Structure to hold info about a Dictionary.
- */
-struct dictvar_S
-{
- int dv_refcount; /* reference count */
- hashtable dv_hashtable; /* hashtable that refers to the items */
-};
-
-typedef struct dictvar_S dictvar;
-
-/*
* Structure returned by get_lval() and used by set_var_lval().
* For a plain name:
* "name" points to the variable name.
@@ -178,26 +68,26 @@ typedef struct dictvar_S dictvar;
* 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 typeval
+ * "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. */
- typeval *ll_tv; /* Typeval of item being used. If "newkey"
+ 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 *ll_li; /* The list item or NULL. */
- listvar *ll_list; /* The list or NULL. */
+ 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:] */
- dictvar *ll_dict; /* The Dictionary or NULL */
- dictitem *ll_di; /* The dictitem or NULL */
+ 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;
+} lval_T;
static char *e_letunexp = N_("E18: Unexpected characters in :let");
@@ -218,15 +108,26 @@ static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary");
static char *e_letwrong = N_("E734: Wrong variable type for %s=");
/*
- * All user-defined global variables are stored in "variables".
+ * All user-defined global variables are stored in dictionary "globvardict".
+ * "globvars_var" is the variable that is used for "g:".
*/
-hashtable variables;
+static dict_T globvardict;
+static dictitem_T globvars_var;
+#define globvarht globvardict.dv_hashtab
/*
- * Array to hold the hashtable with variables local to each sourced script.
+ * Array to hold the hashtab with variables local to each sourced script.
+ * Each item holds a variable (nameless) that points to the dict_T.
*/
-static garray_T ga_scripts = {0, 0, sizeof(hashtable), 4, NULL};
-#define SCRIPT_VARS(id) (((hashtable *)ga_scripts.ga_data)[(id) - 1])
+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" */
@@ -268,53 +169,453 @@ ufunc_T *firstfunc = NULL;
#define FUNCARG(fp, j) ((char_u **)(fp->args.ga_data))[j]
#define FUNCLINE(fp, j) ((char_u **)(fp->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. */
-struct funccall
+typedef struct funccall_S
{
ufunc_T *func; /* function being called */
int linenr; /* next line to be executed */
int returned; /* ":return" used */
- int argcount; /* nr of arguments */
- typeval *argvars; /* arguments */
- var a0_var; /* "a:0" variable */
- var firstline; /* "a:firstline" variable */
- var lastline; /* "a:lastline" variable */
- hashtable l_vars; /* local function variables */
- typeval *rettv; /* return value */
+ 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 */
-};
+} funccall_T;
/*
* Info used by a ":for" loop.
*/
-typedef struct forinfo_S
+typedef struct
{
int fi_semicolon; /* TRUE if ending in '; var]' */
int fi_varcount; /* nr of variables in the list */
- listwatch fi_lw; /* keep an eye on the item used. */
- listvar *fi_list; /* list being used */
-} forinfo;
+ 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
{
- dictvar *fd_dict; /* Dictionary used */
+ dict_T *fd_dict; /* Dictionary used */
char_u *fd_newkey; /* new key in "dict" */
- dictitem *fd_di; /* Dictionary item used */
-} funcdict;
+ 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, sizeof(s) - 1, {{t}}, {0}
+
+static struct vimvar
+{
+ char *vv_name; /* name of variable, without v: */
+ int vv_len; /* length of name */
+ 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_STRING), VV_RO},
+ {VV_NAME("key", VAR_STRING), VV_RO},
+};
+
+/* 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 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));
+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 list_T *list_alloc __ARGS((void));
+static void list_unref __ARGS((list_T *l));
+static void list_free __ARGS((list_T *l));
+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 int string_isa_number __ARGS((char_u *s));
+static listitem_T *list_find __ARGS((list_T *l, long n));
+static long list_idx_of_item __ARGS((list_T *l, listitem_T *item));
+static listitem_T *list_find_ext __ARGS((list_T *l, long *ip));
+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_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));
+static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));
+static char_u *list2string __ARGS((typval_T *tv));
+static void list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo));
+
+static dict_T *dict_alloc __ARGS((void));
+static void dict_unref __ARGS((dict_T *d));
+static void dict_free __ARGS((dict_T *d));
+static dictitem_T *dictitem_alloc __ARGS((char_u *key));
+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 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));
+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));
+static char_u *tv2string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf));
+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 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_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));
+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));
+static void f_extend __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_filereadable __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_filewritable __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_filter __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_finddir __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_findfile __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_fnamemodify __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_foldclosed __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_foldclosedend __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_foldlevel __ARGS((typval_T *argvars, typval_T *rettv));
+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_foreground __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_function __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_getchar __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_getcharmod __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_getcmdline __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_getcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_getcwd __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_getfontname __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_getfperm __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_getfsize __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_getftime __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_getftype __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_getline __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_getreg __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_getregtype __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_getwinposx __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_getwinposy __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_getwinvar __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_glob __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_globpath __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_has __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_has_key __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_hasmapto __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_histadd __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_histdel __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_histget __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_histnr __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_hlID __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_hlexists __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_hostname __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_iconv __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_indent __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_index __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_input __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_inputdialog __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_inputrestore __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_inputsave __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_inputsecret __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_insert __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_isdirectory __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_items __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_join __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_keys __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_last_buffer_nr __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_len __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_libcall __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_libcallnr __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_line __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_line2byte __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_lispindent __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_localtime __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_map __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_match __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_matchend __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));
+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));
+static void f_prevnonblank __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_range __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_remote_expr __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_remote_foreground __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_remote_peek __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_remote_read __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_remote_send __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_remove __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_rename __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_repeat __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_resolve __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_reverse __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_search __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_searchpair __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_server2client __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_serverlist __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_setbufvar __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_setcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_setline __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_setreg __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_setwinvar __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_simplify __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_sort __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_split __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef HAVE_STRFTIME
+static void f_strftime __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
+static void f_stridx __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_string __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_strlen __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_strpart __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_strridx __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_strtrans __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_submatch __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_substitute __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_synID __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_synIDattr __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_synIDtrans __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_system __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_tempname __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_tolower __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_toupper __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_tr __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_type __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_values __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_virtcol __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_visualmode __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_winbufnr __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_wincol __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_winheight __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_winline __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_winnr __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_winrestcmd __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_winwidth __ARGS((typval_T *argvars, typval_T *rettv));
+
+static win_T *find_win_by_nr __ARGS((typval_T *vp));
+static pos_T *var2fpos __ARGS((typval_T *varp, int lnum));
+static int get_env_len __ARGS((char_u **arg));
+static int get_id_len __ARGS((char_u **arg));
+static int get_name_len __ARGS((char_u **arg, char_u **alias, int evaluate));
+static char_u *find_name_end __ARGS((char_u *arg, char_u **expr_start, char_u **expr_end, int incl_br));
+static int eval_isnamec __ARGS((int c));
+static int get_var_tv __ARGS((char_u *name, int len, typval_T *rettv));
+static typval_T *alloc_tv __ARGS((void));
+static typval_T *alloc_string_tv __ARGS((char_u *string));
+static void free_tv __ARGS((typval_T *varp));
+static void clear_tv __ARGS((typval_T *varp));
+static void init_tv __ARGS((typval_T *varp));
+static long get_tv_number __ARGS((typval_T *varp));
+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 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));
+static void list_one_var __ARGS((dictitem_T *v, char_u *prefix));
+static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string));
+static void set_var __ARGS((char_u *name, typval_T *varp, int copy));
+static int var_check_ro __ARGS((int flags, char_u *name));
+static void copy_tv __ARGS((typval_T *from, typval_T *to));
+static void item_copy __ARGS((typval_T *from, typval_T *to, int deep));
+static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags));
+static char_u *trans_function_name __ARGS((char_u **pp, int skip, int flags, funcdict_T *fd));
+static int eval_fname_script __ARGS((char_u *p));
+static int eval_fname_sid __ARGS((char_u *p));
+static void list_func_head __ARGS((ufunc_T *fp, int indent));
+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 void func_free __ARGS((ufunc_T *fp));
+static void func_unref __ARGS((char_u *name));
+static void func_ref __ARGS((char_u *name));
+static void call_user_func __ARGS((ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, linenr_T firstline, linenr_T lastline, dict_T *selfdict));
+static void add_nr_var __ARGS((dict_T *dp, dictitem_T *v, char *name, varnumber_T nr));
+static char_u * make_expanded_name __ARGS((char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end));
+
+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));
+static void list_vim_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));
+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 int do_unlet_var __ARGS((lval_T *lp, char_u *name_end, int forceit));
/*
- * Initialize the global variables.
+ * Initialize the global and v: variables.
*/
void
eval_init()
{
- hash_init(&variables);
+ int i;
+ struct vimvar *p;
+
+ init_var_dict(&globvardict, &globvars_var);
+ init_var_dict(&vimvardict, &vimvars_var);
+
+ for (i = 0; i < VV_LEN; ++i)
+ {
+ p = &vimvars[i];
+ STRCPY(p->vv_di.di_key, p->vv_name);
+ if (p->vv_flags & VV_RO)
+ p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
+ else if (p->vv_flags & VV_RO_SBX)
+ p->vv_di.di_flags = DI_FLAGS_RO_SBX | DI_FLAGS_FIX;
+ else
+ p->vv_di.di_flags = DI_FLAGS_FIX;
+ /* add to v: scope dict */
+ hash_add(&vimvarht, p->vv_di.di_key);
+ if (p->vv_flags & VV_COMPAT)
+ /* add to g: scope dict */
+ hash_add(&globvardict.dv_hashtab, p->vv_di.di_key);
+ }
}
/*
@@ -324,7 +625,7 @@ eval_init()
func_name(cookie)
void *cookie;
{
- return ((struct funccall *)cookie)->func->name;
+ return ((funccall_T *)cookie)->func->name;
}
/*
@@ -334,7 +635,7 @@ func_name(cookie)
func_breakpoint(cookie)
void *cookie;
{
- return &((struct funccall *)cookie)->breakpoint;
+ return &((funccall_T *)cookie)->breakpoint;
}
/*
@@ -344,7 +645,7 @@ func_breakpoint(cookie)
func_dbg_tick(cookie)
void *cookie;
{
- return &((struct funccall *)cookie)->dbg_tick;
+ return &((funccall_T *)cookie)->dbg_tick;
}
/*
@@ -354,11 +655,11 @@ func_dbg_tick(cookie)
func_level(cookie)
void *cookie;
{
- return ((struct funccall *)cookie)->level;
+ return ((funccall_T *)cookie)->level;
}
/* pointer to funccal for currently active function */
-struct funccall *current_funccal = NULL;
+funccall_T *current_funccal = NULL;
/*
* Return TRUE when a function was ended by a ":return" command.
@@ -371,361 +672,6 @@ current_func_returned()
/*
- * Array to hold the value of v: variables.
- */
-#include "version.h"
-
-/* values for 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) s, sizeof(s) - 1
-
-struct vimvar
-{
- char *name; /* name of variable, without v: */
- int len; /* length of name */
- typeval tv; /* type and value */
- char 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},
-};
-
-/* shorthand */
-#define vv_nr tv.vval.v_number
-#define vv_str tv.vval.v_string
-
-static int eval0 __ARGS((char_u *arg, typeval *rettv, char_u **nextcmd, int evaluate));
-static int eval1 __ARGS((char_u **arg, typeval *rettv, int evaluate));
-static int eval2 __ARGS((char_u **arg, typeval *rettv, int evaluate));
-static int eval3 __ARGS((char_u **arg, typeval *rettv, int evaluate));
-static int eval4 __ARGS((char_u **arg, typeval *rettv, int evaluate));
-static int eval5 __ARGS((char_u **arg, typeval *rettv, int evaluate));
-static int eval6 __ARGS((char_u **arg, typeval *rettv, int evaluate));
-static int eval7 __ARGS((char_u **arg, typeval *rettv, int evaluate));
-static int eval_index __ARGS((char_u **arg, typeval *rettv, int evaluate));
-static int get_option_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
-static int get_string_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
-static int get_lit_string_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
-static int get_list_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
-static listvar *list_alloc __ARGS((void));
-static void list_unref __ARGS((listvar *l));
-static void list_free __ARGS((listvar *l));
-static listitem *listitem_alloc __ARGS((void));
-static void listitem_free __ARGS((listitem *item));
-static void listitem_remove __ARGS((listvar *l, listitem *item));
-static long list_len __ARGS((listvar *l));
-static int list_equal __ARGS((listvar *l1, listvar *l2, int ic));
-static int dict_equal __ARGS((dictvar *d1, dictvar *d2, int ic));
-static int tv_equal __ARGS((typeval *tv1, typeval *tv2, int ic));
-static int string_isa_number __ARGS((char_u *s));
-static listitem *list_find __ARGS((listvar *l, long n));
-static long list_idx_of_item __ARGS((listvar *l, listitem *item));
-static listitem *list_find_ext __ARGS((listvar *l, long *ip));
-static void list_append __ARGS((listvar *l, listitem *item));
-static int list_append_tv __ARGS((listvar *l, typeval *tv));
-static int list_insert_tv __ARGS((listvar *l, typeval *tv, listitem *item));
-static int list_extend __ARGS((listvar *l1, listvar *l2, listitem *bef));
-static int list_concat __ARGS((listvar *l1, listvar *l2, typeval *tv));
-static listvar *list_copy __ARGS((listvar *orig, int deep));
-static void list_remove __ARGS((listvar *l, listitem *item, listitem *item2));
-static char_u *list2string __ARGS((typeval *tv));
-static void list_join __ARGS((garray_T *gap, listvar *l, char_u *sep, int echo));
-
-static dictvar *dict_alloc __ARGS((void));
-static void dict_unref __ARGS((dictvar *d));
-static void dict_free __ARGS((dictvar *d));
-static dictitem *dictitem_alloc __ARGS((char_u *key));
-static dictitem *dictitem_copy __ARGS((dictitem *org));
-static void dictitem_remove __ARGS((dictvar *dict, dictitem *item));
-static void dictitem_free __ARGS((dictitem *item));
-static int dict_add __ARGS((dictvar *d, dictitem *item));
-static long dict_len __ARGS((dictvar *d));
-static dictitem *dict_find __ARGS((dictvar *d, char_u *key, int len));
-static char_u *dict2string __ARGS((typeval *tv));
-static int get_dict_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
-
-static char_u *echo_string __ARGS((typeval *tv, char_u **tofree, char_u *numbuf));
-static char_u *tv2string __ARGS((typeval *tv, char_u **tofree, char_u *numbuf));
-static char_u *string_quote __ARGS((char_u *str, int function));
-static int get_env_tv __ARGS((char_u **arg, typeval *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, typeval *rettv, char_u **arg, linenr_T firstline, linenr_T