From 49cd957922488b6745ba023fa381af605b068121 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 3 Jan 2005 21:06:01 +0000 Subject: updated for version 7.0029 --- src/eval.c | 3850 +++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 2396 insertions(+), 1454 deletions(-) (limited to 'src') diff --git a/src/eval.c b/src/eval.c index 8a2c2052e5..82d1c69c52 100644 --- a/src/eval.c +++ b/src/eval.c @@ -37,25 +37,65 @@ typedef int varnumber_T; #endif /* - * Structure to hold an internal variable. + * Structure to hold an internal variable without a name. */ typedef struct { - char_u *var_name; /* name of variable */ - char var_type; /* VAR_NUMBER or VAR_STRING */ + char v_type; /* see below: VAR_NUMBER, VAR_STRING, etc. */ union { - varnumber_T var_number; /* number value */ - char_u *var_string; /* string value (Careful: can be NULL!) */ - } var_val; -} var; + 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!) */ + } vval; +} typeval; +/* Values for "v_type". */ #define VAR_UNKNOWN 0 -#define VAR_NUMBER 1 -#define VAR_STRING 2 +#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 */ + +/* + * 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; /* name of variable */ +} var; typedef var * VAR; +/* + * 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; + +/* + * Structure to hold the 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 */ +}; + +typedef struct listvar_S listvar; + +#define VAR_LIST_MAXNEST 100 /* maximum nesting of lists */ +static char_u *e_listidx = (char_u *)N_("E999: list index out of range: %ld"); + /* * All user-defined global variables are stored in "variables". */ @@ -114,12 +154,12 @@ struct funccall int linenr; /* next line to be executed */ int returned; /* ":return" used */ int argcount; /* nr of arguments */ - VAR argvars; /* arguments */ + typeval *argvars; /* arguments */ var a0_var; /* "a:0" variable */ var firstline; /* "a:firstline" variable */ var lastline; /* "a:lastline" variable */ garray_T l_vars; /* local function variables */ - VAR retvar; /* return value variable */ + typeval *retvar; /* return value variable */ 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 */ @@ -236,190 +276,214 @@ struct vimvar }; static int eval0 __ARGS((char_u *arg, VAR retvar, char_u **nextcmd, int evaluate)); -static int eval1 __ARGS((char_u **arg, VAR retvar, int evaluate)); -static int eval2 __ARGS((char_u **arg, VAR retvar, int evaluate)); -static int eval3 __ARGS((char_u **arg, VAR retvar, int evaluate)); -static int eval4 __ARGS((char_u **arg, VAR retvar, int evaluate)); -static int eval5 __ARGS((char_u **arg, VAR retvar, int evaluate)); -static int eval6 __ARGS((char_u **arg, VAR retvar, int evaluate)); -static int eval7 __ARGS((char_u **arg, VAR retvar, int evaluate)); -static int get_option_var __ARGS((char_u **arg, VAR retvar, int evaluate)); -static int get_string_var __ARGS((char_u **arg, VAR retvar, int evaluate)); -static int get_lit_string_var __ARGS((char_u **arg, VAR retvar, int evaluate)); -static int get_env_var __ARGS((char_u **arg, VAR retvar, int evaluate)); +static int eval1 __ARGS((char_u **arg, typeval *retvar, int evaluate)); +static int eval2 __ARGS((char_u **arg, typeval *retvar, int evaluate)); +static int eval3 __ARGS((char_u **arg, typeval *retvar, int evaluate)); +static int eval4 __ARGS((char_u **arg, typeval *retvar, int evaluate)); +static int eval5 __ARGS((char_u **arg, typeval *retvar, int evaluate)); +static int eval6 __ARGS((char_u **arg, typeval *retvar, int evaluate)); +static int eval7 __ARGS((char_u **arg, typeval *retvar, int evaluate)); +static int eval_index __ARGS((char_u **arg, typeval *retvar, int evaluate)); +static int get_option_vartv __ARGS((char_u **arg, typeval *retvar, int evaluate)); +static int get_string_vartv __ARGS((char_u **arg, typeval *retvar, int evaluate)); +static int get_lit_string_vartv __ARGS((char_u **arg, typeval *retvar, int evaluate)); +static int get_list_vartv __ARGS((char_u **arg, typeval *retvar, 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 long list_len __ARGS((listvar *l)); +static listitem *list_find __ARGS((listvar *l, long n)); +static void list_append __ARGS((listvar *l, listitem *item)); +static int list_append_tv __ARGS((listvar *l, typeval *tv)); +static listvar *list_copy __ARGS((listvar *orig, int deep)); +static listitem *list_getrem __ARGS((listvar *l, long n)); +static char_u *list2string __ARGS((typeval *tv)); +static char_u *tv2string __ARGS((typeval *tv, char_u **tofree)); +static int get_env_vartv __ARGS((char_u **arg, typeval *retvar, int evaluate)); static int find_internal_func __ARGS((char_u *name)); -static int get_func_var __ARGS((char_u *name, int len, VAR retvar, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate)); -static int call_func __ARGS((char_u *name, int len, VAR retvar, int argcount, VAR argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate)); -static void f_append __ARGS((VAR argvars, VAR retvar)); -static void f_argc __ARGS((VAR argvars, VAR retvar)); -static void f_argidx __ARGS((VAR argvars, VAR retvar)); -static void f_argv __ARGS((VAR argvars, VAR retvar)); -static void f_browse __ARGS((VAR argvars, VAR retvar)); -static void f_browsedir __ARGS((VAR argvars, VAR retvar)); -static buf_T *find_buffer __ARGS((VAR avar)); -static void f_bufexists __ARGS((VAR argvars, VAR retvar)); -static void f_buflisted __ARGS((VAR argvars, VAR retvar)); -static void f_bufloaded __ARGS((VAR argvars, VAR retvar)); -static buf_T *get_buf_var __ARGS((VAR avar)); -static void f_bufname __ARGS((VAR argvars, VAR retvar)); -static void f_bufnr __ARGS((VAR argvars, VAR retvar)); -static void f_bufwinnr __ARGS((VAR argvars, VAR retvar)); -static void f_byte2line __ARGS((VAR argvars, VAR retvar)); -static void f_byteidx __ARGS((VAR argvars, VAR retvar)); -static void f_char2nr __ARGS((VAR argvars, VAR retvar)); -static void f_cindent __ARGS((VAR argvars, VAR retvar)); -static void f_col __ARGS((VAR argvars, VAR retvar)); -static void f_confirm __ARGS((VAR argvars, VAR retvar)); -static void f_cscope_connection __ARGS((VAR argvars, VAR retvar)); -static void f_cursor __ARGS((VAR argsvars, VAR retvar)); -static void f_delete __ARGS((VAR argvars, VAR retvar)); -static void f_did_filetype __ARGS((VAR argvars, VAR retvar)); -static void f_diff_filler __ARGS((VAR argvars, VAR retvar)); -static void f_diff_hlID __ARGS((VAR argvars, VAR retvar)); -static void f_escape __ARGS((VAR argvars, VAR retvar)); -static void f_eventhandler __ARGS((VAR argvars, VAR retvar)); -static void f_executable __ARGS((VAR argvars, VAR retvar)); -static void f_exists __ARGS((VAR argvars, VAR retvar)); -static void f_expand __ARGS((VAR argvars, VAR retvar)); -static void f_filereadable __ARGS((VAR argvars, VAR retvar)); -static void f_filewritable __ARGS((VAR argvars, VAR retvar)); -static void f_finddir __ARGS((VAR argvars, VAR retvar)); -static void f_findfile __ARGS((VAR argvars, VAR retvar)); -static void f_findfilendir __ARGS((VAR argvars, VAR retvar, int dir)); -static void f_fnamemodify __ARGS((VAR argvars, VAR retvar)); -static void f_foldclosed __ARGS((VAR argvars, VAR retvar)); -static void f_foldclosedend __ARGS((VAR argvars, VAR retvar)); -static void foldclosed_both __ARGS((VAR argvars, VAR retvar, int end)); -static void f_foldlevel __ARGS((VAR argvars, VAR retvar)); -static void f_foldtext __ARGS((VAR argvars, VAR retvar)); -static void f_foldtextresult __ARGS((VAR argvars, VAR retvar)); -static void f_foreground __ARGS((VAR argvars, VAR retvar)); -static void f_getbufvar __ARGS((VAR argvars, VAR retvar)); -static void f_getchar __ARGS((VAR argvars, VAR retvar)); -static void f_getcharmod __ARGS((VAR argvars, VAR retvar)); -static void f_getcmdline __ARGS((VAR argvars, VAR retvar)); -static void f_getcmdpos __ARGS((VAR argvars, VAR retvar)); -static void f_getcwd __ARGS((VAR argvars, VAR retvar)); -static void f_getfontname __ARGS((VAR argvars, VAR retvar)); -static void f_getfperm __ARGS((VAR argvars, VAR retvar)); -static void f_getfsize __ARGS((VAR argvars, VAR retvar)); -static void f_getftime __ARGS((VAR argvars, VAR retvar)); -static void f_getftype __ARGS((VAR argvars, VAR retvar)); -static void f_getline __ARGS((VAR argvars, VAR retvar)); -static void f_getreg __ARGS((VAR argvars, VAR retvar)); -static void f_getregtype __ARGS((VAR argvars, VAR retvar)); -static void f_getwinposx __ARGS((VAR argvars, VAR retvar)); -static void f_getwinposy __ARGS((VAR argvars, VAR retvar)); -static void f_getwinvar __ARGS((VAR argvars, VAR retvar)); -static void f_glob __ARGS((VAR argvars, VAR retvar)); -static void f_globpath __ARGS((VAR argvars, VAR retvar)); -static void f_has __ARGS((VAR argvars, VAR retvar)); -static void f_hasmapto __ARGS((VAR argvars, VAR retvar)); -static void f_histadd __ARGS((VAR argvars, VAR retvar)); -static void f_histdel __ARGS((VAR argvars, VAR retvar)); -static void f_histget __ARGS((VAR argvars, VAR retvar)); -static void f_histnr __ARGS((VAR argvars, VAR retvar)); -static void f_hlexists __ARGS((VAR argvars, VAR retvar)); -static void f_hlID __ARGS((VAR argvars, VAR retvar)); -static void f_hostname __ARGS((VAR argvars, VAR retvar)); -static void f_iconv __ARGS((VAR argvars, VAR retvar)); -static void f_indent __ARGS((VAR argvars, VAR retvar)); -static void f_isdirectory __ARGS((VAR argvars, VAR retvar)); -static void f_input __ARGS((VAR argvars, VAR retvar)); -static void f_inputdialog __ARGS((VAR argvars, VAR retvar)); -static void f_inputrestore __ARGS((VAR argvars, VAR retvar)); -static void f_inputsave __ARGS((VAR argvars, VAR retvar)); -static void f_inputsecret __ARGS((VAR argvars, VAR retvar)); -static void f_last_buffer_nr __ARGS((VAR argvars, VAR retvar)); -static void f_libcall __ARGS((VAR argvars, VAR retvar)); -static void f_libcallnr __ARGS((VAR argvars, VAR retvar)); -static void libcall_common __ARGS((VAR argvars, VAR retvar, int type)); -static void f_line __ARGS((VAR argvars, VAR retvar)); -static void f_line2byte __ARGS((VAR argvars, VAR retvar)); -static void f_lispindent __ARGS((VAR argvars, VAR retvar)); -static void f_localtime __ARGS((VAR argvars, VAR retvar)); -static void f_maparg __ARGS((VAR argvars, VAR retvar)); -static void f_mapcheck __ARGS((VAR argvars, VAR retvar)); -static void get_maparg __ARGS((VAR argvars, VAR retvar, int exact)); -static void f_match __ARGS((VAR argvars, VAR retvar)); -static void f_matchend __ARGS((VAR argvars, VAR retvar)); -static void f_matchstr __ARGS((VAR argvars, VAR retvar)); -static void f_mode __ARGS((VAR argvars, VAR retvar)); -static void f_nextnonblank __ARGS((VAR argvars, VAR retvar)); -static void f_nr2char __ARGS((VAR argvars, VAR retvar)); -static void f_prevnonblank __ARGS((VAR argvars, VAR retvar)); -static void f_setbufvar __ARGS((VAR argvars, VAR retvar)); -static void f_setcmdpos __ARGS((VAR argvars, VAR retvar)); -static void f_setwinvar __ARGS((VAR argvars, VAR retvar)); -static void f_rename __ARGS((VAR argvars, VAR retvar)); -static void f_resolve __ARGS((VAR argvars, VAR retvar)); -static void f_search __ARGS((VAR argvars, VAR retvar)); -static void f_searchpair __ARGS((VAR argvars, VAR retvar)); -static int get_search_arg __ARGS((VAR varp, int *flagsp)); -static void f_remote_expr __ARGS((VAR argvars, VAR retvar)); -static void f_remote_foreground __ARGS((VAR argvars, VAR retvar)); -static void f_remote_peek __ARGS((VAR argvars, VAR retvar)); -static void f_remote_read __ARGS((VAR argvars, VAR retvar)); -static void f_remote_send __ARGS((VAR argvars, VAR retvar)); -static void f_repeat __ARGS((VAR argvars, VAR retvar)); -static void f_server2client __ARGS((VAR argvars, VAR retvar)); -static void f_serverlist __ARGS((VAR argvars, VAR retvar)); -static void f_setline __ARGS((VAR argvars, VAR retvar)); -static void f_setreg __ARGS((VAR argvars, VAR retvar)); -static void f_simplify __ARGS((VAR argvars, VAR retvar)); -static void find_some_match __ARGS((VAR argvars, VAR retvar, int start)); -static void f_strftime __ARGS((VAR argvars, VAR retvar)); -static void f_stridx __ARGS((VAR argvars, VAR retvar)); -static void f_strlen __ARGS((VAR argvars, VAR retvar)); -static void f_strpart __ARGS((VAR argvars, VAR retvar)); -static void f_strridx __ARGS((VAR argvars, VAR retvar)); -static void f_strtrans __ARGS((VAR argvars, VAR retvar)); -static void f_synID __ARGS((VAR argvars, VAR retvar)); -static void f_synIDattr __ARGS((VAR argvars, VAR retvar)); -static void f_synIDtrans __ARGS((VAR argvars, VAR retvar)); -static void f_system __ARGS((VAR argvars, VAR retvar)); -static void f_submatch __ARGS((VAR argvars, VAR retvar)); -static void f_substitute __ARGS((VAR argvars, VAR retvar)); -static void f_tempname __ARGS((VAR argvars, VAR retvar)); -static void f_tolower __ARGS((VAR argvars, VAR retvar)); -static void f_toupper __ARGS((VAR argvars, VAR retvar)); -static void f_tr __ARGS((VAR argvars, VAR retvar)); -static void f_type __ARGS((VAR argvars, VAR retvar)); -static void f_virtcol __ARGS((VAR argvars, VAR retvar)); -static void f_visualmode __ARGS((VAR argvars, VAR retvar)); -static void f_winbufnr __ARGS((VAR argvars, VAR retvar)); -static void f_wincol __ARGS((VAR argvars, VAR retvar)); -static void f_winheight __ARGS((VAR argvars, VAR retvar)); -static void f_winline __ARGS((VAR argvars, VAR retvar)); -static void f_winnr __ARGS((VAR argvars, VAR retvar)); -static void f_winrestcmd __ARGS((VAR argvars, VAR retvar)); -static void f_winwidth __ARGS((VAR argvars, VAR retvar)); -static win_T *find_win_by_nr __ARGS((VAR vp)); -static pos_T *var2fpos __ARGS((VAR varp, int lnum)); +static char_u *deref_func_name __ARGS((char_u *name, int *lenp)); +static int get_func_vartv __ARGS((char_u *name, int len, typeval *retvar, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate)); +static int call_func __ARGS((char_u *name, int len, typeval *retvar, int argcount, typeval *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate)); +static void f_append __ARGS((typeval *argvars, typeval *retvar)); +static void f_argc __ARGS((typeval *argvars, typeval *retvar)); +static void f_argidx __ARGS((typeval *argvars, typeval *retvar)); +static void f_argv __ARGS((typeval *argvars, typeval *retvar)); +static void f_browse __ARGS((typeval *argvars, typeval *retvar)); +static void f_browsedir __ARGS((typeval *argvars, typeval *retvar)); +static buf_T *find_buffer __ARGS((typeval *avar)); +static void f_bufexists __ARGS((typeval *argvars, typeval *retvar)); +static void f_buflisted __ARGS((typeval *argvars, typeval *retvar)); +static void f_bufloaded __ARGS((typeval *argvars, typeval *retvar)); +static buf_T *get_buf_vartv __ARGS((typeval *avar)); +static void f_bufname __ARGS((typeval *argvars, typeval *retvar)); +static void f_bufnr __ARGS((typeval *argvars, typeval *retvar)); +static void f_bufwinnr __ARGS((typeval *argvars, typeval *retvar)); +static void f_byte2line __ARGS((typeval *argvars, typeval *retvar)); +static void f_byteidx __ARGS((typeval *argvars, typeval *retvar)); +static void f_char2nr __ARGS((typeval *argvars, typeval *retvar)); +static void f_cindent __ARGS((typeval *argvars, typeval *retvar)); +static void f_col __ARGS((typeval *argvars, typeval *retvar)); +static void f_confirm __ARGS((typeval *argvars, typeval *retvar)); +static void f_copy __ARGS((typeval *argvars, typeval *retvar)); +static void f_cscope_connection __ARGS((typeval *argvars, typeval *retvar)); +static void f_cursor __ARGS((typeval *argsvars, typeval *retvar)); +static void f_deepcopy __ARGS((typeval *argvars, typeval *retvar)); +static void f_delete __ARGS((typeval *argvars, typeval *retvar)); +static void f_did_filetype __ARGS((typeval *argvars, typeval *retvar)); +static void f_diff_filler __ARGS((typeval *argvars, typeval *retvar)); +static void f_diff_hlID __ARGS((typeval *argvars, typeval *retvar)); +static void f_escape __ARGS((typeval *argvars, typeval *retvar)); +static void f_eventhandler __ARGS((typeval *argvars, typeval *retvar)); +static void f_executable __ARGS((typeval *argvars, typeval *retvar)); +static void f_exists __ARGS((typeval *argvars, typeval *retvar)); +static void f_expand __ARGS((typeval *argvars, typeval *retvar)); +static void f_filereadable __ARGS((typeval *argvars, typeval *retvar)); +static void f_filewritable __ARGS((typeval *argvars, typeval *retvar)); +static void f_finddir __ARGS((typeval *argvars, typeval *retvar)); +static void f_findfile __ARGS((typeval *argvars, typeval *retvar)); +static void f_findfilendir __ARGS((typeval *argvars, typeval *retvar, int dir)); +static void f_fnamemodify __ARGS((typeval *argvars, typeval *retvar)); +static void f_foldclosed __ARGS((typeval *argvars, typeval *retvar)); +static void f_foldclosedend __ARGS((typeval *argvars, typeval *retvar)); +static void foldclosed_both __ARGS((typeval *argvars, typeval *retvar, int end)); +static void f_foldlevel __ARGS((typeval *argvars, typeval *retvar)); +static void f_foldtext __ARGS((typeval *argvars, typeval *retvar)); +static void f_foldtextresult __ARGS((typeval *argvars, typeval *retvar)); +static void f_foreground __ARGS((typeval *argvars, typeval *retvar)); +static void f_function __ARGS((typeval *argvars, typeval *retvar)); +static void f_getbufvar __ARGS((typeval *argvars, typeval *retvar)); +static void f_getchar __ARGS((typeval *argvars, typeval *retvar)); +static void f_getcharmod __ARGS((typeval *argvars, typeval *retvar)); +static void f_getcmdline __ARGS((typeval *argvars, typeval *retvar)); +static void f_getcmdpos __ARGS((typeval *argvars, typeval *retvar)); +static void f_getcwd __ARGS((typeval *argvars, typeval *retvar)); +static void f_getfontname __ARGS((typeval *argvars, typeval *retvar)); +static void f_getfperm __ARGS((typeval *argvars, typeval *retvar)); +static void f_getfsize __ARGS((typeval *argvars, typeval *retvar)); +static void f_getftime __ARGS((typeval *argvars, typeval *retvar)); +static void f_getftype __ARGS((typeval *argvars, typeval *retvar)); +static void f_getline __ARGS((typeval *argvars, typeval *retvar)); +static void f_getreg __ARGS((typeval *argvars, typeval *retvar)); +static void f_getregtype __ARGS((typeval *argvars, typeval *retvar)); +static void f_getwinposx __ARGS((typeval *argvars, typeval *retvar)); +static void f_getwinposy __ARGS((typeval *argvars, typeval *retvar)); +static void f_getwinvar __ARGS((typeval *argvars, typeval *retvar)); +static void f_glob __ARGS((typeval *argvars, typeval *retvar)); +static void f_globpath __ARGS((typeval *argvars, typeval *retvar)); +static void f_has __ARGS((typeval *argvars, typeval *retvar)); +static void f_hasmapto __ARGS((typeval *argvars, typeval *retvar)); +static void f_histadd __ARGS((typeval *argvars, typeval *retvar)); +static void f_histdel __ARGS((typeval *argvars, typeval *retvar)); +static void f_histget __ARGS((typeval *argvars, typeval *retvar)); +static void f_histnr __ARGS((typeval *argvars, typeval *retvar)); +static void f_hlexists __ARGS((typeval *argvars, typeval *retvar)); +static void f_hlID __ARGS((typeval *argvars, typeval *retvar)); +static void f_hostname __ARGS((typeval *argvars, typeval *retvar)); +static void f_iconv __ARGS((typeval *argvars, typeval *retvar)); +static void f_indent __ARGS((typeval *argvars, typeval *retvar)); +static void f_insert __ARGS((typeval *argvars, typeval *retvar)); +static void f_isdirectory __ARGS((typeval *argvars, typeval *retvar)); +static void f_input __ARGS((typeval *argvars, typeval *retvar)); +static void f_inputdialog __ARGS((typeval *argvars, typeval *retvar)); +static void f_inputrestore __ARGS((typeval *argvars, typeval *retvar)); +static void f_inputsave __ARGS((typeval *argvars, typeval *retvar)); +static void f_inputsecret __ARGS((typeval *argvars, typeval *retvar)); +static void f_last_buffer_nr __ARGS((typeval *argvars, typeval *retvar)); +static void f_len __ARGS((typeval *argvars, typeval *retvar)); +static void f_libcall __ARGS((typeval *argvars, typeval *retvar)); +static void f_libcallnr __ARGS((typeval *argvars, typeval *retvar)); +static void libcall_common __ARGS((typeval *argvars, typeval *retvar, int type)); +static void f_line __ARGS((typeval *argvars, typeval *retvar)); +static void f_line2byte __ARGS((typeval *argvars, typeval *retvar)); +static void f_lispindent __ARGS((typeval *argvars, typeval *retvar)); +static void f_localtime __ARGS((typeval *argvars, typeval *retvar)); +static void f_maparg __ARGS((typeval *argvars, typeval *retvar)); +static void f_mapcheck __ARGS((typeval *argvars, typeval *retvar)); +static void get_maparg __ARGS((typeval *argvars, typeval *retvar, int exact)); +static void f_match __ARGS((typeval *argvars, typeval *retvar)); +static void f_matchend __ARGS((typeval *argvars, typeval *retvar)); +static void f_matchstr __ARGS((typeval *argvars, typeval *retvar)); +static void f_mode __ARGS((typeval *argvars, typeval *retvar)); +static void f_nextnonblank __ARGS((typeval *argvars, typeval *retvar)); +static void f_nr2char __ARGS((typeval *argvars, typeval *retvar)); +static void f_prevnonblank __ARGS((typeval *argvars, typeval *retvar)); +static void f_setbufvar __ARGS((typeval *argvars, typeval *retvar)); +static void f_setcmdpos __ARGS((typeval *argvars, typeval *retvar)); +static void f_setwinvar __ARGS((typeval *argvars, typeval *retvar)); +static void f_remove __ARGS((typeval *argvars, typeval *retvar)); +static void f_rename __ARGS((typeval *argvars, typeval *retvar)); +static void f_resolve __ARGS((typeval *argvars, typeval *retvar)); +static void f_search __ARGS((typeval *argvars, typeval *retvar)); +static void f_searchpair __ARGS((typeval *argvars, typeval *retvar)); +static int get_search_arg __ARGS((typeval *varp, int *flagsp)); +static void f_remote_expr __ARGS((typeval *argvars, typeval *retvar)); +static void f_remote_foreground __ARGS((typeval *argvars, typeval *retvar)); +static void f_remote_peek __ARGS((typeval *argvars, typeval *retvar)); +static void f_remote_read __ARGS((typeval *argvars, typeval *retvar)); +static void f_remote_send __ARGS((typeval *argvars, typeval *retvar)); +static void f_repeat __ARGS((typeval *argvars, typeval *retvar)); +static void f_server2client __ARGS((typeval *argvars, typeval *retvar)); +static void f_serverlist __ARGS((typeval *argvars, typeval *retvar)); +static void f_setline __ARGS((typeval *argvars, typeval *retvar)); +static void f_setreg __ARGS((typeval *argvars, typeval *retvar)); +static void f_simplify __ARGS((typeval *argvars, typeval *retvar)); +static void find_some_match __ARGS((typeval *argvars, typeval *retvar, int start)); +static void f_strftime __ARGS((typeval *argvars, typeval *retvar)); +static void f_stridx __ARGS((typeval *argvars, typeval *retvar)); +static void f_string __ARGS((typeval *argvars, typeval *retvar)); +static void f_strlen __ARGS((typeval *argvars, typeval *retvar)); +static void f_strpart __ARGS((typeval *argvars, typeval *retvar)); +static void f_strridx __ARGS((typeval *argvars, typeval *retvar)); +static void f_strtrans __ARGS((typeval *argvars, typeval *retvar)); +static void f_synID __ARGS((typeval *argvars, typeval *retvar)); +static void f_synIDattr __ARGS((typeval *argvars, typeval *retvar)); +static void f_synIDtrans __ARGS((typeval *argvars, typeval *retvar)); +static void f_system __ARGS((typeval *argvars, typeval *retvar)); +static void f_submatch __ARGS((typeval *argvars, typeval *retvar)); +static void f_substitute __ARGS((typeval *argvars, typeval *retvar)); +static void f_tempname __ARGS((typeval *argvars, typeval *retvar)); +static void f_tolower __ARGS((typeval *argvars, typeval *retvar)); +static void f_toupper __ARGS((typeval *argvars, typeval *retvar)); +static void f_tr __ARGS((typeval *argvars, typeval *retvar)); +static void f_type __ARGS((typeval *argvars, typeval *retvar)); +static void f_virtcol __ARGS((typeval *argvars, typeval *retvar)); +static void f_visualmode __ARGS((typeval *argvars, typeval *retvar)); +static void f_winbufnr __ARGS((typeval *argvars, typeval *retvar)); +static void f_wincol __ARGS((typeval *argvars, typeval *retvar)); +static void f_winheight __ARGS((typeval *argvars, typeval *retvar)); +static void f_winline __ARGS((typeval *argvars, typeval *retvar)); +static void f_winnr __ARGS((typeval *argvars, typeval *retvar)); +static void f_winrestcmd __ARGS((typeval *argvars, typeval *retvar)); +static void f_winwidth __ARGS((typeval *argvars, typeval *retvar)); +static win_T *find_win_by_nr __ARGS((typeval *vp)); +static pos_T *var2fpos __ARGS((typeval *varp, int lnum)); static int get_env_len __ARGS((char_u **arg)); static int get_id_len __ARGS((char_u **arg)); static int get_func_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)); static int eval_isnamec __ARGS((int c)); static int find_vim_var __ARGS((char_u *name, int len)); -static int get_var_var __ARGS((char_u *name, int len, VAR retvar)); +static int get_var_vartv __ARGS((char_u *name, int len, typeval *retvar)); static VAR alloc_var __ARGS((void)); -static VAR alloc_string_var __ARGS((char_u *string)); -static void free_var __ARGS((VAR varp)); -static void clear_var __ARGS((VAR varp)); -static long get_var_number __ARGS((VAR varp)); -static linenr_T get_var_lnum __ARGS((VAR argvars)); -static char_u *get_var_string __ARGS((VAR varp)); -static char_u *get_var_string_buf __ARGS((VAR varp, char_u *buf)); +static typeval *alloc_vartv __ARGS((void)); +static typeval *alloc_string_vartv __ARGS((char_u *string)); +static void free_vartv __ARGS((typeval *varp)); +static void clear_vartv __ARGS((typeval *varp)); +static long get_vartv_number __ARGS((typeval *varp)); +static linenr_T get_vartv_lnum __ARGS((typeval *argvars)); +static char_u *get_vartv_string __ARGS((typeval *varp)); +static char_u *get_vartv_string_buf __ARGS((typeval *varp, char_u *buf)); static VAR find_var __ARGS((char_u *name, int writing)); static VAR find_var_in_ga __ARGS((garray_T *gap, char_u *varname)); static garray_T *find_var_ga __ARGS((char_u *name, char_u **varname)); -static void var_free_one __ARGS((VAR v)); +static void clear_var __ARGS((VAR v)); static void list_one_var __ARGS((VAR v, char_u *prefix)); static void list_vim_var __ARGS((int i)); 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, VAR varp, int copy)); -static void copy_var __ARGS((VAR from, VAR to)); +static void set_var __ARGS((char_u *name, typeval *varp, int copy)); +static void copy_vartv __ARGS((typeval *from, typeval *to)); 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 internal)); static int eval_fname_script __ARGS((char_u *p)); @@ -427,7 +491,12 @@ 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 void call_user_func __ARGS((ufunc_T *fp, int argcount, VAR argvars, VAR retvar, linenr_T firstline, linenr_T lastline)); +static int function_exists __ARGS((char_u *name)); +static void call_user_func __ARGS((ufunc_T *fp, int argcount, typeval *argvars, typeval *retvar, linenr_T firstline, linenr_T lastline)); + +#define get_var_string(p) get_vartv_string(&(p)->tv) +#define get_var_string_buf(p, b) get_vartv_string_buf(&(p)->tv, (b)) +#define get_var_number(p) get_vartv_number(&((p)->tv)) /* Magic braces are always enabled, otherwise Vim scripts would not be * portable. */ @@ -446,17 +515,17 @@ set_internal_string_var(name, value) char_u *name; char_u *value; { - char_u *val; - VAR varp; + char_u *val; + typeval *tvp; val = vim_strsave(value); if (val != NULL) { - varp = alloc_string_var(val); - if (varp != NULL) + tvp = alloc_string_vartv(val); + if (tvp != NULL) { - set_var(name, varp, FALSE); - free_var(varp); + set_var(name, tvp, FALSE); + free_vartv(tvp); } } } @@ -575,7 +644,7 @@ eval_to_bool(arg, error, nextcmd, skip) if (!skip) { retval = (get_var_number(&retvar) != 0); - clear_var(&retvar); + clear_vartv(&retvar.tv); } } if (skip) @@ -605,7 +674,7 @@ eval_to_string_skip(arg, nextcmd, skip) else { retval = vim_strsave(get_var_string(&retvar)); - clear_var(&retvar); + clear_vartv(&retvar.tv); } if (skip) --emsg_skip; @@ -621,7 +690,7 @@ eval_to_string_skip(arg, nextcmd, skip) skip_expr(pp) char_u **pp; { - var retvar; + typeval retvar; *pp = skipwhite(*pp); return eval1(pp, &retvar, FALSE); @@ -644,7 +713,7 @@ eval_to_string(arg, nextcmd) else { retval = vim_strsave(get_var_string(&retvar)); - clear_var(&retvar); + clear_vartv(&retvar.tv); } return retval; @@ -680,7 +749,7 @@ eval_to_string_safe(arg, nextcmd) eval_arg_to_string(arg) char_u **arg; { - var retvar; + typeval retvar; char_u *retval; int ret; @@ -691,8 +760,8 @@ eval_arg_to_string(arg) retval = NULL; else { - retval = vim_strsave(get_var_string(&retvar)); - clear_var(&retvar); + retval = vim_strsave(get_vartv_string(&retvar)); + clear_vartv(&retvar); } --emsg_off; @@ -710,7 +779,7 @@ eval_arg_to_string(arg) eval_to_number(expr) char_u *expr; { - var retvar; + typeval retvar; int retval; char_u *p = expr; @@ -720,8 +789,8 @@ eval_to_number(expr) retval = -1; else { - retval = get_var_number(&retvar); - clear_var(&retvar); + retval = get_vartv_number(&retvar); + clear_vartv(&retvar); } --emsg_off; @@ -742,14 +811,14 @@ call_vim_function(func, argc, argv, safe) { char_u *retval = NULL; var retvar; - VAR argvars; + typeval *argvars; long n; int len; int i; int doesrange; void *save_funccalp = NULL; - argvars = (VAR)alloc((unsigned)(argc * sizeof(var))); + argvars = (typeval *)alloc((unsigned)(argc * sizeof(typeval))); if (argvars == NULL) return NULL; @@ -758,8 +827,8 @@ call_vim_function(func, argc, argv, safe) /* Pass a NULL or empty argument as an empty string */ if (argv[i] == NULL || *argv[i] == NUL) { - argvars[i].var_type = VAR_STRING; - argvars[i].var_val.var_string = (char_u *)""; + argvars[i].v_type = VAR_STRING; + argvars[i].vval.v_string = (char_u *)""; continue; } @@ -767,13 +836,13 @@ call_vim_function(func, argc, argv, safe) vim_str2nr(argv[i], NULL, &len, TRUE, TRUE, &n, NULL); if (len != 0 && len == (int)STRLEN(argv[i])) { - argvars[i].var_type = VAR_NUMBER; - argvars[i].var_val.var_number = n; + argvars[i].v_type = VAR_NUMBER; + argvars[i].vval.v_number = n; } else { - argvars[i].var_type = VAR_STRING; - argvars[i].var_val.var_string = argv[i]; + argvars[i].v_type = VAR_STRING; + argvars[i].vval.v_string = argv[i]; } } @@ -783,13 +852,13 @@ call_vim_function(func, argc, argv, safe) ++sandbox; } - retvar.var_type = VAR_UNKNOWN; /* clear_var() uses this */ - if (call_func(func, (int)STRLEN(func), &retvar, argc, argvars, + retvar.tv.v_type = VAR_UNKNOWN; /* clear_vartv() uses this */ + if (call_func(func, (int)STRLEN(func), &retvar.tv, argc, argvars, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &doesrange, TRUE) == OK) retval = vim_strsave(get_var_string(&retvar)); - clear_var(&retvar); + clear_vartv(&retvar.tv); vim_free(argvars); if (safe) @@ -844,21 +913,21 @@ eval_foldexpr(arg, cp) else { /* If the result is a number, just return the number. */ - if (retvar.var_type == VAR_NUMBER) - retval = retvar.var_val.var_number; - else if (retvar.var_type == VAR_UNKNOWN - || retvar.var_val.var_string == NULL) + if (retvar.tv.v_type == VAR_NUMBER) + retval = retvar.tv.vval.v_number; + else if (retvar.tv.v_type == VAR_UNKNOWN + || retvar.tv.vval.v_string == NULL) retval = 0; else { /* If the result is a string, check if there is a non-digit before * the number. */ - s = retvar.var_val.var_string; + s = retvar.tv.vval.v_string; if (!VIM_ISDIGIT(*s) && *s != '-') *cp = *s++; retval = atol((char *)s); } - clear_var(&retvar); + clear_vartv(&retvar.tv); } --emsg_off; --sandbox; @@ -970,13 +1039,13 @@ ex_let(eap) * List all variables. */ for (i = 0; i < variables.ga_len && !got_int; ++i) - if (VAR_ENTRY(i).var_name != NULL) + if (VAR_ENTRY(i).v_name != NULL) list_one_var(&VAR_ENTRY(i), (char_u *)""); for (i = 0; i < curbuf->b_vars.ga_len && !got_int; ++i) - if (BVAR_ENTRY(i).var_name != NULL) + if (BVAR_ENTRY(i).v_name != NULL) list_one_var(&BVAR_ENTRY(i), (char_u *)"b:"); for (i = 0; i < curwin->w_vars.ga_len && !got_int; ++i) - if (WVAR_ENTRY(i).var_name != NULL) + if (WVAR_ENTRY(i).v_name != NULL) list_one_var(&WVAR_ENTRY(i), (char_u *)"w:"); for (i = 0; i < VV_LEN && !got_int; ++i) if (vimvars[i].type == VAR_NUMBER || vimvars[i].val != NULL) @@ -1103,7 +1172,7 @@ ex_let(eap) if (eap->skip) { if (i != FAIL) - clear_var(&retvar); + clear_vartv(&retvar.tv); --emsg_skip; } else if (i != FAIL) @@ -1214,7 +1283,7 @@ ex_let(eap) } else { - set_var(temp_string, &retvar, TRUE); + set_var(temp_string, &retvar.tv, TRUE); vim_free(temp_string); } } @@ -1223,7 +1292,7 @@ ex_let(eap) { c1 = *p; *p = NUL; - set_var(arg, &retvar, TRUE); + set_var(arg, &retvar.tv, TRUE); *p = c1; /* put char back for error messages */ } } @@ -1233,7 +1302,7 @@ ex_let(eap) EMSG2(_(e_invarg2), arg); } - clear_var(&retvar); + clear_vartv(&retvar.tv); } } } @@ -1350,7 +1419,7 @@ ex_call(eap) name = alias; startarg = arg; - retvar.var_type = VAR_UNKNOWN; /* clear_var() uses this */ + retvar.tv.v_type = VAR_UNKNOWN; /* clear_vartv() uses this */ if (*startarg != '(') { @@ -1379,19 +1448,19 @@ ex_call(eap) curwin->w_cursor.col = 0; } arg = startarg; - if (get_func_var(name, len, &retvar, &arg, + if (get_func_vartv(name, len, &retvar.tv, &arg, eap->line1, eap->line2, &doesrange, !eap->skip) == FAIL) { failed = TRUE; break; } - clear_var(&retvar); + clear_vartv(&retvar.tv); if (doesrange || eap->skip) break; /* Stop when immediately aborting on error, or when an interrupt - * occurred or an exception was thrown but not caught. get_func_var() - * returned OK, so that the check for trailing characters below is - * executed. */ + * occurred or an exception was thrown but not caught. + * get_func_vartv() returned OK, so that the check for trailing + * characters below is executed. */ if (aborting()) break; } @@ -1508,7 +1577,7 @@ do_unlet(name) v = find_var(name, TRUE); if (v != NULL) { - var_free_one(v); + clear_var(v); return OK; } return FAIL; @@ -1524,9 +1593,9 @@ del_menutrans_vars() int i; for (i = 0; i < variables.ga_len; ++i) - if (VAR_ENTRY(i).var_name != NULL - && STRNCMP(VAR_ENTRY(i).var_name, "menutrans_", 10) == 0) - var_free_one(&VAR_ENTRY(i)); + if (VAR_ENTRY(i).v_name != NULL + && STRNCMP(VAR_ENTRY(i).v_name, "menutrans_", 10) == 0) + clear_var(&VAR_ENTRY(i)); } #endif @@ -1592,7 +1661,7 @@ get_user_var_name(xp, idx) gidx = bidx = widx = vidx = 0; if (gidx < variables.ga_len) /* Global variables */ { - while ((name = VAR_ENTRY(gidx++).var_name) == NULL + while ((name = VAR_ENTRY(gidx++).v_name) == NULL && gidx < variables.ga_len) /* skip */; if (name != NULL) @@ -1605,7 +1674,7 @@ get_user_var_name(xp, idx) } if (bidx < curbuf->b_vars.ga_len) /* Current buffer variables */ { - while ((name = BVAR_ENTRY(bidx++).var_name) == NULL + while ((name = BVAR_ENTRY(bidx++).v_name) == NULL && bidx < curbuf->b_vars.ga_len) /* skip */; if (name != NULL) @@ -1618,7 +1687,7 @@ get_user_var_name(xp, idx) } if (widx < curwin->w_vars.ga_len) /* Current window variables */ { - while ((name = WVAR_ENTRY(widx++).var_name) == NULL + while ((name = WVAR_ENTRY(widx++).v_name) == NULL && widx < curwin->w_vars.ga_len) /* skip */; if (name != NULL) @@ -1673,11 +1742,11 @@ eval0(arg, retvar, nextcmd, evaluate) char_u *p; p = skipwhite(arg); - ret = eval1(&p, retvar, evaluate); + ret = eval1(&p, &retvar->tv, evaluate); if (ret == FAIL || !ends_excmd(*p)) { if (ret != FAIL) - clear_var(retvar); + clear_vartv(&retvar->tv); /* * Report the invalid expression unless the expression evaluation has * been cancelled due to an aborting error, an interrupt, or an @@ -1705,11 +1774,11 @@ eval0(arg, retvar, nextcmd, evaluate) static int eval1(arg, retvar, evaluate) char_u **arg; - VAR retvar; + typeval *retvar; int evaluate; { int result; - var var2; + typeval var2; /* * Get the first variable. @@ -1722,9 +1791,9 @@ eval1(arg, retvar, evaluate) result = FALSE; if (evaluate) { - if (get_var_number(retvar) != 0) + if (get_vartv_number(retvar) != 0) result = TRUE; - clear_var(retvar); + clear_vartv(retvar); } /* @@ -1741,7 +1810,7 @@ eval1(arg, retvar, evaluate) { EMSG(_("E109: Missing ':' after '?'")); if (evaluate && result) - clear_var(retvar); + clear_vartv(retvar); return FAIL; } @@ -1752,7 +1821,7 @@ eval1(arg, retvar, evaluate) if (eval1(arg, &var2, evaluate && !result) == FAIL) /* recursive! */ { if (evaluate && result) - clear_var(retvar); + clear_vartv(retvar); return FAIL; } if (evaluate && !result) @@ -1774,10 +1843,10 @@ eval1(arg, retvar, evaluate) static int eval2(arg, retvar, evaluate) char_u **arg; - VAR retvar; + typeval *retvar; int evaluate; { - var var2; + typeval var2; long result; int first; @@ -1796,9 +1865,9 @@ eval2(arg, retvar, evaluate) { if (evaluate && first) { - if (get_var_number(retvar) != 0) + if (get_vartv_number(retvar) != 0) result = TRUE; - clear_var(retvar); + clear_vartv(retvar); first = FALSE; } @@ -1814,14 +1883,14 @@ eval2(arg, retvar, evaluate) */ if (evaluate && !result) { - if (get_var_number(&var2) != 0) + if (get_vartv_number(&var2) != 0) result = TRUE; - clear_var(&var2); + clear_vartv(&var2); } if (evaluate) { - retvar->var_type = VAR_NUMBER; - retvar->var_val.var_number = result; + retvar->v_type = VAR_NUMBER; + retvar->vval.v_number = result; } } @@ -1840,10 +1909,10 @@ eval2(arg, retvar, evaluate) static int eval3(arg, retvar, evaluate) char_u **arg; - VAR retvar; + typeval *retvar; int evaluate; { - var var2; + typeval var2; long result; int first; @@ -1862,9 +1931,9 @@ eval3(arg, retvar, evaluate) { if (evaluate && first) { - if (get_var_number(retvar) == 0) + if (get_vartv_number(retvar) == 0) result = FALSE; - clear_var(retvar); + clear_vartv(retvar); first = FALSE; } @@ -1880,14 +1949,14 @@ eval3(arg, retvar, evaluate) */ if (evaluate && result) { - if (get_var_number(&var2) == 0) + if (get_vartv_number(&var2) == 0) result = FALSE; - clear_var(&var2); + clear_vartv(&var2); } if (evaluate) { - retvar->var_type = VAR_NUMBER; - retvar->var_val.var_number = result; + retvar->v_type = VAR_NUMBER; + retvar->vval.v_number = result; } } @@ -1913,10 +1982,10 @@ eval3(arg, retvar, evaluate) static int eval4(arg, retvar, evaluate) char_u **arg; - VAR retvar; + typeval *retvar; int evaluate; { - var var2; + typeval var2; char_u *p; int i; exptype_T type = TYPE_UNKNOWN; @@ -1992,7 +2061,7 @@ eval4(arg, retvar, evaluate) *arg = skipwhite(p + len); if (eval5(arg, &var2, evaluate) == FAIL) { - clear_var(retvar); + clear_vartv(retvar); return FAIL; } @@ -2002,11 +2071,11 @@ eval4(arg, retvar, evaluate) * If one of the two variables is a number, compare as a number. * When using "=~" or "!~", always compare as string. */ - if ((retvar->var_type == VAR_NUMBER || var2.var_type == VAR_NUMBER) + if ((retvar->v_type == VAR_NUMBER || var2.v_type == VAR_NUMBER) && type != TYPE_MATCH && type != TYPE_NOMATCH) { - n1 = get_var_number(retvar); - n2 = get_var_number(&var2); + n1 = get_vartv_number(retvar); + n2 = get_vartv_number(&var2); switch (type) { case TYPE_EQUAL: n1 = (n1 == n2); break; @@ -2022,8 +2091,8 @@ eval4(arg, retvar, evaluate) } else { - s1 = get_var_string_buf(retvar, buf1); - s2 = get_var_string_buf(&var2, buf2); + s1 = get_vartv_string_buf(retvar, buf1); + s2 = get_vartv_string_buf(&var2, buf2); if (type != TYPE_MATCH && type != TYPE_NOMATCH) i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2); else @@ -2059,10 +2128,10 @@ eval4(arg, retvar, evaluate) case TYPE_UNKNOWN: break; /* avoid gcc warning */ } } - clear_var(retvar); - clear_var(&var2); - retvar->var_type = VAR_NUMBER; - retvar->var_val.var_number = n1; + clear_vartv(retvar); + clear_vartv(&var2); + retvar->v_type = VAR_NUMBER; + retvar->vval.v_number = n1; } } @@ -2083,10 +2152,10 @@ eval4(arg, retvar, evaluate) static int eval5(arg, retvar, evaluate) char_u **arg; - VAR retvar; + typeval *retvar; int evaluate; { - var var2; + typeval var2; int op; long n1, n2; char_u *s1, *s2; @@ -2114,7 +2183,7 @@ eval5(arg, retvar, evaluate) *arg = skipwhite(*arg + 1); if (eval6(arg, &var2, evaluate) == FAIL) { - clear_var(retvar); + clear_vartv(retvar); return FAIL; } @@ -2125,8 +2194,8 @@ eval5(arg, retvar, evaluate) */ if (op == '.') { - s1 = get_var_string_buf(retvar, buf1); - s2 = get_var_string_buf(&var2, buf2); + s1 = get_vartv_string_buf(retvar, buf1); + s2 = get_vartv_string_buf(&var2, buf2); op = (int)STRLEN(s1); p = alloc((unsigned)(op + STRLEN(s2) + 1)); if (p != NULL) @@ -2134,23 +2203,23 @@ eval5(arg, retvar, evaluate) STRCPY(p, s1); STRCPY(p + op, s2); } - clear_var(retvar); - retvar->var_type = VAR_STRING; - retvar->var_val.var_string = p; + clear_vartv(retvar); + retvar->v_type = VAR_STRING; + retvar->vval.v_string = p; } else { - n1 = get_var_number(retvar); - n2 = get_var_number(&var2); - clear_var(retvar); + n1 = get_vartv_number(retvar); + n2 = get_vartv_number(&var2); + clear_vartv(retvar); if (op == '+') n1 = n1 + n2; else n1 = n1 - n2; - retvar->var_type = VAR_NUMBER; - retvar->var_val.var_number = n1; + retvar->v_type = VAR_NUMBER; + retvar->vval.v_number = n1; } - clear_var(&var2); + clear_vartv(&var2); } } return OK; @@ -2170,10 +2239,10 @@ eval5(arg, retvar, evaluate) static int eval6(arg, retvar, evaluate) char_u **arg; - VAR retvar; + typeval *retvar; int evaluate; { - var var2; + typeval var2; int op; long n1, n2; @@ -2194,8 +2263,8 @@ eval6(arg, retvar, evaluate) if (evaluate) { - n1 = get_var_number(retvar); - clear_var(retvar); + n1 = get_vartv_number(retvar); + clear_vartv(retvar); } else n1 = 0; @@ -2209,8 +2278,8 @@ eval6(arg, retvar, evaluate) if (evaluate) { - n2 = get_var_number(&var2); - clear_var(&var2); + n2 = get_vartv_number(&var2); + clear_vartv(&var2); /* * Compute the result. @@ -2231,8 +2300,8 @@ eval6(arg, retvar, evaluate) else n1 = n1 % n2; } - retvar->var_type = VAR_NUMBER; - retvar->var_val.var_number = n1; + retvar->v_type = VAR_NUMBER; + retvar->vval.v_number = n1; } } @@ -2265,10 +2334,9 @@ eval6(arg, retvar, evaluate) static int eval7(arg, retvar, evaluate) char_u **arg; - VAR retvar; + typeval *retvar; int evaluate; { - var var2; long n; int len; char_u *s; @@ -2278,10 +2346,10 @@ eval7(arg, retvar, evaluate) char_u *alias; /* - * Initialise variable so that clear_var() can't mistake this for a string - * and free a string that isn't there. + * Initialise variable so that clear_vartv() can't mistake this for a + * string and free a string that isn't there. */ - retvar->var_type = VAR_UNKNOWN; + retvar->v_type = VAR_UNKNOWN; /* * Skip '!' and '-' characters. They are handled later. @@ -2310,33 +2378,39 @@ eval7(arg, retvar, evaluate) *arg += len; if (evaluate) { - retvar->var_type = VAR_NUMBER; - retvar->var_val.var_number = n; + retvar->v_type = VAR_NUMBER; + retvar->vval.v_number = n; } break; /* * String constant: "string". */ - case '"': ret = get_string_var(arg, retvar, evaluate); + case '"': ret = get_string_vartv(arg, retvar, evaluate); break; /* * Literal string constant: 'string'. */ - case '\'': ret = get_lit_string_var(arg, retvar, evaluate); + case '\'': ret = get_lit_string_vartv(arg, retvar, evaluate); + break; + + /* + * List: [expr, expr] + */ + case '[': ret = get_list_vartv(arg, retvar, evaluate); break; /* * Option value: &name */ - case '&': ret = get_option_var(arg, retvar, evaluate); + case '&': ret = get_option_vartv(arg, retvar, evaluate); break; /* * Environment variable: $VAR. */ - case '$': ret = get_env_var(arg, retvar, evaluate); + case '$': ret = get_env_vartv(arg, retvar, evaluate); break; /* @@ -2345,8 +2419,8 @@ eval7(arg, retvar, evaluate) case '@': ++*arg; if (evaluate) { - retvar->var_type = VAR_STRING; - retvar->var_val.var_string = get_reg_contents(**arg, FALSE); + retvar->v_type = VAR_STRING; + retvar->vval.v_string = get_reg_contents(**arg, FALSE); } if (**arg != NUL) ++*arg; @@ -2362,7 +2436,7 @@ eval7(arg, retvar, evaluate) else if (ret == OK) { EMSG(_("E110: Missing ')'")); - clear_var(retvar); + clear_vartv(retvar); ret = FAIL; } break; @@ -2381,7 +2455,12 @@ eval7(arg, retvar, evaluate) { if (**arg == '(') /* recursive! */ { - ret = get_func_var(s, len, retvar, arg, + /* If "s" is the name of a variable of type VAR_FUNC + * use its contents. */ + s = deref_func_name(s, &len); + + /* Invoke the function. */ + ret = get_func_vartv(s, len, retvar, arg, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &len, evaluate); /* Stop the expression evaluation when immediately @@ -2390,12 +2469,12 @@ eval7(arg, retvar, evaluate) if (aborting()) { if (ret == OK) - clear_var(retvar); + clear_vartv(retvar); ret = FAIL; } } else if (evaluate) - ret = get_var_var(s, len, retvar); + ret = get_var_vartv(s, len, retvar); } if (alias != NULL) @@ -2406,48 +2485,15 @@ eval7(arg, retvar, evaluate) *arg = skipwhite(*arg); /* - * Handle expr[expr] subscript. + * Handle expr[expr] and expr[expr:expr] subscript. */ - if (**arg == '[' && ret == OK) + while (**arg == '[' && ret == OK) { - /* - * Get the variable from inside the []. - */ - *arg = skipwhite(*arg + 1); - if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */ - { - clear_var(retvar); - return FAIL; - } - - /* Check for the ']'. */ - if (**arg != ']') + if (eval_index(arg, retvar, evaluate) == FAIL) { - EMSG(_("E111: Missing ']'")); - clear_var(retvar); - clear_var(&var2); + clear_vartv(retvar); return FAIL; } - - if (evaluate) - { - n = get_var_number(&var2); - clear_var(&var2); - - /* - * The resulting variable is a string of a single character. - * If the index is too big or negative, the result is empty. - */ - s = get_var_string(retvar); - if (n >= (long)STRLEN(s) || n < 0) - s = NULL; - else - s = vim_strnsave(s + n, 1); - clear_var(retvar); - retvar->var_type = VAR_STRING; - retvar->var_val.var_string = s; - } - *arg = skipwhite(*arg + 1); /* skip the ']' */ } /* @@ -2455,7 +2501,7 @@ eval7(arg, retvar, evaluate) */ if (ret == OK && evaluate && end_leader > start_leader) { - val = get_var_number(retvar); + val = get_vartv_number(retvar); while (end_leader > start_leader) { --end_leader; @@ -2464,14 +2510,188 @@ eval7(arg, retvar, evaluate) else if (*end_leader == '-') val = -val; } - clear_var(retvar); - retvar->var_type = VAR_NUMBER; - retvar->var_val.var_number = val; + clear_vartv(retvar); + retvar->v_type = VAR_NUMBER; + retvar->vval.v_number = val; } return ret; } +/* + * Evaluate an "[expr]" or "[expr:expr]" index. + * "*arg" points to the '['. + * Returns FAIL or OK. "*arg" is advanced to after the ']'. + */ + static int +eval_index(arg, retvar, evaluate) + char_u **arg; + typeval *retvar; + int evaluate; +{ + int empty1 = FALSE, empty2 = FALSE; + typeval var1, var2; + long n1, n2 = 0; + long len; + int range; + char_u *s; + + if (retvar->v_type == VAR_FUNC) + { + EMSG(_("E999: Cannot index a Funcref")); + return FAIL; + } + + /* + * Get the (first) variable from inside the []. + */ + *arg = skipwhite(*arg + 1); + if (**arg == ':') + empty1 = TRUE; + else if (eval1(arg, &var1, evaluate) == FAIL) /* recursive! */ + return FAIL; + + /* + * Get the second variable from inside the [:]. + */ + if (**arg == ':') + { + range = TRUE; + *arg = skipwhite(*arg + 1); + if (**arg == ']') + empty2 = TRUE; + else if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */ + { + clear_vartv(&var1); + return FAIL; + } + } + else + range = FALSE; + + /* Check for the ']'. */ + if (**arg != ']') + { + EMSG(_("E111: Missing ']'")); + clear_vartv(&var1); + if (range) + clear_vartv(&var2); + return FAIL; + } + + if (evaluate) + { + if (empty1) + n1 = 0; + else + { + n1 = get_vartv_number(&var1); + clear_vartv(&var1); + } + if (range) + { + if (empty2) + n2 = -1; + else + { + n2 = get_vartv_number(&var2); + clear_vartv(&var2); + } + } + + switch (retvar->v_type) + { + case VAR_NUMBER: + case VAR_STRING: + s = get_vartv_string(retvar); + len = (long)STRLEN(s); + if (range) + { + /* The resulting variable is a substring. If the indexes + * are out of range the result is empty. */ + if (n1 < 0) + { + n1 = len + n1; + if (n1 < 0) + n1 = 0; + } + if (n2 < 0) + n2 = len + n2; + else if (n2 >= len) + n2 = len; + if (n1 >= len || n2 < 0 || n1 > n2) + s = NULL; + else + s = vim_strnsave(s + n1, (int)(n2 - n1 + 1)); + } + else + { + /* The resulting variable is a string of a single + * character. If the index is too big or negative the + * result is empty. */ + if (n1 >= len || n1 < 0) + s = NULL; + else + s = vim_strnsave(s + n1, 1); + } + clear_vartv(retvar); + retvar->v_type = VAR_STRING; + retvar->vval.v_string = s; + break; + + case VAR_LIST: + len = list_len(retvar->vval.v_list); + if (n1 < 0) + n1 = len + n1; + if (!empty1 && (n1 < 0 || n1 >= len)) + { + EMSGN(_(e_listidx), n1); + return FAIL; + } + if (range) + { + listvar *l; + listitem *item; + + if (n2 < 0) + n2 = len + n2; + if (!empty2 && (n2 < 0 || n2 >= len || n2 < n1)) + { + EMSGN(_(e_listidx), n2); + return FAIL; + } + l = list_alloc(); + if (l == NULL) + return FAIL; + for (item = list_find(retvar->vval.v_list, n1); + n1 <= n2; ++n1) + { + if (list_append_tv(l, &item->li_tv) == FAIL) + { + list_free(l); + return FAIL; + } + item = item->li_next; + } + clear_vartv(retvar); + retvar->v_type = VAR_LIST; + retvar->vval.v_list = l; + } + else + { + copy_vartv(&list_find(retvar->vval.v_list, n1)->li_tv, + &var1); + clear_vartv(retvar); + *retvar = var1; + } + break; + } + } + + *arg = skipwhite(*arg + 1); /* skip the ']' */ + return OK; +} + /* * Get an option value. * "arg" points to the '&' or '+' before the option name. @@ -2479,9 +2699,9 @@ eval7(arg, retvar, evaluate) * Return OK or FAIL. */ static int -get_option_var(arg, retvar, evaluate) +get_option_vartv(arg, retvar, evaluate) char_u **arg; - VAR retvar; /* when NULL, only check if option exists */ + typeval *retvar; /* when NULL, only check if option exists */ int evaluate; { char_u *option_end; @@ -2525,23 +2745,23 @@ get_option_var(arg, retvar, evaluate) { if (opt_type == -2) /* hidden string option */ { - retvar->var_type = VAR_STRING; - retvar->var_val.var_string = NULL; + retvar->v_type = VAR_STRING; + retvar->vval.v_string = NULL; } else if (opt_type == -1) /* hidden number option */ { - retvar->var_type = VAR_NUMBER; - retvar->var_val.var_number = 0; + retvar->v_type = VAR_NUMBER; + retvar->vval.v_number = 0; } else if (opt_type == 1) /* number option */ { - retvar->var_type = VAR_NUMBER; - retvar->var_val.var_number = numval; + retvar->v_type = VAR_NUMBER; + retvar->vval.v_number = numval; } else /* string option */ { - retvar->var_type = VAR_STRING; - retvar->var_val.var_string = stringval; + retvar->v_type = VAR_STRING; + retvar->vval.v_string = stringval; } } else if (working && (opt_type == -2 || opt_type == -1)) @@ -2558,9 +2778,9 @@ get_option_var(arg, retvar, evaluate) * Return OK or FAIL. */ static int -get_string_var(arg, retvar, evaluate) +get_string_vartv(arg, retvar, evaluate) char_u **arg; - VAR retvar; + typeval *retvar; int evaluate; { char_u *p; @@ -2703,8 +2923,8 @@ get_string_var(arg, retvar, evaluate) name[i] = NUL; *arg = p + 1; - retvar->var_type = VAR_STRING; - retvar->var_val.var_string = name; + retvar->v_type = VAR_STRING; + retvar->vval.v_string = name; return OK; } @@ -2714,9 +2934,9 @@ get_string_var(arg, retvar, evaluate) * Return OK or FAIL. */ static int -get_lit_string_var(arg, retvar, evaluate) +get_lit_string_vartv(arg, retvar, evaluate) char_u **arg; - VAR retvar; + typeval *retvar; int evaluate; { char_u *p; @@ -2732,22 +2952,382 @@ get_lit_string_var(arg, retvar, evaluate) return FAIL; } - if (evaluate) + if (evaluate) + { + /* + * Copy the string into allocated memory. + */ + name = vim_strnsave(*arg + 1, (int)(p - (*arg + 1))); + if (name == NULL) + return FAIL; + + retvar->v_type = VAR_STRING; + retvar->vval.v_string = name; + } + + *arg = p + 1; + + return OK; +} + +/* + * Allocate a variable for a List and fill it from "*arg". + * Return OK or FAIL. + */ + static int +get_list_vartv(arg, retvar, evaluate) + char_u **arg; + typeval *retvar; + int evaluate; +{ + listvar *l = NULL; + typeval tv; + listitem *item; + + if (evaluate) + { + l = list_alloc(); + if (l == NULL) + return FAIL; + } + + *arg = skipwhite(*arg + 1); + while (**arg != ']' && **arg != NUL) + { + if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */ + goto failret; + if (evaluate) + { + item = listitem_alloc(); + if (item != NULL) + { + item->li_tv = tv; + list_append(l, item); + } + } + + if (**arg == ']') + break; + if (**arg != ',') + { + EMSG2(_("E999: Missing comma in list: %s"), *arg); + goto failret; + } + *arg = skipwhite(*arg + 1); + } + + if (**arg != ']') + { + EMSG2(_("E999: Missing end of list ']': %s"), *arg); +failret: + if (evaluate) + list_free(l); + return FAIL; + } + + *arg = skipwhite(*arg + 1); + if (evaluate) + { + retvar->v_type = VAR_LIST; + retvar->vval.v_list = l; + ++l->lv_refcount; + } + + return OK; +} + +/* + * Allocate an empty header for a list. + */ + static listvar * +list_alloc() +{ + return (listvar *)alloc_clear(sizeof(listvar)); +} + +/* + * Unreference a list: decrement the reference count and free it when it + * becomes zero. + */ + static void +list_unref(l) + listvar *l; +{ + if (l != NULL && --l->lv_refcount <= 0) + list_free(l); +} + +/* + * Free a list, including all items it points to. + * Ignores the reference count. + */ + static void +list_free(l) + listvar *l; +{ + listitem *item; + listitem *next; + + for (item = l->lv_first; item != NULL; item = next) + { + next = item->li_next; + listitem_free(item); + } + vim_free(l); +} + +/* + * Allocate a list item. + */ + static listitem * +listitem_alloc() +{ + return (listitem *)alloc(sizeof(listitem)); +} + +/* + * Free a list item. Also clears the value; + */ + static void +listitem_free(item) + listitem *item; +{ + clear_vartv(&item->li_tv); + vim_free(item); +} + +/* + * Get the number of items in a list. + */ + static long +list_len(l) + listvar *l; +{ + listitem *item; + long len = 0; + + if (l == NULL) + return 0L; + for (item = l->lv_first; item != NULL; item = item->li_next) + ++len; + return len; +} + +/* + * Locate item with index "n" in list "l" and return it. + * A negative index is counted from the end; -1 is the last item. + * Returns NULL when "n" is out of range. + */ + static listitem * +list_find(l, n) + listvar *l; + long n; +{ + listitem *item; + long idx; + + if (l == NULL) + return NULL; + if (n < 0) + { + idx = -1; /* search from the end */ + for (item = l->lv_last; item != NULL && idx > n; item = item->li_prev) + --idx; + } + else + { + idx = 0; /* search from the start */ + for (item = l->lv_first; item != NULL && idx < n; item = item->li_next) + ++idx; + } + if (idx != n) + return NULL; + return item; +} + +/* + * Append item "item" to the end of list "l". + */ + static void +list_append(l, item) + listvar *l; + listitem *item; +{ + if (l->lv_last == NULL) + { + /* empty list */ + l->lv_first = item; + l->lv_last = item; + item->li_prev = NULL; + } + else + { + l->lv_last->li_next = item; + item->li_prev = l->lv_last; + l->lv_last = item; + } + item->li_next = NULL; +} + +/* + * Append typeval "tv" to the end of list "l". + */ + static int +list_append_tv(l, tv) + listvar *l; + typeval *tv; +{ + listitem *ni = listitem_alloc(); + + if (ni == NULL) + return FAIL; + copy_vartv(tv, &ni->li_tv); + list_append(l, ni); + return OK; +} + +/* + * Make a copy of list "l". Shallow if "deep" is FALSE. + * The refcount of the new list is set to 1. + * Returns NULL when out of memory. + */ + static listvar * +list_copy(orig, deep) + listvar *orig; + int deep; +{ + listvar *copy; + listitem *item; + listitem *ni; + static int recurse = 0; + + if (orig == NULL) + return NULL; + if (recurse >= VAR_LIST_MAXNEST) + { + EMSG(_("E999: List nested too deep for making a copy")); + return NULL; + } + ++recurse; + + copy = list_alloc(); + if (copy != NULL) + { + for (item = orig->lv_first; item != NULL; item = item->li_next) + { + ni = listitem_alloc(); + if (ni == NULL) + break; + if (deep && item->li_tv.v_type == VAR_LIST) + { + ni->li_tv.v_type = VAR_LIST; + ni->li_tv.vval.v_list = list_copy(item->li_tv.vval.v_list, + TRUE); + if (ni->li_tv.vval.v_list == NULL) + { + vim_free(ni); + break; + } + } + else + copy_vartv(&item->li_tv, &ni->li_tv); + list_append(copy, ni); + } + ++copy->lv_refcount; + } + + --recurse; + return copy; +} + +/* + * Remove item with index "n" from list "l" and return it. + * Returns NULL when "n" is out of range. + */ + static listitem * +list_getrem(l, n) + listvar *l; + long n; +{ + listitem *item; + + item = list_find(l, n); + if (item != NULL) + { + if (item->li_next == NULL) + l->lv_last = item->li_prev; + else + item->li_next->li_prev = item->li_prev; + if (item->li_prev == NULL) + l->lv_first = item->li_next; + else + item->li_prev->li_next = item->li_next; + } + return item; +} + +/* + * Return an allocated string with the string representation of a list. + * May return NULL. + */ + static char_u * +list2string(tv) + typeval *tv; +{ + garray_T ga; + listitem *item; + int first = TRUE; + char_u *tofree; + char_u *s; + + if (tv->vval.v_list == NULL) + return NULL; + ga_init2(&ga, (int)sizeof(char), 80); + ga_append(&ga, '['); + + for (item = tv->vval.v_list->lv_first; item != NULL; item = item->li_next) { - /* - * Copy the string into allocated memory. - */ - name = vim_strnsave(*arg + 1, (int)(p - (*arg + 1))); - if (name == NULL) - return FAIL; + if (first) + first = FALSE; + else + ga_concat(&ga, (char_u *)", "); - retvar->var_type = VAR_STRING; - retvar->var_val.var_string = name; + s = tv2string(&item->li_tv, &tofree); + if (s != NULL) + ga_concat(&ga, s); + vim_free(tofree); } - *arg = p + 1; + ga_append(&ga, ']'); + ga_append(&ga, NUL); + return (char_u *)ga.ga_data; +} - return OK; +/* + * Return a string with the string representation of a variable. + * If the memory is allocated "tofree" is set to it, otherwise NULL. + * Can only be used once before the value is used, it may call + * get_var_string(). + * May return NULL; + */ + static char_u * +tv2string(tv, tofree) + typeval *tv; + char_u **tofree; +{ + switch (tv->v_type) + { + case VAR_FUNC: + *tofree = NULL; + return tv->vval.v_string; + case VAR_LIST: + *tofree = list2string(tv); + return *tofree; + default: + break; + } + *tofree = NULL; + return get_vartv_string(tv); } /* @@ -2757,9 +3337,9 @@ get_lit_string_var(arg, retvar, evaluate) * Always return OK. */ static int -get_env_var(arg, retvar, evaluate) +get_env_vartv(arg, retvar, evaluate) char_u **arg; - VAR retvar; + typeval *retvar; int evaluate; { char_u *string = NULL; @@ -2792,8 +3372,8 @@ get_env_var(arg, retvar, evaluate) } name[len] = cc; } - retvar->var_type = VAR_STRING; - retvar->var_val.var_string = string; + retvar->v_type = VAR_STRING; + retvar->vval.v_string = string; } return OK; @@ -2808,7 +3388,8 @@ static struct fst char *f_name; /* function name */ char f_min_argc; /* minimal number of arguments */ char f_max_argc; /* maximal number of arguments */ - void (*f_func) __ARGS((VAR args, VAR rvar)); /* impl. function */ + void (*f_func) __ARGS((typeval *args, typeval *rvar)); + /* implemenation of function */ } functions[] = { {"append", 2, 2, f_append}, @@ -2832,8 +3413,10 @@ static struct fst {"cindent", 1, 1, f_cindent}, {"col", 1, 1, f_col}, {"confirm", 1, 4, f_confirm}, + {"copy", 1, 1, f_copy}, {"cscope_connection",0,3, f_cscope_connection}, {"cursor", 2, 2, f_cursor}, + {"deepcopy", 1, 1, f_deepcopy}, {"delete", 1, 1, f_delete}, {"did_filetype", 0, 0, f_did_filetype}, {"diff_filler", 1, 1, f_diff_fill