From da51dc9cf202772f60bd2da975dbef257bd9237c Mon Sep 17 00:00:00 2001 From: Eliseo Martínez Date: Mon, 12 May 2014 02:25:17 +0200 Subject: Introduce nvim namespace: Move files. Move files from src/ to src/nvim/. - src/nvim/ becomes the new root dir for nvim executable sources. - src/libnvim/ is planned to become root dir of the neovim library. --- src/eval.c | 19819 ----------------------------------------------------------- 1 file changed, 19819 deletions(-) delete mode 100644 src/eval.c (limited to 'src/eval.c') diff --git a/src/eval.c b/src/eval.c deleted file mode 100644 index 98ab1ea2fe..0000000000 --- a/src/eval.c +++ /dev/null @@ -1,19819 +0,0 @@ -/* - * VIM - Vi IMproved by Bram Moolenaar - * - * Do ":help uganda" in Vim to read copying and usage conditions. - * Do ":help credits" in Vim to see a list of people who contributed. - * See README.txt for an overview of the Vim source code. - */ - -/* - * eval.c: Expression evaluation. - */ - -#include -#include - -#include "vim.h" -#include "eval.h" -#include "buffer.h" -#include "charset.h" -#include "diff.h" -#include "edit.h" -#include "ex_cmds.h" -#include "ex_cmds2.h" -#include "ex_docmd.h" -#include "ex_eval.h" -#include "ex_getln.h" -#include "fileio.h" -#include "fold.h" -#include "getchar.h" -#include "hashtab.h" -#include "if_cscope.h" -#include "indent_c.h" -#include "indent.h" -#include "mark.h" -#include "mbyte.h" -#include "memline.h" -#include "memory.h" -#include "message.h" -#include "misc1.h" -#include "misc2.h" -#include "keymap.h" -#include "file_search.h" -#include "garray.h" -#include "move.h" -#include "normal.h" -#include "ops.h" -#include "option.h" -#include "os_unix.h" -#include "path.h" -#include "popupmnu.h" -#include "quickfix.h" -#include "regexp.h" -#include "screen.h" -#include "search.h" -#include "sha256.h" -#include "spell.h" -#include "syntax.h" -#include "tag.h" -#include "term.h" -#include "ui.h" -#include "undo.h" -#include "version.h" -#include "window.h" -#include "os/os.h" -#include "os/job.h" -#include "os/rstream.h" -#include "os/rstream_defs.h" -#include "os/time.h" - -#if defined(FEAT_FLOAT) -# include -#endif - -#define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */ - -#define DO_NOT_FREE_CNT 99999 /* refcount for dict or list that should not - be freed. */ - -/* - * In a hashtab item "hi_key" points to "di_key" in a dictitem. - * This avoids adding a pointer to the hashtab item. - * DI2HIKEY() converts a dictitem pointer to a hashitem key pointer. - * HIKEY2DI() converts a hashitem key pointer to a dictitem pointer. - * HI2DI() converts a hashitem pointer to a dictitem pointer. - */ -static dictitem_T dumdi; -#define DI2HIKEY(di) ((di)->di_key) -#define HIKEY2DI(p) ((dictitem_T *)(p - (dumdi.di_key - (char_u *)&dumdi))) -#define HI2DI(hi) HIKEY2DI((hi)->hi_key) - -/* - * Structure returned by get_lval() and used by set_var_lval(). - * For a plain name: - * "name" points to the variable name. - * "exp_name" is NULL. - * "tv" is NULL - * For a magic braces name: - * "name" points to the expanded variable name. - * "exp_name" is non-NULL, to be freed later. - * "tv" is NULL - * For an index in a list: - * "name" points to the (expanded) variable name. - * "exp_name" NULL or non-NULL, to be freed later. - * "tv" points to the (first) list item value - * "li" points to the (first) list item - * "range", "n1", "n2" and "empty2" indicate what items are used. - * For an existing Dict item: - * "name" points to the (expanded) variable name. - * "exp_name" NULL or non-NULL, to be freed later. - * "tv" points to the dict item value - * "newkey" is NULL - * For a non-existing Dict item: - * "name" points to the (expanded) variable name. - * "exp_name" NULL or non-NULL, to be freed later. - * "tv" points to the Dictionary typval_T - * "newkey" is the key for the new item. - */ -typedef struct lval_S { - char_u *ll_name; /* start of variable name (can be NULL) */ - char_u *ll_exp_name; /* NULL or expanded name in allocated memory. */ - typval_T *ll_tv; /* Typeval of item being used. If "newkey" - isn't NULL it's the Dict to which to add - the item. */ - listitem_T *ll_li; /* The list item or NULL. */ - list_T *ll_list; /* The list or NULL. */ - int ll_range; /* TRUE when a [i:j] range was used */ - long ll_n1; /* First index for list */ - long ll_n2; /* Second index for list range */ - int ll_empty2; /* Second index is empty: [i:] */ - dict_T *ll_dict; /* The Dictionary or NULL */ - dictitem_T *ll_di; /* The dictitem or NULL */ - char_u *ll_newkey; /* New key for Dict in alloc. mem or NULL. */ -} lval_T; - - -static char *e_letunexp = N_("E18: Unexpected characters in :let"); -static char *e_listidx = N_("E684: list index out of range: %" PRId64); -static char *e_undefvar = N_("E121: Undefined variable: %s"); -static char *e_missbrac = N_("E111: Missing ']'"); -static char *e_listarg = N_("E686: Argument of %s must be a List"); -static char *e_listdictarg = N_( - "E712: Argument of %s must be a List or Dictionary"); -static char *e_emptykey = N_("E713: Cannot use empty key for Dictionary"); -static char *e_listreq = N_("E714: List required"); -static char *e_dictreq = N_("E715: Dictionary required"); -static char *e_toomanyarg = N_("E118: Too many arguments for function: %s"); -static char *e_dictkey = N_("E716: Key not present in Dictionary: %s"); -static char *e_funcexts = N_( - "E122: Function %s already exists, add ! to replace it"); -static char *e_funcdict = N_("E717: Dictionary entry already exists"); -static char *e_funcref = N_("E718: Funcref required"); -static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary"); -static char *e_letwrong = N_("E734: Wrong variable type for %s="); -static char *e_nofunc = N_("E130: Unknown function: %s"); -static char *e_illvar = N_("E461: Illegal variable name: %s"); -static char *e_float_as_string = N_("E806: using Float as a String"); - -static dictitem_T globvars_var; /* variable used for g: */ -#define globvarht globvardict.dv_hashtab - -/* - * Old Vim variables such as "v:version" are also available without the "v:". - * Also in functions. We need a special hashtable for them. - */ -static hashtab_T compat_hashtab; - -/* - * When recursively copying lists and dicts we need to remember which ones we - * have done to avoid endless recursiveness. This unique ID is used for that. - * The last bit is used for previous_funccal, ignored when comparing. - */ -static int current_copyID = 0; -#define COPYID_INC 2 -#define COPYID_MASK (~0x1) - -/* - * Array to hold the hashtab with variables local to each sourced script. - * Each item holds a variable (nameless) that points to the dict_T. - */ -typedef struct { - dictitem_T sv_var; - dict_T sv_dict; -} scriptvar_T; - -static garray_T ga_scripts = {0, 0, sizeof(scriptvar_T *), 4, NULL}; -#define SCRIPT_SV(id) (((scriptvar_T **)ga_scripts.ga_data)[(id) - 1]) -#define SCRIPT_VARS(id) (SCRIPT_SV(id)->sv_dict.dv_hashtab) - -static int echo_attr = 0; /* attributes used for ":echo" */ - -/* Values for trans_function_name() argument: */ -#define TFN_INT 1 /* internal function name OK */ -#define TFN_QUIET 2 /* no error messages */ -#define TFN_NO_AUTOLOAD 4 /* do not use script autoloading */ - -/* Values for get_lval() flags argument: */ -#define GLV_QUIET TFN_QUIET /* no error messages */ -#define GLV_NO_AUTOLOAD TFN_NO_AUTOLOAD /* do not use script autoloading */ - -/* - * Structure to hold info for a user function. - */ -typedef struct ufunc ufunc_T; - -struct ufunc { - int uf_varargs; /* variable nr of arguments */ - int uf_flags; - int uf_calls; /* nr of active calls */ - garray_T uf_args; /* arguments */ - garray_T uf_lines; /* function lines */ - int uf_profiling; /* TRUE when func is being profiled */ - /* profiling the function as a whole */ - int uf_tm_count; /* nr of calls */ - proftime_T uf_tm_total; /* time spent in function + children */ - proftime_T uf_tm_self; /* time spent in function itself */ - proftime_T uf_tm_children; /* time spent in children this call */ - /* profiling the function per line */ - int *uf_tml_count; /* nr of times line was executed */ - proftime_T *uf_tml_total; /* time spent in a line + children */ - proftime_T *uf_tml_self; /* time spent in a line itself */ - proftime_T uf_tml_start; /* start time for current line */ - proftime_T uf_tml_children; /* time spent in children for this line */ - proftime_T uf_tml_wait; /* start wait time for current line */ - int uf_tml_idx; /* index of line being timed; -1 if none */ - int uf_tml_execed; /* line being timed was executed */ - scid_T uf_script_ID; /* ID of script where function was defined, - used for s: variables */ - int uf_refcount; /* for numbered function: reference count */ - char_u uf_name[1]; /* name of function (actually longer); can - start with 123_ ( is K_SPECIAL - KS_EXTRA KE_SNR) */ -}; - -/* function flags */ -#define FC_ABORT 1 /* abort function on error */ -#define FC_RANGE 2 /* function accepts range */ -#define FC_DICT 4 /* Dict function, uses "self" */ - -/* - * All user-defined functions are found in this hashtable. - */ -static hashtab_T func_hashtab; - -/* The names of packages that once were loaded are remembered. */ -static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL}; - -/* list heads for garbage collection */ -static dict_T *first_dict = NULL; /* list of all dicts */ -static list_T *first_list = NULL; /* list of all lists */ - -/* From user function to hashitem and back. */ -static ufunc_T dumuf; -#define UF2HIKEY(fp) ((fp)->uf_name) -#define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf))) -#define HI2UF(hi) HIKEY2UF((hi)->hi_key) - -#define FUNCARG(fp, j) ((char_u **)(fp->uf_args.ga_data))[j] -#define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j] - -#define MAX_FUNC_ARGS 20 /* maximum number of function arguments */ -#define VAR_SHORT_LEN 20 /* short variable name length */ -#define FIXVAR_CNT 12 /* number of fixed variables */ - -/* structure to hold info for a function that is currently being executed. */ -typedef struct funccall_S funccall_T; - -struct funccall_S { - ufunc_T *func; /* function being called */ - int linenr; /* next line to be executed */ - int returned; /* ":return" used */ - struct /* fixed variables for arguments */ - { - dictitem_T var; /* variable (without room for name) */ - char_u room[VAR_SHORT_LEN]; /* room for the name */ - } fixvar[FIXVAR_CNT]; - dict_T l_vars; /* l: local function variables */ - dictitem_T l_vars_var; /* variable for l: scope */ - dict_T l_avars; /* a: argument variables */ - dictitem_T l_avars_var; /* variable for a: scope */ - list_T l_varlist; /* list for a:000 */ - listitem_T l_listitems[MAX_FUNC_ARGS]; /* listitems for a:000 */ - typval_T *rettv; /* return value */ - linenr_T breakpoint; /* next line with breakpoint or zero */ - int dbg_tick; /* debug_tick when breakpoint was set */ - int level; /* top nesting level of executed function */ - proftime_T prof_child; /* time spent in a child */ - funccall_T *caller; /* calling function or NULL */ -}; - -/* - * Info used by a ":for" loop. - */ -typedef struct { - int fi_semicolon; /* TRUE if ending in '; var]' */ - int fi_varcount; /* nr of variables in the list */ - listwatch_T fi_lw; /* keep an eye on the item used. */ - list_T *fi_list; /* list being used */ -} forinfo_T; - -/* - * Struct used by trans_function_name() - */ -typedef struct { - dict_T *fd_dict; /* Dictionary used */ - char_u *fd_newkey; /* new key in "dict" in allocated memory */ - dictitem_T *fd_di; /* Dictionary item used */ -} funcdict_T; - - -/* - * Array to hold the value of v: variables. - * The value is in a dictitem, so that it can also be used in the v: scope. - * The reason to use this table anyway is for very quick access to the - * variables with the VV_ defines. - */ -#include "version_defs.h" - -/* values for vv_flags: */ -#define VV_COMPAT 1 /* compatible, also used without "v:" */ -#define VV_RO 2 /* read-only */ -#define VV_RO_SBX 4 /* read-only in the sandbox */ - -#define VV_NAME(s, t) s, {{t, 0, {0}}, 0, {0}}, {0} - -static struct vimvar { - char *vv_name; /* name of variable, without v: */ - dictitem_T vv_di; /* value and name for key */ - char vv_filler[16]; /* space for LONGEST name below!!! */ - char vv_flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */ -} vimvars[VV_LEN] = -{ - /* - * The order here must match the VV_ defines in vim.h! - * Initializing a union does not work, leave tv.vval empty to get zero's. - */ - {VV_NAME("count", VAR_NUMBER), VV_COMPAT+VV_RO}, - {VV_NAME("count1", VAR_NUMBER), VV_RO}, - {VV_NAME("prevcount", VAR_NUMBER), VV_RO}, - {VV_NAME("errmsg", VAR_STRING), VV_COMPAT}, - {VV_NAME("warningmsg", VAR_STRING), 0}, - {VV_NAME("statusmsg", VAR_STRING), 0}, - {VV_NAME("shell_error", VAR_NUMBER), VV_COMPAT+VV_RO}, - {VV_NAME("this_session", VAR_STRING), VV_COMPAT}, - {VV_NAME("version", VAR_NUMBER), VV_COMPAT+VV_RO}, - {VV_NAME("lnum", VAR_NUMBER), VV_RO_SBX}, - {VV_NAME("termresponse", VAR_STRING), VV_RO}, - {VV_NAME("fname", VAR_STRING), VV_RO}, - {VV_NAME("lang", VAR_STRING), VV_RO}, - {VV_NAME("lc_time", VAR_STRING), VV_RO}, - {VV_NAME("ctype", VAR_STRING), VV_RO}, - {VV_NAME("charconvert_from", VAR_STRING), VV_RO}, - {VV_NAME("charconvert_to", VAR_STRING), VV_RO}, - {VV_NAME("fname_in", VAR_STRING), VV_RO}, - {VV_NAME("fname_out", VAR_STRING), VV_RO}, - {VV_NAME("fname_new", VAR_STRING), VV_RO}, - {VV_NAME("fname_diff", VAR_STRING), VV_RO}, - {VV_NAME("cmdarg", VAR_STRING), VV_RO}, - {VV_NAME("foldstart", VAR_NUMBER), VV_RO_SBX}, - {VV_NAME("foldend", VAR_NUMBER), VV_RO_SBX}, - {VV_NAME("folddashes", VAR_STRING), VV_RO_SBX}, - {VV_NAME("foldlevel", VAR_NUMBER), VV_RO_SBX}, - {VV_NAME("progname", VAR_STRING), VV_RO}, - {VV_NAME("servername", VAR_STRING), VV_RO}, - {VV_NAME("dying", VAR_NUMBER), VV_RO}, - {VV_NAME("exception", VAR_STRING), VV_RO}, - {VV_NAME("throwpoint", VAR_STRING), VV_RO}, - {VV_NAME("register", VAR_STRING), VV_RO}, - {VV_NAME("cmdbang", VAR_NUMBER), VV_RO}, - {VV_NAME("insertmode", VAR_STRING), VV_RO}, - {VV_NAME("val", VAR_UNKNOWN), VV_RO}, - {VV_NAME("key", VAR_UNKNOWN), VV_RO}, - {VV_NAME("profiling", VAR_NUMBER), VV_RO}, - {VV_NAME("fcs_reason", VAR_STRING), VV_RO}, - {VV_NAME("fcs_choice", VAR_STRING), 0}, - {VV_NAME("beval_bufnr", VAR_NUMBER), VV_RO}, - {VV_NAME("beval_winnr", VAR_NUMBER), VV_RO}, - {VV_NAME("beval_lnum", VAR_NUMBER), VV_RO}, - {VV_NAME("beval_col", VAR_NUMBER), VV_RO}, - {VV_NAME("beval_text", VAR_STRING), VV_RO}, - {VV_NAME("scrollstart", VAR_STRING), 0}, - {VV_NAME("swapname", VAR_STRING), VV_RO}, - {VV_NAME("swapchoice", VAR_STRING), 0}, - {VV_NAME("swapcommand", VAR_STRING), VV_RO}, - {VV_NAME("char", VAR_STRING), 0}, - {VV_NAME("mouse_win", VAR_NUMBER), 0}, - {VV_NAME("mouse_lnum", VAR_NUMBER), 0}, - {VV_NAME("mouse_col", VAR_NUMBER), 0}, - {VV_NAME("operator", VAR_STRING), VV_RO}, - {VV_NAME("searchforward", VAR_NUMBER), 0}, - {VV_NAME("hlsearch", VAR_NUMBER), 0}, - {VV_NAME("oldfiles", VAR_LIST), 0}, - {VV_NAME("windowid", VAR_NUMBER), VV_RO}, - {VV_NAME("progpath", VAR_STRING), VV_RO}, - {VV_NAME("job_data", VAR_LIST), 0} -}; - -/* shorthand */ -#define vv_type vv_di.di_tv.v_type -#define vv_nr vv_di.di_tv.vval.v_number -#define vv_float vv_di.di_tv.vval.v_float -#define vv_str vv_di.di_tv.vval.v_string -#define vv_list vv_di.di_tv.vval.v_list -#define vv_tv vv_di.di_tv - -static dictitem_T vimvars_var; /* variable used for v: */ -#define vimvarht vimvardict.dv_hashtab - -static void on_job_stdout(RStream *rstream, void *data, bool eof); -static void on_job_stderr(RStream *rstream, void *data, bool eof); -static void on_job_exit(Job *job, void *data); -static void on_job_data(RStream *rstream, void *data, bool eof, char *type); -static void apply_job_autocmds(Job *job, char *name, char *type, char *str); -static void prepare_vimvar(int idx, typval_T *save_tv); -static void restore_vimvar(int idx, typval_T *save_tv); -static int ex_let_vars(char_u *arg, typval_T *tv, int copy, - int semicolon, int var_count, - char_u *nextchars); -static char_u *skip_var_list(char_u *arg, int *var_count, - int *semicolon); -static char_u *skip_var_one(char_u *arg); -static void list_hashtable_vars(hashtab_T *ht, char_u *prefix, - int empty, - int *first); -static void list_glob_vars(int *first); -static void list_buf_vars(int *first); -static void list_win_vars(int *first); -static void list_tab_vars(int *first); -static void list_vim_vars(int *first); -static void list_script_vars(int *first); -static void list_func_vars(int *first); -static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first); -static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, - char_u *endchars, char_u *op); -static int check_changedtick(char_u *arg); -static char_u *get_lval(char_u *name, typval_T *rettv, lval_T *lp, - int unlet, int skip, int flags, - int fne_flags); -static void clear_lval(lval_T *lp); -static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, - int copy, - char_u *op); -static int tv_op(typval_T *tv1, typval_T *tv2, char_u *op); -static void list_fix_watch(list_T *l, listitem_T *item); -static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep); -static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit); -static int do_lock_var(lval_T *lp, char_u *name_end, int deep, int lock); -static void item_lock(typval_T *tv, int deep, int lock); -static int tv_islocked(typval_T *tv); - -static int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, - int evaluate); -static int eval1(char_u **arg, typval_T *rettv, int evaluate); -static int eval2(char_u **arg, typval_T *rettv, int evaluate); -static int eval3(char_u **arg, typval_T *rettv, int evaluate); -static int eval4(char_u **arg, typval_T *rettv, int evaluate); -static int eval5(char_u **arg, typval_T *rettv, int evaluate); -static int eval6(char_u **arg, typval_T *rettv, int evaluate, - int want_string); -static int eval7(char_u **arg, typval_T *rettv, int evaluate, - int want_string); - -static int eval_index(char_u **arg, typval_T *rettv, int evaluate, - int verbose); -static int get_option_tv(char_u **arg, typval_T *rettv, int evaluate); -static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate); -static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate); -static int get_list_tv(char_u **arg, typval_T *rettv, int evaluate); -static void rettv_list_alloc(typval_T *rettv); -static long list_len(list_T *l); -static int list_equal(list_T *l1, list_T *l2, int ic, int recursive); -static int dict_equal(dict_T *d1, dict_T *d2, int ic, int recursive); -static int tv_equal(typval_T *tv1, typval_T *tv2, int ic, int recursive); -static long list_find_nr(list_T *l, long idx, int *errorp); -static long list_idx_of_item(list_T *l, listitem_T *item); -static void list_append_number(list_T *l, varnumber_T n); -static int list_extend(list_T *l1, list_T *l2, listitem_T *bef); -static int list_concat(list_T *l1, list_T *l2, typval_T *tv); -static list_T *list_copy(list_T *orig, int deep, int copyID); -static char_u *list2string(typval_T *tv, int copyID); -static int list_join_inner(garray_T *gap, list_T *l, char_u *sep, - int echo_style, int copyID, - garray_T *join_gap); -static int list_join(garray_T *gap, list_T *l, char_u *sep, int echo, - int copyID); -static int free_unref_items(int copyID); -static int rettv_dict_alloc(typval_T *rettv); -static dictitem_T *dictitem_copy(dictitem_T *org); -static void dictitem_remove(dict_T *dict, dictitem_T *item); -static dict_T *dict_copy(dict_T *orig, int deep, int copyID); -static long dict_len(dict_T *d); -static char_u *dict2string(typval_T *tv, int copyID); -static int get_dict_tv(char_u **arg, typval_T *rettv, int evaluate); -static char_u *echo_string(typval_T *tv, char_u **tofree, - char_u *numbuf, - int copyID); -static char_u *tv2string(typval_T *tv, char_u **tofree, char_u *numbuf, - int copyID); -static char_u *string_quote(char_u *str, int function); -static int string2float(char_u *text, float_T *value); -static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate); -static int find_internal_func(char_u *name); -static char_u *deref_func_name(char_u *name, int *lenp, int no_autoload); -static int get_func_tv(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(char_u *funcname, int len, typval_T *rettv, - int argcount, typval_T *argvars, - linenr_T firstline, linenr_T lastline, - int *doesrange, int evaluate, - dict_T *selfdict); -static void emsg_funcname(char *ermsg, char_u *name); -static int non_zero_arg(typval_T *argvars); - -static void f_abs(typval_T *argvars, typval_T *rettv); -static void f_acos(typval_T *argvars, typval_T *rettv); -static void f_add(typval_T *argvars, typval_T *rettv); -static void f_and(typval_T *argvars, typval_T *rettv); -static void f_append(typval_T *argvars, typval_T *rettv); -static void f_argc(typval_T *argvars, typval_T *rettv); -static void f_argidx(typval_T *argvars, typval_T *rettv); -static void f_argv(typval_T *argvars, typval_T *rettv); -static void f_asin(typval_T *argvars, typval_T *rettv); -static void f_atan(typval_T *argvars, typval_T *rettv); -static void f_atan2(typval_T *argvars, typval_T *rettv); -static void f_browse(typval_T *argvars, typval_T *rettv); -static void f_browsedir(typval_T *argvars, typval_T *rettv); -static void f_bufexists(typval_T *argvars, typval_T *rettv); -static void f_buflisted(typval_T *argvars, typval_T *rettv); -static void f_bufloaded(typval_T *argvars, typval_T *rettv); -static void f_bufname(typval_T *argvars, typval_T *rettv); -static void f_bufnr(typval_T *argvars, typval_T *rettv); -static void f_bufwinnr(typval_T *argvars, typval_T *rettv); -static void f_byte2line(typval_T *argvars, typval_T *rettv); -static void byteidx(typval_T *argvars, typval_T *rettv, int comp); -static void f_byteidx(typval_T *argvars, typval_T *rettv); -static void f_byteidxcomp(typval_T *argvars, typval_T *rettv); -static void f_call(typval_T *argvars, typval_T *rettv); -static void f_ceil(typval_T *argvars, typval_T *rettv); -static void f_changenr(typval_T *argvars, typval_T *rettv); -static void f_char2nr(typval_T *argvars, typval_T *rettv); -static void f_cindent(typval_T *argvars, typval_T *rettv); -static void f_clearmatches(typval_T *argvars, typval_T *rettv); -static void f_col(typval_T *argvars, typval_T *rettv); -static void f_complete(typval_T *argvars, typval_T *rettv); -static void f_complete_add(typval_T *argvars, typval_T *rettv); -static void f_complete_check(typval_T *argvars, typval_T *rettv); -static void f_confirm(typval_T *argvars, typval_T *rettv); -static void f_copy(typval_T *argvars, typval_T *rettv); -static void f_cos(typval_T *argvars, typval_T *rettv); -static void f_cosh(typval_T *argvars, typval_T *rettv); -static void f_count(typval_T *argvars, typval_T *rettv); -static void f_cscope_connection(typval_T *argvars, typval_T *rettv); -static void f_cursor(typval_T *argsvars, typval_T *rettv); -static void f_deepcopy(typval_T *argvars, typval_T *rettv); -static void f_delete(typval_T *argvars, typval_T *rettv); -static void f_did_filetype(typval_T *argvars, typval_T *rettv); -static void f_diff_filler(typval_T *argvars, typval_T *rettv); -static void f_diff_hlID(typval_T *argvars, typval_T *rettv); -static void f_empty(typval_T *argvars, typval_T *rettv); -static void f_escape(typval_T *argvars, typval_T *rettv); -static void f_eval(typval_T *argvars, typval_T *rettv); -static void f_eventhandler(typval_T *argvars, typval_T *rettv); -static void f_executable(typval_T *argvars, typval_T *rettv); -static void f_exists(typval_T *argvars, typval_T *rettv); -static void f_exp(typval_T *argvars, typval_T *rettv); -static void f_expand(typval_T *argvars, typval_T *rettv); -static void f_extend(typval_T *argvars, typval_T *rettv); -static void f_feedkeys(typval_T *argvars, typval_T *rettv); -static void f_filereadable(typval_T *argvars, typval_T *rettv); -static void f_filewritable(typval_T *argvars, typval_T *rettv); -static void f_filter(typval_T *argvars, typval_T *rettv); -static void f_finddir(typval_T *argvars, typval_T *rettv); -static void f_findfile(typval_T *argvars, typval_T *rettv); -static void f_float2nr(typval_T *argvars, typval_T *rettv); -static void f_floor(typval_T *argvars, typval_T *rettv); -static void f_fmod(typval_T *argvars, typval_T *rettv); -static void f_fnameescape(typval_T *argvars, typval_T *rettv); -static void f_fnamemodify(typval_T *argvars, typval_T *rettv); -static void f_foldclosed(typval_T *argvars, typval_T *rettv); -static void f_foldclosedend(typval_T *argvars, typval_T *rettv); -static void f_foldlevel(typval_T *argvars, typval_T *rettv); -static void f_foldtext(typval_T *argvars, typval_T *rettv); -static void f_foldtextresult(typval_T *argvars, typval_T *rettv); -static void f_foreground(typval_T *argvars, typval_T *rettv); -static void f_function(typval_T *argvars, typval_T *rettv); -static void f_garbagecollect(typval_T *argvars, typval_T *rettv); -static void f_get(typval_T *argvars, typval_T *rettv); -static void f_getbufline(typval_T *argvars, typval_T *rettv); -static void f_getbufvar(typval_T *argvars, typval_T *rettv); -static void f_getchar(typval_T *argvars, typval_T *rettv); -static void f_getcharmod(typval_T *argvars, typval_T *rettv); -static void f_getcmdline(typval_T *argvars, typval_T *rettv); -static void f_getcmdpos(typval_T *argvars, typval_T *rettv); -static void f_getcmdtype(typval_T *argvars, typval_T *rettv); -static void f_getcwd(typval_T *argvars, typval_T *rettv); -static void f_getfontname(typval_T *argvars, typval_T *rettv); -static void f_getfperm(typval_T *argvars, typval_T *rettv); -static void f_getfsize(typval_T *argvars, typval_T *rettv); -static void f_getftime(typval_T *argvars, typval_T *rettv); -static void f_getftype(typval_T *argvars, typval_T *rettv); -static void f_getline(typval_T *argvars, typval_T *rettv); -static void f_getmatches(typval_T *argvars, typval_T *rettv); -static void f_getpid(typval_T *argvars, typval_T *rettv); -static void f_getpos(typval_T *argvars, typval_T *rettv); -static void f_getqflist(typval_T *argvars, typval_T *rettv); -static void f_getreg(typval_T *argvars, typval_T *rettv); -static void f_getregtype(typval_T *argvars, typval_T *rettv); -static void f_gettabvar(typval_T *argvars, typval_T *rettv); -static void f_gettabwinvar(typval_T *argvars, typval_T *rettv); -static void f_getwinposx(typval_T *argvars, typval_T *rettv); -static void f_getwinposy(typval_T *argvars, typval_T *rettv); -static void f_getwinvar(typval_T *argvars, typval_T *rettv); -static void f_glob(typval_T *argvars, typval_T *rettv); -static void f_globpath(typval_T *argvars, typval_T *rettv); -static void f_has(typval_T *argvars, typval_T *rettv); -static void f_has_key(typval_T *argvars, typval_T *rettv); -static void f_haslocaldir(typval_T *argvars, typval_T *rettv); -static void f_hasmapto(typval_T *argvars, typval_T *rettv); -static void f_histadd(typval_T *argvars, typval_T *rettv); -static void f_histdel(typval_T *argvars, typval_T *rettv); -static void f_histget(typval_T *argvars, typval_T *rettv); -static void f_histnr(typval_T *argvars, typval_T *rettv); -static void f_hlID(typval_T *argvars, typval_T *rettv); -static void f_hlexists(typval_T *argvars, typval_T *rettv); -static void f_hostname(typval_T *argvars, typval_T *rettv); -static void f_iconv(typval_T *argvars, typval_T *rettv); -static void f_indent(typval_T *argvars, typval_T *rettv); -static void f_index(typval_T *argvars, typval_T *rettv); -static void f_input(typval_T *argvars, typval_T *rettv); -static void f_inputdialog(typval_T *argvars, typval_T *rettv); -static void f_inputlist(typval_T *argvars, typval_T *rettv); -static void f_inputrestore(typval_T *argvars, typval_T *rettv); -static void f_inputsave(typval_T *argvars, typval_T *rettv); -static void f_inputsecret(typval_T *argvars, typval_T *rettv); -static void f_insert(typval_T *argvars, typval_T *rettv); -static void f_invert(typval_T *argvars, typval_T *rettv); -static void f_isdirectory(typval_T *argvars, typval_T *rettv); -static void f_islocked(typval_T *argvars, typval_T *rettv); -static void f_items(typval_T *argvars, typval_T *rettv); -static void f_job_start(typval_T *argvars, typval_T *rettv); -static void f_job_stop(typval_T *argvars, typval_T *rettv); -static void f_job_write(typval_T *argvars, typval_T *rettv); -static void f_join(typval_T *argvars, typval_T *rettv); -static void f_keys(typval_T *argvars, typval_T *rettv); -static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv); -static void f_len(typval_T *argvars, typval_T *rettv); -static void f_libcall(typval_T *argvars, typval_T *rettv); -static void f_libcallnr(typval_T *argvars, typval_T *rettv); -static void f_line(typval_T *argvars, typval_T *rettv); -static void f_line2byte(typval_T *argvars, typval_T *rettv); -static void f_lispindent(typval_T *argvars, typval_T *rettv); -static void f_localtime(typval_T *argvars, typval_T *rettv); -static void f_log(typval_T *argvars, typval_T *rettv); -static void f_log10(typval_T *argvars, typval_T *rettv); -static void f_map(typval_T *argvars, typval_T *rettv); -static void f_maparg(typval_T *argvars, typval_T *rettv); -static void f_mapcheck(typval_T *argvars, typval_T *rettv); -static void f_match(typval_T *argvars, typval_T *rettv); -static void f_matchadd(typval_T *argvars, typval_T *rettv); -static void f_matcharg(typval_T *argvars, typval_T *rettv); -static void f_matchdelete(typval_T *argvars, typval_T *rettv); -static void f_matchend(typval_T *argvars, typval_T *rettv); -static void f_matchlist(typval_T *argvars, typval_T *rettv); -static void f_matchstr(typval_T *argvars, typval_T *rettv); -static void f_max(typval_T *argvars, typval_T *rettv); -static void f_min(typval_T *argvars, typval_T *rettv); -static void f_mkdir(typval_T *argvars, typval_T *rettv); -static void f_mode(typval_T *argvars, typval_T *rettv); -static void f_nextnonblank(typval_T *argvars, typval_T *rettv); -static void f_nr2char(typval_T *argvars, typval_T *rettv); -static void f_or(typval_T *argvars, typval_T *rettv); -static void f_pathshorten(typval_T *argvars, typval_T *rettv); -static void f_pow(typval_T *argvars, typval_T *rettv); -static void f_prevnonblank(typval_T *argvars, typval_T *rettv); -static void f_printf(typval_T *argvars, typval_T *rettv); -static void f_pumvisible(typval_T *argvars, typval_T *rettv); -static void f_range(typval_T *argvars, typval_T *rettv); -static void f_readfile(typval_T *argvars, typval_T *rettv); -static void f_reltime(typval_T *argvars, typval_T *rettv); -static void f_reltimestr(typval_T *argvars, typval_T *rettv); -static void f_remote_expr(typval_T *argvars, typval_T *rettv); -static void f_remote_foreground(typval_T *argvars, typval_T *rettv); -static void f_remote_peek(typval_T *argvars, typval_T *rettv); -static void f_remote_read(typval_T *argvars, typval_T *rettv); -static void f_remote_send(typval_T *argvars, typval_T *rettv); -static void f_remove(typval_T *argvars, typval_T *rettv); -static void f_rename(typval_T *argvars, typval_T *rettv); -static void f_repeat(typval_T *argvars, typval_T *rettv); -static void f_resolve(typval_T *argvars, typval_T *rettv); -static void f_reverse(typval_T *argvars, typval_T *rettv); -static void f_round(typval_T *argvars, typval_T *rettv); -static void f_screenattr(typval_T *argvars, typval_T *rettv); -static void f_screenchar(typval_T *argvars, typval_T *rettv); -static void f_screencol(typval_T *argvars, typval_T *rettv); -static void f_screenrow(typval_T *argvars, typval_T *rettv); -static void f_search(typval_T *argvars, typval_T *rettv); -static void f_searchdecl(typval_T *argvars, typval_T *rettv); -static void f_searchpair(typval_T *argvars, typval_T *rettv); -static void f_searchpairpos(typval_T *argvars, typval_T *rettv); -static void f_searchpos(typval_T *argvars, typval_T *rettv); -static void f_server2client(typval_T *argvars, typval_T *rettv); -static void f_serverlist(typval_T *argvars, typval_T *rettv); -static void f_setbufvar(typval_T *argvars, typval_T *rettv); -static void f_setcmdpos(typval_T *argvars, typval_T *rettv); -static void f_setline(typval_T *argvars, typval_T *rettv); -static void f_setloclist(typval_T *argvars, typval_T *rettv); -static void f_setmatches(typval_T *argvars, typval_T *rettv); -static void f_setpos(typval_T *argvars, typval_T *rettv); -static void f_setqflist(typval_T *argvars, typval_T *rettv); -static void f_setreg(typval_T *argvars, typval_T *rettv); -static void f_settabvar(typval_T *argvars, typval_T *rettv); -static void f_settabwinvar(typval_T *argvars, typval_T *rettv); -static void f_setwinvar(typval_T *argvars, typval_T *rettv); -static void f_sha256(typval_T *argvars, typval_T *rettv); -static void f_shellescape(typval_T *argvars, typval_T *rettv); -static void f_shiftwidth(typval_T *argvars, typval_T *rettv); -static void f_simplify(typval_T *argvars, typval_T *rettv); -static void f_sin(typval_T *argvars, typval_T *rettv); -static void f_sinh(typval_T *argvars, typval_T *rettv); -static void f_sort(typval_T *argvars, typval_T *rettv); -static void f_soundfold(typval_T *argvars, typval_T *rettv); -static void f_spellbadword(typval_T *argvars, typval_T *rettv); -static void f_spellsuggest(typval_T *argvars, typval_T *rettv); -static void f_split(typval_T *argvars, typval_T *rettv); -static void f_sqrt(typval_T *argvars, typval_T *rettv); -static void f_str2float(typval_T *argvars, typval_T *rettv); -static void f_str2nr(typval_T *argvars, typval_T *rettv); -static void f_strchars(typval_T *argvars, typval_T *rettv); -static void f_strftime(typval_T *argvars, typval_T *rettv); -static void f_stridx(typval_T *argvars, typval_T *rettv); -static void f_string(typval_T *argvars, typval_T *rettv); -static void f_strlen(typval_T *argvars, typval_T *rettv); -static void f_strpart(typval_T *argvars, typval_T *rettv); -static void f_strridx(typval_T *argvars, typval_T *rettv); -static void f_strtrans(typval_T *argvars, typval_T *rettv); -static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv); -static void f_strwidth(typval_T *argvars, typval_T *rettv); -static void f_submatch(typval_T *argvars, typval_T *rettv); -static void f_substitute(typval_T *argvars, typval_T *rettv); -static void f_synID(typval_T *argvars, typval_T *rettv); -static void f_synIDattr(typval_T *argvars, typval_T *rettv); -static void f_synIDtrans(typval_T *argvars, typval_T *rettv); -static void f_synstack(typval_T *argvars, typval_T *rettv); -static void f_synconcealed(typval_T *argvars, typval_T *rettv); -static void f_system(typval_T *argvars, typval_T *rettv); -static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv); -static void f_tabpagenr(typval_T *argvars, typval_T *rettv); -static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv); -static void f_taglist(typval_T *argvars, typval_T *rettv); -static void f_tagfiles(typval_T *argvars, typval_T *rettv); -static void f_tempname(typval_T *argvars, typval_T *rettv); -static void f_test(typval_T *argvars, typval_T *rettv); -static void f_tan(typval_T *argvars, typval_T *rettv); -static void f_tanh(typval_T *argvars, typval_T *rettv); -static void f_tolower(typval_T *argvars, typval_T *rettv); -static void f_toupper(typval_T *argvars, typval_T *rettv); -static void f_tr(typval_T *argvars, typval_T *rettv); -static void f_trunc(typval_T *argvars, typval_T *rettv); -static void f_type(typval_T *argvars, typval_T *rettv); -static void f_undofile(typval_T *argvars, typval_T *rettv); -static void f_undotree(typval_T *argvars, typval_T *rettv); -static void f_uniq(typval_T *argvars, typval_T *rettv); -static void f_values(typval_T *argvars, typval_T *rettv); -static void f_virtcol(typval_T *argvars, typval_T *rettv); -static void f_visualmode(typval_T *argvars, typval_T *rettv); -static void f_wildmenumode(typval_T *argvars, typval_T *rettv); -static void f_winbufnr(typval_T *argvars, typval_T *rettv); -static void f_wincol(typval_T *argvars, typval_T *rettv); -static void f_winheight(typval_T *argvars, typval_T *rettv); -static void f_winline(typval_T *argvars, typval_T *rettv); -static void f_winnr(typval_T *argvars, typval_T *rettv); -static void f_winrestcmd(typval_T *argvars, typval_T *rettv); -static void f_winrestview(typval_T *argvars, typval_T *rettv); -static void f_winsaveview(typval_T *argvars, typval_T *rettv); -static void f_winwidth(typval_T *argvars, typval_T *rettv); -static void f_writefile(typval_T *argvars, typval_T *rettv); -static void f_xor(typval_T *argvars, typval_T *rettv); - -static int list2fpos(typval_T *arg, pos_T *posp, int *fnump); -static pos_T *var2fpos(typval_T *varp, int dollar_lnum, int *fnum); -static int get_env_len(char_u **arg); -static int get_id_len(char_u **arg); -static int get_name_len(char_u **arg, char_u **alias, int evaluate, - int verbose); -static char_u *find_name_end(char_u *arg, char_u **expr_start, char_u * - *expr_end, - int flags); -#define FNE_INCL_BR 1 /* find_name_end(): include [] in name */ -#define FNE_CHECK_START 2 /* find_name_end(): check name starts with - valid character */ -static char_u * -make_expanded_name(char_u *in_start, char_u *expr_start, char_u * - expr_end, - char_u *in_end); -static int eval_isnamec(int c); -static int eval_isnamec1(int c); -static int get_var_tv(char_u *name, int len, typval_T *rettv, - int verbose, - int no_autoload); -static int handle_subscript(char_u **arg, typval_T *rettv, int evaluate, - int verbose); -static void init_tv(typval_T *varp); -static long get_tv_number(typval_T *varp); -static linenr_T get_tv_lnum(typval_T *argvars); -static linenr_T get_tv_lnum_buf(typval_T *argvars, buf_T *buf); -static char_u *get_tv_string(typval_T *varp); -static char_u *get_tv_string_buf(typval_T *varp, char_u *buf); -static char_u *get_tv_string_buf_chk(typval_T *varp, char_u *buf); -static dictitem_T *find_var(char_u *name, hashtab_T **htp, - int no_autoload); -static dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, - char_u *varname, - int no_autoload); -static hashtab_T *find_var_ht(char_u *name, char_u **varname); -static void vars_clear_ext(hashtab_T *ht, int free_val); -static void delete_var(hashtab_T *ht, hashitem_T *hi); -static void list_one_var(dictitem_T *v, char_u *prefix, int *first); -static void list_one_var_a(char_u *prefix, char_u *name, int type, - char_u *string, - int *first); -static void set_var(char_u *name, typval_T *varp, int copy); -static int var_check_ro(int flags, char_u *name); -static int var_check_fixed(int flags, char_u *name); -static int var_check_func_name(char_u *name, int new_var); -static int valid_varname(char_u *varname); -static int tv_check_lock(int lock, char_u *name); -static int item_copy(typval_T *from, typval_T *to, int deep, int copyID); -static char_u *find_option_end(char_u **arg, int *opt_flags); -static char_u *trans_function_name(char_u **pp, int skip, int flags, - funcdict_T *fd); -static int eval_fname_script(char_u *p); -static int eval_fname_sid(char_u *p); -static void list_func_head(ufunc_T *fp, int indent); -static ufunc_T *find_func(char_u *name); -static int function_exists(char_u *name); -static bool builtin_function(char_u *name, int len); -static void func_do_profile(ufunc_T *fp); -static void prof_sort_list(FILE *fd, ufunc_T **sorttab, int st_len, - char *title, - int prefer_self); -static void prof_func_line(FILE *fd, int count, proftime_T *total, - proftime_T *self, - int prefer_self); -static int -prof_total_cmp(const void *s1, const void *s2); -static int -prof_self_cmp(const void *s1, const void *s2); -static int script_autoload(char_u *name, int reload); -static char_u *autoload_name(char_u *name); -static void cat_func_name(char_u *buf, ufunc_T *fp); -static void func_free(ufunc_T *fp); -static void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, - typval_T *rettv, linenr_T firstline, - linenr_T lastline, - dict_T *selfdict); -static int can_free_funccal(funccall_T *fc, int copyID); -static void free_funccal(funccall_T *fc, int free_val); -static void add_nr_var(dict_T *dp, dictitem_T *v, char *name, - varnumber_T nr); -static win_T *find_win_by_nr(typval_T *vp, tabpage_T *tp); -static void getwinvar(typval_T *argvars, typval_T *rettv, int off); -static int searchpair_cmn(typval_T *argvars, pos_T *match_pos); -static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp); -static void setwinvar(typval_T *argvars, typval_T *rettv, int off); - - - -/* - * Initialize the global and v: variables. - */ -void eval_init(void) -{ - int i; - struct vimvar *p; - - init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE); - init_var_dict(&vimvardict, &vimvars_var, VAR_SCOPE); - vimvardict.dv_lock = VAR_FIXED; - hash_init(&compat_hashtab); - hash_init(&func_hashtab); - - 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, unless the value is not always available */ - if (p->vv_type != VAR_UNKNOWN) - hash_add(&vimvarht, p->vv_di.di_key); - if (p->vv_flags & VV_COMPAT) - /* add to compat scope dict */ - hash_add(&compat_hashtab, p->vv_di.di_key); - } - set_vim_var_nr(VV_SEARCHFORWARD, 1L); - set_vim_var_nr(VV_HLSEARCH, 1L); - set_reg_var(0); /* default for v:register is not 0 but '"' */ - -} - -#if defined(EXITFREE) || defined(PROTO) -void eval_clear(void) -{ - int i; - struct vimvar *p; - - for (i = 0; i < VV_LEN; ++i) { - p = &vimvars[i]; - if (p->vv_di.di_tv.v_type == VAR_STRING) { - free(p->vv_str); - p->vv_str = NULL; - } else if (p->vv_di.di_tv.v_type == VAR_LIST) { - list_unref(p->vv_list); - p->vv_list = NULL; - } - } - hash_clear(&vimvarht); - hash_init(&vimvarht); /* garbage_collect() will access it */ - hash_clear(&compat_hashtab); - - free_scriptnames(); - free_locales(); - - /* global variables */ - vars_clear(&globvarht); - - /* autoloaded script names */ - ga_clear_strings(&ga_loaded); - - /* Script-local variables. First clear all the variables and in a second - * loop free the scriptvar_T, because a variable in one script might hold - * a reference to the whole scope of another script. */ - for (i = 1; i <= ga_scripts.ga_len; ++i) - vars_clear(&SCRIPT_VARS(i)); - for (i = 1; i <= ga_scripts.ga_len; ++i) - free(SCRIPT_SV(i)); - ga_clear(&ga_scripts); - - /* unreferenced lists and dicts */ - (void)garbage_collect(); - - /* functions */ - free_all_functions(); - hash_clear(&func_hashtab); -} - -#endif - -/* - * Return the name of the executed function. - */ -char_u *func_name(void *cookie) -{ - return ((funccall_T *)cookie)->func->uf_name; -} - -/* - * Return the address holding the next breakpoint line for a funccall cookie. - */ -linenr_T *func_breakpoint(void *cookie) -{ - return &((funccall_T *)cookie)->breakpoint; -} - -/* - * Return the address holding the debug tick for a funccall cookie. - */ -int *func_dbg_tick(void *cookie) -{ - return &((funccall_T *)cookie)->dbg_tick; -} - -/* - * Return the nesting level for a funccall cookie. - */ -int func_level(void *cookie) -{ - return ((funccall_T *)cookie)->level; -} - -/* pointer to funccal for currently active function */ -funccall_T *current_funccal = NULL; - -/* pointer to list of previously used funccal, still around because some - * item in it is still being used. */ -funccall_T *previous_funccal = NULL; - -/* - * Return TRUE when a function was ended by a ":return" command. - */ -int current_func_returned(void) -{ - return current_funccal->returned; -} - -/* - * Set an internal variable to a string value. Creates the variable if it does - * not already exist. - */ -void set_internal_string_var(char_u *name, char_u *value) -{ - char_u *val = vim_strsave(value); - typval_T *tvp = xcalloc(1, sizeof(typval_T)); - - tvp->v_type = VAR_STRING; - tvp->vval.v_string = val; - set_var(name, tvp, FALSE); - free_tv(tvp); -} - -static lval_T *redir_lval = NULL; -static garray_T redir_ga; /* only valid when redir_lval is not NULL */ -static char_u *redir_endp = NULL; -static char_u *redir_varname = NULL; - -/* - * Start recording command output to a variable - * Returns OK if successfully completed the setup. FAIL otherwise. - */ -int -var_redir_start ( - char_u *name, - int append /* append to an existing variable */ -) -{ - int save_emsg; - int err; - typval_T tv; - - /* Catch a bad name early. */ - if (!eval_isnamec1(*name)) { - EMSG(_(e_invarg)); - return FAIL; - } - - /* Make a copy of the name, it is used in redir_lval until redir ends. */ - redir_varname = vim_strsave(name); - if (redir_varname == NULL) - return FAIL; - - redir_lval = xcalloc(1, sizeof(lval_T)); - - /* The output is stored in growarray "redir_ga" until redirection ends. */ - ga_init(&redir_ga, (int)sizeof(char), 500); - - /* Parse the variable name (can be a dict or list entry). */ - redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, 0, - FNE_CHECK_START); - if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != - NUL) { - clear_lval(redir_lval); - if (redir_endp != NULL && *redir_endp != NUL) - /* Trailing characters are present after the variable name */ - EMSG(_(e_trailing)); - else - EMSG(_(e_invarg)); - redir_endp = NULL; /* don't store a value, only cleanup */ - var_redir_stop(); - return FAIL; - } - - /* check if we can write to the variable: set it to or append an empty - * string */ - save_emsg = did_emsg; - did_emsg = FALSE; - tv.v_type = VAR_STRING; - tv.vval.v_string = (char_u *)""; - if (append) - set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)"."); - else - set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)"="); - clear_lval(redir_lval); - err = did_emsg; - did_emsg |= save_emsg; - if (err) { - redir_endp = NULL; /* don't store a value, only cleanup */ - var_redir_stop(); - return FAIL; - } - - return OK; -} - -/* - * Append "value[value_len]" to the variable set by var_redir_start(). - * The actual appending is postponed until redirection ends, because the value - * appended may in fact be the string we write to, changing it may cause freed - * memory to be used: - * :redir => foo - * :let foo - * :redir END - */ -void var_redir_str(char_u *value, int value_len) -{ - int len; - - if (redir_lval == NULL) - return; - - if (value_len == -1) - len = (int)STRLEN(value); /* Append the entire string */ - else - len = value_len; /* Append only "value_len" characters */ - - ga_grow(&redir_ga, len); - memmove((char *)redir_ga.ga_data + redir_ga.ga_len, value, len); - redir_ga.ga_len += len; -} - -/* - * Stop redirecting command output to a variable. - * Frees the allocated memory. - */ -void var_redir_stop(void) -{ - typval_T tv; - - if (redir_lval != NULL) { - /* If there was no error: assign the text to the variable. */ - if (redir_endp != NULL) { - ga_append(&redir_ga, NUL); /* Append the trailing NUL. */ - tv.v_type = VAR_STRING; - tv.vval.v_string = redir_ga.ga_data; - /* Call get_lval() again, if it's inside a Dict or List it may - * have changed. */ - redir_endp = get_lval(redir_varname, NULL, redir_lval, - FALSE, FALSE, 0, FNE_CHECK_START); - if (redir_endp != NULL && redir_lval->ll_name != NULL) - set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)"."); - clear_lval(redir_lval); - } - - /* free the collected output */ - free(redir_ga.ga_data); - redir_ga.ga_data = NULL; - - free(redir_lval); - redir_lval = NULL; - } - free(redir_varname); - redir_varname = NULL; -} - -int eval_charconvert(char_u *enc_from, char_u *enc_to, char_u *fname_from, char_u *fname_to) -{ - int err = FALSE; - - set_vim_var_string(VV_CC_FROM, enc_from, -1); - set_vim_var_string(VV_CC_TO, enc_to, -1); - set_vim_var_string(VV_FNAME_IN, fname_from, -1); - set_vim_var_string(VV_FNAME_OUT, fname_to, -1); - if (eval_to_bool(p_ccv, &err, NULL, FALSE)) - err = TRUE; - set_vim_var_string(VV_CC_FROM, NULL, -1); - set_vim_var_string(VV_CC_TO, NULL, -1); - set_vim_var_string(VV_FNAME_IN, NULL, -1); - set_vim_var_string(VV_FNAME_OUT, NULL, -1); - - if (err) - return FAIL; - return OK; -} - -int eval_printexpr(char_u *fname, char_u *args) -{ - int err = FALSE; - - set_vim_var_string(VV_FNAME_IN, fname, -1); - set_vim_var_string(VV_CMDARG, args, -1); - if (eval_to_bool(p_pexpr, &err, NULL, FALSE)) - err = TRUE; - set_vim_var_string(VV_FNAME_IN, NULL, -1); - set_vim_var_string(VV_CMDARG, NULL, -1); - - if (err) { - os_remove((char *)fname); - return FAIL; - } - return OK; -} - -void eval_diff(char_u *origfile, char_u *newfile, char_u *outfile) -{ - int err = FALSE; - - set_vim_var_string(VV_FNAME_IN, origfile, -1); - set_vim_var_string(VV_FNAME_NEW, newfile, -1); - set_vim_var_string(VV_FNAME_OUT, outfile, -1); - (void)eval_to_bool(p_dex, &err, NULL, FALSE); - set_vim_var_string(VV_FNAME_IN, NULL, -1); - set_vim_var_string(VV_FNAME_NEW, NULL, -1); - set_vim_var_string(VV_FNAME_OUT, NULL, -1); -} - -void eval_patch(char_u *origfile, char_u *difffile, char_u *outfile) -{ - int err; - - set_vim_var_string(VV_FNAME_IN, origfile, -1); - set_vim_var_string(VV_FNAME_DIFF, difffile, -1); - set_vim_var_string(VV_FNAME_OUT, outfile, -1); - (void)eval_to_bool(p_pex, &err, NULL, FALSE); - set_vim_var_string(VV_FNAME_IN, NULL, -1); - set_vim_var_string(VV_FNAME_DIFF, NULL, -1); - set_vim_var_string(VV_FNAME_OUT, NULL, -1); -} - -/* - * Top level evaluation function, returning a boolean. - * Sets "error" to TRUE if there was an error. - * Return TRUE or FALSE. - */ -int -eval_to_bool ( - char_u *arg, - int *error, - char_u **nextcmd, - int skip /* only parse, don't execute */ -) -{ - typval_T tv; - int retval = FALSE; - - if (skip) - ++emsg_skip; - if (eval0(arg, &tv, nextcmd, !skip) == FAIL) - *error = TRUE; - else { - *error = FALSE; - if (!skip) { - retval = (get_tv_number_chk(&tv, error) != 0); - clear_tv(&tv); - } - } - if (skip) - --emsg_skip; - - return retval; -} - -/* - * Top level evaluation function, returning a string. If "skip" is TRUE, - * only parsing to "nextcmd" is done, without reporting errors. Return - * pointer to allocated memory, or NULL for failure or when "skip" is TRUE. - */ -char_u * -eval_to_string_skip ( - char_u *arg, - char_u **nextcmd, - int skip /* only parse, don't execute */ -) -{ - typval_T tv; - char_u *retval; - - if (skip) - ++emsg_skip; - if (eval0(arg, &tv, nextcmd, !skip) == FAIL || skip) - retval = NULL; - else { - retval = vim_strsave(get_tv_string(&tv)); - clear_tv(&tv); - } - if (skip) - --emsg_skip; - - return retval; -} - -/* - * Skip over an expression at "*pp". - * Return FAIL for an error, OK otherwise. - */ -int skip_expr(char_u **pp) -{ - typval_T rettv; - - *pp = skipwhite(*pp); - return eval1(pp, &rettv, FALSE); -} - -/* - * Top level evaluation function, returning a string. - * When "convert" is TRUE convert a List into a sequence of lines and convert - * a Float to a String. - * Return pointer to allocated memory, or NULL for failure. - */ -char_u *eval_to_string(char_u *arg, char_u **nextcmd, int convert) -{ - typval_T tv; - char_u *retval; - garray_T ga; - char_u numbuf[NUMBUFLEN]; - - if (eval0(arg, &tv, nextcmd, TRUE) == FAIL) - retval = NULL; - else { - if (convert && tv.v_type == VAR_LIST) { - ga_init(&ga, (int)sizeof(char), 80); - if (tv.vval.v_list != NULL) { - list_join(&ga, tv.vval.v_list, (char_u *)"\n", TRUE, 0); - if (tv.vval.v_list->lv_len > 0) - ga_append(&ga, NL); - } - ga_append(&ga, NUL); - retval = (char_u *)ga.ga_data; - } else if (convert && tv.v_type == VAR_FLOAT) { - vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv.vval.v_float); - retval = vim_strsave(numbuf); - } else - retval = vim_strsave(get_tv_string(&tv)); - clear_tv(&tv); - } - - return retval; -} - -/* - * Call eval_to_string() without using current local variables and using - * textlock. When "use_sandbox" is TRUE use the sandbox. - */ -char_u *eval_to_string_safe(char_u *arg, char_u **nextcmd, int use_sandbox) -{ - char_u *retval; - void *save_funccalp; - - save_funccalp = save_funccal(); - if (use_sandbox) - ++sandbox; - ++textlock; - retval = eval_to_string(arg, nextcmd, FALSE); - if (use_sandbox) - --sandbox; - --textlock; - restore_funccal(save_funccalp); - return retval; -} - -/* - * Top level evaluation function, returning a number. - * Evaluates "expr" silently. - * Returns -1 for an error. - */ -int eval_to_number(char_u *expr) -{ - typval_T rettv; - int retval; - char_u *p = skipwhite(expr); - - ++emsg_off; - - if (eval1(&p, &rettv, TRUE) == FAIL) - retval = -1; - else { - retval = get_tv_number_chk(&rettv, NULL); - clear_tv(&rettv); - } - --emsg_off; - - return retval; -} - - -/* - * Prepare v: variable "idx" to be used. - * Save the current typeval in "save_tv". - * When not used yet add the variable to the v: hashtable. - */ -static void prepare_vimvar(int idx, typval_T *save_tv) -{ - *save_tv = vimvars[idx].vv_tv; - if (vimvars[idx].vv_type == VAR_UNKNOWN) - hash_add(&vimvarht, vimvars[idx].vv_di.di_key); -} - -/* - * Restore v: variable "idx" to typeval "save_tv". - * When no longer defined, remove the variable from the v: hashtable. - */ -static void restore_vimvar(int idx, typval_T *save_tv) -{ - hashitem_T *hi; - - vimvars[idx].vv_tv = *save_tv; - if (vimvars[idx].vv_type == VAR_UNKNOWN) { - hi = hash_find(&vimvarht, vimvars[idx].vv_di.di_key); - if (HASHITEM_EMPTY(hi)) - EMSG2(_(e_intern2), "restore_vimvar()"); - else - hash_remove(&vimvarht, hi); - } -} - -/* - * Evaluate an expression to a list with suggestions. - * For the "expr:" part of 'spellsuggest'. - * Returns NULL when there is an error. - */ -list_T *eval_spell_expr(char_u *badword, char_u *expr) -{ - typval_T save_val; - typval_T rettv; - list_T *list = NULL; - char_u *p = skipwhite(expr); - - /* Set "v:val" to the bad word. */ - prepare_vimvar(VV_VAL, &save_val); - vimvars[VV_VAL].vv_type = VAR_STRING; - vimvars[VV_VAL].vv_str = badword; - if (p_verbose == 0) - ++emsg_off; - - if (eval1(&p, &rettv, TRUE) == OK) { - if (rettv.v_type != VAR_LIST) - clear_tv(&rettv); - else - list = rettv.vval.v_list; - } - - if (p_verbose == 0) - --emsg_off; - restore_vimvar(VV_VAL, &save_val); - - return list; -} - -/* - * "list" is supposed to contain two items: a word and a number. Return the - * word in "pp" and the number as the return value. - * Return -1 if anything isn't right. - * Used to get the good word and score from the eval_spell_expr() result. - */ -int get_spellword(list_T *list, char_u **pp) -{ - listitem_T *li; - - li = list->lv_first; - if (li == NULL) - return -1; - *pp = get_tv_string(&li->li_tv); - - li = li->li_next; - if (li == NULL) - return -1; - return get_tv_number(&li->li_tv); -} - -/* - * Top level evaluation function. - * Returns an allocated typval_T with the result. - * Returns NULL when there is an error. - */ -typval_T *eval_expr(char_u *arg, char_u **nextcmd) -{ - typval_T *tv; - - tv = (typval_T *)alloc(sizeof(typval_T)); - if (tv != NULL && eval0(arg, tv, nextcmd, TRUE) == FAIL) { - free(tv); - tv = NULL; - } - - return tv; -} - - -/* - * Call some vimL function and return the result in "*rettv". - * Uses argv[argc] for the function arguments. Only Number and String - * arguments are currently supported. - * Returns OK or FAIL. - */ -int -call_vim_function ( - char_u *func, - int argc, - char_u **argv, - int safe, /* use the sandbox */ - int str_arg_only, /* all arguments are strings */ - typval_T *rettv -) -{ - typval_T *argvars; - long n; - int len; - int i; - int doesrange; - void *save_funccalp = NULL; - int ret; - - argvars = (typval_T *)alloc((unsigned)((argc + 1) * sizeof(typval_T))); - if (argvars == NULL) - return FAIL; - - for (i = 0; i < argc; i++) { - /* Pass a NULL or empty argument as an empty string */ - if (argv[i] == NULL || *argv[i] == NUL) { - argvars[i].v_type = VAR_STRING; - argvars[i].vval.v_string = (char_u *)""; - continue; - } - - if (str_arg_only) - len = 0; - else - /* Recognize a number argument, the others must be strings. */ - vim_str2nr(argv[i], NULL, &len, TRUE, TRUE, &n, NULL); - if (len != 0 && len == (int)STRLEN(argv[i])) { - argvars[i].v_type = VAR_NUMBER; - argvars[i].vval.v_number = n; - } else { - argvars[i].v_type = VAR_STRING; - argvars[i].vval.v_string = argv[i]; - } - } - - if (safe) { - save_funccalp = save_funccal(); - ++sandbox; - } - - rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */ - ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars, - curwin->w_cursor.lnum, curwin->w_cursor.lnum, - &doesrange, TRUE, NULL); - if (safe) { - --sandbox; - restore_funccal(save_funccalp); - } - free(argvars); - - if (ret == FAIL) - clear_tv(rettv); - - return ret; -} - -/* - * Call vimL function "func" and return the result as a number. - * Returns -1 when calling the function fails. - * Uses argv[argc] for the function arguments. - */ -long -call_func_retnr ( - char_u *func, - int argc, - char_u **argv, - int safe /* use the sandbox */ -) -{ - typval_T rettv; - long retval; - - /* All arguments are passed as strings, no conversion to number. */ - if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL) - return -1; - - retval = get_tv_number_chk(&rettv, NULL); - clear_tv(&rettv); - return retval; -} - -#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) \ - || defined(FEAT_COMPL_FUNC) || defined(PROTO) - -/* - * Call vimL function "func" and return the result as a string. - * Returns NULL when calling the function fails. - * Uses argv[argc] for the function arguments. - */ -void * -call_func_retstr ( - char_u *func, - int argc, - char_u **argv, - int safe /* use the sandbox */ -) -{ - typval_T rettv; - char_u *retval; - - /* All arguments are passed as strings, no conversion to number. */ - if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL) - return NULL; - - retval = vim_strsave(get_tv_string(&rettv)); - clear_tv(&rettv); - return retval; -} - -/* - * Call vimL function "func" and return the result as a List. - * Uses argv[argc] for the function arguments. - * Returns NULL when there is something wrong. - */ -void * -call_func_retlist ( - char_u *func, - int argc, - char_u **argv, - int safe /* use the sandbox */ -) -{ - typval_T rettv; - - /* All arguments are passed as strings, no conversion to number. */ - if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL) - return NULL; - - if (rettv.v_type != VAR_LIST) { - clear_tv(&rettv); - return NULL; - } - - return rettv.vval.v_list; -} -#endif - -/* - * Save the current function call pointer, and set it to NULL. - * Used when executing autocommands and for ":source". - */ -void *save_funccal(void) -{ - funccall_T *fc = current_funccal; - - current_funccal = NULL; - return (void *)fc; -} - -void restore_funccal(void *vfc) -{ - funccall_T *fc = (funccall_T *)vfc; - - current_funccal = fc; -} - -/* - * Prepare profiling for entering a child or something else that is not - * counted for the script/function itself. - * Should always be called in pair with prof_child_exit(). - */ -void prof_child_enter(tm) -proftime_T *tm; /* place to store waittime */ -{ - funccall_T *fc = current_funccal; - - if (fc != NULL && fc->func->uf_profiling) - profile_start(&fc->prof_child); - script_prof_save(tm); -} - -/* - * Take care of time spent in a child. - * Should always be called after prof_child_enter(). - */ -void prof_child_exit(tm) -proftime_T *tm; /* where waittime was stored */ -{ - funccall_T *fc = current_funccal; - - if (fc != NULL && fc->func->uf_profiling) { - profile_end(&fc->prof_child); - profile_sub_wait(tm, &fc->prof_child); /* don't count waiting time */ - profile_add(&fc->func->uf_tm_children, &fc->prof_child); - profile_add(&fc->func->uf_tml_children, &fc->prof_child); - } - script_prof_restore(tm); -} - - -/* - * Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding - * it in "*cp". Doesn't give error messages. - */ -int eval_foldexpr(char_u *arg, int *cp) -{ - typval_T tv; - int retval; - char_u *s; - int use_sandbox = was_set_insecurely((char_u *)"foldexpr", - OPT_LOCAL); - - ++emsg_off; - if (use_sandbox) - ++sandbox; - ++textlock; - *cp = NUL; - if (eval0(arg, &tv, NULL, TRUE) == FAIL) - retval = 0; - else { - /* If the result is a number, just return the number. */ - if (tv.v_type == VAR_NUMBER) - retval = tv.vval.v_number; - else if (tv.v_type != VAR_STRING || tv.vval.v_string == NULL) - retval = 0; - else { - /* If the result is a string, check if there is a non-digit before - * the number. */ -