blob: caac2a1da2c1fae6c0bdc7557ff83216fcf9ef6c [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * eval.c: Expression evaluation.
12 */
Bram Moolenaarfefecb02016-02-27 21:27:20 +010013#define USING_FLOAT_STUFF
Bram Moolenaar071d4272004-06-13 20:20:40 +000014
15#include "vim.h"
16
Bram Moolenaar8c8de832008-06-24 22:58:06 +000017#if defined(FEAT_EVAL) || defined(PROTO)
18
Bram Moolenaar314f11d2010-08-09 22:07:08 +020019#ifdef VMS
20# include <float.h>
21#endif
22
Bram Moolenaar33570922005-01-25 22:26:29 +000023#define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */
Bram Moolenaar071d4272004-06-13 20:20:40 +000024
Bram Moolenaarc70646c2005-01-04 21:52:38 +000025static char *e_letunexp = N_("E18: Unexpected characters in :let");
Bram Moolenaarc70646c2005-01-04 21:52:38 +000026static char *e_undefvar = N_("E121: Undefined variable: %s");
27static char *e_missbrac = N_("E111: Missing ']'");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000028static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary");
29static char *e_letwrong = N_("E734: Wrong variable type for %s=");
Bram Moolenaar92124a32005-06-17 22:03:40 +000030static char *e_illvar = N_("E461: Illegal variable name: %s");
Bram Moolenaar9937a052019-06-15 15:45:06 +020031static char *e_cannot_mod = N_("E995: Cannot modify existing variable");
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020032#ifdef FEAT_FLOAT
Bram Moolenaar2a876e42013-06-12 22:08:58 +020033static char *e_float_as_string = N_("E806: using Float as a String");
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020034#endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +000035
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +010036#define NAMESPACE_CHAR (char_u *)"abglstvw"
37
Bram Moolenaar230bb3f2013-04-24 14:07:45 +020038static dictitem_T globvars_var; /* variable used for g: */
Bram Moolenaar071d4272004-06-13 20:20:40 +000039
40/*
Bram Moolenaar532c7802005-01-27 14:44:31 +000041 * Old Vim variables such as "v:version" are also available without the "v:".
42 * Also in functions. We need a special hashtable for them.
43 */
Bram Moolenaar4debb442005-06-01 21:57:40 +000044static hashtab_T compat_hashtab;
Bram Moolenaar532c7802005-01-27 14:44:31 +000045
46/*
Bram Moolenaard9fba312005-06-26 22:34:35 +000047 * When recursively copying lists and dicts we need to remember which ones we
48 * have done to avoid endless recursiveness. This unique ID is used for that.
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +000049 * The last bit is used for previous_funccal, ignored when comparing.
Bram Moolenaard9fba312005-06-26 22:34:35 +000050 */
51static int current_copyID = 0;
Bram Moolenaar8502c702014-06-17 12:51:16 +020052
Bram Moolenaard9fba312005-06-26 22:34:35 +000053/*
Bram Moolenaar33570922005-01-25 22:26:29 +000054 * Array to hold the hashtab with variables local to each sourced script.
55 * Each item holds a variable (nameless) that points to the dict_T.
Bram Moolenaar071d4272004-06-13 20:20:40 +000056 */
Bram Moolenaar33570922005-01-25 22:26:29 +000057typedef struct
58{
59 dictitem_T sv_var;
60 dict_T sv_dict;
61} scriptvar_T;
62
Bram Moolenaar9577c3e2010-05-14 12:16:25 +020063static garray_T ga_scripts = {0, 0, sizeof(scriptvar_T *), 4, NULL};
64#define SCRIPT_SV(id) (((scriptvar_T **)ga_scripts.ga_data)[(id) - 1])
65#define SCRIPT_VARS(id) (SCRIPT_SV(id)->sv_dict.dv_hashtab)
Bram Moolenaar071d4272004-06-13 20:20:40 +000066
67static int echo_attr = 0; /* attributes used for ":echo" */
68
Bram Moolenaarc9b4b052006-04-30 18:54:39 +000069/* The names of packages that once were loaded are remembered. */
Bram Moolenaaraa35dd12006-04-29 22:03:41 +000070static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL};
71
Bram Moolenaar071d4272004-06-13 20:20:40 +000072/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000073 * Info used by a ":for" loop.
74 */
Bram Moolenaar33570922005-01-25 22:26:29 +000075typedef struct
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000076{
77 int fi_semicolon; /* TRUE if ending in '; var]' */
78 int fi_varcount; /* nr of variables in the list */
Bram Moolenaar33570922005-01-25 22:26:29 +000079 listwatch_T fi_lw; /* keep an eye on the item used. */
80 list_T *fi_list; /* list being used */
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +010081 int fi_bi; /* index of blob */
82 blob_T *fi_blob; /* blob being used */
Bram Moolenaar33570922005-01-25 22:26:29 +000083} forinfo_T;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000084
Bram Moolenaara7043832005-01-21 11:56:39 +000085
86/*
Bram Moolenaar33570922005-01-25 22:26:29 +000087 * Array to hold the value of v: variables.
88 * The value is in a dictitem, so that it can also be used in the v: scope.
89 * The reason to use this table anyway is for very quick access to the
90 * variables with the VV_ defines.
91 */
Bram Moolenaar33570922005-01-25 22:26:29 +000092
93/* values for vv_flags: */
94#define VV_COMPAT 1 /* compatible, also used without "v:" */
95#define VV_RO 2 /* read-only */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000096#define VV_RO_SBX 4 /* read-only in the sandbox */
Bram Moolenaar33570922005-01-25 22:26:29 +000097
Bram Moolenaarbee6c0c2016-03-25 15:40:50 +010098#define VV_NAME(s, t) s, {{t, 0, {0}}, 0, {0}}
Bram Moolenaar33570922005-01-25 22:26:29 +000099
100static struct vimvar
101{
102 char *vv_name; /* name of variable, without v: */
Bram Moolenaarbee6c0c2016-03-25 15:40:50 +0100103 dictitem16_T vv_di; /* value and name for key (max 16 chars!) */
Bram Moolenaar33570922005-01-25 22:26:29 +0000104 char vv_flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */
105} vimvars[VV_LEN] =
106{
107 /*
108 * The order here must match the VV_ defines in vim.h!
109 * Initializing a union does not work, leave tv.vval empty to get zero's.
110 */
111 {VV_NAME("count", VAR_NUMBER), VV_COMPAT+VV_RO},
112 {VV_NAME("count1", VAR_NUMBER), VV_RO},
113 {VV_NAME("prevcount", VAR_NUMBER), VV_RO},
114 {VV_NAME("errmsg", VAR_STRING), VV_COMPAT},
115 {VV_NAME("warningmsg", VAR_STRING), 0},
116 {VV_NAME("statusmsg", VAR_STRING), 0},
117 {VV_NAME("shell_error", VAR_NUMBER), VV_COMPAT+VV_RO},
118 {VV_NAME("this_session", VAR_STRING), VV_COMPAT},
119 {VV_NAME("version", VAR_NUMBER), VV_COMPAT+VV_RO},
120 {VV_NAME("lnum", VAR_NUMBER), VV_RO_SBX},
121 {VV_NAME("termresponse", VAR_STRING), VV_RO},
122 {VV_NAME("fname", VAR_STRING), VV_RO},
123 {VV_NAME("lang", VAR_STRING), VV_RO},
124 {VV_NAME("lc_time", VAR_STRING), VV_RO},
125 {VV_NAME("ctype", VAR_STRING), VV_RO},
126 {VV_NAME("charconvert_from", VAR_STRING), VV_RO},
127 {VV_NAME("charconvert_to", VAR_STRING), VV_RO},
128 {VV_NAME("fname_in", VAR_STRING), VV_RO},
129 {VV_NAME("fname_out", VAR_STRING), VV_RO},
130 {VV_NAME("fname_new", VAR_STRING), VV_RO},
131 {VV_NAME("fname_diff", VAR_STRING), VV_RO},
132 {VV_NAME("cmdarg", VAR_STRING), VV_RO},
133 {VV_NAME("foldstart", VAR_NUMBER), VV_RO_SBX},
134 {VV_NAME("foldend", VAR_NUMBER), VV_RO_SBX},
135 {VV_NAME("folddashes", VAR_STRING), VV_RO_SBX},
136 {VV_NAME("foldlevel", VAR_NUMBER), VV_RO_SBX},
137 {VV_NAME("progname", VAR_STRING), VV_RO},
138 {VV_NAME("servername", VAR_STRING), VV_RO},
139 {VV_NAME("dying", VAR_NUMBER), VV_RO},
140 {VV_NAME("exception", VAR_STRING), VV_RO},
141 {VV_NAME("throwpoint", VAR_STRING), VV_RO},
142 {VV_NAME("register", VAR_STRING), VV_RO},
143 {VV_NAME("cmdbang", VAR_NUMBER), VV_RO},
144 {VV_NAME("insertmode", VAR_STRING), VV_RO},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000145 {VV_NAME("val", VAR_UNKNOWN), VV_RO},
146 {VV_NAME("key", VAR_UNKNOWN), VV_RO},
Bram Moolenaar05159a02005-02-26 23:04:13 +0000147 {VV_NAME("profiling", VAR_NUMBER), VV_RO},
Bram Moolenaar19a09a12005-03-04 23:39:37 +0000148 {VV_NAME("fcs_reason", VAR_STRING), VV_RO},
149 {VV_NAME("fcs_choice", VAR_STRING), 0},
Bram Moolenaare2ac10d2005-03-07 23:26:06 +0000150 {VV_NAME("beval_bufnr", VAR_NUMBER), VV_RO},
151 {VV_NAME("beval_winnr", VAR_NUMBER), VV_RO},
Bram Moolenaarc9721bd2016-06-04 17:41:03 +0200152 {VV_NAME("beval_winid", VAR_NUMBER), VV_RO},
Bram Moolenaare2ac10d2005-03-07 23:26:06 +0000153 {VV_NAME("beval_lnum", VAR_NUMBER), VV_RO},
154 {VV_NAME("beval_col", VAR_NUMBER), VV_RO},
155 {VV_NAME("beval_text", VAR_STRING), VV_RO},
Bram Moolenaar761b1132005-10-03 22:05:45 +0000156 {VV_NAME("scrollstart", VAR_STRING), 0},
Bram Moolenaard5bc83f2005-12-07 21:07:59 +0000157 {VV_NAME("swapname", VAR_STRING), VV_RO},
158 {VV_NAME("swapchoice", VAR_STRING), 0},
Bram Moolenaar63a121b2005-12-11 21:36:39 +0000159 {VV_NAME("swapcommand", VAR_STRING), VV_RO},
Bram Moolenaare659c952011-05-19 17:25:41 +0200160 {VV_NAME("char", VAR_STRING), 0},
Bram Moolenaar219b8702006-11-01 14:32:36 +0000161 {VV_NAME("mouse_win", VAR_NUMBER), 0},
Bram Moolenaar511972d2016-06-04 18:09:59 +0200162 {VV_NAME("mouse_winid", VAR_NUMBER), 0},
Bram Moolenaar219b8702006-11-01 14:32:36 +0000163 {VV_NAME("mouse_lnum", VAR_NUMBER), 0},
164 {VV_NAME("mouse_col", VAR_NUMBER), 0},
Bram Moolenaar8af1fbf2008-01-05 12:35:21 +0000165 {VV_NAME("operator", VAR_STRING), VV_RO},
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000166 {VV_NAME("searchforward", VAR_NUMBER), 0},
Bram Moolenaar8050efa2013-11-08 04:30:20 +0100167 {VV_NAME("hlsearch", VAR_NUMBER), 0},
Bram Moolenaard812df62008-11-09 12:46:09 +0000168 {VV_NAME("oldfiles", VAR_LIST), 0},
Bram Moolenaar727c8762010-10-20 19:17:48 +0200169 {VV_NAME("windowid", VAR_NUMBER), VV_RO},
Bram Moolenaara1706c92014-04-01 19:55:49 +0200170 {VV_NAME("progpath", VAR_STRING), VV_RO},
Bram Moolenaar42a45122015-07-10 17:56:23 +0200171 {VV_NAME("completed_item", VAR_DICT), VV_RO},
Bram Moolenaar53744302015-07-17 17:38:22 +0200172 {VV_NAME("option_new", VAR_STRING), VV_RO},
173 {VV_NAME("option_old", VAR_STRING), VV_RO},
Bram Moolenaard7c96872019-06-15 17:12:48 +0200174 {VV_NAME("option_oldlocal", VAR_STRING), VV_RO},
175 {VV_NAME("option_oldglobal", VAR_STRING), VV_RO},
176 {VV_NAME("option_command", VAR_STRING), VV_RO},
Bram Moolenaar53744302015-07-17 17:38:22 +0200177 {VV_NAME("option_type", VAR_STRING), VV_RO},
Bram Moolenaar43345542015-11-29 17:35:35 +0100178 {VV_NAME("errors", VAR_LIST), 0},
Bram Moolenaar520e1e42016-01-23 19:46:28 +0100179 {VV_NAME("false", VAR_SPECIAL), VV_RO},
180 {VV_NAME("true", VAR_SPECIAL), VV_RO},
181 {VV_NAME("null", VAR_SPECIAL), VV_RO},
182 {VV_NAME("none", VAR_SPECIAL), VV_RO},
Bram Moolenaar14735512016-03-26 21:00:08 +0100183 {VV_NAME("vim_did_enter", VAR_NUMBER), VV_RO},
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +0200184 {VV_NAME("testing", VAR_NUMBER), 0},
Bram Moolenaarf562e722016-07-19 17:25:25 +0200185 {VV_NAME("t_number", VAR_NUMBER), VV_RO},
186 {VV_NAME("t_string", VAR_NUMBER), VV_RO},
187 {VV_NAME("t_func", VAR_NUMBER), VV_RO},
188 {VV_NAME("t_list", VAR_NUMBER), VV_RO},
189 {VV_NAME("t_dict", VAR_NUMBER), VV_RO},
190 {VV_NAME("t_float", VAR_NUMBER), VV_RO},
191 {VV_NAME("t_bool", VAR_NUMBER), VV_RO},
192 {VV_NAME("t_none", VAR_NUMBER), VV_RO},
193 {VV_NAME("t_job", VAR_NUMBER), VV_RO},
194 {VV_NAME("t_channel", VAR_NUMBER), VV_RO},
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +0100195 {VV_NAME("t_blob", VAR_NUMBER), VV_RO},
Bram Moolenaar65e4c4f2017-10-14 23:24:25 +0200196 {VV_NAME("termrfgresp", VAR_STRING), VV_RO},
197 {VV_NAME("termrbgresp", VAR_STRING), VV_RO},
Bram Moolenaarf3af54e2017-08-30 14:53:06 +0200198 {VV_NAME("termu7resp", VAR_STRING), VV_RO},
Bram Moolenaar37df9a42019-06-14 14:39:51 +0200199 {VV_NAME("termstyleresp", VAR_STRING), VV_RO},
200 {VV_NAME("termblinkresp", VAR_STRING), VV_RO},
201 {VV_NAME("event", VAR_DICT), VV_RO},
202 {VV_NAME("versionlong", VAR_NUMBER), VV_RO},
Bram Moolenaar33570922005-01-25 22:26:29 +0000203};
204
205/* shorthand */
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000206#define vv_type vv_di.di_tv.v_type
207#define vv_nr vv_di.di_tv.vval.v_number
208#define vv_float vv_di.di_tv.vval.v_float
209#define vv_str vv_di.di_tv.vval.v_string
Bram Moolenaard812df62008-11-09 12:46:09 +0000210#define vv_list vv_di.di_tv.vval.v_list
Bram Moolenaar42a45122015-07-10 17:56:23 +0200211#define vv_dict vv_di.di_tv.vval.v_dict
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +0100212#define vv_blob vv_di.di_tv.vval.v_blob
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000213#define vv_tv vv_di.di_tv
Bram Moolenaar33570922005-01-25 22:26:29 +0000214
Bram Moolenaar230bb3f2013-04-24 14:07:45 +0200215static dictitem_T vimvars_var; /* variable used for v: */
Bram Moolenaar33570922005-01-25 22:26:29 +0000216#define vimvarht vimvardict.dv_hashtab
217
Bram Moolenaar9937a052019-06-15 15:45:06 +0200218static void ex_let_const(exarg_T *eap, int is_const);
219static int ex_let_vars(char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, int is_const, char_u *nextchars);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100220static char_u *skip_var_list(char_u *arg, int *var_count, int *semicolon);
221static char_u *skip_var_one(char_u *arg);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100222static void list_glob_vars(int *first);
223static void list_buf_vars(int *first);
224static void list_win_vars(int *first);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100225static void list_tab_vars(int *first);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100226static void list_vim_vars(int *first);
227static void list_script_vars(int *first);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100228static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first);
Bram Moolenaar9937a052019-06-15 15:45:06 +0200229static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, int is_const, char_u *endchars, char_u *op);
230static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, int is_const, char_u *op);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100231static int tv_op(typval_T *tv1, typval_T *tv2, char_u *op);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100232static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep);
233static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit);
234static int do_lock_var(lval_T *lp, char_u *name_end, int deep, int lock);
235static void item_lock(typval_T *tv, int deep, int lock);
Bram Moolenaara40058a2005-07-11 22:42:07 +0000236
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100237static int eval2(char_u **arg, typval_T *rettv, int evaluate);
238static int eval3(char_u **arg, typval_T *rettv, int evaluate);
239static int eval4(char_u **arg, typval_T *rettv, int evaluate);
240static int eval5(char_u **arg, typval_T *rettv, int evaluate);
241static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string);
242static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string);
Bram Moolenaara40058a2005-07-11 22:42:07 +0000243
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100244static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate);
245static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100246static int free_unref_items(int copyID);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100247static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100248static int get_env_len(char_u **arg);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100249static char_u * make_expanded_name(char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end);
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +0200250static void check_vars(char_u *name, int len);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100251static typval_T *alloc_string_tv(char_u *string);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100252static void delete_var(hashtab_T *ht, hashitem_T *hi);
Bram Moolenaar32526b32019-01-19 17:43:09 +0100253static void list_one_var(dictitem_T *v, char *prefix, int *first);
254static void list_one_var_a(char *prefix, char_u *name, int type, char_u *string, int *first);
Bram Moolenaar9937a052019-06-15 15:45:06 +0200255static void set_var_const(char_u *name, typval_T *tv, int copy, int is_const);
Bram Moolenaar05c00c02019-02-11 22:00:11 +0100256static int tv_check_lock(typval_T *tv, char_u *name, int use_gettext);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100257static char_u *find_option_end(char_u **arg, int *opt_flags);
Bram Moolenaar2c704a72010-06-03 21:17:25 +0200258
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200259/* for VIM_VERSION_ defines */
260#include "version.h"
261
Bram Moolenaare21c1582019-03-02 11:57:09 +0100262/*
263 * Return "n1" divided by "n2", taking care of dividing by zero.
264 */
265 static varnumber_T
266num_divide(varnumber_T n1, varnumber_T n2)
267{
268 varnumber_T result;
269
270 if (n2 == 0) // give an error message?
271 {
272 if (n1 == 0)
273 result = VARNUM_MIN; // similar to NaN
274 else if (n1 < 0)
275 result = -VARNUM_MAX;
276 else
277 result = VARNUM_MAX;
278 }
279 else
280 result = n1 / n2;
281
282 return result;
283}
284
285/*
286 * Return "n1" modulus "n2", taking care of dividing by zero.
287 */
288 static varnumber_T
289num_modulus(varnumber_T n1, varnumber_T n2)
290{
291 // Give an error when n2 is 0?
292 return (n2 == 0) ? 0 : (n1 % n2);
293}
294
Bram Moolenaara1fa8922017-01-12 20:06:33 +0100295
296#if defined(EBCDIC) || defined(PROTO)
297/*
298 * Compare struct fst by function name.
299 */
300 static int
301compare_func_name(const void *s1, const void *s2)
302{
303 struct fst *p1 = (struct fst *)s1;
304 struct fst *p2 = (struct fst *)s2;
305
306 return STRCMP(p1->f_name, p2->f_name);
307}
308
309/*
310 * Sort the function table by function name.
Bram Moolenaarb5443cc2019-01-15 20:19:40 +0100311 * The sorting of the table above is ASCII dependent.
Bram Moolenaara1fa8922017-01-12 20:06:33 +0100312 * On machines using EBCDIC we have to sort it.
313 */
314 static void
315sortFunctions(void)
316{
317 int funcCnt = (int)(sizeof(functions) / sizeof(struct fst)) - 1;
318
319 qsort(functions, (size_t)funcCnt, sizeof(struct fst), compare_func_name);
320}
321#endif
322
323
Bram Moolenaar33570922005-01-25 22:26:29 +0000324/*
325 * Initialize the global and v: variables.
Bram Moolenaara7043832005-01-21 11:56:39 +0000326 */
327 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100328eval_init(void)
Bram Moolenaara7043832005-01-21 11:56:39 +0000329{
Bram Moolenaar33570922005-01-25 22:26:29 +0000330 int i;
331 struct vimvar *p;
332
Bram Moolenaarbdb62052012-07-16 17:31:53 +0200333 init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE);
334 init_var_dict(&vimvardict, &vimvars_var, VAR_SCOPE);
Bram Moolenaar32f649e2011-04-11 13:46:13 +0200335 vimvardict.dv_lock = VAR_FIXED;
Bram Moolenaar532c7802005-01-27 14:44:31 +0000336 hash_init(&compat_hashtab);
Bram Moolenaara9b579f2016-07-17 18:29:19 +0200337 func_init();
Bram Moolenaar33570922005-01-25 22:26:29 +0000338
339 for (i = 0; i < VV_LEN; ++i)
340 {
341 p = &vimvars[i];
Bram Moolenaard7c96872019-06-15 17:12:48 +0200342 if (STRLEN(p->vv_name) > DICTITEM16_KEY_LEN)
Bram Moolenaaref9d9b92016-03-28 22:44:50 +0200343 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100344 iemsg("INTERNAL: name too long, increase size of dictitem16_T");
Bram Moolenaaref9d9b92016-03-28 22:44:50 +0200345 getout(1);
346 }
Bram Moolenaar33570922005-01-25 22:26:29 +0000347 STRCPY(p->vv_di.di_key, p->vv_name);
348 if (p->vv_flags & VV_RO)
349 p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
350 else if (p->vv_flags & VV_RO_SBX)
351 p->vv_di.di_flags = DI_FLAGS_RO_SBX | DI_FLAGS_FIX;
352 else
353 p->vv_di.di_flags = DI_FLAGS_FIX;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000354
355 /* add to v: scope dict, unless the value is not always available */
356 if (p->vv_type != VAR_UNKNOWN)
357 hash_add(&vimvarht, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000358 if (p->vv_flags & VV_COMPAT)
Bram Moolenaar532c7802005-01-27 14:44:31 +0000359 /* add to compat scope dict */
360 hash_add(&compat_hashtab, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000361 }
Bram Moolenaara542c682016-01-31 16:28:04 +0100362 vimvars[VV_VERSION].vv_nr = VIM_VERSION_100;
Bram Moolenaar37df9a42019-06-14 14:39:51 +0200363 vimvars[VV_VERSIONLONG].vv_nr = VIM_VERSION_100 * 10000 + highest_patch();
Bram Moolenaara542c682016-01-31 16:28:04 +0100364
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000365 set_vim_var_nr(VV_SEARCHFORWARD, 1L);
Bram Moolenaar8050efa2013-11-08 04:30:20 +0100366 set_vim_var_nr(VV_HLSEARCH, 1L);
Bram Moolenaar7e1652c2017-12-16 18:27:02 +0100367 set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED));
Bram Moolenaar4649ded2015-12-03 14:55:55 +0100368 set_vim_var_list(VV_ERRORS, list_alloc());
Bram Moolenaar7e1652c2017-12-16 18:27:02 +0100369 set_vim_var_dict(VV_EVENT, dict_alloc_lock(VAR_FIXED));
Bram Moolenaar520e1e42016-01-23 19:46:28 +0100370
371 set_vim_var_nr(VV_FALSE, VVAL_FALSE);
372 set_vim_var_nr(VV_TRUE, VVAL_TRUE);
373 set_vim_var_nr(VV_NONE, VVAL_NONE);
374 set_vim_var_nr(VV_NULL, VVAL_NULL);
375
Bram Moolenaarf562e722016-07-19 17:25:25 +0200376 set_vim_var_nr(VV_TYPE_NUMBER, VAR_TYPE_NUMBER);
377 set_vim_var_nr(VV_TYPE_STRING, VAR_TYPE_STRING);
378 set_vim_var_nr(VV_TYPE_FUNC, VAR_TYPE_FUNC);
379 set_vim_var_nr(VV_TYPE_LIST, VAR_TYPE_LIST);
380 set_vim_var_nr(VV_TYPE_DICT, VAR_TYPE_DICT);
381 set_vim_var_nr(VV_TYPE_FLOAT, VAR_TYPE_FLOAT);
382 set_vim_var_nr(VV_TYPE_BOOL, VAR_TYPE_BOOL);
383 set_vim_var_nr(VV_TYPE_NONE, VAR_TYPE_NONE);
384 set_vim_var_nr(VV_TYPE_JOB, VAR_TYPE_JOB);
385 set_vim_var_nr(VV_TYPE_CHANNEL, VAR_TYPE_CHANNEL);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +0100386 set_vim_var_nr(VV_TYPE_BLOB, VAR_TYPE_BLOB);
Bram Moolenaarf562e722016-07-19 17:25:25 +0200387
Bram Moolenaarb429cde2012-04-25 18:24:29 +0200388 set_reg_var(0); /* default for v:register is not 0 but '"' */
Bram Moolenaar2c704a72010-06-03 21:17:25 +0200389
390#ifdef EBCDIC
391 /*
Bram Moolenaar195ea0f2011-11-30 14:57:31 +0100392 * Sort the function table, to enable binary search.
Bram Moolenaar2c704a72010-06-03 21:17:25 +0200393 */
394 sortFunctions();
395#endif
Bram Moolenaara7043832005-01-21 11:56:39 +0000396}
397
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000398#if defined(EXITFREE) || defined(PROTO)
399 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100400eval_clear(void)
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000401{
402 int i;
403 struct vimvar *p;
404
405 for (i = 0; i < VV_LEN; ++i)
406 {
407 p = &vimvars[i];
408 if (p->vv_di.di_tv.v_type == VAR_STRING)
Bram Moolenaard23a8232018-02-10 18:45:26 +0100409 VIM_CLEAR(p->vv_str);
Bram Moolenaard812df62008-11-09 12:46:09 +0000410 else if (p->vv_di.di_tv.v_type == VAR_LIST)
411 {
412 list_unref(p->vv_list);
413 p->vv_list = NULL;
Bram Moolenaard9fba312005-06-26 22:34:35 +0000414 }
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000415 }
416 hash_clear(&vimvarht);
Bram Moolenaar0f71c6d2008-11-12 14:29:28 +0000417 hash_init(&vimvarht); /* garbage_collect() will access it */
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000418 hash_clear(&compat_hashtab);
419
Bram Moolenaard9fba312005-06-26 22:34:35 +0000420 free_scriptnames();
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +0100421# if defined(FEAT_CMDL_COMPL)
Bram Moolenaar9b486ca2011-05-19 18:26:40 +0200422 free_locales();
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +0100423# endif
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000424
425 /* global variables */
426 vars_clear(&globvarht);
Bram Moolenaard9fba312005-06-26 22:34:35 +0000427
Bram Moolenaaraa35dd12006-04-29 22:03:41 +0000428 /* autoloaded script names */
429 ga_clear_strings(&ga_loaded);
430
Bram Moolenaarcca74132013-09-25 21:00:28 +0200431 /* Script-local variables. First clear all the variables and in a second
432 * loop free the scriptvar_T, because a variable in one script might hold
433 * a reference to the whole scope of another script. */
Bram Moolenaar9577c3e2010-05-14 12:16:25 +0200434 for (i = 1; i <= ga_scripts.ga_len; ++i)
Bram Moolenaar9577c3e2010-05-14 12:16:25 +0200435 vars_clear(&SCRIPT_VARS(i));
Bram Moolenaarcca74132013-09-25 21:00:28 +0200436 for (i = 1; i <= ga_scripts.ga_len; ++i)
Bram Moolenaar9577c3e2010-05-14 12:16:25 +0200437 vim_free(SCRIPT_SV(i));
Bram Moolenaar9577c3e2010-05-14 12:16:25 +0200438 ga_clear(&ga_scripts);
439
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200440 // unreferenced lists and dicts
441 (void)garbage_collect(FALSE);
Bram Moolenaarc07f67a2019-06-06 19:03:17 +0200442
443 // functions not garbage collected
444 free_all_functions();
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000445}
446#endif
447
Bram Moolenaar071d4272004-06-13 20:20:40 +0000448
449/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000450 * Set an internal variable to a string value. Creates the variable if it does
451 * not already exist.
452 */
453 void
Bram Moolenaarb7604cc2016-01-15 21:23:22 +0100454set_internal_string_var(char_u *name, char_u *value)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000455{
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000456 char_u *val;
Bram Moolenaar33570922005-01-25 22:26:29 +0000457 typval_T *tvp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000458
459 val = vim_strsave(value);
460 if (val != NULL)
461 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000462 tvp = alloc_string_tv(val);
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000463 if (tvp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000464 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000465 set_var(name, tvp, FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000466 free_tv(tvp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000467 }
468 }
469}
470
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000471static lval_T *redir_lval = NULL;
Bram Moolenaar1e5e1232016-07-07 17:33:02 +0200472#define EVALCMD_BUSY (redir_lval == (lval_T *)&redir_lval)
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000473static garray_T redir_ga; /* only valid when redir_lval is not NULL */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000474static char_u *redir_endp = NULL;
475static char_u *redir_varname = NULL;
476
477/*
478 * Start recording command output to a variable
Bram Moolenaarb7604cc2016-01-15 21:23:22 +0100479 * When "append" is TRUE append to an existing variable.
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000480 * Returns OK if successfully completed the setup. FAIL otherwise.
481 */
482 int
Bram Moolenaarb7604cc2016-01-15 21:23:22 +0100483var_redir_start(char_u *name, int append)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000484{
485 int save_emsg;
486 int err;
487 typval_T tv;
488
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000489 /* Catch a bad name early. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000490 if (!eval_isnamec1(*name))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000491 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100492 emsg(_(e_invarg));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000493 return FAIL;
494 }
495
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000496 /* Make a copy of the name, it is used in redir_lval until redir ends. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000497 redir_varname = vim_strsave(name);
498 if (redir_varname == NULL)
499 return FAIL;
500
Bram Moolenaarc799fe22019-05-28 23:08:19 +0200501 redir_lval = ALLOC_CLEAR_ONE(lval_T);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000502 if (redir_lval == NULL)
503 {
504 var_redir_stop();
505 return FAIL;
506 }
507
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000508 /* The output is stored in growarray "redir_ga" until redirection ends. */
509 ga_init2(&redir_ga, (int)sizeof(char), 500);
510
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000511 /* Parse the variable name (can be a dict or list entry). */
Bram Moolenaar6d977d62014-01-14 15:24:39 +0100512 redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, 0,
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000513 FNE_CHECK_START);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000514 if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != NUL)
515 {
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +0200516 clear_lval(redir_lval);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000517 if (redir_endp != NULL && *redir_endp != NUL)
518 /* Trailing characters are present after the variable name */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100519 emsg(_(e_trailing));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000520 else
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100521 emsg(_(e_invarg));
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000522 redir_endp = NULL; /* don't store a value, only cleanup */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000523 var_redir_stop();
524 return FAIL;
525 }
526
527 /* check if we can write to the variable: set it to or append an empty
528 * string */
529 save_emsg = did_emsg;
530 did_emsg = FALSE;
531 tv.v_type = VAR_STRING;
532 tv.vval.v_string = (char_u *)"";
533 if (append)
Bram Moolenaar9937a052019-06-15 15:45:06 +0200534 set_var_lval(redir_lval, redir_endp, &tv, TRUE, FALSE, (char_u *)".");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000535 else
Bram Moolenaar9937a052019-06-15 15:45:06 +0200536 set_var_lval(redir_lval, redir_endp, &tv, TRUE, FALSE, (char_u *)"=");
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +0200537 clear_lval(redir_lval);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000538 err = did_emsg;
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000539 did_emsg |= save_emsg;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000540 if (err)
541 {
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000542 redir_endp = NULL; /* don't store a value, only cleanup */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000543 var_redir_stop();
544 return FAIL;
545 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000546
547 return OK;
548}
549
550/*
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000551 * Append "value[value_len]" to the variable set by var_redir_start().
552 * The actual appending is postponed until redirection ends, because the value
553 * appended may in fact be the string we write to, changing it may cause freed
554 * memory to be used:
555 * :redir => foo
556 * :let foo
557 * :redir END
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000558 */
559 void
Bram Moolenaarb7604cc2016-01-15 21:23:22 +0100560var_redir_str(char_u *value, int value_len)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000561{
Bram Moolenaar5fdec472007-07-24 08:45:13 +0000562 int len;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000563
564 if (redir_lval == NULL)
565 return;
566
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000567 if (value_len == -1)
Bram Moolenaar5fdec472007-07-24 08:45:13 +0000568 len = (int)STRLEN(value); /* Append the entire string */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000569 else
Bram Moolenaar5fdec472007-07-24 08:45:13 +0000570 len = value_len; /* Append only "value_len" characters */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000571
Bram Moolenaar5fdec472007-07-24 08:45:13 +0000572 if (ga_grow(&redir_ga, len) == OK)
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000573 {
574 mch_memmove((char *)redir_ga.ga_data + redir_ga.ga_len, value, len);
Bram Moolenaar5fdec472007-07-24 08:45:13 +0000575 redir_ga.ga_len += len;
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000576 }
577 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000578 var_redir_stop();
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000579}
580
581/*
582 * Stop redirecting command output to a variable.
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000583 * Frees the allocated memory.
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000584 */
585 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100586var_redir_stop(void)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000587{
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000588 typval_T tv;
589
Bram Moolenaar1e5e1232016-07-07 17:33:02 +0200590 if (EVALCMD_BUSY)
591 {
592 redir_lval = NULL;
593 return;
594 }
595
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000596 if (redir_lval != NULL)
597 {
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000598 /* If there was no error: assign the text to the variable. */
599 if (redir_endp != NULL)
600 {
601 ga_append(&redir_ga, NUL); /* Append the trailing NUL. */
602 tv.v_type = VAR_STRING;
603 tv.vval.v_string = redir_ga.ga_data;
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +0200604 /* Call get_lval() again, if it's inside a Dict or List it may
605 * have changed. */
606 redir_endp = get_lval(redir_varname, NULL, redir_lval,
Bram Moolenaar6d977d62014-01-14 15:24:39 +0100607 FALSE, FALSE, 0, FNE_CHECK_START);
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +0200608 if (redir_endp != NULL && redir_lval->ll_name != NULL)
Bram Moolenaar9937a052019-06-15 15:45:06 +0200609 set_var_lval(redir_lval, redir_endp, &tv, FALSE, FALSE,
610 (char_u *)".");
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +0200611 clear_lval(redir_lval);
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000612 }
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000613
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000614 /* free the collected output */
Bram Moolenaard23a8232018-02-10 18:45:26 +0100615 VIM_CLEAR(redir_ga.ga_data);
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000616
Bram Moolenaard23a8232018-02-10 18:45:26 +0100617 VIM_CLEAR(redir_lval);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000618 }
Bram Moolenaard23a8232018-02-10 18:45:26 +0100619 VIM_CLEAR(redir_varname);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000620}
621
Bram Moolenaar071d4272004-06-13 20:20:40 +0000622 int
Bram Moolenaarb7604cc2016-01-15 21:23:22 +0100623eval_charconvert(
624 char_u *enc_from,
625 char_u *enc_to,
626 char_u *fname_from,
627 char_u *fname_to)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000628{
629 int err = FALSE;
630
631 set_vim_var_string(VV_CC_FROM, enc_from, -1);
632 set_vim_var_string(VV_CC_TO, enc_to, -1);
633 set_vim_var_string(VV_FNAME_IN, fname_from, -1);
634 set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
635 if (eval_to_bool(p_ccv, &err, NULL, FALSE))
636 err = TRUE;
637 set_vim_var_string(VV_CC_FROM, NULL, -1);
638 set_vim_var_string(VV_CC_TO, NULL, -1);
639 set_vim_var_string(VV_FNAME_IN, NULL, -1);
640 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
641
642 if (err)
643 return FAIL;
644 return OK;
645}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000646
647# if defined(FEAT_POSTSCRIPT) || defined(PROTO)
648 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100649eval_printexpr(char_u *fname, char_u *args)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000650{
651 int err = FALSE;
652
653 set_vim_var_string(VV_FNAME_IN, fname, -1);
654 set_vim_var_string(VV_CMDARG, args, -1);
655 if (eval_to_bool(p_pexpr, &err, NULL, FALSE))
656 err = TRUE;
657 set_vim_var_string(VV_FNAME_IN, NULL, -1);
658 set_vim_var_string(VV_CMDARG, NULL, -1);
659
660 if (err)
661 {
662 mch_remove(fname);
663 return FAIL;
664 }
665 return OK;
666}
667# endif
668
669# if defined(FEAT_DIFF) || defined(PROTO)
670 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100671eval_diff(
672 char_u *origfile,
673 char_u *newfile,
674 char_u *outfile)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000675{
676 int err = FALSE;
677
678 set_vim_var_string(VV_FNAME_IN, origfile, -1);
679 set_vim_var_string(VV_FNAME_NEW, newfile, -1);
680 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
681 (void)eval_to_bool(p_dex, &err, NULL, FALSE);
682 set_vim_var_string(VV_FNAME_IN, NULL, -1);
683 set_vim_var_string(VV_FNAME_NEW, NULL, -1);
684 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
685}
686
687 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100688eval_patch(
689 char_u *origfile,
690 char_u *difffile,
691 char_u *outfile)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000692{
693 int err;
694
695 set_vim_var_string(VV_FNAME_IN, origfile, -1);
696 set_vim_var_string(VV_FNAME_DIFF, difffile, -1);
697 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
698 (void)eval_to_bool(p_pex, &err, NULL, FALSE);
699 set_vim_var_string(VV_FNAME_IN, NULL, -1);
700 set_vim_var_string(VV_FNAME_DIFF, NULL, -1);
701 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
702}
703# endif
704
705/*
706 * Top level evaluation function, returning a boolean.
707 * Sets "error" to TRUE if there was an error.
708 * Return TRUE or FALSE.
709 */
710 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100711eval_to_bool(
712 char_u *arg,
713 int *error,
714 char_u **nextcmd,
715 int skip) /* only parse, don't execute */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000716{
Bram Moolenaar33570922005-01-25 22:26:29 +0000717 typval_T tv;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +0200718 varnumber_T retval = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000719
720 if (skip)
721 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000722 if (eval0(arg, &tv, nextcmd, !skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000723 *error = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000724 else
725 {
726 *error = FALSE;
727 if (!skip)
728 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +0100729 retval = (tv_get_number_chk(&tv, error) != 0);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000730 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000731 }
732 }
733 if (skip)
734 --emsg_skip;
735
Bram Moolenaar22fcfad2016-07-01 18:17:26 +0200736 return (int)retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000737}
738
Bram Moolenaarce9d50d2019-01-14 22:22:29 +0100739/*
740 * Call eval1() and give an error message if not done at a lower level.
741 */
742 static int
743eval1_emsg(char_u **arg, typval_T *rettv, int evaluate)
744{
Bram Moolenaar6acc79f2019-01-14 22:53:31 +0100745 char_u *start = *arg;
Bram Moolenaarce9d50d2019-01-14 22:22:29 +0100746 int ret;
747 int did_emsg_before = did_emsg;
748 int called_emsg_before = called_emsg;
749
750 ret = eval1(arg, rettv, evaluate);
751 if (ret == FAIL)
752 {
753 // Report the invalid expression unless the expression evaluation has
754 // been cancelled due to an aborting error, an interrupt, or an
755 // exception, or we already gave a more specific error.
756 // Also check called_emsg for when using assert_fails().
757 if (!aborting() && did_emsg == did_emsg_before
758 && called_emsg == called_emsg_before)
Bram Moolenaar6acc79f2019-01-14 22:53:31 +0100759 semsg(_(e_invexpr2), start);
Bram Moolenaarce9d50d2019-01-14 22:22:29 +0100760 }
761 return ret;
762}
763
Bram Moolenaar543c9b12019-04-05 22:50:40 +0200764 int
Bram Moolenaar48570482017-10-30 21:48:41 +0100765eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv)
766{
767 char_u *s;
Bram Moolenaar48570482017-10-30 21:48:41 +0100768 char_u buf[NUMBUFLEN];
Bram Moolenaarc6538bc2019-08-03 18:17:11 +0200769 funcexe_T funcexe;
Bram Moolenaar48570482017-10-30 21:48:41 +0100770
771 if (expr->v_type == VAR_FUNC)
772 {
773 s = expr->vval.v_string;
774 if (s == NULL || *s == NUL)
775 return FAIL;
Bram Moolenaarc6538bc2019-08-03 18:17:11 +0200776 vim_memset(&funcexe, 0, sizeof(funcexe));
777 funcexe.evaluate = TRUE;
778 if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL)
Bram Moolenaar48570482017-10-30 21:48:41 +0100779 return FAIL;
780 }
781 else if (expr->v_type == VAR_PARTIAL)
782 {
783 partial_T *partial = expr->vval.v_partial;
784
785 s = partial_name(partial);
786 if (s == NULL || *s == NUL)
787 return FAIL;
Bram Moolenaarc6538bc2019-08-03 18:17:11 +0200788 vim_memset(&funcexe, 0, sizeof(funcexe));
789 funcexe.evaluate = TRUE;
790 funcexe.partial = partial;
791 if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL)
Bram Moolenaar48570482017-10-30 21:48:41 +0100792 return FAIL;
793 }
794 else
795 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +0100796 s = tv_get_string_buf_chk(expr, buf);
Bram Moolenaar48570482017-10-30 21:48:41 +0100797 if (s == NULL)
798 return FAIL;
799 s = skipwhite(s);
Bram Moolenaarce9d50d2019-01-14 22:22:29 +0100800 if (eval1_emsg(&s, rettv, TRUE) == FAIL)
Bram Moolenaar48570482017-10-30 21:48:41 +0100801 return FAIL;
802 if (*s != NUL) /* check for trailing chars after expr */
803 {
Bram Moolenaara43ebe92018-07-14 17:25:01 +0200804 clear_tv(rettv);
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100805 semsg(_(e_invexpr2), s);
Bram Moolenaar48570482017-10-30 21:48:41 +0100806 return FAIL;
807 }
808 }
809 return OK;
810}
811
812/*
813 * Like eval_to_bool() but using a typval_T instead of a string.
814 * Works for string, funcref and partial.
815 */
816 int
817eval_expr_to_bool(typval_T *expr, int *error)
818{
819 typval_T rettv;
820 int res;
821
822 if (eval_expr_typval(expr, NULL, 0, &rettv) == FAIL)
823 {
824 *error = TRUE;
825 return FALSE;
826 }
Bram Moolenaard155d7a2018-12-21 16:04:21 +0100827 res = (tv_get_number_chk(&rettv, error) != 0);
Bram Moolenaar48570482017-10-30 21:48:41 +0100828 clear_tv(&rettv);
829 return res;
830}
831
Bram Moolenaar071d4272004-06-13 20:20:40 +0000832/*
833 * Top level evaluation function, returning a string. If "skip" is TRUE,
834 * only parsing to "nextcmd" is done, without reporting errors. Return
835 * pointer to allocated memory, or NULL for failure or when "skip" is TRUE.
836 */
837 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100838eval_to_string_skip(
839 char_u *arg,
840 char_u **nextcmd,
841 int skip) /* only parse, don't execute */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000842{
Bram Moolenaar33570922005-01-25 22:26:29 +0000843 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000844 char_u *retval;
845
846 if (skip)
847 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000848 if (eval0(arg, &tv, nextcmd, !skip) == FAIL || skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000849 retval = NULL;
850 else
851 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +0100852 retval = vim_strsave(tv_get_string(&tv));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000853 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000854 }
855 if (skip)
856 --emsg_skip;
857
858 return retval;
859}
860
861/*
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000862 * Skip over an expression at "*pp".
863 * Return FAIL for an error, OK otherwise.
864 */
865 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100866skip_expr(char_u **pp)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000867{
Bram Moolenaar33570922005-01-25 22:26:29 +0000868 typval_T rettv;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000869
870 *pp = skipwhite(*pp);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000871 return eval1(pp, &rettv, FALSE);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000872}
873
874/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000875 * Top level evaluation function, returning a string.
Bram Moolenaara85fb752008-09-07 11:55:43 +0000876 * When "convert" is TRUE convert a List into a sequence of lines and convert
877 * a Float to a String.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000878 * Return pointer to allocated memory, or NULL for failure.
879 */
880 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100881eval_to_string(
882 char_u *arg,
883 char_u **nextcmd,
884 int convert)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000885{
Bram Moolenaar33570922005-01-25 22:26:29 +0000886 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000887 char_u *retval;
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000888 garray_T ga;
Bram Moolenaar798b30b2009-04-22 10:56:16 +0000889#ifdef FEAT_FLOAT
Bram Moolenaara85fb752008-09-07 11:55:43 +0000890 char_u numbuf[NUMBUFLEN];
Bram Moolenaar798b30b2009-04-22 10:56:16 +0000891#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000892
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000893 if (eval0(arg, &tv, nextcmd, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000894 retval = NULL;
895 else
896 {
Bram Moolenaara85fb752008-09-07 11:55:43 +0000897 if (convert && tv.v_type == VAR_LIST)
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000898 {
899 ga_init2(&ga, (int)sizeof(char), 80);
Bram Moolenaar9bf749b2008-07-27 13:57:29 +0000900 if (tv.vval.v_list != NULL)
Bram Moolenaar213b10a2011-08-10 12:38:08 +0200901 {
Bram Moolenaar18dfb442016-05-31 22:31:23 +0200902 list_join(&ga, tv.vval.v_list, (char_u *)"\n", TRUE, FALSE, 0);
Bram Moolenaar213b10a2011-08-10 12:38:08 +0200903 if (tv.vval.v_list->lv_len > 0)
904 ga_append(&ga, NL);
905 }
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000906 ga_append(&ga, NUL);
907 retval = (char_u *)ga.ga_data;
908 }
Bram Moolenaara85fb752008-09-07 11:55:43 +0000909#ifdef FEAT_FLOAT
910 else if (convert && tv.v_type == VAR_FLOAT)
911 {
912 vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv.vval.v_float);
913 retval = vim_strsave(numbuf);
914 }
915#endif
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000916 else
Bram Moolenaard155d7a2018-12-21 16:04:21 +0100917 retval = vim_strsave(tv_get_string(&tv));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000918 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000919 }
920
921 return retval;
922}
923
924/*
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000925 * Call eval_to_string() without using current local variables and using
926 * textlock. When "use_sandbox" is TRUE use the sandbox.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000927 */
928 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100929eval_to_string_safe(
930 char_u *arg,
931 char_u **nextcmd,
932 int use_sandbox)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000933{
934 char_u *retval;
Bram Moolenaar27e80c82018-10-14 21:41:01 +0200935 funccal_entry_T funccal_entry;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000936
Bram Moolenaar27e80c82018-10-14 21:41:01 +0200937 save_funccal(&funccal_entry);
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000938 if (use_sandbox)
939 ++sandbox;
940 ++textlock;
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000941 retval = eval_to_string(arg, nextcmd, FALSE);
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000942 if (use_sandbox)
943 --sandbox;
944 --textlock;
Bram Moolenaar27e80c82018-10-14 21:41:01 +0200945 restore_funccal();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000946 return retval;
947}
948
Bram Moolenaar071d4272004-06-13 20:20:40 +0000949/*
950 * Top level evaluation function, returning a number.
951 * Evaluates "expr" silently.
952 * Returns -1 for an error.
953 */
Bram Moolenaar22fcfad2016-07-01 18:17:26 +0200954 varnumber_T
Bram Moolenaar7454a062016-01-30 15:14:10 +0100955eval_to_number(char_u *expr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000956{
Bram Moolenaar33570922005-01-25 22:26:29 +0000957 typval_T rettv;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +0200958 varnumber_T retval;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +0000959 char_u *p = skipwhite(expr);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000960
961 ++emsg_off;
962
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000963 if (eval1(&p, &rettv, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000964 retval = -1;
965 else
966 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +0100967 retval = tv_get_number_chk(&rettv, NULL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000968 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000969 }
970 --emsg_off;
971
972 return retval;
973}
974
Bram Moolenaara40058a2005-07-11 22:42:07 +0000975/*
976 * Prepare v: variable "idx" to be used.
977 * Save the current typeval in "save_tv".
978 * When not used yet add the variable to the v: hashtable.
979 */
Bram Moolenaar543c9b12019-04-05 22:50:40 +0200980 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100981prepare_vimvar(int idx, typval_T *save_tv)
Bram Moolenaara40058a2005-07-11 22:42:07 +0000982{
983 *save_tv = vimvars[idx].vv_tv;
984 if (vimvars[idx].vv_type == VAR_UNKNOWN)
985 hash_add(&vimvarht, vimvars[idx].vv_di.di_key);
986}
987
988/*
989 * Restore v: variable "idx" to typeval "save_tv".
990 * When no longer defined, remove the variable from the v: hashtable.
991 */
Bram Moolenaar543c9b12019-04-05 22:50:40 +0200992 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100993restore_vimvar(int idx, typval_T *save_tv)
Bram Moolenaara40058a2005-07-11 22:42:07 +0000994{
995 hashitem_T *hi;
996
Bram Moolenaara40058a2005-07-11 22:42:07 +0000997 vimvars[idx].vv_tv = *save_tv;
998 if (vimvars[idx].vv_type == VAR_UNKNOWN)
999 {
1000 hi = hash_find(&vimvarht, vimvars[idx].vv_di.di_key);
1001 if (HASHITEM_EMPTY(hi))
Bram Moolenaar95f09602016-11-10 20:01:45 +01001002 internal_error("restore_vimvar()");
Bram Moolenaara40058a2005-07-11 22:42:07 +00001003 else
1004 hash_remove(&vimvarht, hi);
1005 }
1006}
1007
Bram Moolenaar3c56a962006-03-12 22:19:04 +00001008#if defined(FEAT_SPELL) || defined(PROTO)
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001009/*
1010 * Evaluate an expression to a list with suggestions.
1011 * For the "expr:" part of 'spellsuggest'.
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00001012 * Returns NULL when there is an error.
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001013 */
1014 list_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001015eval_spell_expr(char_u *badword, char_u *expr)
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001016{
1017 typval_T save_val;
1018 typval_T rettv;
1019 list_T *list = NULL;
1020 char_u *p = skipwhite(expr);
1021
1022 /* Set "v:val" to the bad word. */
1023 prepare_vimvar(VV_VAL, &save_val);
1024 vimvars[VV_VAL].vv_type = VAR_STRING;
1025 vimvars[VV_VAL].vv_str = badword;
1026 if (p_verbose == 0)
1027 ++emsg_off;
1028
1029 if (eval1(&p, &rettv, TRUE) == OK)
1030 {
1031 if (rettv.v_type != VAR_LIST)
1032 clear_tv(&rettv);
1033 else
1034 list = rettv.vval.v_list;
1035 }
1036
1037 if (p_verbose == 0)
1038 --emsg_off;
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001039 restore_vimvar(VV_VAL, &save_val);
1040
1041 return list;
1042}
1043
1044/*
1045 * "list" is supposed to contain two items: a word and a number. Return the
1046 * word in "pp" and the number as the return value.
1047 * Return -1 if anything isn't right.
1048 * Used to get the good word and score from the eval_spell_expr() result.
1049 */
1050 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001051get_spellword(list_T *list, char_u **pp)
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001052{
1053 listitem_T *li;
1054
1055 li = list->lv_first;
1056 if (li == NULL)
1057 return -1;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01001058 *pp = tv_get_string(&li->li_tv);
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001059
1060 li = li->li_next;
1061 if (li == NULL)
1062 return -1;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01001063 return (int)tv_get_number(&li->li_tv);
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001064}
1065#endif
1066
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001067/*
Bram Moolenaar4770d092006-01-12 23:22:24 +00001068 * Top level evaluation function.
1069 * Returns an allocated typval_T with the result.
1070 * Returns NULL when there is an error.
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001071 */
1072 typval_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001073eval_expr(char_u *arg, char_u **nextcmd)
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001074{
1075 typval_T *tv;
1076
Bram Moolenaarc799fe22019-05-28 23:08:19 +02001077 tv = ALLOC_ONE(typval_T);
Bram Moolenaar4770d092006-01-12 23:22:24 +00001078 if (tv != NULL && eval0(arg, tv, nextcmd, TRUE) == FAIL)
Bram Moolenaard23a8232018-02-10 18:45:26 +01001079 VIM_CLEAR(tv);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001080
1081 return tv;
1082}
1083
1084
Bram Moolenaar071d4272004-06-13 20:20:40 +00001085/*
Bram Moolenaarb544f3c2017-02-23 19:03:28 +01001086 * Call some Vim script function and return the result in "*rettv".
Bram Moolenaarffa96842018-06-12 22:05:14 +02001087 * Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc]
1088 * should have type VAR_UNKNOWN.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001089 * Returns OK or FAIL.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001090 */
Bram Moolenaar82139082011-09-14 16:52:09 +02001091 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001092call_vim_function(
1093 char_u *func,
1094 int argc,
Bram Moolenaarffa96842018-06-12 22:05:14 +02001095 typval_T *argv,
Bram Moolenaarded27a12018-08-01 19:06:03 +02001096 typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001097{
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001098 int ret;
Bram Moolenaarc6538bc2019-08-03 18:17:11 +02001099 funcexe_T funcexe;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001100
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001101 rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */
Bram Moolenaarc6538bc2019-08-03 18:17:11 +02001102 vim_memset(&funcexe, 0, sizeof(funcexe));
1103 funcexe.firstline = curwin->w_cursor.lnum;
1104 funcexe.lastline = curwin->w_cursor.lnum;
1105 funcexe.evaluate = TRUE;
1106 ret = call_func(func, -1, rettv, argc, argv, &funcexe);
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001107 if (ret == FAIL)
1108 clear_tv(rettv);
1109
1110 return ret;
1111}
1112
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001113/*
Bram Moolenaarb544f3c2017-02-23 19:03:28 +01001114 * Call Vim script function "func" and return the result as a number.
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001115 * Returns -1 when calling the function fails.
Bram Moolenaarffa96842018-06-12 22:05:14 +02001116 * Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc] should
1117 * have type VAR_UNKNOWN.
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001118 */
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001119 varnumber_T
Bram Moolenaar7454a062016-01-30 15:14:10 +01001120call_func_retnr(
1121 char_u *func,
1122 int argc,
Bram Moolenaarded27a12018-08-01 19:06:03 +02001123 typval_T *argv)
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001124{
1125 typval_T rettv;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001126 varnumber_T retval;
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001127
Bram Moolenaarded27a12018-08-01 19:06:03 +02001128 if (call_vim_function(func, argc, argv, &rettv) == FAIL)
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001129 return -1;
1130
Bram Moolenaard155d7a2018-12-21 16:04:21 +01001131 retval = tv_get_number_chk(&rettv, NULL);
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001132 clear_tv(&rettv);
1133 return retval;
1134}
1135
Bram Moolenaarac9fb182019-04-27 13:04:13 +02001136#if defined(FEAT_CMDL_COMPL) \
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001137 || defined(FEAT_COMPL_FUNC) || defined(PROTO)
1138
Bram Moolenaarac9fb182019-04-27 13:04:13 +02001139# if defined(FEAT_CMDL_COMPL) || defined(PROTO)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001140/*
Bram Moolenaarb544f3c2017-02-23 19:03:28 +01001141 * Call Vim script function "func" and return the result as a string.
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001142 * Returns NULL when calling the function fails.
Bram Moolenaarffa96842018-06-12 22:05:14 +02001143 * Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc] should
1144 * have type VAR_UNKNOWN.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001145 */
1146 void *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001147call_func_retstr(
1148 char_u *func,
1149 int argc,
Bram Moolenaarded27a12018-08-01 19:06:03 +02001150 typval_T *argv)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001151{
1152 typval_T rettv;
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001153 char_u *retval;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001154
Bram Moolenaarded27a12018-08-01 19:06:03 +02001155 if (call_vim_function(func, argc, argv, &rettv) == FAIL)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001156 return NULL;
1157
Bram Moolenaard155d7a2018-12-21 16:04:21 +01001158 retval = vim_strsave(tv_get_string(&rettv));
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001159 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001160 return retval;
1161}
Bram Moolenaar4f688582007-07-24 12:34:30 +00001162# endif
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001163
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001164/*
Bram Moolenaarb544f3c2017-02-23 19:03:28 +01001165 * Call Vim script function "func" and return the result as a List.
Bram Moolenaarffa96842018-06-12 22:05:14 +02001166 * Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc] should
1167 * have type VAR_UNKNOWN.
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00001168 * Returns NULL when there is something wrong.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001169 */
1170 void *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001171call_func_retlist(
1172 char_u *func,
1173 int argc,
Bram Moolenaarded27a12018-08-01 19:06:03 +02001174 typval_T *argv)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001175{
1176 typval_T rettv;
1177
Bram Moolenaarded27a12018-08-01 19:06:03 +02001178 if (call_vim_function(func, argc, argv, &rettv) == FAIL)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001179 return NULL;
1180
1181 if (rettv.v_type != VAR_LIST)
1182 {
1183 clear_tv(&rettv);
1184 return NULL;
1185 }
1186
1187 return rettv.vval.v_list;
1188}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001189#endif
1190
Bram Moolenaar05159a02005-02-26 23:04:13 +00001191
Bram Moolenaar071d4272004-06-13 20:20:40 +00001192#ifdef FEAT_FOLDING
1193/*
1194 * Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding
1195 * it in "*cp". Doesn't give error messages.
1196 */
1197 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001198eval_foldexpr(char_u *arg, int *cp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001199{
Bram Moolenaar33570922005-01-25 22:26:29 +00001200 typval_T tv;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001201 varnumber_T retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001202 char_u *s;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00001203 int use_sandbox = was_set_insecurely((char_u *)"foldexpr",
1204 OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001205
1206 ++emsg_off;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001207 if (use_sandbox)
1208 ++sandbox;
1209 ++textlock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001210 *cp = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001211 if (eval0(arg, &tv, NULL, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001212 retval = 0;
1213 else
1214 {
1215 /* If the result is a number, just return the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001216 if (tv.v_type == VAR_NUMBER)
1217 retval = tv.vval.v_number;
Bram Moolenaar758711c2005-02-02 23:11:38 +00001218 else if (tv.v_type != VAR_STRING || tv.vval.v_string == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001219 retval = 0;
1220 else
1221 {
1222 /* If the result is a string, check if there is a non-digit before
1223 * the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001224 s = tv.vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001225 if (!VIM_ISDIGIT(*s) && *s != '-')
1226 *cp = *s++;
1227 retval = atol((char *)s);
1228 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001229 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001230 }
1231 --emsg_off;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001232 if (use_sandbox)
1233 --sandbox;
1234 --textlock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001235
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001236 return (int)retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001237}
1238#endif
1239
Bram Moolenaar071d4272004-06-13 20:20:40 +00001240/*
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001241 * Get a list of lines from a HERE document. The here document is a list of
1242 * lines surrounded by a marker.
1243 * cmd << {marker}
1244 * {line1}
1245 * {line2}
1246 * ....
1247 * {marker}
1248 *
1249 * The {marker} is a string. If the optional 'trim' word is supplied before the
1250 * marker, then the leading indentation before the lines (matching the
1251 * indentation in the 'cmd' line) is stripped.
1252 * Returns a List with {lines} or NULL.
1253 */
1254 static list_T *
1255heredoc_get(exarg_T *eap, char_u *cmd)
1256{
1257 char_u *theline;
1258 char_u *marker;
1259 list_T *l;
1260 char_u *p;
Bram Moolenaare7eb9272019-06-24 00:58:07 +02001261 int marker_indent_len = 0;
1262 int text_indent_len = 0;
1263 char_u *text_indent = NULL;
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001264
1265 if (eap->getline == NULL)
1266 {
1267 emsg(_("E991: cannot use =<< here"));
1268 return NULL;
1269 }
1270
1271 // Check for the optional 'trim' word before the marker
1272 cmd = skipwhite(cmd);
1273 if (STRNCMP(cmd, "trim", 4) == 0 && (cmd[4] == NUL || VIM_ISWHITE(cmd[4])))
1274 {
1275 cmd = skipwhite(cmd + 4);
1276
Bram Moolenaare7eb9272019-06-24 00:58:07 +02001277 // Trim the indentation from all the lines in the here document.
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001278 // The amount of indentation trimmed is the same as the indentation of
Bram Moolenaare7eb9272019-06-24 00:58:07 +02001279 // the first line after the :let command line. To find the end marker
1280 // the indent of the :let command line is trimmed.
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001281 p = *eap->cmdlinep;
1282 while (VIM_ISWHITE(*p))
1283 {
1284 p++;
Bram Moolenaare7eb9272019-06-24 00:58:07 +02001285 marker_indent_len++;
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001286 }
Bram Moolenaare7eb9272019-06-24 00:58:07 +02001287 text_indent_len = -1;
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001288 }
1289
Bram Moolenaar24582002019-07-21 14:14:26 +02001290 // The marker is the next word.
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001291 if (*cmd != NUL && *cmd != '"')
1292 {
1293 marker = skipwhite(cmd);
1294 p = skiptowhite(marker);
1295 if (*skipwhite(p) != NUL && *skipwhite(p) != '"')
1296 {
1297 emsg(_(e_trailing));
1298 return NULL;
1299 }
1300 *p = NUL;
Bram Moolenaar24582002019-07-21 14:14:26 +02001301 if (vim_islower(*marker))
1302 {
1303 emsg(_("E221: Marker cannot start with lower case letter"));
1304 return NULL;
1305 }
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001306 }
1307 else
Bram Moolenaar24582002019-07-21 14:14:26 +02001308 {
1309 emsg(_("E172: Missing marker"));
1310 return NULL;
1311 }
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001312
1313 l = list_alloc();
1314 if (l == NULL)
1315 return NULL;
1316
1317 for (;;)
1318 {
Bram Moolenaare7eb9272019-06-24 00:58:07 +02001319 int mi = 0;
1320 int ti = 0;
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001321
Bram Moolenaare96a2492019-06-25 04:12:16 +02001322 theline = eap->getline(NUL, eap->cookie, 0, FALSE);
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001323 if (theline == NULL)
1324 {
1325 semsg(_("E990: Missing end marker '%s'"), marker);
1326 break;
1327 }
Bram Moolenaare7eb9272019-06-24 00:58:07 +02001328
1329 // with "trim": skip the indent matching the :let line to find the
1330 // marker
1331 if (marker_indent_len > 0
1332 && STRNCMP(theline, *eap->cmdlinep, marker_indent_len) == 0)
1333 mi = marker_indent_len;
1334 if (STRCMP(marker, theline + mi) == 0)
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001335 {
1336 vim_free(theline);
1337 break;
1338 }
1339
Bram Moolenaare7eb9272019-06-24 00:58:07 +02001340 if (text_indent_len == -1 && *theline != NUL)
1341 {
1342 // set the text indent from the first line.
1343 p = theline;
1344 text_indent_len = 0;
1345 while (VIM_ISWHITE(*p))
1346 {
1347 p++;
1348 text_indent_len++;
1349 }
1350 text_indent = vim_strnsave(theline, text_indent_len);
1351 }
1352 // with "trim": skip the indent matching the first line
1353 if (text_indent != NULL)
1354 for (ti = 0; ti < text_indent_len; ++ti)
1355 if (theline[ti] != text_indent[ti])
1356 break;
1357
1358 if (list_append_string(l, theline + ti, -1) == FAIL)
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001359 break;
1360 vim_free(theline);
1361 }
Bram Moolenaare7eb9272019-06-24 00:58:07 +02001362 vim_free(text_indent);
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001363
1364 return l;
1365}
1366
1367/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001368 * ":let" list all variable values
1369 * ":let var1 var2" list variable values
1370 * ":let var = expr" assignment command.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001371 * ":let var += expr" assignment command.
1372 * ":let var -= expr" assignment command.
Bram Moolenaarff697e62019-02-12 22:28:33 +01001373 * ":let var *= expr" assignment command.
1374 * ":let var /= expr" assignment command.
1375 * ":let var %= expr" assignment command.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001376 * ":let var .= expr" assignment command.
Bram Moolenaar0f248b02019-04-04 15:36:05 +02001377 * ":let var ..= expr" assignment command.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001378 * ":let [var1, var2] = expr" unpack list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001379 */
1380 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001381ex_let(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001382{
Bram Moolenaar9937a052019-06-15 15:45:06 +02001383 ex_let_const(eap, FALSE);
1384}
1385
1386/*
1387 * ":const" list all variable values
1388 * ":const var1 var2" list variable values
1389 * ":const var = expr" assignment command.
1390 * ":const [var1, var2] = expr" unpack list.
1391 */
1392 void
1393ex_const(exarg_T *eap)
1394{
1395 ex_let_const(eap, TRUE);
1396}
1397
1398 static void
1399ex_let_const(exarg_T *eap, int is_const)
1400{
Bram Moolenaar071d4272004-06-13 20:20:40 +00001401 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001402 char_u *expr = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00001403 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001404 int i;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001405 int var_count = 0;
1406 int semicolon = 0;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001407 char_u op[2];
Bram Moolenaardb552d602006-03-23 22:59:57 +00001408 char_u *argend;
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001409 int first = TRUE;
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02001410 int concat;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001411
Bram Moolenaardb552d602006-03-23 22:59:57 +00001412 argend = skip_var_list(arg, &var_count, &semicolon);
1413 if (argend == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001414 return;
Bram Moolenaarff697e62019-02-12 22:28:33 +01001415 if (argend > arg && argend[-1] == '.') // for var.='str'
Bram Moolenaar76b92b22006-03-24 22:46:53 +00001416 --argend;
Bram Moolenaara3920382014-03-30 16:49:09 +02001417 expr = skipwhite(argend);
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02001418 concat = expr[0] == '.'
1419 && ((expr[1] == '=' && current_sctx.sc_version < 2)
1420 || (expr[1] == '.' && expr[2] == '='));
1421 if (*expr != '=' && !((vim_strchr((char_u *)"+-*/%", *expr) != NULL
1422 && expr[1] == '=') || concat))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001423 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001424 /*
1425 * ":let" without "=": list variables
1426 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001427 if (*arg == '[')
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001428 emsg(_(e_invarg));
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02001429 else if (expr[0] == '.')
1430 emsg(_("E985: .= is not supported with script version 2"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001431 else if (!ends_excmd(*arg))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001432 /* ":let var1 var2" */
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001433 arg = list_arg_vars(eap, arg, &first);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001434 else if (!eap->skip)
Bram Moolenaara7043832005-01-21 11:56:39 +00001435 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001436 /* ":let" */
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001437 list_glob_vars(&first);
1438 list_buf_vars(&first);
1439 list_win_vars(&first);
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001440 list_tab_vars(&first);
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001441 list_script_vars(&first);
1442 list_func_vars(&first);
1443 list_vim_vars(&first);
Bram Moolenaara7043832005-01-21 11:56:39 +00001444 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001445 eap->nextcmd = check_nextcmd(arg);
1446 }
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001447 else if (expr[0] == '=' && expr[1] == '<' && expr[2] == '<')
1448 {
1449 list_T *l;
1450
1451 // HERE document
1452 l = heredoc_get(eap, expr + 3);
1453 if (l != NULL)
1454 {
1455 rettv_list_set(&rettv, l);
1456 op[0] = '=';
1457 op[1] = NUL;
1458 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
Bram Moolenaar9937a052019-06-15 15:45:06 +02001459 is_const, op);
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001460 clear_tv(&rettv);
1461 }
1462 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001463 else
1464 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001465 op[0] = '=';
1466 op[1] = NUL;
Bram Moolenaara3920382014-03-30 16:49:09 +02001467 if (*expr != '=')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001468 {
Bram Moolenaarff697e62019-02-12 22:28:33 +01001469 if (vim_strchr((char_u *)"+-*/%.", *expr) != NULL)
Bram Moolenaar0f248b02019-04-04 15:36:05 +02001470 {
Bram Moolenaarff697e62019-02-12 22:28:33 +01001471 op[0] = *expr; // +=, -=, *=, /=, %= or .=
Bram Moolenaar0f248b02019-04-04 15:36:05 +02001472 if (expr[0] == '.' && expr[1] == '.') // ..=
1473 ++expr;
1474 }
Bram Moolenaara3920382014-03-30 16:49:09 +02001475 expr = skipwhite(expr + 2);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001476 }
Bram Moolenaara3920382014-03-30 16:49:09 +02001477 else
1478 expr = skipwhite(expr + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001479
Bram Moolenaar071d4272004-06-13 20:20:40 +00001480 if (eap->skip)
1481 ++emsg_skip;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001482 i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001483 if (eap->skip)
1484 {
1485 if (i != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001486 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001487 --emsg_skip;
1488 }
1489 else if (i != FAIL)
1490 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001491 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
Bram Moolenaar9937a052019-06-15 15:45:06 +02001492 is_const, op);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001493 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001494 }
1495 }
1496}
1497
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001498/*
1499 * Assign the typevalue "tv" to the variable or variables at "arg_start".
1500 * Handles both "var" with any type and "[var, var; var]" with a list type.
Bram Moolenaar61343f02019-07-20 21:11:13 +02001501 * When "op" is not NULL it points to a string with characters that
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001502 * must appear after the variable(s). Use "+", "-" or "." for add, subtract
1503 * or concatenate.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001504 * Returns OK or FAIL;
1505 */
1506 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001507ex_let_vars(
1508 char_u *arg_start,
1509 typval_T *tv,
Bram Moolenaar9937a052019-06-15 15:45:06 +02001510 int copy, // copy values from "tv", don't move
1511 int semicolon, // from skip_var_list()
1512 int var_count, // from skip_var_list()
1513 int is_const, // lock variables for const
Bram Moolenaar61343f02019-07-20 21:11:13 +02001514 char_u *op)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001515{
1516 char_u *arg = arg_start;
Bram Moolenaar33570922005-01-25 22:26:29 +00001517 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001518 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00001519 listitem_T *item;
1520 typval_T ltv;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001521
1522 if (*arg != '[')
1523 {
1524 /*
1525 * ":let var = expr" or ":for var in list"
1526 */
Bram Moolenaar61343f02019-07-20 21:11:13 +02001527 if (ex_let_one(arg, tv, copy, is_const, op, op) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001528 return FAIL;
1529 return OK;
1530 }
1531
1532 /*
1533 * ":let [v1, v2] = list" or ":for [v1, v2] in listlist"
1534 */
Bram Moolenaar758711c2005-02-02 23:11:38 +00001535 if (tv->v_type != VAR_LIST || (l = tv->vval.v_list) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001536 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001537 emsg(_(e_listreq));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001538 return FAIL;
1539 }
1540
1541 i = list_len(l);
1542 if (semicolon == 0 && var_count < i)
1543 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001544 emsg(_("E687: Less targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001545 return FAIL;
1546 }
1547 if (var_count - semicolon > i)
1548 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001549 emsg(_("E688: More targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001550 return FAIL;
1551 }
1552
1553 item = l->lv_first;
1554 while (*arg != ']')
1555 {
1556 arg = skipwhite(arg + 1);
Bram Moolenaar9937a052019-06-15 15:45:06 +02001557 arg = ex_let_one(arg, &item->li_tv, TRUE, is_const,
Bram Moolenaar61343f02019-07-20 21:11:13 +02001558 (char_u *)",;]", op);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001559 item = item->li_next;
1560 if (arg == NULL)
1561 return FAIL;
1562
1563 arg = skipwhite(arg);
1564 if (*arg == ';')
1565 {
1566 /* Put the rest of the list (may be empty) in the var after ';'.
1567 * Create a new list for this. */
1568 l = list_alloc();
1569 if (l == NULL)
1570 return FAIL;
1571 while (item != NULL)
1572 {
1573 list_append_tv(l, &item->li_tv);
1574 item = item->li_next;
1575 }
1576
1577 ltv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001578 ltv.v_lock = 0;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001579 ltv.vval.v_list = l;
1580 l->lv_refcount = 1;
1581
Bram Moolenaar9937a052019-06-15 15:45:06 +02001582 arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE, is_const,
Bram Moolenaar61343f02019-07-20 21:11:13 +02001583 (char_u *)"]", op);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001584 clear_tv(&ltv);
1585 if (arg == NULL)
1586 return FAIL;
1587 break;
1588 }
1589 else if (*arg != ',' && *arg != ']')
1590 {
Bram Moolenaar95f09602016-11-10 20:01:45 +01001591 internal_error("ex_let_vars()");
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001592 return FAIL;
1593 }
1594 }
1595
1596 return OK;
1597}
1598
1599/*
1600 * Skip over assignable variable "var" or list of variables "[var, var]".
1601 * Used for ":let varvar = expr" and ":for varvar in expr".
1602 * For "[var, var]" increment "*var_count" for each variable.
1603 * for "[var, var; var]" set "semicolon".
1604 * Return NULL for an error.
1605 */
1606 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001607skip_var_list(
1608 char_u *arg,
1609 int *var_count,
1610 int *semicolon)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001611{
1612 char_u *p, *s;
1613
1614 if (*arg == '[')
1615 {
1616 /* "[var, var]": find the matching ']'. */
1617 p = arg;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001618 for (;;)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001619 {
1620 p = skipwhite(p + 1); /* skip whites after '[', ';' or ',' */
1621 s = skip_var_one(p);
1622 if (s == p)
1623 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001624 semsg(_(e_invarg2), p);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001625 return NULL;
1626 }
1627 ++*var_count;
1628
1629 p = skipwhite(s);
1630 if (*p == ']')
1631 break;
1632 else if (*p == ';')
1633 {
1634 if (*semicolon == 1)
1635 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001636 emsg(_("Double ; in list of variables"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001637 return NULL;
1638 }
1639 *semicolon = 1;
1640 }
1641 else if (*p != ',')
1642 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001643 semsg(_(e_invarg2), p);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001644 return NULL;
1645 }
1646 }
1647 return p + 1;
1648 }
1649 else
1650 return skip_var_one(arg);
1651}
1652
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001653/*
Bram Moolenaarbae0c162007-05-10 19:30:25 +00001654 * Skip one (assignable) variable name, including @r, $VAR, &option, d.key,
Bram Moolenaar92124a32005-06-17 22:03:40 +00001655 * l[idx].
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001656 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001657 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001658skip_var_one(char_u *arg)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001659{
Bram Moolenaar92124a32005-06-17 22:03:40 +00001660 if (*arg == '@' && arg[1] != NUL)
1661 return arg + 2;
1662 return find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg,
1663 NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001664}
1665
Bram Moolenaara7043832005-01-21 11:56:39 +00001666/*
Bram Moolenaar33570922005-01-25 22:26:29 +00001667 * List variables for hashtab "ht" with prefix "prefix".
1668 * If "empty" is TRUE also list NULL strings as empty strings.
Bram Moolenaara7043832005-01-21 11:56:39 +00001669 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02001670 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001671list_hashtable_vars(
1672 hashtab_T *ht,
Bram Moolenaar32526b32019-01-19 17:43:09 +01001673 char *prefix,
Bram Moolenaar7454a062016-01-30 15:14:10 +01001674 int empty,
1675 int *first)
Bram Moolenaara7043832005-01-21 11:56:39 +00001676{
Bram Moolenaar33570922005-01-25 22:26:29 +00001677 hashitem_T *hi;
1678 dictitem_T *di;
Bram Moolenaara7043832005-01-21 11:56:39 +00001679 int todo;
Bram Moolenaarf86db782018-10-25 13:31:37 +02001680 char_u buf[IOSIZE];
Bram Moolenaara7043832005-01-21 11:56:39 +00001681
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001682 todo = (int)ht->ht_used;
Bram Moolenaara7043832005-01-21 11:56:39 +00001683 for (hi = ht->ht_array; todo > 0 && !got_int; ++hi)
1684 {
1685 if (!HASHITEM_EMPTY(hi))
1686 {
1687 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00001688 di = HI2DI(hi);
Bram Moolenaarf86db782018-10-25 13:31:37 +02001689
1690 // apply :filter /pat/ to variable name
Bram Moolenaar32526b32019-01-19 17:43:09 +01001691 vim_strncpy((char_u *)buf, (char_u *)prefix, IOSIZE - 1);
1692 vim_strcat((char_u *)buf, di->di_key, IOSIZE);
Bram Moolenaarf86db782018-10-25 13:31:37 +02001693 if (message_filtered(buf))
1694 continue;
1695
Bram Moolenaar33570922005-01-25 22:26:29 +00001696 if (empty || di->di_tv.v_type != VAR_STRING
1697 || di->di_tv.vval.v_string != NULL)
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001698 list_one_var(di, prefix, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00001699 }
1700 }
1701}
1702
1703/*
1704 * List global variables.
1705 */
1706 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001707list_glob_vars(int *first)
Bram Moolenaara7043832005-01-21 11:56:39 +00001708{
Bram Moolenaar32526b32019-01-19 17:43:09 +01001709 list_hashtable_vars(&globvarht, "", TRUE, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00001710}
1711
1712/*
1713 * List buffer variables.
1714 */
1715 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001716list_buf_vars(int *first)
Bram Moolenaara7043832005-01-21 11:56:39 +00001717{
Bram Moolenaar32526b32019-01-19 17:43:09 +01001718 list_hashtable_vars(&curbuf->b_vars->dv_hashtab, "b:", TRUE, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00001719}
1720
1721/*
1722 * List window variables.
1723 */
1724 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001725list_win_vars(int *first)
Bram Moolenaara7043832005-01-21 11:56:39 +00001726{
Bram Moolenaar32526b32019-01-19 17:43:09 +01001727 list_hashtable_vars(&curwin->w_vars->dv_hashtab, "w:", TRUE, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00001728}
1729
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001730/*
1731 * List tab page variables.
1732 */
1733 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001734list_tab_vars(int *first)
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001735{
Bram Moolenaar32526b32019-01-19 17:43:09 +01001736 list_hashtable_vars(&curtab->tp_vars->dv_hashtab, "t:", TRUE, first);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001737}
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001738
Bram Moolenaara7043832005-01-21 11:56:39 +00001739/*
1740 * List Vim variables.
1741 */
1742 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001743list_vim_vars(int *first)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001744{
Bram Moolenaar32526b32019-01-19 17:43:09 +01001745 list_hashtable_vars(&vimvarht, "v:", FALSE, first);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001746}
1747
1748/*
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00001749 * List script-local variables, if there is a script.
1750 */
1751 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001752list_script_vars(int *first)
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00001753{
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02001754 if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= ga_scripts.ga_len)
1755 list_hashtable_vars(&SCRIPT_VARS(current_sctx.sc_sid),
Bram Moolenaar32526b32019-01-19 17:43:09 +01001756 "s:", FALSE, first);
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00001757}
1758
1759/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001760 * List variables in "arg".
1761 */
1762 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001763list_arg_vars(exarg_T *eap, char_u *arg, int *first)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001764{
1765 int error = FALSE;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001766 int len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001767 char_u *name;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001768 char_u *name_start;
1769 char_u *arg_subsc;
1770 char_u *tofree;
1771 typval_T tv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001772
1773 while (!ends_excmd(*arg) && !got_int)
1774 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001775 if (error || eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001776 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001777 arg = find_name_end(arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
Bram Moolenaar1c465442017-03-12 20:10:05 +01001778 if (!VIM_ISWHITE(*arg) && !ends_excmd(*arg))
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001779 {
1780 emsg_severe = TRUE;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001781 emsg(_(e_trailing));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001782 break;
1783 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001784 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001785 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001786 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001787 /* get_name_len() takes care of expanding curly braces */
1788 name_start = name = arg;
1789 len = get_name_len(&arg, &tofree, TRUE, TRUE);
1790 if (len <= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001791 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001792 /* This is mainly to keep test 49 working: when expanding
1793 * curly braces fails overrule the exception error message. */
1794 if (len < 0 && !aborting())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001795 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001796 emsg_severe = TRUE;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001797 semsg(_(e_invarg2), arg);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001798 break;
1799 }
1800 error = TRUE;
1801 }
1802 else
1803 {
1804 if (tofree != NULL)
1805 name = tofree;
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02001806 if (get_var_tv(name, len, &tv, NULL, TRUE, FALSE) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001807 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001808 else
1809 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001810 /* handle d.key, l[idx], f(expr) */
1811 arg_subsc = arg;
1812 if (handle_subscript(&arg, &tv, TRUE, TRUE) == FAIL)
Bram Moolenaara7043832005-01-21 11:56:39 +00001813 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001814 else
Bram Moolenaara7043832005-01-21 11:56:39 +00001815 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001816 if (arg == arg_subsc && len == 2 && name[1] == ':')
Bram Moolenaara7043832005-01-21 11:56:39 +00001817 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001818 switch (*name)
Bram Moolenaara7043832005-01-21 11:56:39 +00001819 {
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001820 case 'g': list_glob_vars(first); break;
1821 case 'b': list_buf_vars(first); break;
1822 case 'w': list_win_vars(first); break;
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001823 case 't': list_tab_vars(first); break;
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001824 case 'v': list_vim_vars(first); break;
1825 case 's': list_script_vars(first); break;
1826 case 'l': list_func_vars(first); break;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001827 default:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001828 semsg(_("E738: Can't list variables for %s"), name);
Bram Moolenaara7043832005-01-21 11:56:39 +00001829 }
Bram Moolenaara7043832005-01-21 11:56:39 +00001830 }
1831 else
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001832 {
1833 char_u numbuf[NUMBUFLEN];
1834 char_u *tf;
1835 int c;
1836 char_u *s;
1837
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001838 s = echo_string(&tv, &tf, numbuf, 0);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001839 c = *arg;
1840 *arg = NUL;
Bram Moolenaar32526b32019-01-19 17:43:09 +01001841 list_one_var_a("",
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001842 arg == arg_subsc ? name : name_start,
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001843 tv.v_type,
1844 s == NULL ? (char_u *)"" : s,
1845 first);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001846 *arg = c;
1847 vim_free(tf);
1848 }
1849 clear_tv(&tv);
Bram Moolenaara7043832005-01-21 11:56:39 +00001850 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001851 }
1852 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001853
1854 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001855 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001856
1857 arg = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001858 }
1859
1860 return arg;
1861}
1862
1863/*
1864 * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value.
1865 * Returns a pointer to the char just after the var name.
1866 * Returns NULL if there is an error.
1867 */
1868 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001869ex_let_one(
Bram Moolenaar9937a052019-06-15 15:45:06 +02001870 char_u *arg, // points to variable name
1871 typval_T *tv, // value to assign to variable
1872 int copy, // copy value from "tv"
1873 int is_const, // lock variable for const
1874 char_u *endchars, // valid chars after variable name or NULL
1875 char_u *op) // "+", "-", "." or NULL
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001876{
1877 int c1;
1878 char_u *name;
1879 char_u *p;
1880 char_u *arg_end = NULL;
1881 int len;
1882 int opt_flags;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001883 char_u *tofree = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001884
1885 /*
1886 * ":let $VAR = expr": Set environment variable.
1887 */
1888 if (*arg == '$')
1889 {
Bram Moolenaar9937a052019-06-15 15:45:06 +02001890 if (is_const)
1891 {
1892 emsg(_("E996: Cannot lock an environment variable"));
1893 return NULL;
1894 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001895 /* Find the end of the name. */
1896 ++arg;
1897 name = arg;
1898 len = get_env_len(&arg);
1899 if (len == 0)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001900 semsg(_(e_invarg2), name - 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001901 else
1902 {
Bram Moolenaarff697e62019-02-12 22:28:33 +01001903 if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001904 semsg(_(e_letwrong), op);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001905 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001906 && vim_strchr(endchars, *skipwhite(arg)) == NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001907 emsg(_(e_letunexp));
Bram Moolenaard4ddfaf2010-12-02 14:48:14 +01001908 else if (!check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001909 {
1910 c1 = name[len];
1911 name[len] = NUL;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01001912 p = tv_get_string_chk(tv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001913 if (p != NULL && op != NULL && *op == '.')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001914 {
1915 int mustfree = FALSE;
1916 char_u *s = vim_getenv(name, &mustfree);
1917
1918 if (s != NULL)
1919 {
1920 p = tofree = concat_str(s, p);
1921 if (mustfree)
1922 vim_free(s);
1923 }
1924 }
1925 if (p != NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001926 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001927 vim_setenv(name, p);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001928 if (STRICMP(name, "HOME") == 0)
1929 init_homedir();
1930 else if (didset_vim && STRICMP(name, "VIM") == 0)
1931 didset_vim = FALSE;
1932 else if (didset_vimruntime
1933 && STRICMP(name, "VIMRUNTIME") == 0)
1934 didset_vimruntime = FALSE;
1935 arg_end = arg;
1936 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001937 name[len] = c1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001938 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001939 }
1940 }
1941 }
1942
1943 /*
1944 * ":let &option = expr": Set option value.
1945 * ":let &l:option = expr": Set local option value.
1946 * ":let &g:option = expr": Set global option value.
1947 */
1948 else if (*arg == '&')
1949 {
Bram Moolenaar9937a052019-06-15 15:45:06 +02001950 if (is_const)
1951 {
1952 emsg(_("E996: Cannot lock an option"));
1953 return NULL;
1954 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001955 /* Find the end of the name. */
1956 p = find_option_end(&arg, &opt_flags);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001957 if (p == NULL || (endchars != NULL
1958 && vim_strchr(endchars, *skipwhite(p)) == NULL))
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001959 emsg(_(e_letunexp));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001960 else
1961 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001962 long n;
1963 int opt_type;
1964 long numval;
1965 char_u *stringval = NULL;
1966 char_u *s;
1967
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001968 c1 = *p;
1969 *p = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001970
Bram Moolenaard155d7a2018-12-21 16:04:21 +01001971 n = (long)tv_get_number(tv);
1972 s = tv_get_string_chk(tv); /* != NULL if number or string */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001973 if (s != NULL && op != NULL && *op != '=')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001974 {
1975 opt_type = get_option_value(arg, &numval,
1976 &stringval, opt_flags);
1977 if ((opt_type == 1 && *op == '.')
1978 || (opt_type == 0 && *op != '.'))
Bram Moolenaar2a6a6c32017-10-02 19:29:48 +02001979 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001980 semsg(_(e_letwrong), op);
Bram Moolenaarff697e62019-02-12 22:28:33 +01001981 s = NULL; // don't set the value
Bram Moolenaar2a6a6c32017-10-02 19:29:48 +02001982 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001983 else
1984 {
Bram Moolenaarff697e62019-02-12 22:28:33 +01001985 if (opt_type == 1) // number
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001986 {
Bram Moolenaarff697e62019-02-12 22:28:33 +01001987 switch (*op)
1988 {
1989 case '+': n = numval + n; break;
1990 case '-': n = numval - n; break;
1991 case '*': n = numval * n; break;
Bram Moolenaare21c1582019-03-02 11:57:09 +01001992 case '/': n = (long)num_divide(numval, n); break;
1993 case '%': n = (long)num_modulus(numval, n); break;
Bram Moolenaarff697e62019-02-12 22:28:33 +01001994 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001995 }
Bram Moolenaarff697e62019-02-12 22:28:33 +01001996 else if (opt_type == 0 && stringval != NULL) // string
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001997 {
1998 s = concat_str(stringval, s);
1999 vim_free(stringval);
2000 stringval = s;
2001 }
2002 }
2003 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002004 if (s != NULL)
2005 {
2006 set_option_value(arg, n, s, opt_flags);
2007 arg_end = p;
2008 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002009 *p = c1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002010 vim_free(stringval);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002011 }
2012 }
2013
2014 /*
2015 * ":let @r = expr": Set register contents.
2016 */
2017 else if (*arg == '@')
2018 {
Bram Moolenaar9937a052019-06-15 15:45:06 +02002019 if (is_const)
2020 {
2021 emsg(_("E996: Cannot lock a register"));
2022 return NULL;
2023 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002024 ++arg;
Bram Moolenaarff697e62019-02-12 22:28:33 +01002025 if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002026 semsg(_(e_letwrong), op);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002027 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002028 && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002029 emsg(_(e_letunexp));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002030 else
2031 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00002032 char_u *ptofree = NULL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002033 char_u *s;
2034
Bram Moolenaard155d7a2018-12-21 16:04:21 +01002035 p = tv_get_string_chk(tv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002036 if (p != NULL && op != NULL && *op == '.')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002037 {
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +02002038 s = get_reg_contents(*arg == '@' ? '"' : *arg, GREG_EXPR_SRC);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002039 if (s != NULL)
2040 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00002041 p = ptofree = concat_str(s, p);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002042 vim_free(s);
2043 }
2044 }
2045 if (p != NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002046 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002047 write_reg_contents(*arg == '@' ? '"' : *arg, p, -1, FALSE);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002048 arg_end = arg + 1;
2049 }
Bram Moolenaar89d40322006-08-29 15:30:07 +00002050 vim_free(ptofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002051 }
2052 }
2053
2054 /*
2055 * ":let var = expr": Set internal variable.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002056 * ":let {expr} = expr": Idem, name made with curly braces
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002057 */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002058 else if (eval_isnamec1(*arg) || *arg == '{')
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002059 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002060 lval_T lv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002061
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002062 p = get_lval(arg, tv, &lv, FALSE, FALSE, 0, FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002063 if (p != NULL && lv.ll_name != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002064 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002065 if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002066 emsg(_(e_letunexp));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002067 else
2068 {
Bram Moolenaar9937a052019-06-15 15:45:06 +02002069 set_var_lval(&lv, p, tv, copy, is_const, op);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002070 arg_end = p;
2071 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002072 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002073 clear_lval(&lv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002074 }
2075
2076 else
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002077 semsg(_(e_invarg2), arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002078
2079 return arg_end;
2080}
2081
2082/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002083 * Get an lval: variable, Dict item or List item that can be assigned a value
2084 * to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]",
2085 * "name.key", "name.key[expr]" etc.
2086 * Indexing only works if "name" is an existing List or Dictionary.
2087 * "name" points to the start of the name.
2088 * If "rettv" is not NULL it points to the value to be assigned.
2089 * "unlet" is TRUE for ":unlet": slightly different behavior when something is
2090 * wrong; must end in space or cmd separator.
2091 *
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002092 * flags:
2093 * GLV_QUIET: do not give error messages
Bram Moolenaar3a257732017-02-21 20:47:13 +01002094 * GLV_READ_ONLY: will not change the variable
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002095 * GLV_NO_AUTOLOAD: do not use script autoloading
2096 *
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002097 * Returns a pointer to just after the name, including indexes.
Bram Moolenaara7043832005-01-21 11:56:39 +00002098 * When an evaluation error occurs "lp->ll_name" is NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002099 * Returns NULL for a parsing error. Still need to free items in "lp"!
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002100 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02002101 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01002102get_lval(
2103 char_u *name,
2104 typval_T *rettv,
2105 lval_T *lp,
2106 int unlet,
2107 int skip,
2108 int flags, /* GLV_ values */
2109 int fne_flags) /* flags for find_name_end() */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002110{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002111 char_u *p;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002112 char_u *expr_start, *expr_end;
2113 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00002114 dictitem_T *v;
2115 typval_T var1;
2116 typval_T var2;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002117 int empty1 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00002118 listitem_T *ni;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002119 char_u *key = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002120 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +00002121 hashtab_T *ht;
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002122 int quiet = flags & GLV_QUIET;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002123
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002124 /* Clear everything in "lp". */
Bram Moolenaar33570922005-01-25 22:26:29 +00002125 vim_memset(lp, 0, sizeof(lval_T));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002126
2127 if (skip)
2128 {
2129 /* When skipping just find the end of the name. */
2130 lp->ll_name = name;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002131 return find_name_end(name, NULL, NULL, FNE_INCL_BR | fne_flags);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002132 }
2133
2134 /* Find the end of the name. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002135 p = find_name_end(name, &expr_start, &expr_end, fne_flags);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002136 if (expr_start != NULL)
2137 {
2138 /* Don't expand the name when we already know there is an error. */
Bram Moolenaar1c465442017-03-12 20:10:05 +01002139 if (unlet && !VIM_ISWHITE(*p) && !ends_excmd(*p)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002140 && *p != '[' && *p != '.')
2141 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002142 emsg(_(e_trailing));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002143 return NULL;
2144 }
2145
2146 lp->ll_exp_name = make_expanded_name(name, expr_start, expr_end, p);
2147 if (lp->ll_exp_name == NULL)
2148 {
2149 /* Report an invalid expression in braces, unless the
2150 * expression evaluation has been cancelled due to an
2151 * aborting error, an interrupt, or an exception. */
2152 if (!aborting() && !quiet)
2153 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002154 emsg_severe = TRUE;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002155 semsg(_(e_invarg2), name);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002156 return NULL;
2157 }
2158 }
2159 lp->ll_name = lp->ll_exp_name;
2160 }
2161 else
2162 lp->ll_name = name;
2163
2164 /* Without [idx] or .key we are done. */
2165 if ((*p != '[' && *p != '.') || lp->ll_name == NULL)
2166 return p;
2167
2168 cc = *p;
2169 *p = NUL;
Bram Moolenaar6e65d592017-12-07 22:11:27 +01002170 /* Only pass &ht when we would write to the variable, it prevents autoload
2171 * as well. */
2172 v = find_var(lp->ll_name, (flags & GLV_READ_ONLY) ? NULL : &ht,
2173 flags & GLV_NO_AUTOLOAD);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002174 if (v == NULL && !quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002175 semsg(_(e_undefvar), lp->ll_name);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002176 *p = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002177 if (v == NULL)
2178 return NULL;
2179
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002180 /*
2181 * Loop until no more [idx] or .key is following.
2182 */
Bram Moolenaar33570922005-01-25 22:26:29 +00002183 lp->ll_tv = &v->di_tv;
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002184 var1.v_type = VAR_UNKNOWN;
2185 var2.v_type = VAR_UNKNOWN;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002186 while (*p == '[' || (*p == '.' && lp->ll_tv->v_type == VAR_DICT))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002187 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002188 if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL)
2189 && !(lp->ll_tv->v_type == VAR_DICT
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002190 && lp->ll_tv->vval.v_dict != NULL)
2191 && !(lp->ll_tv->v_type == VAR_BLOB
2192 && lp->ll_tv->vval.v_blob != NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002193 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002194 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002195 emsg(_("E689: Can only index a List, Dictionary or Blob"));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002196 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002197 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002198 if (lp->ll_range)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002199 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002200 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002201 emsg(_("E708: [:] must come last"));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002202 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002203 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002204
Bram Moolenaar8c711452005-01-14 21:53:12 +00002205 len = -1;
2206 if (*p == '.')
2207 {
2208 key = p + 1;
2209 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
2210 ;
2211 if (len == 0)
2212 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002213 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002214 emsg(_(e_emptykey));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002215 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002216 }
2217 p = key + len;
2218 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002219 else
2220 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002221 /* Get the index [expr] or the first index [expr: ]. */
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002222 p = skipwhite(p + 1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002223 if (*p == ':')
2224 empty1 = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002225 else
2226 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002227 empty1 = FALSE;
2228 if (eval1(&p, &var1, TRUE) == FAIL) /* recursive! */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002229 return NULL;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01002230 if (tv_get_string_chk(&var1) == NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002231 {
2232 /* not a number or string */
2233 clear_tv(&var1);
2234 return NULL;
2235 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002236 }
2237
2238 /* Optionally get the second index [ :expr]. */
2239 if (*p == ':')
2240 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002241 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002242 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002243 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002244 emsg(_(e_dictrange));
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002245 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002246 return NULL;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002247 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002248 if (rettv != NULL
2249 && !(rettv->v_type == VAR_LIST
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002250 && rettv->vval.v_list != NULL)
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002251 && !(rettv->v_type == VAR_BLOB
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002252 && rettv->vval.v_blob != NULL))
Bram Moolenaar8c711452005-01-14 21:53:12 +00002253 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002254 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002255 emsg(_("E709: [:] requires a List or Blob value"));
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002256 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002257 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002258 }
2259 p = skipwhite(p + 1);
2260 if (*p == ']')
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002261 lp->ll_empty2 = TRUE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002262 else
2263 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002264 lp->ll_empty2 = FALSE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002265 if (eval1(&p, &var2, TRUE) == FAIL) /* recursive! */
2266 {
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002267 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002268 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002269 }
Bram Moolenaard155d7a2018-12-21 16:04:21 +01002270 if (tv_get_string_chk(&var2) == NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002271 {
2272 /* not a number or string */
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002273 clear_tv(&var1);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002274 clear_tv(&var2);
2275 return NULL;
2276 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002277 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002278 lp->ll_range = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002279 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002280 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002281 lp->ll_range = FALSE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002282
Bram Moolenaar8c711452005-01-14 21:53:12 +00002283 if (*p != ']')
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002284 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002285 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002286 emsg(_(e_missbrac));
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002287 clear_tv(&var1);
2288 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002289 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002290 }
2291
2292 /* Skip to past ']'. */
2293 ++p;
2294 }
2295
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002296 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002297 {
2298 if (len == -1)
2299 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002300 /* "[key]": get key from "var1" */
Bram Moolenaard155d7a2018-12-21 16:04:21 +01002301 key = tv_get_string_chk(&var1); /* is number or string */
Bram Moolenaar0921ecf2016-04-03 22:44:36 +02002302 if (key == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002303 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002304 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002305 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002306 }
2307 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002308 lp->ll_list = NULL;
2309 lp->ll_dict = lp->ll_tv->vval.v_dict;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002310 lp->ll_di = dict_find(lp->ll_dict, key, len);
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002311
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002312 /* When assigning to a scope dictionary check that a function and
2313 * variable name is valid (only variable name unless it is l: or
2314 * g: dictionary). Disallow overwriting a builtin function. */
2315 if (rettv != NULL && lp->ll_dict->dv_scope != 0)
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002316 {
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002317 int prevval;
2318 int wrong;
2319
2320 if (len != -1)
2321 {
2322 prevval = key[len];
2323 key[len] = NUL;
2324 }
Bram Moolenaar4380d1e2013-06-09 20:51:00 +02002325 else
2326 prevval = 0; /* avoid compiler warning */
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002327 wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE
2328 && rettv->v_type == VAR_FUNC
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002329 && var_check_func_name(key, lp->ll_di == NULL))
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002330 || !valid_varname(key);
2331 if (len != -1)
2332 key[len] = prevval;
2333 if (wrong)
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002334 return NULL;
2335 }
2336
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002337 if (lp->ll_di == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002338 {
Bram Moolenaar31b81602019-02-10 22:14:27 +01002339 // Can't add "v:" or "a:" variable.
2340 if (lp->ll_dict == &vimvardict
2341 || &lp->ll_dict->dv_hashtab == get_funccal_args_ht())
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002342 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002343 semsg(_(e_illvar), name);
Bram Moolenaarab89d7a2019-03-17 14:43:31 +01002344 clear_tv(&var1);
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002345 return NULL;
2346 }
2347
Bram Moolenaar31b81602019-02-10 22:14:27 +01002348 // Key does not exist in dict: may need to add it.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002349 if (*p == '[' || *p == '.' || unlet)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002350 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002351 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002352 semsg(_(e_dictkey), key);
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002353 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002354 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002355 }
2356 if (len == -1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002357 lp->ll_newkey = vim_strsave(key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002358 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002359 lp->ll_newkey = vim_strnsave(key, len);
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002360 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002361 if (lp->ll_newkey == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002362 p = NULL;
2363 break;
2364 }
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002365 /* existing variable, need to check if it can be changed */
Bram Moolenaar3a257732017-02-21 20:47:13 +01002366 else if ((flags & GLV_READ_ONLY) == 0
2367 && var_check_ro(lp->ll_di->di_flags, name, FALSE))
Bram Moolenaar49439c42017-02-20 23:07:05 +01002368 {
2369 clear_tv(&var1);
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002370 return NULL;
Bram Moolenaar49439c42017-02-20 23:07:05 +01002371 }
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002372
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002373 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002374 lp->ll_tv = &lp->ll_di->di_tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002375 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002376 else if (lp->ll_tv->v_type == VAR_BLOB)
2377 {
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002378 long bloblen = blob_len(lp->ll_tv->vval.v_blob);
2379
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002380 /*
2381 * Get the number and item for the only or first index of the List.
2382 */
2383 if (empty1)
2384 lp->ll_n1 = 0;
2385 else
2386 // is number or string
2387 lp->ll_n1 = (long)tv_get_number(&var1);
2388 clear_tv(&var1);
2389
2390 if (lp->ll_n1 < 0
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002391 || lp->ll_n1 > bloblen
2392 || (lp->ll_range && lp->ll_n1 == bloblen))
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002393 {
2394 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002395 semsg(_(e_blobidx), lp->ll_n1);
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002396 clear_tv(&var2);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002397 return NULL;
2398 }
2399 if (lp->ll_range && !lp->ll_empty2)
2400 {
2401 lp->ll_n2 = (long)tv_get_number(&var2);
2402 clear_tv(&var2);
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002403 if (lp->ll_n2 < 0
2404 || lp->ll_n2 >= bloblen
2405 || lp->ll_n2 < lp->ll_n1)
2406 {
2407 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002408 semsg(_(e_blobidx), lp->ll_n2);
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002409 return NULL;
2410 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002411 }
2412 lp->ll_blob = lp->ll_tv->vval.v_blob;
2413 lp->ll_tv = NULL;
Bram Moolenaar61be3762019-03-19 23:04:17 +01002414 break;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002415 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002416 else
2417 {
2418 /*
2419 * Get the number and item for the only or first index of the List.
2420 */
2421 if (empty1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002422 lp->ll_n1 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002423 else
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002424 /* is number or string */
Bram Moolenaard155d7a2018-12-21 16:04:21 +01002425 lp->ll_n1 = (long)tv_get_number(&var1);
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002426 clear_tv(&var1);
2427
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002428 lp->ll_dict = NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002429 lp->ll_list = lp->ll_tv->vval.v_list;
2430 lp->ll_li = list_find(lp->ll_list, lp->ll_n1);
2431 if (lp->ll_li == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002432 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00002433 if (lp->ll_n1 < 0)
2434 {
2435 lp->ll_n1 = 0;
2436 lp->ll_li = list_find(lp->ll_list, lp->ll_n1);
2437 }
2438 }
2439 if (lp->ll_li == NULL)
2440 {
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002441 clear_tv(&var2);
Bram Moolenaare9623882011-04-21 14:27:28 +02002442 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002443 semsg(_(e_listidx), lp->ll_n1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002444 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002445 }
2446
2447 /*
2448 * May need to find the item or absolute index for the second
2449 * index of a range.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002450 * When no index given: "lp->ll_empty2" is TRUE.
2451 * Otherwise "lp->ll_n2" is set to the second index.
Bram Moolenaar8c711452005-01-14 21:53:12 +00002452 */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002453 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002454 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01002455 lp->ll_n2 = (long)tv_get_number(&var2);
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02002456 /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002457 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002458 if (lp->ll_n2 < 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002459 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002460 ni = list_find(lp->ll_list, lp->ll_n2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002461 if (ni == NULL)
Bram Moolenaare9623882011-04-21 14:27:28 +02002462 {
2463 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002464 semsg(_(e_listidx), lp->ll_n2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002465 return NULL;
Bram Moolenaare9623882011-04-21 14:27:28 +02002466 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002467 lp->ll_n2 = list_idx_of_item(lp->ll_list, ni);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002468 }
2469
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002470 /* Check that lp->ll_n2 isn't before lp->ll_n1. */
2471 if (lp->ll_n1 < 0)
2472 lp->ll_n1 = list_idx_of_item(lp->ll_list, lp->ll_li);
2473 if (lp->ll_n2 < lp->ll_n1)
Bram Moolenaare9623882011-04-21 14:27:28 +02002474 {
2475 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002476 semsg(_(e_listidx), lp->ll_n2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002477 return NULL;
Bram Moolenaare9623882011-04-21 14:27:28 +02002478 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002479 }
2480
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002481 lp->ll_tv = &lp->ll_li->li_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002482 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002483 }
2484
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002485 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002486 return p;
2487}
2488
2489/*
Bram Moolenaar33570922005-01-25 22:26:29 +00002490 * Clear lval "lp" that was filled by get_lval().
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002491 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02002492 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002493clear_lval(lval_T *lp)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002494{
2495 vim_free(lp->ll_exp_name);
2496 vim_free(lp->ll_newkey);
2497}
2498
2499/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002500 * Set a variable that was parsed by get_lval() to "rettv".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002501 * "endp" points to just after the parsed name.
Bram Moolenaarff697e62019-02-12 22:28:33 +01002502 * "op" is NULL, "+" for "+=", "-" for "-=", "*" for "*=", "/" for "/=",
2503 * "%" for "%=", "." for ".=" or "=" for "=".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002504 */
2505 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002506set_var_lval(
2507 lval_T *lp,
2508 char_u *endp,
2509 typval_T *rettv,
2510 int copy,
Bram Moolenaar9937a052019-06-15 15:45:06 +02002511 int is_const, // Disallow to modify existing variable for :const
Bram Moolenaar7454a062016-01-30 15:14:10 +01002512 char_u *op)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002513{
2514 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00002515 listitem_T *ri;
2516 dictitem_T *di;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002517
2518 if (lp->ll_tv == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002519 {
Bram Moolenaar79518e22017-02-17 16:31:35 +01002520 cc = *endp;
2521 *endp = NUL;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002522 if (lp->ll_blob != NULL)
2523 {
2524 int error = FALSE, val;
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002525
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002526 if (op != NULL && *op != '=')
2527 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002528 semsg(_(e_letwrong), op);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002529 return;
2530 }
2531
2532 if (lp->ll_range && rettv->v_type == VAR_BLOB)
2533 {
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002534 int il, ir;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002535
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002536 if (lp->ll_empty2)
2537 lp->ll_n2 = blob_len(lp->ll_blob) - 1;
2538
2539 if (lp->ll_n2 - lp->ll_n1 + 1 != blob_len(rettv->vval.v_blob))
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002540 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002541 emsg(_("E972: Blob value does not have the right number of bytes"));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002542 return;
2543 }
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002544 if (lp->ll_empty2)
2545 lp->ll_n2 = blob_len(lp->ll_blob);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002546
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002547 ir = 0;
2548 for (il = lp->ll_n1; il <= lp->ll_n2; il++)
2549 blob_set(lp->ll_blob, il,
2550 blob_get(rettv->vval.v_blob, ir++));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002551 }
2552 else
2553 {
2554 val = (int)tv_get_number_chk(rettv, &error);
2555 if (!error)
2556 {
2557 garray_T *gap = &lp->ll_blob->bv_ga;
2558
2559 // Allow for appending a byte. Setting a byte beyond
2560 // the end is an error otherwise.
2561 if (lp->ll_n1 < gap->ga_len
2562 || (lp->ll_n1 == gap->ga_len
2563 && ga_grow(&lp->ll_blob->bv_ga, 1) == OK))
2564 {
2565 blob_set(lp->ll_blob, lp->ll_n1, val);
2566 if (lp->ll_n1 == gap->ga_len)
2567 ++gap->ga_len;
2568 }
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002569 // error for invalid range was already given in get_lval()
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002570 }
2571 }
2572 }
2573 else if (op != NULL && *op != '=')
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002574 {
Bram Moolenaar79518e22017-02-17 16:31:35 +01002575 typval_T tv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002576
Bram Moolenaar9937a052019-06-15 15:45:06 +02002577 if (is_const)
2578 {
2579 emsg(_(e_cannot_mod));
2580 *endp = cc;
2581 return;
2582 }
2583
Bram Moolenaarff697e62019-02-12 22:28:33 +01002584 // handle +=, -=, *=, /=, %= and .=
Bram Moolenaar79518e22017-02-17 16:31:35 +01002585 di = NULL;
2586 if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
2587 &tv, &di, TRUE, FALSE) == OK)
2588 {
2589 if ((di == NULL
Bram Moolenaar05c00c02019-02-11 22:00:11 +01002590 || (!var_check_ro(di->di_flags, lp->ll_name, FALSE)
2591 && !tv_check_lock(&di->di_tv, lp->ll_name, FALSE)))
Bram Moolenaar79518e22017-02-17 16:31:35 +01002592 && tv_op(&tv, rettv, op) == OK)
2593 set_var(lp->ll_name, &tv, FALSE);
2594 clear_tv(&tv);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002595 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002596 }
Bram Moolenaar79518e22017-02-17 16:31:35 +01002597 else
Bram Moolenaar9937a052019-06-15 15:45:06 +02002598 set_var_const(lp->ll_name, rettv, copy, is_const);
Bram Moolenaar79518e22017-02-17 16:31:35 +01002599 *endp = cc;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002600 }
Bram Moolenaar05c00c02019-02-11 22:00:11 +01002601 else if (var_check_lock(lp->ll_newkey == NULL
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002602 ? lp->ll_tv->v_lock
Bram Moolenaar77354e72015-04-21 16:49:05 +02002603 : lp->ll_tv->vval.v_dict->dv_lock, lp->ll_name, FALSE))
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002604 ;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002605 else if (lp->ll_range)
2606 {
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02002607 listitem_T *ll_li = lp->ll_li;
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002608 int ll_n1 = lp->ll_n1;
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02002609
Bram Moolenaar9937a052019-06-15 15:45:06 +02002610 if (is_const)
2611 {
2612 emsg(_("E996: Cannot lock a range"));
2613 return;
2614 }
2615
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02002616 /*
2617 * Check whether any of the list items is locked
2618 */
Bram Moolenaarb2a851f2014-12-07 00:18:33 +01002619 for (ri = rettv->vval.v_list->lv_first; ri != NULL && ll_li != NULL; )
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02002620 {
Bram Moolenaar05c00c02019-02-11 22:00:11 +01002621 if (var_check_lock(ll_li->li_tv.v_lock, lp->ll_name, FALSE))
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02002622 return;
2623 ri = ri->li_next;
2624 if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == ll_n1))
2625 break;
2626 ll_li = ll_li->li_next;
2627 ++ll_n1;
2628 }
2629
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002630 /*
2631 * Assign the List values to the list items.
2632 */
2633 for (ri = rettv->vval.v_list->lv_first; ri != NULL; )
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002634 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002635 if (op != NULL && *op != '=')
2636 tv_op(&lp->ll_li->li_tv, &ri->li_tv, op);
2637 else
2638 {
2639 clear_tv(&lp->ll_li->li_tv);
2640 copy_tv(&ri->li_tv, &lp->ll_li->li_tv);
2641 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002642 ri = ri->li_next;
2643 if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == lp->ll_n1))
2644 break;
2645 if (lp->ll_li->li_next == NULL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002646 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002647 /* Need to add an empty item. */
Bram Moolenaar4463f292005-09-25 22:20:24 +00002648 if (list_append_number(lp->ll_list, 0) == FAIL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002649 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002650 ri = NULL;
2651 break;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002652 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002653 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002654 lp->ll_li = lp->ll_li->li_next;
2655 ++lp->ll_n1;
2656 }
2657 if (ri != NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002658 emsg(_("E710: List value has more items than target"));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002659 else if (lp->ll_empty2
2660 ? (lp->ll_li != NULL && lp->ll_li->li_next != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002661 : lp->ll_n1 != lp->ll_n2)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002662 emsg(_("E711: List value has not enough items"));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002663 }
2664 else
2665 {
2666 /*
2667 * Assign to a List or Dictionary item.
2668 */
Bram Moolenaar9937a052019-06-15 15:45:06 +02002669 if (is_const)
2670 {
2671 emsg(_("E996: Cannot lock a list or dict"));
2672 return;
2673 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002674 if (lp->ll_newkey != NULL)
2675 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002676 if (op != NULL && *op != '=')
2677 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002678 semsg(_(e_letwrong), op);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002679 return;
2680 }
2681
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002682 /* Need to add an item to the Dictionary. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002683 di = dictitem_alloc(lp->ll_newkey);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002684 if (di == NULL)
2685 return;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002686 if (dict_add(lp->ll_tv->vval.v_dict, di) == FAIL)
2687 {
2688 vim_free(di);
2689 return;
2690 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002691 lp->ll_tv = &di->di_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002692 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002693 else if (op != NULL && *op != '=')
2694 {
2695 tv_op(lp->ll_tv, rettv, op);
2696 return;
2697 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002698 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002699 clear_tv(lp->ll_tv);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002700
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002701 /*
2702 * Assign the value to the variable or list item.
2703 */
2704 if (copy)
2705 copy_tv(rettv, lp->ll_tv);
2706 else
2707 {
2708 *lp->ll_tv = *rettv;
Bram Moolenaar758711c2005-02-02 23:11:38 +00002709 lp->ll_tv->v_lock = 0;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002710 init_tv(rettv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002711 }
2712 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002713}
2714
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002715/*
Bram Moolenaarff697e62019-02-12 22:28:33 +01002716 * Handle "tv1 += tv2", "tv1 -= tv2", "tv1 *= tv2", "tv1 /= tv2", "tv1 %= tv2"
2717 * and "tv1 .= tv2"
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002718 * Returns OK or FAIL.
2719 */
2720 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01002721tv_op(typval_T *tv1, typval_T *tv2, char_u *op)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002722{
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02002723 varnumber_T n;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002724 char_u numbuf[NUMBUFLEN];
2725 char_u *s;
2726
Bram Moolenaar520e1e42016-01-23 19:46:28 +01002727 /* Can't do anything with a Funcref, Dict, v:true on the right. */
2728 if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT
2729 && tv2->v_type != VAR_SPECIAL)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002730 {
2731 switch (tv1->v_type)
2732 {
Bram Moolenaar835dc632016-02-07 14:27:38 +01002733 case VAR_UNKNOWN:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002734 case VAR_DICT:
2735 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01002736 case VAR_PARTIAL:
Bram Moolenaar520e1e42016-01-23 19:46:28 +01002737 case VAR_SPECIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01002738 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01002739 case VAR_CHANNEL:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002740 break;
2741
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002742 case VAR_BLOB:
2743 if (*op != '+' || tv2->v_type != VAR_BLOB)
2744 break;
2745 // BLOB += BLOB
2746 if (tv1->vval.v_blob != NULL && tv2->vval.v_blob != NULL)
2747 {
2748 blob_T *b1 = tv1->vval.v_blob;
2749 blob_T *b2 = tv2->vval.v_blob;
2750 int i, len = blob_len(b2);
2751 for (i = 0; i < len; i++)
2752 ga_append(&b1->bv_ga, blob_get(b2, i));
2753 }
2754 return OK;
2755
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002756 case VAR_LIST:
2757 if (*op != '+' || tv2->v_type != VAR_LIST)
2758 break;
Bram Moolenaarff697e62019-02-12 22:28:33 +01002759 // List += List
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002760 if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL)
2761 list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL);
2762 return OK;
2763
2764 case VAR_NUMBER:
2765 case VAR_STRING:
2766 if (tv2->v_type == VAR_LIST)
2767 break;
Bram Moolenaarff697e62019-02-12 22:28:33 +01002768 if (vim_strchr((char_u *)"+-*/%", *op) != NULL)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002769 {
Bram Moolenaarff697e62019-02-12 22:28:33 +01002770 // nr += nr , nr -= nr , nr *=nr , nr /= nr , nr %= nr
Bram Moolenaard155d7a2018-12-21 16:04:21 +01002771 n = tv_get_number(tv1);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002772#ifdef FEAT_FLOAT
2773 if (tv2->v_type == VAR_FLOAT)
2774 {
2775 float_T f = n;
2776
Bram Moolenaarff697e62019-02-12 22:28:33 +01002777 if (*op == '%')
2778 break;
2779 switch (*op)
2780 {
2781 case '+': f += tv2->vval.v_float; break;
2782 case '-': f -= tv2->vval.v_float; break;
2783 case '*': f *= tv2->vval.v_float; break;
2784 case '/': f /= tv2->vval.v_float; break;
2785 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002786 clear_tv(tv1);
2787 tv1->v_type = VAR_FLOAT;
2788 tv1->vval.v_float = f;
2789 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002790 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002791#endif
2792 {
Bram Moolenaarff697e62019-02-12 22:28:33 +01002793 switch (*op)
2794 {
2795 case '+': n += tv_get_number(tv2); break;
2796 case '-': n -= tv_get_number(tv2); break;
2797 case '*': n *= tv_get_number(tv2); break;
Bram Moolenaare21c1582019-03-02 11:57:09 +01002798 case '/': n = num_divide(n, tv_get_number(tv2)); break;
2799 case '%': n = num_modulus(n, tv_get_number(tv2)); break;
Bram Moolenaarff697e62019-02-12 22:28:33 +01002800 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002801 clear_tv(tv1);
2802 tv1->v_type = VAR_NUMBER;
2803 tv1->vval.v_number = n;
2804 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002805 }
2806 else
2807 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002808 if (tv2->v_type == VAR_FLOAT)
2809 break;
2810
Bram Moolenaarff697e62019-02-12 22:28:33 +01002811 // str .= str
Bram Moolenaard155d7a2018-12-21 16:04:21 +01002812 s = tv_get_string(tv1);
2813 s = concat_str(s, tv_get_string_buf(tv2, numbuf));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002814 clear_tv(tv1);
2815 tv1->v_type = VAR_STRING;
2816 tv1->vval.v_string = s;
2817 }
2818 return OK;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002819
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002820 case VAR_FLOAT:
Bram Moolenaar5fac4672016-03-02 22:16:32 +01002821#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002822 {
2823 float_T f;
2824
Bram Moolenaarff697e62019-02-12 22:28:33 +01002825 if (*op == '%' || *op == '.'
2826 || (tv2->v_type != VAR_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002827 && tv2->v_type != VAR_NUMBER
2828 && tv2->v_type != VAR_STRING))
2829 break;
2830 if (tv2->v_type == VAR_FLOAT)
2831 f = tv2->vval.v_float;
2832 else
Bram Moolenaard155d7a2018-12-21 16:04:21 +01002833 f = tv_get_number(tv2);
Bram Moolenaarff697e62019-02-12 22:28:33 +01002834 switch (*op)
2835 {
2836 case '+': tv1->vval.v_float += f; break;
2837 case '-': tv1->vval.v_float -= f; break;
2838 case '*': tv1->vval.v_float *= f; break;
2839 case '/': tv1->vval.v_float /= f; break;
2840 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002841 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002842#endif
Bram Moolenaar5fac4672016-03-02 22:16:32 +01002843 return OK;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002844 }
2845 }
2846
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002847 semsg(_(e_letwrong), op);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002848 return FAIL;
2849}
2850
2851/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002852 * Evaluate the expression used in a ":for var in expr" command.
2853 * "arg" points to "var".
2854 * Set "*errp" to TRUE for an error, FALSE otherwise;
2855 * Return a pointer that holds the info. Null when there is an error.
2856 */
2857 void *
Bram Moolenaar7454a062016-01-30 15:14:10 +01002858eval_for_line(
2859 char_u *arg,
2860 int *errp,
2861 char_u **nextcmdp,
2862 int skip)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002863{
Bram Moolenaar33570922005-01-25 22:26:29 +00002864 forinfo_T *fi;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002865 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +00002866 typval_T tv;
2867 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002868
2869 *errp = TRUE; /* default: there is an error */
2870
Bram Moolenaarc799fe22019-05-28 23:08:19 +02002871 fi = ALLOC_CLEAR_ONE(forinfo_T);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002872 if (fi == NULL)
2873 return NULL;
2874
2875 expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
2876 if (expr == NULL)
2877 return fi;
2878
2879 expr = skipwhite(expr);
Bram Moolenaar1c465442017-03-12 20:10:05 +01002880 if (expr[0] != 'i' || expr[1] != 'n' || !VIM_ISWHITE(expr[2]))
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002881 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002882 emsg(_("E690: Missing \"in\" after :for"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002883 return fi;
2884 }
2885
2886 if (skip)
2887 ++emsg_skip;
2888 if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK)
2889 {
2890 *errp = FALSE;
2891 if (!skip)
2892 {
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002893 if (tv.v_type == VAR_LIST)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002894 {
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002895 l = tv.vval.v_list;
2896 if (l == NULL)
2897 {
2898 // a null list is like an empty list: do nothing
2899 clear_tv(&tv);
2900 }
2901 else
2902 {
2903 // No need to increment the refcount, it's already set for
2904 // the list being used in "tv".
2905 fi->fi_list = l;
2906 list_add_watch(l, &fi->fi_lw);
2907 fi->fi_lw.lw_item = l->lv_first;
2908 }
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002909 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002910 else if (tv.v_type == VAR_BLOB)
Bram Moolenaard8585ed2016-05-01 23:05:53 +02002911 {
Bram Moolenaardd29ea12019-01-23 21:56:21 +01002912 fi->fi_bi = 0;
2913 if (tv.vval.v_blob != NULL)
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002914 {
Bram Moolenaardd29ea12019-01-23 21:56:21 +01002915 typval_T btv;
2916
2917 // Make a copy, so that the iteration still works when the
2918 // blob is changed.
2919 blob_copy(&tv, &btv);
2920 fi->fi_blob = btv.vval.v_blob;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002921 }
Bram Moolenaardd29ea12019-01-23 21:56:21 +01002922 clear_tv(&tv);
Bram Moolenaard8585ed2016-05-01 23:05:53 +02002923 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002924 else
2925 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002926 emsg(_(e_listreq));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002927 clear_tv(&tv);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002928 }
2929 }
2930 }
2931 if (skip)
2932 --emsg_skip;
2933
2934 return fi;
2935}
2936
2937/*
2938 * Use the first item in a ":for" list. Advance to the next.
2939 * Assign the values to the variable (list). "arg" points to the first one.
2940 * Return TRUE when a valid item was found, FALSE when at end of list or
2941 * something wrong.
2942 */
2943 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01002944next_for_item(void *fi_void, char_u *arg)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002945{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002946 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002947 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00002948 listitem_T *item;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002949
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002950 if (fi->fi_blob != NULL)
2951 {
2952 typval_T tv;
2953
2954 if (fi->fi_bi >= blob_len(fi->fi_blob))
2955 return FALSE;
2956 tv.v_type = VAR_NUMBER;
2957 tv.v_lock = VAR_FIXED;
2958 tv.vval.v_number = blob_get(fi->fi_blob, fi->fi_bi);
2959 ++fi->fi_bi;
Bram Moolenaar9937a052019-06-15 15:45:06 +02002960 return ex_let_vars(arg, &tv, TRUE, fi->fi_semicolon,
2961 fi->fi_varcount, FALSE, NULL) == OK;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002962 }
2963
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002964 item = fi->fi_lw.lw_item;
2965 if (item == NULL)
2966 result = FALSE;
2967 else
2968 {
2969 fi->fi_lw.lw_item = item->li_next;
Bram Moolenaar9937a052019-06-15 15:45:06 +02002970 result = (ex_let_vars(arg, &item->li_tv, TRUE, fi->fi_semicolon,
2971 fi->fi_varcount, FALSE, NULL) == OK);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002972 }
2973 return result;
2974}
2975
2976/*
2977 * Free the structure used to store info used by ":for".
2978 */
2979 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002980free_for_info(void *fi_void)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002981{
Bram Moolenaar33570922005-01-25 22:26:29 +00002982 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002983
Bram Moolenaarab7013c2005-01-09 21:23:56 +00002984 if (fi != NULL && fi->fi_list != NULL)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002985 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002986 list_rem_watch(fi->fi_list, &fi->fi_lw);
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002987 list_unref(fi->fi_list);
2988 }
Bram Moolenaarecc8bc42019-01-13 16:07:21 +01002989 if (fi != NULL && fi->fi_blob != NULL)
2990 blob_unref(fi->fi_blob);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002991 vim_free(fi);
2992}
2993
Bram Moolenaar071d4272004-06-13 20:20:40 +00002994#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
2995
2996 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002997set_context_for_expression(
2998 expand_T *xp,
2999 char_u *arg,
3000 cmdidx_T cmdidx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003001{
3002 int got_eq = FALSE;
3003 int c;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003004 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003005
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003006 if (cmdidx == CMD_let)
3007 {
3008 xp->xp_context = EXPAND_USER_VARS;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00003009 if (vim_strpbrk(arg, (char_u *)"\"'+-*/%.=!?~|&$([<>,#") == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003010 {
3011 /* ":let var1 var2 ...": find last space. */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00003012 for (p = arg + STRLEN(arg); p >= arg; )
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003013 {
3014 xp->xp_pattern = p;
Bram Moolenaar91acfff2017-03-12 19:22:36 +01003015 MB_PTR_BACK(arg, p);
Bram Moolenaar1c465442017-03-12 20:10:05 +01003016 if (VIM_ISWHITE(*p))
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003017 break;
3018 }
3019 return;
3020 }
3021 }
3022 else
3023 xp->xp_context = cmdidx == CMD_call ? EXPAND_FUNCTIONS
3024 : EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003025 while ((xp->xp_pattern = vim_strpbrk(arg,
3026 (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL)
3027 {
3028 c = *xp->xp_pattern;
3029 if (c == '&')
3030 {
3031 c = xp->xp_pattern[1];
3032 if (c == '&')
3033 {
3034 ++xp->xp_pattern;
3035 xp->xp_context = cmdidx != CMD_let || got_eq
3036 ? EXPAND_EXPRESSION : EXPAND_NOTHING;
3037 }
3038 else if (c != ' ')
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00003039 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00003040 xp->xp_context = EXPAND_SETTINGS;
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00003041 if ((c == 'l' || c == 'g') && xp->xp_pattern[2] == ':')
3042 xp->xp_pattern += 2;
3043
3044 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003045 }
3046 else if (c == '$')
3047 {
3048 /* environment variable */
3049 xp->xp_context = EXPAND_ENV_VARS;
3050 }
3051 else if (c == '=')
3052 {
3053 got_eq = TRUE;
3054 xp->xp_context = EXPAND_EXPRESSION;
3055 }
Bram Moolenaara32095f2016-03-28 19:27:13 +02003056 else if (c == '#'
3057 && xp->xp_context == EXPAND_EXPRESSION)
3058 {
3059 /* Autoload function/variable contains '#'. */
3060 break;
3061 }
Bram Moolenaar8a349ff2014-11-12 20:09:06 +01003062 else if ((c == '<' || c == '#')
Bram Moolenaar071d4272004-06-13 20:20:40 +00003063 && xp->xp_context == EXPAND_FUNCTIONS
3064 && vim_strchr(xp->xp_pattern, '(') == NULL)
3065 {
Bram Moolenaar8a349ff2014-11-12 20:09:06 +01003066 /* Function name can start with "<SNR>" and contain '#'. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003067 break;
3068 }
3069 else if (cmdidx != CMD_let || got_eq)
3070 {
3071 if (c == '"') /* string */
3072 {
3073 while ((c = *++xp->xp_pattern) != NUL && c != '"')
3074 if (c == '\\' && xp->xp_pattern[1] != NUL)
3075 ++xp->xp_pattern;
3076 xp->xp_context = EXPAND_NOTHING;
3077 }
3078 else if (c == '\'') /* literal string */
3079 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00003080 /* Trick: '' is like stopping and starting a literal string. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003081 while ((c = *++xp->xp_pattern) != NUL && c != '\'')
3082 /* skip */ ;
3083 xp->xp_context = EXPAND_NOTHING;
3084 }
3085 else if (c == '|')
3086 {
3087 if (xp->xp_pattern[1] == '|')
3088 {
3089 ++xp->xp_pattern;
3090 xp->xp_context = EXPAND_EXPRESSION;
3091 }
3092 else
3093 xp->xp_context = EXPAND_COMMANDS;
3094 }
3095 else
3096 xp->xp_context = EXPAND_EXPRESSION;
3097 }
3098 else
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003099 /* Doesn't look like something valid, expand as an expression
3100 * anyway. */
3101 xp->xp_context = EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003102 arg = xp->xp_pattern;
3103 if (*arg != NUL)
3104 while ((c = *++arg) != NUL && (c == ' ' || c == '\t'))
3105 /* skip */ ;
3106 }
3107 xp->xp_pattern = arg;
3108}
3109
3110#endif /* FEAT_CMDL_COMPL */
3111
3112/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003113 * ":unlet[!] var1 ... " command.
3114 */
3115 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003116ex_unlet(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003117{
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003118 ex_unletlock(eap, eap->arg, 0);
3119}
3120
3121/*
3122 * ":lockvar" and ":unlockvar" commands
3123 */
3124 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003125ex_lockvar(exarg_T *eap)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003126{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003127 char_u *arg = eap->arg;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003128 int deep = 2;
3129
3130 if (eap->forceit)
3131 deep = -1;
3132 else if (vim_isdigit(*arg))
3133 {
3134 deep = getdigits(&arg);
3135 arg = skipwhite(arg);
3136 }
3137
3138 ex_unletlock(eap, arg, deep);
3139}
3140
3141/*
3142 * ":unlet", ":lockvar" and ":unlockvar" are quite similar.
3143 */
3144 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003145ex_unletlock(
3146 exarg_T *eap,
3147 char_u *argstart,
3148 int deep)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003149{
3150 char_u *arg = argstart;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003151 char_u *name_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003152 int error = FALSE;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003153 lval_T lv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003154
3155 do
3156 {
Bram Moolenaar137374f2018-05-13 15:59:50 +02003157 if (*arg == '$')
3158 {
3159 char_u *name = ++arg;
3160
3161 if (get_env_len(&arg) == 0)
3162 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003163 semsg(_(e_invarg2), name - 1);
Bram Moolenaar137374f2018-05-13 15:59:50 +02003164 return;
3165 }
3166 vim_unsetenv(name);
3167 arg = skipwhite(arg);
3168 continue;
3169 }
3170
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003171 /* Parse the name and find the end. */
Bram Moolenaar6d977d62014-01-14 15:24:39 +01003172 name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error, 0,
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00003173 FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003174 if (lv.ll_name == NULL)
3175 error = TRUE; /* error but continue parsing */
Bram Moolenaar1c465442017-03-12 20:10:05 +01003176 if (name_end == NULL || (!VIM_ISWHITE(*name_end)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003177 && !ends_excmd(*name_end)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003178 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003179 if (name_end != NULL)
3180 {
3181 emsg_severe = TRUE;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003182 emsg(_(e_trailing));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003183 }
3184 if (!(eap->skip || error))
3185 clear_lval(&lv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003186 break;
3187 }
3188
3189 if (!error && !eap->skip)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003190 {
3191 if (eap->cmdidx == CMD_unlet)
3192 {
3193 if (do_unlet_var(&lv, name_end, eap->forceit) == FAIL)
3194 error = TRUE;
3195 }
3196 else
3197 {
3198 if (do_lock_var(&lv, name_end, deep,
3199 eap->cmdidx == CMD_lockvar) == FAIL)
3200 error = TRUE;
3201 }
3202 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003203
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003204 if (!eap->skip)
3205 clear_lval(&lv);
3206
Bram Moolenaar071d4272004-06-13 20:20:40 +00003207 arg = skipwhite(name_end);
3208 } while (!ends_excmd(*arg));
3209
3210 eap->nextcmd = check_nextcmd(arg);
3211}
3212
Bram Moolenaar8c711452005-01-14 21:53:12 +00003213 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003214do_unlet_var(
3215 lval_T *lp,
3216 char_u *name_end,
3217 int forceit)
Bram Moolenaar8c711452005-01-14 21:53:12 +00003218{
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003219 int ret = OK;
3220 int cc;
3221
3222 if (lp->ll_tv == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00003223 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003224 cc = *name_end;
3225 *name_end = NUL;
3226
3227 /* Normal name or expanded name. */
Bram Moolenaar79518e22017-02-17 16:31:35 +01003228 if (do_unlet(lp->ll_name, forceit) == FAIL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003229 ret = FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003230 *name_end = cc;
Bram Moolenaar8c711452005-01-14 21:53:12 +00003231 }
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02003232 else if ((lp->ll_list != NULL
Bram Moolenaar05c00c02019-02-11 22:00:11 +01003233 && var_check_lock(lp->ll_list->lv_lock, lp->ll_name, FALSE))
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02003234 || (lp->ll_dict != NULL
Bram Moolenaar05c00c02019-02-11 22:00:11 +01003235 && var_check_lock(lp->ll_dict->dv_lock, lp->ll_name, FALSE)))
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003236 return FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003237 else if (lp->ll_range)
3238 {
Bram Moolenaar33570922005-01-25 22:26:29 +00003239 listitem_T *li;
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02003240 listitem_T *ll_li = lp->ll_li;
Bram Moolenaarc9703302016-01-17 21:49:33 +01003241 int ll_n1 = lp->ll_n1;
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02003242
3243 while (ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= ll_n1))
3244 {
3245 li = ll_li->li_next;
Bram Moolenaar05c00c02019-02-11 22:00:11 +01003246 if (var_check_lock(ll_li->li_tv.v_lock, lp->ll_name, FALSE))
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02003247 return FAIL;
3248 ll_li = li;
3249 ++ll_n1;
3250 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003251
3252 /* Delete a range of List items. */
3253 while (lp->ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
3254 {
3255 li = lp->ll_li->li_next;
3256 listitem_remove(lp->ll_list, lp->ll_li);
3257 lp->ll_li = li;
3258 ++lp->ll_n1;
3259 }
3260 }
3261 else
3262 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003263 if (lp->ll_list != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003264 /* unlet a List item. */
3265 listitem_remove(lp->ll_list, lp->ll_li);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003266 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003267 /* unlet a Dictionary item. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003268 dictitem_remove(lp->ll_dict, lp->ll_di);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003269 }
3270
3271 return ret;
Bram Moolenaar8c711452005-01-14 21:53:12 +00003272}
3273
Bram Moolenaar071d4272004-06-13 20:20:40 +00003274/*
3275 * "unlet" a variable. Return OK if it existed, FAIL if not.
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003276 * When "forceit" is TRUE don't complain if the variable doesn't exist.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003277 */
3278 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003279do_unlet(char_u *name, int forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003280{
Bram Moolenaar33570922005-01-25 22:26:29 +00003281 hashtab_T *ht;
3282 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003283 char_u *varname;
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02003284 dict_T *d;
Bram Moolenaarafbdeb82008-01-05 21:16:31 +00003285 dictitem_T *di;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003286
Bram Moolenaar33570922005-01-25 22:26:29 +00003287 ht = find_var_ht(name, &varname);
3288 if (ht != NULL && *varname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003289 {
Bram Moolenaara9b579f2016-07-17 18:29:19 +02003290 d = get_current_funccal_dict(ht);
Bram Moolenaar71bcfdf2016-01-09 18:20:46 +01003291 if (d == NULL)
3292 {
Bram Moolenaara9b579f2016-07-17 18:29:19 +02003293 if (ht == &globvarht)
3294 d = &globvardict;
3295 else if (ht == &compat_hashtab)
3296 d = &vimvardict;
3297 else
3298 {
3299 di = find_var_in_ht(ht, *name, (char_u *)"", FALSE);
3300 d = di == NULL ? NULL : di->di_tv.vval.v_dict;
3301 }
3302 if (d == NULL)
3303 {
Bram Moolenaar95f09602016-11-10 20:01:45 +01003304 internal_error("do_unlet()");
Bram Moolenaara9b579f2016-07-17 18:29:19 +02003305 return FAIL;
3306 }
Bram Moolenaar71bcfdf2016-01-09 18:20:46 +01003307 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003308 hi = hash_find(ht, varname);
Bram Moolenaar10ce39a2016-07-29 22:37:06 +02003309 if (HASHITEM_EMPTY(hi))
Bram Moolenaarba96e9a2016-08-01 17:10:20 +02003310 hi = find_hi_in_scoped_ht(name, &ht);
Bram Moolenaar10ce39a2016-07-29 22:37:06 +02003311 if (hi != NULL && !HASHITEM_EMPTY(hi))
Bram Moolenaara7043832005-01-21 11:56:39 +00003312 {
Bram Moolenaarafbdeb82008-01-05 21:16:31 +00003313 di = HI2DI(hi);
Bram Moolenaar77354e72015-04-21 16:49:05 +02003314 if (var_check_fixed(di->di_flags, name, FALSE)
Bram Moolenaar71bcfdf2016-01-09 18:20:46 +01003315 || var_check_ro(di->di_flags, name, FALSE)
Bram Moolenaar05c00c02019-02-11 22:00:11 +01003316 || var_check_lock(d->dv_lock, name, FALSE))
Bram Moolenaaraf8af8b2016-01-04 22:05:24 +01003317 return FAIL;
3318
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003319 delete_var(ht, hi);
3320 return OK;
Bram Moolenaara7043832005-01-21 11:56:39 +00003321 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003322 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003323 if (forceit)
3324 return OK;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003325 semsg(_("E108: No such variable: \"%s\""), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003326 return FAIL;
3327}
3328
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003329/*
3330 * Lock or unlock variable indicated by "lp".
3331 * "deep" is the levels to go (-1 for unlimited);
3332 * "lock" is TRUE for ":lockvar", FALSE for ":unlockvar".
3333 */
3334 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003335do_lock_var(
3336 lval_T *lp,
3337 char_u *name_end,
3338 int deep,
3339 int lock)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003340{
3341 int ret = OK;
3342 int cc;
3343 dictitem_T *di;
3344
3345 if (deep == 0) /* nothing to do */
3346 return OK;
3347
3348 if (lp->ll_tv == NULL)
3349 {
3350 cc = *name_end;
3351 *name_end = NUL;
3352
3353 /* Normal name or expanded name. */
Bram Moolenaar79518e22017-02-17 16:31:35 +01003354 di = find_var(lp->ll_name, NULL, TRUE);
3355 if (di == NULL)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003356 ret = FAIL;
Bram Moolenaare7877fe2017-02-20 22:35:33 +01003357 else if ((di->di_flags & DI_FLAGS_FIX)
3358 && di->di_tv.v_type != VAR_DICT
3359 && di->di_tv.v_type != VAR_LIST)
3360 /* For historic reasons this error is not given for a list or dict.
3361 * E.g., the b: dict could be locked/unlocked. */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003362 semsg(_("E940: Cannot lock or unlock variable %s"), lp->ll_name);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003363 else
3364 {
Bram Moolenaar79518e22017-02-17 16:31:35 +01003365 if (lock)
3366 di->di_flags |= DI_FLAGS_LOCK;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003367 else
Bram Moolenaar79518e22017-02-17 16:31:35 +01003368 di->di_flags &= ~DI_FLAGS_LOCK;
3369 item_lock(&di->di_tv, deep, lock);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003370 }
3371 *name_end = cc;
3372 }
3373 else if (lp->ll_range)
3374 {
3375 listitem_T *li = lp->ll_li;
3376
3377 /* (un)lock a range of List items. */
3378 while (li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
3379 {
3380 item_lock(&li->li_tv, deep, lock);
3381 li = li->li_next;
3382 ++lp->ll_n1;
3383 }
3384 }
3385 else if (lp->ll_list != NULL)
3386 /* (un)lock a List item. */
3387 item_lock(&lp->ll_li->li_tv, deep, lock);
3388 else
Bram Moolenaar641e48c2015-06-25 16:09:26 +02003389 /* (un)lock a Dictionary item. */
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003390 item_lock(&lp->ll_di->di_tv, deep, lock);
3391
3392 return ret;
3393}
3394
3395/*
3396 * Lock or unlock an item. "deep" is nr of levels to go.
3397 */
3398 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003399item_lock(typval_T *tv, int deep, int lock)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003400{
3401 static int recurse = 0;
3402 list_T *l;
3403 listitem_T *li;
3404 dict_T *d;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01003405 blob_T *b;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003406 hashitem_T *hi;
3407 int todo;
3408
3409 if (recurse >= DICT_MAXNEST)
3410 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003411 emsg(_("E743: variable nested too deep for (un)lock"));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003412 return;
3413 }
3414 if (deep == 0)
3415 return;
3416 ++recurse;
3417
3418 /* lock/unlock the item itself */
3419 if (lock)
3420 tv->v_lock |= VAR_LOCKED;
3421 else
3422 tv->v_lock &= ~VAR_LOCKED;
3423
3424 switch (tv->v_type)
3425 {
Bram Moolenaara03f2332016-02-06 18:09:59 +01003426 case VAR_UNKNOWN:
3427 case VAR_NUMBER:
3428 case VAR_STRING:
3429 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01003430 case VAR_PARTIAL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01003431 case VAR_FLOAT:
3432 case VAR_SPECIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01003433 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01003434 case VAR_CHANNEL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01003435 break;
3436
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01003437 case VAR_BLOB:
3438 if ((b = tv->vval.v_blob) != NULL)
3439 {
3440 if (lock)
3441 b->bv_lock |= VAR_LOCKED;
3442 else
3443 b->bv_lock &= ~VAR_LOCKED;
3444 }
3445 break;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003446 case VAR_LIST:
3447 if ((l = tv->vval.v_list) != NULL)
3448 {
3449 if (lock)
3450 l->lv_lock |= VAR_LOCKED;
3451 else
3452 l->lv_lock &= ~VAR_LOCKED;
3453 if (deep < 0 || deep > 1)
3454 /* recursive: lock/unlock the items the List contains */
3455 for (li = l->lv_first; li != NULL; li = li->li_next)
3456 item_lock(&li->li_tv, deep - 1, lock);
3457 }
3458 break;
3459 case VAR_DICT:
3460 if ((d = tv->vval.v_dict) != NULL)
3461 {
3462 if (lock)
3463 d->dv_lock |= VAR_LOCKED;
3464 else
3465 d->dv_lock &= ~VAR_LOCKED;
3466 if (deep < 0 || deep > 1)
3467 {
3468 /* recursive: lock/unlock the items the List contains */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003469 todo = (int)d->dv_hashtab.ht_used;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003470 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
3471 {
3472 if (!HASHITEM_EMPTY(hi))
3473 {
3474 --todo;
3475 item_lock(&HI2DI(hi)->di_tv, deep - 1, lock);
3476 }
3477 }
3478 }
3479 }
3480 }
3481 --recurse;
3482}
3483
Bram Moolenaar071d4272004-06-13 20:20:40 +00003484#if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO)
3485/*
3486 * Delete all "menutrans_" variables.
3487 */
3488 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003489del_menutrans_vars(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003490{
Bram Moolenaar33570922005-01-25 22:26:29 +00003491 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003492 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003493
Bram Moolenaar33570922005-01-25 22:26:29 +00003494 hash_lock(&globvarht);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003495 todo = (int)globvarht.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00003496 for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaara7043832005-01-21 11:56:39 +00003497 {
3498 if (!HASHITEM_EMPTY(hi))
3499 {
3500 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00003501 if (STRNCMP(HI2DI(hi)->di_key, "menutrans_", 10) == 0)
3502 delete_var(&globvarht, hi);
Bram Moolenaara7043832005-01-21 11:56:39 +00003503 }
3504 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003505 hash_unlock(&globvarht);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003506}
3507#endif
3508
3509#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
3510
3511/*
3512 * Local string buffer for the next two functions to store a variable name
3513 * with its prefix. Allocated in cat_prefix_varname(), freed later in
3514 * get_user_var_name().
3515 */
3516
Bram Moolenaar071d4272004-06-13 20:20:40 +00003517static char_u *varnamebuf = NULL;
3518static int varnamebuflen = 0;
3519
3520/*
3521 * Function to concatenate a prefix and a variable name.
3522 */
3523 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01003524cat_prefix_varname(int prefix, char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003525{
3526 int len;
3527
3528 len = (int)STRLEN(name) + 3;
3529 if (len > varnamebuflen)
3530 {
3531 vim_free(varnamebuf);
3532 len += 10; /* some additional space */
3533 varnamebuf = alloc(len);
3534 if (varnamebuf == NULL)
3535 {
3536 varnamebuflen = 0;
3537 return NULL;
3538 }
3539 varnamebuflen = len;
3540 }
3541 *varnamebuf = prefix;
3542 varnamebuf[1] = ':';
3543 STRCPY(varnamebuf + 2, name);
3544 return varnamebuf;
3545}
3546
3547/*
3548 * Function given to ExpandGeneric() to obtain the list of user defined
3549 * (global/buffer/window/built-in) variable names.
3550 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003551 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01003552get_user_var_name(expand_T *xp, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003553{
Bram Moolenaar532c7802005-01-27 14:44:31 +00003554 static long_u gdone;
3555 static long_u bdone;
3556 static long_u wdone;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003557 static long_u tdone;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003558 static int vidx;
3559 static hashitem_T *hi;
3560 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003561
3562 if (idx == 0)
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003563 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003564 gdone = bdone = wdone = vidx = 0;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003565 tdone = 0;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003566 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003567
3568 /* Global variables */
3569 if (gdone < globvarht.ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003570 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003571 if (gdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003572 hi = globvarht.ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003573 else
3574 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003575 while (HASHITEM_EMPTY(hi))
3576 ++hi;
3577 if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
3578 return cat_prefix_varname('g', hi->hi_key);
3579 return hi->hi_key;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003580 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003581
3582 /* b: variables */
Bram Moolenaar429fa852013-04-15 12:27:36 +02003583 ht = &curbuf->b_vars->dv_hashtab;
Bram Moolenaar33570922005-01-25 22:26:29 +00003584 if (bdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003585 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003586 if (bdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003587 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003588 else
3589 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003590 while (HASHITEM_EMPTY(hi))
3591 ++hi;
3592 return cat_prefix_varname('b', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003593 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003594
3595 /* w: variables */
Bram Moolenaar429fa852013-04-15 12:27:36 +02003596 ht = &curwin->w_vars->dv_hashtab;
Bram Moolenaar33570922005-01-25 22:26:29 +00003597 if (wdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003598 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00003599 if (wdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003600 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003601 else
3602 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003603 while (HASHITEM_EMPTY(hi))
3604 ++hi;
3605 return cat_prefix_varname('w', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003606 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003607
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003608 /* t: variables */
Bram Moolenaar429fa852013-04-15 12:27:36 +02003609 ht = &curtab->tp_vars->dv_hashtab;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003610 if (tdone < ht->ht_used)
3611 {
3612 if (tdone++ == 0)
3613 hi = ht->ht_array;
3614 else
3615 ++hi;
3616 while (HASHITEM_EMPTY(hi))
3617 ++hi;
3618 return cat_prefix_varname('t', hi->hi_key);
3619 }
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003620
Bram Moolenaar33570922005-01-25 22:26:29 +00003621 /* v: variables */
3622 if (vidx < VV_LEN)
3623 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].vv_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003624
Bram Moolenaard23a8232018-02-10 18:45:26 +01003625 VIM_CLEAR(varnamebuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003626 varnamebuflen = 0;
3627 return NULL;
3628}
3629
3630#endif /* FEAT_CMDL_COMPL */
3631
3632/*
Bram Moolenaarea6553b2016-03-27 15:13:38 +02003633 * Return TRUE if "pat" matches "text".
3634 * Does not use 'cpo' and always uses 'magic'.
3635 */
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02003636 int
Bram Moolenaarea6553b2016-03-27 15:13:38 +02003637pattern_match(char_u *pat, char_u *text, int ic)
3638{
3639 int matches = FALSE;
3640 char_u *save_cpo;
3641 regmatch_T regmatch;
3642
3643 /* avoid 'l' flag in 'cpoptions' */
3644 save_cpo = p_cpo;
3645 p_cpo = (char_u *)"";
3646 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
3647 if (regmatch.regprog != NULL)
3648 {
3649 regmatch.rm_ic = ic;
3650 matches = vim_regexec_nl(&regmatch, text, (colnr_T)0);
3651 vim_regfree(regmatch.regprog);
3652 }
3653 p_cpo = save_cpo;
3654 return matches;
3655}
3656
3657/*
Bram Moolenaar761fdf02019-08-05 23:10:16 +02003658 * Handle a name followed by "(". Both for just "name(arg)" and for
3659 * "expr->name(arg)".
3660 * Returns OK or FAIL.
3661 */
3662 static int
3663eval_func(
3664 char_u **arg, // points to "(", will be advanced
3665 char_u *name,
3666 int name_len,
3667 typval_T *rettv,
3668 int evaluate,
3669 typval_T *basetv) // "expr" for "expr->name(arg)"
3670{
3671 char_u *s = name;
3672 int len = name_len;
3673 partial_T *partial;
3674 int ret = OK;
3675
3676 if (!evaluate)
3677 check_vars(s, len);
3678
3679 /* If "s" is the name of a variable of type VAR_FUNC
3680 * use its contents. */
3681 s = deref_func_name(s, &len, &partial, !evaluate);
3682
3683 /* Need to make a copy, in case evaluating the arguments makes
3684 * the name invalid. */
3685 s = vim_strsave(s);
3686 if (s == NULL)
3687 ret = FAIL;
3688 else
3689 {
3690 funcexe_T funcexe;
3691
3692 // Invoke the function.
3693 vim_memset(&funcexe, 0, sizeof(funcexe));
3694 funcexe.firstline = curwin->w_cursor.lnum;
3695 funcexe.lastline = curwin->w_cursor.lnum;
3696 funcexe.doesrange = &len;
3697 funcexe.evaluate = evaluate;
3698 funcexe.partial = partial;
3699 funcexe.basetv = basetv;
3700 ret = get_func_tv(s, len, rettv, arg, &funcexe);
3701 }
3702 vim_free(s);
3703
3704 /* If evaluate is FALSE rettv->v_type was not set in
3705 * get_func_tv, but it's needed in handle_subscript() to parse
3706 * what follows. So set it here. */
3707 if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(')
3708 {
3709 rettv->vval.v_string = NULL;
3710 rettv->v_type = VAR_FUNC;
3711 }
3712
3713 /* Stop the expression evaluation when immediately
3714 * aborting on error, or when an interrupt occurred or
3715 * an exception was thrown but not caught. */
3716 if (evaluate && aborting())
3717 {
3718 if (ret == OK)
3719 clear_tv(rettv);
3720 ret = FAIL;
3721 }
3722 return ret;
3723}
3724
3725/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003726 * The "evaluate" argument: When FALSE, the argument is only parsed but not
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003727 * executed. The function may return OK, but the rettv will be of type
Bram Moolenaar071d4272004-06-13 20:20:40 +00003728 * VAR_UNKNOWN. The function still returns FAIL for a syntax error.
3729 */
3730
3731/*
3732 * Handle zero level expression.
3733 * This calls eval1() and handles error message and nextcmd.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003734 * Put the result in "rettv" when returning OK and "evaluate" is TRUE.
Bram Moolenaar4463f292005-09-25 22:20:24 +00003735 * Note: "rettv.v_lock" is not set.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003736 * Return OK or FAIL.
3737 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02003738 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003739eval0(
3740 char_u *arg,
3741 typval_T *rettv,
3742 char_u **nextcmd,
3743 int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003744{
3745 int ret;
3746 char_u *p;
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01003747 int did_emsg_before = did_emsg;
3748 int called_emsg_before = called_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003749
3750 p = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003751 ret = eval1(&p, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003752 if (ret == FAIL || !ends_excmd(*p))
3753 {
3754 if (ret != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003755 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003756 /*
3757 * Report the invalid expression unless the expression evaluation has
3758 * been cancelled due to an aborting error, an interrupt, or an
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01003759 * exception, or we already gave a more specific error.
3760 * Also check called_emsg for when using assert_fails().
Bram Moolenaar071d4272004-06-13 20:20:40 +00003761 */
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01003762 if (!aborting() && did_emsg == did_emsg_before
3763 && called_emsg == called_emsg_before)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003764 semsg(_(e_invexpr2), arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003765 ret = FAIL;
3766 }
3767 if (nextcmd != NULL)
3768 *nextcmd = check_nextcmd(p);
3769
3770 return ret;
3771}
3772
3773/*
3774 * Handle top level expression:
Bram Moolenaarb67cc162009-02-04 15:27:06 +00003775 * expr2 ? expr1 : expr1
Bram Moolenaar071d4272004-06-13 20:20:40 +00003776 *
3777 * "arg" must point to the first non-white of the expression.
3778 * "arg" is advanced to the next non-white after the recognized expression.
3779 *
Bram Moolenaar4463f292005-09-25 22:20:24 +00003780 * Note: "rettv.v_lock" is not set.
3781 *
Bram Moolenaar071d4272004-06-13 20:20:40 +00003782 * Return OK or FAIL.
3783 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02003784 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003785eval1(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003786{
3787 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00003788 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003789
3790 /*
3791 * Get the first variable.
3792 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003793 if (eval2(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003794 return FAIL;
3795
3796 if ((*arg)[0] == '?')
3797 {
3798 result = FALSE;
3799 if (evaluate)
3800 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003801 int error = FALSE;
3802
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003803 if (tv_get_number_chk(rettv, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003804 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003805 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003806 if (error)
3807 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003808 }
3809
3810 /*
3811 * Get the second variable.
3812 */
3813 *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003814 if (eval1(arg, rettv, evaluate && result) == FAIL) /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003815 return FAIL;
3816
3817 /*
3818 * Check for the ":".
3819 */
3820 if ((*arg)[0] != ':')
3821 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003822 emsg(_("E109: Missing ':' after '?'"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003823 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003824 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003825 return FAIL;
3826 }
3827
3828 /*
3829 * Get the third variable.
3830 */
3831 *arg = skipwhite(*arg + 1);
3832 if (eval1(arg, &var2, evaluate && !result) == FAIL) /* recursive! */
3833 {
3834 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003835 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003836 return FAIL;
3837 }
3838 if (evaluate && !result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003839 *rettv = var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003840 }
3841
3842 return OK;
3843}
3844
3845/*
3846 * Handle first level expression:
3847 * expr2 || expr2 || expr2 logical OR
3848 *
3849 * "arg" must point to the first non-white of the expression.
3850 * "arg" is advanced to the next non-white after the recognized expression.
3851 *
3852 * Return OK or FAIL.
3853 */
3854 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003855eval2(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003856{
Bram Moolenaar33570922005-01-25 22:26:29 +00003857 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003858 long result;
3859 int first;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003860 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003861
3862 /*
3863 * Get the first variable.
3864 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003865 if (eval3(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003866 return FAIL;
3867
3868 /*
3869 * Repeat until there is no following "||".
3870 */
3871 first = TRUE;
3872 result = FALSE;
3873 while ((*arg)[0] == '|' && (*arg)[1] == '|')
3874 {
3875 if (evaluate && first)
3876 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003877 if (tv_get_number_chk(rettv, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003878 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003879 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003880 if (error)
3881 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003882 first = FALSE;
3883 }
3884
3885 /*
3886 * Get the second variable.
3887 */
3888 *arg = skipwhite(*arg + 2);
3889 if (eval3(arg, &var2, evaluate && !result) == FAIL)
3890 return FAIL;
3891
3892 /*
3893 * Compute the result.
3894 */
3895 if (evaluate && !result)
3896 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003897 if (tv_get_number_chk(&var2, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003898 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003899 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003900 if (error)
3901 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003902 }
3903 if (evaluate)
3904 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003905 rettv->v_type = VAR_NUMBER;
3906 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003907 }
3908 }
3909
3910 return OK;
3911}
3912
3913/*
3914 * Handle second level expression:
3915 * expr3 && expr3 && expr3 logical AND
3916 *
3917 * "arg" must point to the first non-white of the expression.
3918 * "arg" is advanced to the next non-white after the recognized expression.
3919 *
3920 * Return OK or FAIL.
3921 */
3922 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003923eval3(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003924{
Bram Moolenaar33570922005-01-25 22:26:29 +00003925 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003926 long result;
3927 int first;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003928 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003929
3930 /*
3931 * Get the first variable.
3932 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003933 if (eval4(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003934 return FAIL;
3935
3936 /*
3937 * Repeat until there is no following "&&".
3938 */
3939 first = TRUE;
3940 result = TRUE;
3941 while ((*arg)[0] == '&' && (*arg)[1] == '&')
3942 {
3943 if (evaluate && first)
3944 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003945 if (tv_get_number_chk(rettv, &error) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003946 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003947 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003948 if (error)
3949 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003950 first = FALSE;
3951 }
3952
3953 /*
3954 * Get the second variable.
3955 */
3956 *arg = skipwhite(*arg + 2);
3957 if (eval4(arg, &var2, evaluate && result) == FAIL)
3958 return FAIL;
3959
3960 /*
3961 * Compute the result.
3962 */
3963 if (evaluate && result)
3964 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003965 if (tv_get_number_chk(&var2, &error) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003966 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003967 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003968 if (error)
3969 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003970 }
3971 if (evaluate)
3972 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003973 rettv->v_type = VAR_NUMBER;
3974 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003975 }
3976 }
3977
3978 return OK;
3979}
3980
3981/*
3982 * Handle third level expression:
3983 * var1 == var2
3984 * var1 =~ var2
3985 * var1 != var2
3986 * var1 !~ var2
3987 * var1 > var2
3988 * var1 >= var2
3989 * var1 < var2
3990 * var1 <= var2
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003991 * var1 is var2
3992 * var1 isnot var2
Bram Moolenaar071d4272004-06-13 20:20:40 +00003993 *
3994 * "arg" must point to the first non-white of the expression.
3995 * "arg" is advanced to the next non-white after the recognized expression.
3996 *
3997 * Return OK or FAIL.
3998 */
3999 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004000eval4(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004001{
Bram Moolenaar33570922005-01-25 22:26:29 +00004002 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004003 char_u *p;
4004 int i;
4005 exptype_T type = TYPE_UNKNOWN;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004006 int type_is = FALSE; /* TRUE for "is" and "isnot" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004007 int len = 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004008 int ic;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004009
4010 /*
4011 * Get the first variable.
4012 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004013 if (eval5(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004014 return FAIL;
4015
4016 p = *arg;
4017 switch (p[0])
4018 {
4019 case '=': if (p[1] == '=')
4020 type = TYPE_EQUAL;
4021 else if (p[1] == '~')
4022 type = TYPE_MATCH;
4023 break;
4024 case '!': if (p[1] == '=')
4025 type = TYPE_NEQUAL;
4026 else if (p[1] == '~')
4027 type = TYPE_NOMATCH;
4028 break;
4029 case '>': if (p[1] != '=')
4030 {
4031 type = TYPE_GREATER;
4032 len = 1;
4033 }
4034 else
4035 type = TYPE_GEQUAL;
4036 break;
4037 case '<': if (p[1] != '=')
4038 {
4039 type = TYPE_SMALLER;
4040 len = 1;
4041 }
4042 else
4043 type = TYPE_SEQUAL;
4044 break;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004045 case 'i': if (p[1] == 's')
4046 {
4047 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
4048 len = 5;
Bram Moolenaar37a8de12015-09-01 16:05:00 +02004049 i = p[len];
4050 if (!isalnum(i) && i != '_')
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004051 {
4052 type = len == 2 ? TYPE_EQUAL : TYPE_NEQUAL;
4053 type_is = TRUE;
4054 }
4055 }
4056 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004057 }
4058
4059 /*
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004060 * If there is a comparative operator, use it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004061 */
4062 if (type != TYPE_UNKNOWN)
4063 {
4064 /* extra question mark appended: ignore case */
4065 if (p[len] == '?')
4066 {
4067 ic = TRUE;
4068 ++len;
4069 }
4070 /* extra '#' appended: match case */
4071 else if (p[len] == '#')
4072 {
4073 ic = FALSE;
4074 ++len;
4075 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004076 /* nothing appended: use 'ignorecase' */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004077 else
4078 ic = p_ic;
4079
4080 /*
4081 * Get the second variable.
4082 */
4083 *arg = skipwhite(p + len);
4084 if (eval5(arg, &var2, evaluate) == FAIL)
4085 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004086 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004087 return FAIL;
4088 }
Bram Moolenaar31988702018-02-13 12:57:42 +01004089 if (evaluate)
4090 {
4091 int ret = typval_compare(rettv, &var2, type, type_is, ic);
4092
4093 clear_tv(&var2);
4094 return ret;
4095 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004096 }
4097
4098 return OK;
4099}
4100
4101/*
4102 * Handle fourth level expression:
4103 * + number addition
4104 * - number subtraction
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004105 * . string concatenation (if script version is 1)
Bram Moolenaar0f248b02019-04-04 15:36:05 +02004106 * .. string concatenation
Bram Moolenaar071d4272004-06-13 20:20:40 +00004107 *
4108 * "arg" must point to the first non-white of the expression.
4109 * "arg" is advanced to the next non-white after the recognized expression.
4110 *
4111 * Return OK or FAIL.
4112 */
4113 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004114eval5(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004115{
Bram Moolenaar33570922005-01-25 22:26:29 +00004116 typval_T var2;
4117 typval_T var3;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004118 int op;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02004119 varnumber_T n1, n2;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004120#ifdef FEAT_FLOAT
4121 float_T f1 = 0, f2 = 0;
4122#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004123 char_u *s1, *s2;
4124 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4125 char_u *p;
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004126 int concat;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004127
4128 /*
4129 * Get the first variable.
4130 */
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004131 if (eval6(arg, rettv, evaluate, FALSE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004132 return FAIL;
4133
4134 /*
4135 * Repeat computing, until no '+', '-' or '.' is following.
4136 */
4137 for (;;)
4138 {
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004139 // "." is only string concatenation when scriptversion is 1
Bram Moolenaar071d4272004-06-13 20:20:40 +00004140 op = **arg;
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004141 concat = op == '.'
4142 && (*(*arg + 1) == '.' || current_sctx.sc_version < 2);
4143 if (op != '+' && op != '-' && !concat)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004144 break;
4145
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004146 if ((op != '+' || (rettv->v_type != VAR_LIST
4147 && rettv->v_type != VAR_BLOB))
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004148#ifdef FEAT_FLOAT
4149 && (op == '.' || rettv->v_type != VAR_FLOAT)
4150#endif
4151 )
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004152 {
4153 /* For "list + ...", an illegal use of the first operand as
4154 * a number cannot be determined before evaluating the 2nd
4155 * operand: if this is also a list, all is ok.
4156 * For "something . ...", "something - ..." or "non-list + ...",
4157 * we know that the first operand needs to be a string or number
4158 * without evaluating the 2nd operand. So check before to avoid
4159 * side effects after an error. */
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004160 if (evaluate && tv_get_string_chk(rettv) == NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004161 {
4162 clear_tv(rettv);
4163 return FAIL;
4164 }
4165 }
4166
Bram Moolenaar071d4272004-06-13 20:20:40 +00004167 /*
4168 * Get the second variable.
4169 */
Bram Moolenaar0f248b02019-04-04 15:36:05 +02004170 if (op == '.' && *(*arg + 1) == '.') // .. string concatenation
4171 ++*arg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004172 *arg = skipwhite(*arg + 1);
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004173 if (eval6(arg, &var2, evaluate, op == '.') == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004174 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004175 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004176 return FAIL;
4177 }
4178
4179 if (evaluate)
4180 {
4181 /*
4182 * Compute the result.
4183 */
4184 if (op == '.')
4185 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004186 s1 = tv_get_string_buf(rettv, buf1); /* already checked */
4187 s2 = tv_get_string_buf_chk(&var2, buf2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004188 if (s2 == NULL) /* type error ? */
4189 {
4190 clear_tv(rettv);
4191 clear_tv(&var2);
4192 return FAIL;
4193 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004194 p = concat_str(s1, s2);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004195 clear_tv(rettv);
4196 rettv->v_type = VAR_STRING;
4197 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004198 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004199 else if (op == '+' && rettv->v_type == VAR_BLOB
4200 && var2.v_type == VAR_BLOB)
4201 {
4202 blob_T *b1 = rettv->vval.v_blob;
4203 blob_T *b2 = var2.vval.v_blob;
4204 blob_T *b = blob_alloc();
4205 int i;
4206
4207 if (b != NULL)
4208 {
4209 for (i = 0; i < blob_len(b1); i++)
4210 ga_append(&b->bv_ga, blob_get(b1, i));
4211 for (i = 0; i < blob_len(b2); i++)
4212 ga_append(&b->bv_ga, blob_get(b2, i));
4213
4214 clear_tv(rettv);
4215 rettv_blob_set(rettv, b);
4216 }
4217 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00004218 else if (op == '+' && rettv->v_type == VAR_LIST
4219 && var2.v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004220 {
4221 /* concatenate Lists */
4222 if (list_concat(rettv->vval.v_list, var2.vval.v_list,
4223 &var3) == FAIL)
4224 {
4225 clear_tv(rettv);
4226 clear_tv(&var2);
4227 return FAIL;
4228 }
4229 clear_tv(rettv);
4230 *rettv = var3;
4231 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004232 else
4233 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004234 int error = FALSE;
4235
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004236#ifdef FEAT_FLOAT
4237 if (rettv->v_type == VAR_FLOAT)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004238 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004239 f1 = rettv->vval.v_float;
4240 n1 = 0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004241 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004242 else
4243#endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004244 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004245 n1 = tv_get_number_chk(rettv, &error);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004246 if (error)
4247 {
4248 /* This can only happen for "list + non-list". For
4249 * "non-list + ..." or "something - ...", we returned
4250 * before evaluating the 2nd operand. */
4251 clear_tv(rettv);
4252 return FAIL;
4253 }
4254#ifdef FEAT_FLOAT
4255 if (var2.v_type == VAR_FLOAT)
4256 f1 = n1;
4257#endif
4258 }
4259#ifdef FEAT_FLOAT
4260 if (var2.v_type == VAR_FLOAT)
4261 {
4262 f2 = var2.vval.v_float;
4263 n2 = 0;
4264 }
4265 else
4266#endif
4267 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004268 n2 = tv_get_number_chk(&var2, &error);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004269 if (error)
4270 {
4271 clear_tv(rettv);
4272 clear_tv(&var2);
4273 return FAIL;
4274 }
4275#ifdef FEAT_FLOAT
4276 if (rettv->v_type == VAR_FLOAT)
4277 f2 = n2;
4278#endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004279 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004280 clear_tv(rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004281
4282#ifdef FEAT_FLOAT
4283 /* If there is a float on either side the result is a float. */
4284 if (rettv->v_type == VAR_FLOAT || var2.v_type == VAR_FLOAT)
4285 {
4286 if (op == '+')
4287 f1 = f1 + f2;
4288 else
4289 f1 = f1 - f2;
4290 rettv->v_type = VAR_FLOAT;
4291 rettv->vval.v_float = f1;
4292 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004293 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004294#endif
4295 {
4296 if (op == '+')
4297 n1 = n1 + n2;
4298 else
4299 n1 = n1 - n2;
4300 rettv->v_type = VAR_NUMBER;
4301 rettv->vval.v_number = n1;
4302 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004303 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004304 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004305 }
4306 }
4307 return OK;
4308}
4309
4310/*
4311 * Handle fifth level expression:
4312 * * number multiplication
4313 * / number division
4314 * % number modulo
4315 *
4316 * "arg" must point to the first non-white of the expression.
4317 * "arg" is advanced to the next non-white after the recognized expression.
4318 *
4319 * Return OK or FAIL.
4320 */
4321 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004322eval6(
4323 char_u **arg,
4324 typval_T *rettv,
4325 int evaluate,
4326 int want_string) /* after "." operator */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004327{
Bram Moolenaar33570922005-01-25 22:26:29 +00004328 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004329 int op;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02004330 varnumber_T n1, n2;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004331#ifdef FEAT_FLOAT
4332 int use_float = FALSE;
Bram Moolenaar1f3601e2019-04-26 20:33:00 +02004333 float_T f1 = 0, f2 = 0;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004334#endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004335 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004336
4337 /*
4338 * Get the first variable.
4339 */
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004340 if (eval7(arg, rettv, evaluate, want_string) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004341 return FAIL;
4342
4343 /*
4344 * Repeat computing, until no '*', '/' or '%' is following.
4345 */
4346 for (;;)
4347 {
4348 op = **arg;
Bram Moolenaarb8be54d2019-07-14 18:22:59 +02004349 if (op != '*' && op != '/' && op != '%')
Bram Moolenaar071d4272004-06-13 20:20:40 +00004350 break;
4351
4352 if (evaluate)
4353 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004354#ifdef FEAT_FLOAT
4355 if (rettv->v_type == VAR_FLOAT)
4356 {
4357 f1 = rettv->vval.v_float;
4358 use_float = TRUE;
4359 n1 = 0;
4360 }
4361 else
4362#endif
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004363 n1 = tv_get_number_chk(rettv, &error);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004364 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004365 if (error)
4366 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004367 }
4368 else
4369 n1 = 0;
4370
4371 /*
4372 * Get the second variable.
4373 */
4374 *arg = skipwhite(*arg + 1);
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004375 if (eval7(arg, &var2, evaluate, FALSE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004376 return FAIL;
4377
4378 if (evaluate)
4379 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004380#ifdef FEAT_FLOAT
4381 if (var2.v_type == VAR_FLOAT)
4382 {
4383 if (!use_float)
4384 {
4385 f1 = n1;
4386 use_float = TRUE;
4387 }
4388 f2 = var2.vval.v_float;
4389 n2 = 0;
4390 }
4391 else
4392#endif
4393 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004394 n2 = tv_get_number_chk(&var2, &error);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004395 clear_tv(&var2);
4396 if (error)
4397 return FAIL;
4398#ifdef FEAT_FLOAT
4399 if (use_float)
4400 f2 = n2;
4401#endif
4402 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004403
4404 /*
4405 * Compute the result.
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004406 * When either side is a float the result is a float.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004407 */
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004408#ifdef FEAT_FLOAT
4409 if (use_float)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004410 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004411 if (op == '*')
4412 f1 = f1 * f2;
4413 else if (op == '/')
4414 {
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004415# ifdef VMS
4416 /* VMS crashes on divide by zero, work around it */
4417 if (f2 == 0.0)
4418 {
4419 if (f1 == 0)
Bram Moolenaar314f11d2010-08-09 22:07:08 +02004420 f1 = -1 * __F_FLT_MAX - 1L; /* similar to NaN */
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004421 else if (f1 < 0)
Bram Moolenaar314f11d2010-08-09 22:07:08 +02004422 f1 = -1 * __F_FLT_MAX;
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004423 else
Bram Moolenaar314f11d2010-08-09 22:07:08 +02004424 f1 = __F_FLT_MAX;
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004425 }
4426 else
4427 f1 = f1 / f2;
4428# else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004429 /* We rely on the floating point library to handle divide
4430 * by zero to result in "inf" and not a crash. */
4431 f1 = f1 / f2;
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004432# endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004433 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004434 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004435 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004436 emsg(_("E804: Cannot use '%' with Float"));
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004437 return FAIL;
4438 }
4439 rettv->v_type = VAR_FLOAT;
4440 rettv->vval.v_float = f1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004441 }
4442 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004443#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004444 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004445 if (op == '*')
4446 n1 = n1 * n2;
4447 else if (op == '/')
Bram Moolenaare21c1582019-03-02 11:57:09 +01004448 n1 = num_divide(n1, n2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004449 else
Bram Moolenaare21c1582019-03-02 11:57:09 +01004450 n1 = num_modulus(n1, n2);
4451
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004452 rettv->v_type = VAR_NUMBER;
4453 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004454 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004455 }
4456 }
4457
4458 return OK;
4459}
4460
4461/*
4462 * Handle sixth level expression:
4463 * number number constant
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004464 * 0zFFFFFFFF Blob constant
Bram Moolenaarbae0c162007-05-10 19:30:25 +00004465 * "string" string constant
4466 * 'string' literal string constant
Bram Moolenaar071d4272004-06-13 20:20:40 +00004467 * &option-name option value
4468 * @r register contents
4469 * identifier variable value
4470 * function() function call
4471 * $VAR environment variable
4472 * (expression) nested expression
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00004473 * [expr, expr] List
Bram Moolenaard5abb4c2019-07-13 22:46:10 +02004474 * {key: val, key: val} Dictionary
Bram Moolenaar4c6d9042019-07-16 22:04:02 +02004475 * #{key: val, key: val} Dictionary with literal keys
Bram Moolenaar071d4272004-06-13 20:20:40 +00004476 *
4477 * Also handle:
4478 * ! in front logical NOT
4479 * - in front unary minus
4480 * + in front unary plus (ignored)
Bram Moolenaar8c711452005-01-14 21:53:12 +00004481 * trailing [] subscript in String or List
4482 * trailing .name entry in Dictionary
Bram Moolenaarac92e252019-08-03 21:58:38 +02004483 * trailing ->name() method call
Bram Moolenaar071d4272004-06-13 20:20:40 +00004484 *
4485 * "arg" must point to the first non-white of the expression.
4486 * "arg" is advanced to the next non-white after the recognized expression.
4487 *
4488 * Return OK or FAIL.
4489 */
4490 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004491eval7(
4492 char_u **arg,
4493 typval_T *rettv,
4494 int evaluate,
4495 int want_string UNUSED) /* after "." operator */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004496{
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02004497 varnumber_T n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004498 int len;
4499 char_u *s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004500 char_u *start_leader, *end_leader;
4501 int ret = OK;
4502 char_u *alias;
4503
4504 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004505 * Initialise variable so that clear_tv() can't mistake this for a
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004506 * string and free a string that isn't there.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004507 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004508 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004509
4510 /*
Bram Moolenaaredf3f972016-08-29 22:49:24 +02004511 * Skip '!', '-' and '+' characters. They are handled later.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004512 */
4513 start_leader = *arg;
4514 while (**arg == '!' || **arg == '-' || **arg == '+')
4515 *arg = skipwhite(*arg + 1);
4516 end_leader = *arg;
4517
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004518 if (**arg == '.' && (!isdigit(*(*arg + 1))
4519#ifdef FEAT_FLOAT
4520 || current_sctx.sc_version < 2
4521#endif
4522 ))
4523 {
4524 semsg(_(e_invexpr2), *arg);
4525 ++*arg;
4526 return FAIL;
4527 }
4528
Bram Moolenaar071d4272004-06-13 20:20:40 +00004529 switch (**arg)
4530 {
4531 /*
4532 * Number constant.
4533 */
4534 case '0':
4535 case '1':
4536 case '2':
4537 case '3':
4538 case '4':
4539 case '5':
4540 case '6':
4541 case '7':
4542 case '8':
4543 case '9':
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004544 case '.':
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004545 {
4546#ifdef FEAT_FLOAT
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004547 char_u *p;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004548 int get_float = FALSE;
4549
4550 /* We accept a float when the format matches
4551 * "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004552 * strict to avoid backwards compatibility problems.
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004553 * With script version 2 and later the leading digit can be
4554 * omitted.
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004555 * Don't look for a float after the "." operator, so that
4556 * ":let vers = 1.2.3" doesn't fail. */
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004557 if (**arg == '.')
4558 p = *arg;
4559 else
4560 p = skipdigits(*arg + 1);
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004561 if (!want_string && p[0] == '.' && vim_isdigit(p[1]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004562 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004563 get_float = TRUE;
4564 p = skipdigits(p + 2);
4565 if (*p == 'e' || *p == 'E')
4566 {
4567 ++p;
4568 if (*p == '-' || *p == '+')
4569 ++p;
4570 if (!vim_isdigit(*p))
4571 get_float = FALSE;
4572 else
4573 p = skipdigits(p + 1);
4574 }
4575 if (ASCII_ISALPHA(*p) || *p == '.')
4576 get_float = FALSE;
4577 }
4578 if (get_float)
4579 {
4580 float_T f;
4581
4582 *arg += string2float(*arg, &f);
4583 if (evaluate)
4584 {
4585 rettv->v_type = VAR_FLOAT;
4586 rettv->vval.v_float = f;
4587 }
4588 }
4589 else
4590#endif
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004591 if (**arg == '0' && ((*arg)[1] == 'z' || (*arg)[1] == 'Z'))
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004592 {
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004593 char_u *bp;
Bram Moolenaare519dfd2019-01-13 15:42:02 +01004594 blob_T *blob = NULL; // init for gcc
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004595
4596 // Blob constant: 0z0123456789abcdef
4597 if (evaluate)
4598 blob = blob_alloc();
4599 for (bp = *arg + 2; vim_isxdigit(bp[0]); bp += 2)
4600 {
4601 if (!vim_isxdigit(bp[1]))
4602 {
Bram Moolenaarecc8bc42019-01-13 16:07:21 +01004603 if (blob != NULL)
4604 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004605 emsg(_("E973: Blob literal should have an even number of hex characters"));
Bram Moolenaarecc8bc42019-01-13 16:07:21 +01004606 ga_clear(&blob->bv_ga);
4607 VIM_CLEAR(blob);
4608 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004609 ret = FAIL;
4610 break;
4611 }
4612 if (blob != NULL)
4613 ga_append(&blob->bv_ga,
4614 (hex2nr(*bp) << 4) + hex2nr(*(bp+1)));
Bram Moolenaar4131fd52019-01-17 16:32:53 +01004615 if (bp[2] == '.' && vim_isxdigit(bp[3]))
4616 ++bp;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004617 }
4618 if (blob != NULL)
Bram Moolenaarecc8bc42019-01-13 16:07:21 +01004619 rettv_blob_set(rettv, blob);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004620 *arg = bp;
4621 }
4622 else
4623 {
4624 // decimal, hex or octal number
Bram Moolenaar16e9b852019-05-19 19:59:35 +02004625 vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0, TRUE);
4626 if (len == 0)
4627 {
4628 semsg(_(e_invexpr2), *arg);
4629 ret = FAIL;
4630 break;
4631 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004632 *arg += len;
4633 if (evaluate)
4634 {
4635 rettv->v_type = VAR_NUMBER;
4636 rettv->vval.v_number = n;
4637 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004638 }
4639 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004640 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004641
4642 /*
4643 * String constant: "string".
4644 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004645 case '"': ret = get_string_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004646 break;
4647
4648 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004649 * Literal string constant: 'str''ing'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004650 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004651 case '\'': ret = get_lit_string_tv(arg, rettv, evaluate);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004652 break;
4653
4654 /*
4655 * List: [expr, expr]
4656 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004657 case '[': ret = get_list_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004658 break;
4659
4660 /*
Bram Moolenaar4c6d9042019-07-16 22:04:02 +02004661 * Dictionary: #{key: val, key: val}
Bram Moolenaard5abb4c2019-07-13 22:46:10 +02004662 */
Bram Moolenaar4c6d9042019-07-16 22:04:02 +02004663 case '#': if ((*arg)[1] == '{')
Bram Moolenaard5abb4c2019-07-13 22:46:10 +02004664 {
4665 ++*arg;
4666 ret = dict_get_tv(arg, rettv, evaluate, TRUE);
4667 }
4668 else
4669 ret = NOTDONE;
4670 break;
4671
4672 /*
Bram Moolenaar069c1e72016-07-15 21:25:08 +02004673 * Lambda: {arg, arg -> expr}
Bram Moolenaard5abb4c2019-07-13 22:46:10 +02004674 * Dictionary: {'key': val, 'key': val}
Bram Moolenaar8c711452005-01-14 21:53:12 +00004675 */
Bram Moolenaar069c1e72016-07-15 21:25:08 +02004676 case '{': ret = get_lambda_tv(arg, rettv, evaluate);
4677 if (ret == NOTDONE)
Bram Moolenaard5abb4c2019-07-13 22:46:10 +02004678 ret = dict_get_tv(arg, rettv, evaluate, FALSE);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004679 break;
4680
4681 /*
Bram Moolenaare9a41262005-01-15 22:18:47 +00004682 * Option value: &name
Bram Moolenaar071d4272004-06-13 20:20:40 +00004683 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00004684 case '&': ret = get_option_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004685 break;
4686
4687 /*
4688 * Environment variable: $VAR.
4689 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004690 case '$': ret = get_env_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004691 break;
4692
4693 /*
4694 * Register contents: @r.
4695 */
4696 case '@': ++*arg;
4697 if (evaluate)
4698 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004699 rettv->v_type = VAR_STRING;
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +02004700 rettv->vval.v_string = get_reg_contents(**arg,
4701 GREG_EXPR_SRC);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004702 }
4703 if (**arg != NUL)
4704 ++*arg;
4705 break;
4706
4707 /*
4708 * nested expression: (expression).
4709 */
4710 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004711 ret = eval1(arg, rettv, evaluate); /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004712 if (**arg == ')')
4713 ++*arg;
4714 else if (ret == OK)
4715 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004716 emsg(_("E110: Missing ')'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004717 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004718 ret = FAIL;
4719 }
4720 break;
4721
Bram Moolenaar8c711452005-01-14 21:53:12 +00004722 default: ret = NOTDONE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004723 break;
4724 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004725
4726 if (ret == NOTDONE)
4727 {
4728 /*
4729 * Must be a variable or function name.
4730 * Can also be a curly-braces kind of name: {expr}.
4731 */
4732 s = *arg;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004733 len = get_name_len(arg, &alias, evaluate, TRUE);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004734 if (alias != NULL)
4735 s = alias;
4736
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004737 if (len <= 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00004738 ret = FAIL;
4739 else
4740 {
4741 if (**arg == '(') /* recursive! */
Bram Moolenaar761fdf02019-08-05 23:10:16 +02004742 ret = eval_func(arg, s, len, rettv, evaluate, NULL);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004743 else if (evaluate)
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02004744 ret = get_var_tv(s, len, rettv, NULL, TRUE, FALSE);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004745 else
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02004746 {
4747 check_vars(s, len);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004748 ret = OK;
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02004749 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004750 }
Bram Moolenaar3c2d6532011-02-01 13:48:53 +01004751 vim_free(alias);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004752 }
4753
Bram Moolenaar071d4272004-06-13 20:20:40 +00004754 *arg = skipwhite(*arg);
4755
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004756 /* Handle following '[', '(' and '.' for expr[expr], expr.name,
Bram Moolenaarfcfe1a92019-08-04 23:04:39 +02004757 * expr(expr), expr->name(expr) */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004758 if (ret == OK)
4759 ret = handle_subscript(arg, rettv, evaluate, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004760
4761 /*
4762 * Apply logical NOT and unary '-', from right to left, ignore '+'.
4763 */
4764 if (ret == OK && evaluate && end_leader > start_leader)
4765 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004766 int error = FALSE;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02004767 varnumber_T val = 0;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004768#ifdef FEAT_FLOAT
4769 float_T f = 0.0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004770
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004771 if (rettv->v_type == VAR_FLOAT)
4772 f = rettv->vval.v_float;
4773 else
4774#endif
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004775 val = tv_get_number_chk(rettv, &error);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004776 if (error)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004777 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004778 clear_tv(rettv);
4779 ret = FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004780 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004781 else
4782 {
4783 while (end_leader > start_leader)
4784 {
4785 --end_leader;
4786 if (*end_leader == '!')
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004787 {
4788#ifdef FEAT_FLOAT
4789 if (rettv->v_type == VAR_FLOAT)
4790 f = !f;
4791 else
4792#endif
4793 val = !val;
4794 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004795 else if (*end_leader == '-')
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004796 {
4797#ifdef FEAT_FLOAT
4798 if (rettv->v_type == VAR_FLOAT)
4799 f = -f;
4800 else
4801#endif
4802 val = -val;
4803 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004804 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004805#ifdef FEAT_FLOAT
4806 if (rettv->v_type == VAR_FLOAT)
4807 {
4808 clear_tv(rettv);
4809 rettv->vval.v_float = f;
4810 }
4811 else
4812#endif
4813 {
4814 clear_tv(rettv);
4815 rettv->v_type = VAR_NUMBER;
4816 rettv->vval.v_number = val;
4817 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004818 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004819 }
4820
4821 return ret;
4822}
4823
4824/*
Bram Moolenaarac92e252019-08-03 21:58:38 +02004825 * Evaluate "->method()".
4826 * "*arg" points to the '-'.
4827 * Returns FAIL or OK. "*arg" is advanced to after the ')'.
4828 */
4829 static int
4830eval_method(
4831 char_u **arg,
4832 typval_T *rettv,
4833 int evaluate,
4834 int verbose) /* give error messages */
4835{
4836 char_u *name;
4837 long len;
Bram Moolenaar761fdf02019-08-05 23:10:16 +02004838 char_u *alias;
Bram Moolenaarac92e252019-08-03 21:58:38 +02004839 typval_T base = *rettv;
Bram Moolenaar761fdf02019-08-05 23:10:16 +02004840 int ret;
Bram Moolenaarac92e252019-08-03 21:58:38 +02004841
4842 // Skip over the ->.
4843 *arg += 2;
Bram Moolenaar761fdf02019-08-05 23:10:16 +02004844 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaarac92e252019-08-03 21:58:38 +02004845
Bram Moolenaarac92e252019-08-03 21:58:38 +02004846 name = *arg;
Bram Moolenaar761fdf02019-08-05 23:10:16 +02004847 len = get_name_len(arg, &alias, evaluate, TRUE);
4848 if (alias != NULL)
4849 name = alias;
4850
4851 if (len <= 0)
Bram Moolenaarac92e252019-08-03 21:58:38 +02004852 {
4853 if (verbose)
4854 emsg(_("E260: Missing name after ->"));
Bram Moolenaar761fdf02019-08-05 23:10:16 +02004855 ret = FAIL;
Bram Moolenaarac92e252019-08-03 21:58:38 +02004856 }
Bram Moolenaar761fdf02019-08-05 23:10:16 +02004857 else
Bram Moolenaarac92e252019-08-03 21:58:38 +02004858 {
Bram Moolenaar761fdf02019-08-05 23:10:16 +02004859 if (**arg != '(')
4860 {
4861 if (verbose)
4862 semsg(_(e_missingparen), name);
4863 ret = FAIL;
4864 }
4865 else
4866 ret = eval_func(arg, name, len, rettv, evaluate, &base);
Bram Moolenaarac92e252019-08-03 21:58:38 +02004867 }
Bram Moolenaarac92e252019-08-03 21:58:38 +02004868
4869 /* Clear the funcref afterwards, so that deleting it while
4870 * evaluating the arguments is possible (see test55). */
4871 if (evaluate)
4872 clear_tv(&base);
4873
Bram Moolenaarac92e252019-08-03 21:58:38 +02004874 return ret;
4875}
4876
4877/*
Bram Moolenaar9e54a0e2006-04-14 20:42:25 +00004878 * Evaluate an "[expr]" or "[expr:expr]" index. Also "dict.key".
4879 * "*arg" points to the '[' or '.'.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004880 * Returns FAIL or OK. "*arg" is advanced to after the ']'.
4881 */
4882 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004883eval_index(
4884 char_u **arg,
4885 typval_T *rettv,
4886 int evaluate,
4887 int verbose) /* give error messages */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004888{
4889 int empty1 = FALSE, empty2 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00004890 typval_T var1, var2;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004891 long i;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004892 long n1, n2 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004893 long len = -1;
4894 int range = FALSE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004895 char_u *s;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004896 char_u *key = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004897
Bram Moolenaara03f2332016-02-06 18:09:59 +01004898 switch (rettv->v_type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004899 {
Bram Moolenaara03f2332016-02-06 18:09:59 +01004900 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01004901 case VAR_PARTIAL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01004902 if (verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004903 emsg(_("E695: Cannot index a Funcref"));
Bram Moolenaara03f2332016-02-06 18:09:59 +01004904 return FAIL;
4905 case VAR_FLOAT:
Bram Moolenaar2a876e42013-06-12 22:08:58 +02004906#ifdef FEAT_FLOAT
Bram Moolenaara03f2332016-02-06 18:09:59 +01004907 if (verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004908 emsg(_(e_float_as_string));
Bram Moolenaara03f2332016-02-06 18:09:59 +01004909 return FAIL;
Bram Moolenaar2a876e42013-06-12 22:08:58 +02004910#endif
Bram Moolenaara03f2332016-02-06 18:09:59 +01004911 case VAR_SPECIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01004912 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01004913 case VAR_CHANNEL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01004914 if (verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004915 emsg(_("E909: Cannot index a special variable"));
Bram Moolenaara03f2332016-02-06 18:09:59 +01004916 return FAIL;
4917 case VAR_UNKNOWN:
4918 if (evaluate)
4919 return FAIL;
4920 /* FALLTHROUGH */
4921
4922 case VAR_STRING:
4923 case VAR_NUMBER:
4924 case VAR_LIST:
4925 case VAR_DICT:
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004926 case VAR_BLOB:
Bram Moolenaara03f2332016-02-06 18:09:59 +01004927 break;
Bram Moolenaar520e1e42016-01-23 19:46:28 +01004928 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004929
Bram Moolenaar0a38dd22015-08-25 16:49:01 +02004930 init_tv(&var1);
4931 init_tv(&var2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004932 if (**arg == '.')
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004933 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004934 /*
4935 * dict.name
4936 */
4937 key = *arg + 1;
4938 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
4939 ;
4940 if (len == 0)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004941 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004942 *arg = skipwhite(key + len);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004943 }
4944 else
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004945 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004946 /*
4947 * something[idx]
4948 *
4949 * Get the (first) variable from inside the [].
4950 */
4951 *arg = skipwhite(*arg + 1);
4952 if (**arg == ':')
4953 empty1 = TRUE;
4954 else if (eval1(arg, &var1, evaluate) == FAIL) /* recursive! */
4955 return FAIL;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004956 else if (evaluate && tv_get_string_chk(&var1) == NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004957 {
4958 /* not a number or string */
4959 clear_tv(&var1);
4960 return FAIL;
4961 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004962
4963 /*
4964 * Get the second variable from inside the [:].
4965 */
4966 if (**arg == ':')
4967 {
4968 range = TRUE;
4969 *arg = skipwhite(*arg + 1);
4970 if (**arg == ']')
4971 empty2 = TRUE;
4972 else if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */
4973 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004974 if (!empty1)
4975 clear_tv(&var1);
4976 return FAIL;
4977 }
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004978 else if (evaluate && tv_get_string_chk(&var2) == NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004979 {
4980 /* not a number or string */
4981 if (!empty1)
4982 clear_tv(&var1);
4983 clear_tv(&var2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004984 return FAIL;
4985 }
4986 }
4987
4988 /* Check for the ']'. */
4989 if (**arg != ']')
4990 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004991 if (verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004992 emsg(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004993 clear_tv(&var1);
4994 if (range)
4995 clear_tv(&var2);
4996 return FAIL;
4997 }
4998 *arg = skipwhite(*arg + 1); /* skip the ']' */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004999 }
5000
5001 if (evaluate)
5002 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005003 n1 = 0;
5004 if (!empty1 && rettv->v_type != VAR_DICT)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005005 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01005006 n1 = tv_get_number(&var1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005007 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005008 }
5009 if (range)
5010 {
5011 if (empty2)
5012 n2 = -1;
5013 else
5014 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01005015 n2 = tv_get_number(&var2);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005016 clear_tv(&var2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005017 }
5018 }
5019
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005020 switch (rettv->v_type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005021 {
Bram Moolenaar835dc632016-02-07 14:27:38 +01005022 case VAR_UNKNOWN:
Bram Moolenaara03f2332016-02-06 18:09:59 +01005023 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01005024 case VAR_PARTIAL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01005025 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01005026 case VAR_SPECIAL:
5027 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01005028 case VAR_CHANNEL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01005029 break; /* not evaluating, skipping over subscript */
5030
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005031 case VAR_NUMBER:
5032 case VAR_STRING:
Bram Moolenaard155d7a2018-12-21 16:04:21 +01005033 s = tv_get_string(rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005034 len = (long)STRLEN(s);
5035 if (range)
5036 {
5037 /* The resulting variable is a substring. If the indexes
5038 * are out of range the result is empty. */
5039 if (n1 < 0)
5040 {
5041 n1 = len + n1;
5042 if (n1 < 0)
5043 n1 = 0;
5044 }
5045 if (n2 < 0)
5046 n2 = len + n2;
5047 else if (n2 >= len)
5048 n2 = len;
5049 if (n1 >= len || n2 < 0 || n1 > n2)
5050 s = NULL;
5051 else
5052 s = vim_strnsave(s + n1, (int)(n2 - n1 + 1));
5053 }
5054 else
5055 {
5056 /* The resulting variable is a string of a single
5057 * character. If the index is too big or negative the
5058 * result is empty. */
5059 if (n1 >= len || n1 < 0)
5060 s = NULL;
5061 else
5062 s = vim_strnsave(s + n1, 1);
5063 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005064 clear_tv(rettv);
5065 rettv->v_type = VAR_STRING;
5066 rettv->vval.v_string = s;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005067 break;
5068
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01005069 case VAR_BLOB:
5070 len = blob_len(rettv->vval.v_blob);
5071 if (range)
5072 {
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01005073 // The resulting variable is a sub-blob. If the indexes
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01005074 // are out of range the result is empty.
5075 if (n1 < 0)
5076 {
5077 n1 = len + n1;
5078 if (n1 < 0)
5079 n1 = 0;
5080 }
5081 if (n2 < 0)
5082 n2 = len + n2;
5083 else if (n2 >= len)
5084 n2 = len - 1;
5085 if (n1 >= len || n2 < 0 || n1 > n2)
5086 {
5087 clear_tv(rettv);
5088 rettv->v_type = VAR_BLOB;
5089 rettv->vval.v_blob = NULL;
5090 }
5091 else
5092 {
5093 blob_T *blob = blob_alloc();
5094
5095 if (blob != NULL)
5096 {
5097 if (ga_grow(&blob->bv_ga, n2 - n1 + 1) == FAIL)
5098 {
5099 blob_free(blob);
5100 return FAIL;
5101 }
5102 blob->bv_ga.ga_len = n2 - n1 + 1;
5103 for (i = n1; i <= n2; i++)
5104 blob_set(blob, i - n1,
5105 blob_get(rettv->vval.v_blob, i));
5106
5107 clear_tv(rettv);
5108 rettv_blob_set(rettv, blob);
5109 }
5110 }
5111 }
5112 else
5113 {
Bram Moolenaara5be9b62019-01-24 12:31:44 +01005114 // The resulting variable is a byte value.
5115 // If the index is too big or negative that is an error.
5116 if (n1 < 0)
5117 n1 = len + n1;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01005118 if (n1 < len && n1 >= 0)
5119 {
Bram Moolenaara5be9b62019-01-24 12:31:44 +01005120 int v = blob_get(rettv->vval.v_blob, n1);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01005121
5122 clear_tv(rettv);
5123 rettv->v_type = VAR_NUMBER;
5124 rettv->vval.v_number = v;
5125 }
5126 else
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005127 semsg(_(e_blobidx), n1);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01005128 }
5129 break;
5130
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005131 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005132 len = list_len(rettv->vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005133 if (n1 < 0)
5134 n1 = len + n1;
5135 if (!empty1 && (n1 < 0 || n1 >= len))
5136 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00005137 /* For a range we allow invalid values and return an empty
5138 * list. A list index out of range is an error. */
5139 if (!range)
5140 {
5141 if (verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005142 semsg(_(e_listidx), n1);
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00005143 return FAIL;
5144 }
5145 n1 = len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005146 }
5147 if (range)
5148 {
Bram Moolenaar33570922005-01-25 22:26:29 +00005149 list_T *l;
5150 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005151
5152 if (n2 < 0)
5153 n2 = len + n2;
Bram Moolenaar9e54a0e2006-04-14 20:42:25 +00005154 else if (n2 >= len)
5155 n2 = len - 1;
5156 if (!empty2 && (n2 < 0 || n2 + 1 < n1))
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00005157 n2 = -1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005158 l = list_alloc();
5159 if (l == NULL)
5160 return FAIL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005161 for (item = list_find(rettv->vval.v_list, n1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005162 n1 <= n2; ++n1)
5163 {
5164 if (list_append_tv(l, &item->li_tv) == FAIL)
5165 {
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005166 list_free(l);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005167 return FAIL;
5168 }
5169 item = item->li_next;
5170 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005171 clear_tv(rettv);
Bram Moolenaar45cf6e92017-04-30 20:25:19 +02005172 rettv_list_set(rettv, l);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005173 }
5174 else
5175 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00005176 copy_tv(&list_find(rettv->vval.v_list, n1)->li_tv, &var1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005177 clear_tv(rettv);
5178 *rettv = var1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005179 }
5180 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005181
5182 case VAR_DICT:
5183 if (range)
5184 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005185 if (verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005186 emsg(_(e_dictrange));
Bram Moolenaar8c711452005-01-14 21:53:12 +00005187 if (len == -1)
5188 clear_tv(&var1);
5189 return FAIL;
5190 }
5191 {
Bram Moolenaar33570922005-01-25 22:26:29 +00005192 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005193
5194 if (len == -1)
5195 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01005196 key = tv_get_string_chk(&var1);
Bram Moolenaar0921ecf2016-04-03 22:44:36 +02005197 if (key == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005198 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005199 clear_tv(&var1);
5200 return FAIL;
5201 }
5202 }
5203
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005204 item = dict_find(rettv->vval.v_dict, key, (int)len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005205
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005206 if (item == NULL && verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005207 semsg(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005208 if (len == -1)
5209 clear_tv(&var1);
5210 if (item == NULL)
5211 return FAIL;
5212
5213 copy_tv(&item->di_tv, &var1);
5214 clear_tv(rettv);
5215 *rettv = var1;
5216 }
5217 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005218 }
5219 }
5220
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005221 return OK;
5222}
5223
5224/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005225 * Get an option value.
5226 * "arg" points to the '&' or '+' before the option name.
5227 * "arg" is advanced to character after the option name.
5228 * Return OK or FAIL.
5229 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005230 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005231get_option_tv(
5232 char_u **arg,
5233 typval_T *rettv, /* when NULL, only check if option exists */
5234 int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005235{
5236 char_u *option_end;
5237 long numval;
5238 char_u *stringval;
5239 int opt_type;
5240 int c;
5241 int working = (**arg == '+'); /* has("+option") */
5242 int ret = OK;
5243 int opt_flags;
5244
5245 /*
5246 * Isolate the option name and find its value.
5247 */
5248 option_end = find_option_end(arg, &opt_flags);
5249 if (option_end == NULL)
5250 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005251 if (rettv != NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005252 semsg(_("E112: Option name missing: %s"), *arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005253 return FAIL;
5254 }
5255
5256 if (!evaluate)
5257 {
5258 *arg = option_end;
5259 return OK;
5260 }
5261
5262 c = *option_end;
5263 *option_end = NUL;
5264 opt_type = get_option_value(*arg, &numval,
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005265 rettv == NULL ? NULL : &stringval, opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005266
5267 if (opt_type == -3) /* invalid name */
5268 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005269 if (rettv != NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005270 semsg(_("E113: Unknown option: %s"), *arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005271 ret = FAIL;
5272 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005273 else if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005274 {
5275 if (opt_type == -2) /* hidden string option */
5276 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005277 rettv->v_type = VAR_STRING;
5278 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005279 }
5280 else if (opt_type == -1) /* hidden number option */
5281 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005282 rettv->v_type = VAR_NUMBER;
5283 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005284 }
5285 else if (opt_type == 1) /* number option */
5286 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005287 rettv->v_type = VAR_NUMBER;
5288 rettv->vval.v_number = numval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005289 }
5290 else /* string option */
5291 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005292 rettv->v_type = VAR_STRING;
5293 rettv->vval.v_string = stringval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005294 }
5295 }
5296 else if (working && (opt_type == -2 || opt_type == -1))
5297 ret = FAIL;
5298
5299 *option_end = c; /* put back for error messages */
5300 *arg = option_end;
5301
5302 return ret;
5303}
5304
5305/*
5306 * Allocate a variable for a string constant.
5307 * Return OK or FAIL.
5308 */
5309 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005310get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005311{
5312 char_u *p;
5313 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005314 int extra = 0;
5315
5316 /*
5317 * Find the end of the string, skipping backslashed characters.
5318 */
Bram Moolenaar91acfff2017-03-12 19:22:36 +01005319 for (p = *arg + 1; *p != NUL && *p != '"'; MB_PTR_ADV(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005320 {
5321 if (*p == '\\' && p[1] != NUL)
5322 {
5323 ++p;
5324 /* A "\<x>" form occupies at least 4 characters, and produces up
5325 * to 6 characters: reserve space for 2 extra */
5326 if (*p == '<')
5327 extra += 2;
5328 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005329 }
5330
5331 if (*p != '"')
5332 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005333 semsg(_("E114: Missing quote: %s"), *arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005334 return FAIL;
5335 }
5336
5337 /* If only parsing, set *arg and return here */
5338 if (!evaluate)
5339 {
5340 *arg = p + 1;
5341 return OK;
5342 }
5343
5344 /*
5345 * Copy the string into allocated memory, handling backslashed
5346 * characters.
5347 */
Bram Moolenaar964b3742019-05-24 18:54:09 +02005348 name = alloc(p - *arg + extra);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005349 if (name == NULL)
5350 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005351 rettv->v_type = VAR_STRING;
5352 rettv->vval.v_string = name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005353
Bram Moolenaar8c711452005-01-14 21:53:12 +00005354 for (p = *arg + 1; *p != NUL && *p != '"'; )
Bram Moolenaar071d4272004-06-13 20:20:40 +00005355 {
5356 if (*p == '\\')
5357 {
5358 switch (*++p)
5359 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005360 case 'b': *name++ = BS; ++p; break;
5361 case 'e': *name++ = ESC; ++p; break;
5362 case 'f': *name++ = FF; ++p; break;
5363 case 'n': *name++ = NL; ++p; break;
5364 case 'r': *name++ = CAR; ++p; break;
5365 case 't': *name++ = TAB; ++p; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005366
5367 case 'X': /* hex: "\x1", "\x12" */
5368 case 'x':
5369 case 'u': /* Unicode: "\u0023" */
5370 case 'U':
5371 if (vim_isxdigit(p[1]))
5372 {
5373 int n, nr;
5374 int c = toupper(*p);
5375
5376 if (c == 'X')
5377 n = 2;
Bram Moolenaaracc39882015-06-19 12:08:13 +02005378 else if (*p == 'u')
Bram Moolenaar071d4272004-06-13 20:20:40 +00005379 n = 4;
Bram Moolenaaracc39882015-06-19 12:08:13 +02005380 else
5381 n = 8;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005382 nr = 0;
5383 while (--n >= 0 && vim_isxdigit(p[1]))
5384 {
5385 ++p;
5386 nr = (nr << 4) + hex2nr(*p);
5387 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005388 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005389 /* For "\u" store the number according to
5390 * 'encoding'. */
5391 if (c != 'X')
Bram Moolenaar8c711452005-01-14 21:53:12 +00005392 name += (*mb_char2bytes)(nr, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005393 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00005394 *name++ = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005395 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005396 break;
5397
5398 /* octal: "\1", "\12", "\123" */
5399 case '0':
5400 case '1':
5401 case '2':
5402 case '3':
5403 case '4':
5404 case '5':
5405 case '6':
Bram Moolenaar8c711452005-01-14 21:53:12 +00005406 case '7': *name = *p++ - '0';
5407 if (*p >= '0' && *p <= '7')
Bram Moolenaar071d4272004-06-13 20:20:40 +00005408 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005409 *name = (*name << 3) + *p++ - '0';
5410 if (*p >= '0' && *p <= '7')
5411 *name = (*name << 3) + *p++ - '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +00005412 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005413 ++name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005414 break;
5415
5416 /* Special key, e.g.: "\<C-W>" */
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +02005417 case '<': extra = trans_special(&p, name, TRUE, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005418 if (extra != 0)
5419 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005420 name += extra;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005421 break;
5422 }
5423 /* FALLTHROUGH */
5424
Bram Moolenaar8c711452005-01-14 21:53:12 +00005425 default: MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005426 break;
5427 }
5428 }
5429 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00005430 MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005431
Bram Moolenaar071d4272004-06-13 20:20:40 +00005432 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005433 *name = NUL;
Bram Moolenaardb249f22016-08-26 16:29:47 +02005434 if (*p != NUL) /* just in case */
5435 ++p;
5436 *arg = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005437
Bram Moolenaar071d4272004-06-13 20:20:40 +00005438 return OK;
5439}
5440
5441/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005442 * Allocate a variable for a 'str''ing' constant.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005443 * Return OK or FAIL.
5444 */
5445 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005446get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005447{
5448 char_u *p;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005449 char_u *str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005450 int reduce = 0;
5451
5452 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005453 * Find the end of the string, skipping ''.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005454 */
Bram Moolenaar91acfff2017-03-12 19:22:36 +01005455 for (p = *arg + 1; *p != NUL; MB_PTR_ADV(p))
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005456 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005457 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005458 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005459 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005460 break;
5461 ++reduce;
5462 ++p;
5463 }
5464 }
5465
Bram Moolenaar8c711452005-01-14 21:53:12 +00005466 if (*p != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005467 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005468 semsg(_("E115: Missing quote: %s"), *arg);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005469 return FAIL;
5470 }
5471
Bram Moolenaar8c711452005-01-14 21:53:12 +00005472 /* If only parsing return after setting "*arg" */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005473 if (!evaluate)
5474 {
5475 *arg = p + 1;
5476 return OK;
5477 }
5478
5479 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005480 * Copy the string into allocated memory, handling '' to ' reduction.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005481 */
Bram Moolenaar964b3742019-05-24 18:54:09 +02005482 str = alloc((p - *arg) - reduce);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005483 if (str == NULL)
5484 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005485 rettv->v_type = VAR_STRING;
5486 rettv->vval.v_string = str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005487
Bram Moolenaar8c711452005-01-14 21:53:12 +00005488 for (p = *arg + 1; *p != NUL; )
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005489 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005490 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005491 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005492 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005493 break;
5494 ++p;
5495 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005496 MB_COPY_CHAR(p, str);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005497 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005498 *str = NUL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005499 *arg = p + 1;
5500
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005501 return OK;
5502}
5503
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005504/*
5505 * Return the function name of the partial.
5506 */
5507 char_u *
5508partial_name(partial_T *pt)
5509{
5510 if (pt->pt_name != NULL)
5511 return pt->pt_name;
5512 return pt->pt_func->uf_name;
5513}
5514
Bram Moolenaarddecc252016-04-06 22:59:37 +02005515 static void
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005516partial_free(partial_T *pt)
Bram Moolenaarddecc252016-04-06 22:59:37 +02005517{
5518 int i;
5519
5520 for (i = 0; i < pt->pt_argc; ++i)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005521 clear_tv(&pt->pt_argv[i]);
Bram Moolenaarddecc252016-04-06 22:59:37 +02005522 vim_free(pt->pt_argv);
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005523 dict_unref(pt->pt_dict);
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005524 if (pt->pt_name != NULL)
5525 {
5526 func_unref(pt->pt_name);
5527 vim_free(pt->pt_name);
5528 }
5529 else
5530 func_ptr_unref(pt->pt_func);
Bram Moolenaarddecc252016-04-06 22:59:37 +02005531 vim_free(pt);
5532}
5533
5534/*
5535 * Unreference a closure: decrement the reference count and free it when it
5536 * becomes zero.
5537 */
5538 void
5539partial_unref(partial_T *pt)
5540{
5541 if (pt != NULL && --pt->pt_refcount <= 0)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005542 partial_free(pt);
Bram Moolenaarddecc252016-04-06 22:59:37 +02005543}
5544
Bram Moolenaar67b3f992010-11-10 20:41:57 +01005545static int tv_equal_recurse_limit;
5546
Bram Moolenaar8e759ba2016-06-02 17:46:20 +02005547 static int
5548func_equal(
5549 typval_T *tv1,
5550 typval_T *tv2,
5551 int ic) /* ignore case */
5552{
5553 char_u *s1, *s2;
5554 dict_T *d1, *d2;
5555 int a1, a2;
5556 int i;
5557
5558 /* empty and NULL function name considered the same */
5559 s1 = tv1->v_type == VAR_FUNC ? tv1->vval.v_string
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005560 : partial_name(tv1->vval.v_partial);
Bram Moolenaar8e759ba2016-06-02 17:46:20 +02005561 if (s1 != NULL && *s1 == NUL)
5562 s1 = NULL;
5563 s2 = tv2->v_type == VAR_FUNC ? tv2->vval.v_string
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005564 : partial_name(tv2->vval.v_partial);
Bram Moolenaar8e759ba2016-06-02 17:46:20 +02005565 if (s2 != NULL && *s2 == NUL)
5566 s2 = NULL;
5567 if (s1 == NULL || s2 == NULL)
5568 {
5569 if (s1 != s2)
5570 return FALSE;
5571 }
5572 else if (STRCMP(s1, s2) != 0)
5573 return FALSE;
5574
5575 /* empty dict and NULL dict is different */
5576 d1 = tv1->v_type == VAR_FUNC ? NULL : tv1->vval.v_partial->pt_dict;
5577 d2 = tv2->v_type == VAR_FUNC ? NULL : tv2->vval.v_partial->pt_dict;
5578 if (d1 == NULL || d2 == NULL)
5579 {
5580 if (d1 != d2)
5581 return FALSE;
5582 }
5583 else if (!dict_equal(d1, d2, ic, TRUE))
5584 return FALSE;
5585
5586 /* empty list and no list considered the same */
5587 a1 = tv1->v_type == VAR_FUNC ? 0 : tv1->vval.v_partial->pt_argc;
5588 a2 = tv2->v_type == VAR_FUNC ? 0 : tv2->vval.v_partial->pt_argc;
5589 if (a1 != a2)
5590 return FALSE;
5591 for (i = 0; i < a1; ++i)
5592 if (!tv_equal(tv1->vval.v_partial->pt_argv + i,
5593 tv2->vval.v_partial->pt_argv + i, ic, TRUE))
5594 return FALSE;
5595
5596 return TRUE;
5597}
5598
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005599/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005600 * Return TRUE if "tv1" and "tv2" have the same value.
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005601 * Compares the items just like "==" would compare them, but strings and
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005602 * numbers are different. Floats and numbers are also different.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005603 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02005604 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005605tv_equal(
5606 typval_T *tv1,
5607 typval_T *tv2,
5608 int ic, /* ignore case */
5609 int recursive) /* TRUE when used recursively */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005610{
5611 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005612 char_u *s1, *s2;
Bram Moolenaar67b3f992010-11-10 20:41:57 +01005613 static int recursive_cnt = 0; /* catch recursive loops */
Bram Moolenaarb47a2402006-10-15 13:09:12 +00005614 int r;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005615
Bram Moolenaar8b402a02006-10-17 13:16:39 +00005616 /* Catch lists and dicts that have an endless loop by limiting
Bram Moolenaar67b3f992010-11-10 20:41:57 +01005617 * recursiveness to a limit. We guess they are equal then.
5618 * A fixed limit has the problem of still taking an awful long time.
5619 * Reduce the limit every time running into it. That should work fine for
5620 * deeply linked structures that are not recursively linked and catch
5621 * recursiveness quickly. */
5622 if (!recursive)
5623 tv_equal_recurse_limit = 1000;
5624 if (recursive_cnt >= tv_equal_recurse_limit)
5625 {
5626 --tv_equal_recurse_limit;
Bram Moolenaar8b402a02006-10-17 13:16:39 +00005627 return TRUE;
Bram Moolenaar67b3f992010-11-10 20:41:57 +01005628 }
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005629
Bram Moolenaarb33c7eb2016-07-04 22:29:49 +02005630 /* For VAR_FUNC and VAR_PARTIAL compare the function name, bound dict and
5631 * arguments. */
Bram Moolenaar8e759ba2016-06-02 17:46:20 +02005632 if ((tv1->v_type == VAR_FUNC
5633 || (tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial != NULL))
5634 && (tv2->v_type == VAR_FUNC
5635 || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial != NULL)))
5636 {
5637 ++recursive_cnt;
5638 r = func_equal(tv1, tv2, ic);
5639 --recursive_cnt;
5640 return r;
5641 }
5642
5643 if (tv1->v_type != tv2->v_type)
5644 return FALSE;
5645
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005646 switch (tv1->v_type)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005647 {
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005648 case VAR_LIST:
Bram Moolenaar67b3f992010-11-10 20:41:57 +01005649 ++recursive_cnt;
5650 r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic, TRUE);
5651 --recursive_cnt;
Bram Moolenaarb47a2402006-10-15 13:09:12 +00005652 return r;
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005653
5654 case VAR_DICT:
Bram Moolenaar67b3f992010-11-10 20:41:57 +01005655 ++recursive_cnt;
5656 r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, TRUE);
5657 --recursive_cnt;
Bram Moolenaarb47a2402006-10-15 13:09:12 +00005658 return r;
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005659
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01005660 case VAR_BLOB:
5661 return blob_equal(tv1->vval.v_blob, tv2->vval.v_blob);
5662
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005663 case VAR_NUMBER:
5664 return tv1->vval.v_number == tv2->vval.v_number;
5665
5666 case VAR_STRING:
Bram Moolenaard155d7a2018-12-21 16:04:21 +01005667 s1 = tv_get_string_buf(tv1, buf1);
5668 s2 = tv_get_string_buf(tv2, buf2);
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005669 return ((ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2)) == 0);
Bram Moolenaar520e1e42016-01-23 19:46:28 +01005670
5671 case VAR_SPECIAL:
5672 return tv1->vval.v_number == tv2->vval.v_number;
Bram Moolenaar835dc632016-02-07 14:27:38 +01005673
5674 case VAR_FLOAT:
5675#ifdef FEAT_FLOAT
5676 return tv1->vval.v_float == tv2->vval.v_float;
5677#endif
5678 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01005679#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +01005680 return tv1->vval.v_job == tv2->vval.v_job;
5681#endif
Bram Moolenaar77073442016-02-13 23:23:53 +01005682 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01005683#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +01005684 return tv1->vval.v_channel == tv2->vval.v_channel;
5685#endif
Bram Moolenaarf0e86a02016-03-19 19:38:12 +01005686 case VAR_FUNC:
5687 case VAR_PARTIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01005688 case VAR_UNKNOWN:
5689 break;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005690 }
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005691
Bram Moolenaara03f2332016-02-06 18:09:59 +01005692 /* VAR_UNKNOWN can be the result of a invalid expression, let's say it
5693 * does not equal anything, not even itself. */
5694 return FALSE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005695}
5696
5697/*
Bram Moolenaar520e1e42016-01-23 19:46:28 +01005698 * Return the next (unique) copy ID.
5699 * Used for serializing nested structures.
5700 */
5701 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005702get_copyID(void)
Bram Moolenaar520e1e42016-01-23 19:46:28 +01005703{
5704 current_copyID += COPYID_INC;
5705 return current_copyID;
5706}
5707
5708/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005709 * Garbage collection for lists and dictionaries.
5710 *
5711 * We use reference counts to be able to free most items right away when they
5712 * are no longer used. But for composite items it's possible that it becomes
5713 * unused while the reference count is > 0: When there is a recursive
5714 * reference. Example:
5715 * :let l = [1, 2, 3]
5716 * :let d = {9: l}
5717 * :let l[1] = d
5718 *
5719 * Since this is quite unusual we handle this with garbage collection: every
5720 * once in a while find out which lists and dicts are not referenced from any
5721 * variable.
5722 *
5723 * Here is a good reference text about garbage collection (refers to Python
5724 * but it applies to all reference-counting mechanisms):
5725 * http://python.ca/nas/python/gc/
Bram Moolenaard9fba312005-06-26 22:34:35 +00005726 */
Bram Moolenaard9fba312005-06-26 22:34:35 +00005727
5728/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005729 * Do garbage collection for lists and dicts.
Bram Moolenaar574860b2016-05-24 17:33:34 +02005730 * When "testing" is TRUE this is called from test_garbagecollect_now().
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005731 * Return TRUE if some memory was freed.
Bram Moolenaard9fba312005-06-26 22:34:35 +00005732 */
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005733 int
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +02005734garbage_collect(int testing)
Bram Moolenaard9fba312005-06-26 22:34:35 +00005735{
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005736 int copyID;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005737 int abort = FALSE;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005738 buf_T *buf;
5739 win_T *wp;
5740 int i;
Bram Moolenaar934b1362015-02-04 23:06:45 +01005741 int did_free = FALSE;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00005742 tabpage_T *tp;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005743
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +02005744 if (!testing)
5745 {
5746 /* Only do this once. */
5747 want_garbage_collect = FALSE;
5748 may_garbage_collect = FALSE;
5749 garbage_collect_at_exit = FALSE;
5750 }
Bram Moolenaar9fecb462006-09-05 10:59:47 +00005751
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005752 /* We advance by two because we add one for items referenced through
5753 * previous_funccal. */
Bram Moolenaar520e1e42016-01-23 19:46:28 +01005754 copyID = get_copyID();
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005755
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005756 /*
5757 * 1. Go through all accessible variables and mark all lists and dicts
5758 * with copyID.
5759 */
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005760
5761 /* Don't free variables in the previous_funccal list unless they are only
5762 * referenced through previous_funccal. This must be first, because if
Bram Moolenaar2c2398c2009-06-03 11:22:45 +00005763 * the item is referenced elsewhere the funccal must not be freed. */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02005764 abort = abort || set_ref_in_previous_funccal(copyID);
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005765
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005766 /* script-local variables */
5767 for (i = 1; i <= ga_scripts.ga_len; ++i)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005768 abort = abort || set_ref_in_ht(&SCRIPT_VARS(i), copyID, NULL);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005769
5770 /* buffer-local variables */
Bram Moolenaar29323592016-07-24 22:04:11 +02005771 FOR_ALL_BUFFERS(buf)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005772 abort = abort || set_ref_in_item(&buf->b_bufvar.di_tv, copyID,
5773 NULL, NULL);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005774
5775 /* window-local variables */
Bram Moolenaar910f66f2006-04-05 20:41:53 +00005776 FOR_ALL_TAB_WINDOWS(tp, wp)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005777 abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
5778 NULL, NULL);
Bram Moolenaar3bb28552013-04-15 18:25:59 +02005779 if (aucmd_win != NULL)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005780 abort = abort || set_ref_in_item(&aucmd_win->w_winvar.di_tv, copyID,
5781 NULL, NULL);
Bram Moolenaar4d784b22019-05-25 19:51:39 +02005782#ifdef FEAT_TEXT_PROP
5783 for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
5784 abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
5785 NULL, NULL);
Bram Moolenaar4d784b22019-05-25 19:51:39 +02005786 FOR_ALL_TABPAGES(tp)
Bram Moolenaar9c27b1c2019-05-26 18:48:13 +02005787 for (wp = tp->tp_first_popupwin; wp != NULL; wp = wp->w_next)
Bram Moolenaar4d784b22019-05-25 19:51:39 +02005788 abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
5789 NULL, NULL);
5790#endif
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005791
Bram Moolenaar910f66f2006-04-05 20:41:53 +00005792 /* tabpage-local variables */
Bram Moolenaar29323592016-07-24 22:04:11 +02005793 FOR_ALL_TABPAGES(tp)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005794 abort = abort || set_ref_in_item(&tp->tp_winvar.di_tv, copyID,
5795 NULL, NULL);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005796 /* global variables */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005797 abort = abort || set_ref_in_ht(&globvarht, copyID, NULL);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005798
5799 /* function-local variables */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02005800 abort = abort || set_ref_in_call_stack(copyID);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005801
Bram Moolenaarbc7ce672016-08-01 22:49:22 +02005802 /* named functions (matters for closures) */
5803 abort = abort || set_ref_in_functions(copyID);
5804
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +02005805 /* function call arguments, if v:testing is set. */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02005806 abort = abort || set_ref_in_func_args(copyID);
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +02005807
Bram Moolenaard812df62008-11-09 12:46:09 +00005808 /* v: vars */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005809 abort = abort || set_ref_in_ht(&vimvarht, copyID, NULL);
Bram Moolenaard812df62008-11-09 12:46:09 +00005810
Bram Moolenaar75a1a942019-06-20 03:45:36 +02005811 // callbacks in buffers
5812 abort = abort || set_ref_in_buffers(copyID);
5813
Bram Moolenaar1dced572012-04-05 16:54:08 +02005814#ifdef FEAT_LUA
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005815 abort = abort || set_ref_in_lua(copyID);
Bram Moolenaar1dced572012-04-05 16:54:08 +02005816#endif
5817
Bram Moolenaardb913952012-06-29 12:54:53 +02005818#ifdef FEAT_PYTHON
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005819 abort = abort || set_ref_in_python(copyID);
Bram Moolenaardb913952012-06-29 12:54:53 +02005820#endif
5821
5822#ifdef FEAT_PYTHON3
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005823 abort = abort || set_ref_in_python3(copyID);
Bram Moolenaardb913952012-06-29 12:54:53 +02005824#endif
5825
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01005826#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar3780bb92016-04-12 22:18:53 +02005827 abort = abort || set_ref_in_channel(copyID);
Bram Moolenaarb8d49052016-05-01 14:22:16 +02005828 abort = abort || set_ref_in_job(copyID);
Bram Moolenaar4b6a6dc2016-02-04 22:49:49 +01005829#endif
Bram Moolenaar3266c852016-04-30 18:07:05 +02005830#ifdef FEAT_NETBEANS_INTG
5831 abort = abort || set_ref_in_nb_channel(copyID);
5832#endif
Bram Moolenaar4b6a6dc2016-02-04 22:49:49 +01005833
Bram Moolenaare3188e22016-05-31 21:13:04 +02005834#ifdef FEAT_TIMERS
5835 abort = abort || set_ref_in_timer(copyID);
5836#endif
5837
Bram Moolenaar8f77c5a2017-04-30 14:21:00 +02005838#ifdef FEAT_QUICKFIX
5839 abort = abort || set_ref_in_quickfix(copyID);
5840#endif
5841
Bram Moolenaara2c45a12017-07-27 22:14:59 +02005842#ifdef FEAT_TERMINAL
5843 abort = abort || set_ref_in_term(copyID);
5844#endif
5845
Bram Moolenaar75a1a942019-06-20 03:45:36 +02005846#ifdef FEAT_TEXT_PROP
5847 abort = abort || set_ref_in_popups(copyID);
5848#endif
5849
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005850 if (!abort)
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005851 {
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005852 /*
5853 * 2. Free lists and dictionaries that are not referenced.
5854 */
5855 did_free = free_unref_items(copyID);
5856
5857 /*
5858 * 3. Check if any funccal can be freed now.
Bram Moolenaara9b579f2016-07-17 18:29:19 +02005859 * This may call us back recursively.
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005860 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02005861 free_unref_funccal(copyID, testing);
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005862 }
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005863 else if (p_verbose > 0)
5864 {
Bram Moolenaar32526b32019-01-19 17:43:09 +01005865 verb_msg(_("Not enough memory to set references, garbage collection aborted!"));
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005866 }
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005867
5868 return did_free;
5869}
5870
5871/*
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005872 * Free lists, dictionaries, channels and jobs that are no longer referenced.
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005873 */
5874 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005875free_unref_items(int copyID)
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005876{
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005877 int did_free = FALSE;
5878
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005879 /* Let all "free" functions know that we are here. This means no
5880 * dictionaries, lists, channels or jobs are to be freed, because we will
5881 * do that here. */
5882 in_free_unref_items = TRUE;
5883
5884 /*
5885 * PASS 1: free the contents of the items. We don't free the items
5886 * themselves yet, so that it is possible to decrement refcount counters
5887 */
5888
Bram Moolenaarcd524592016-07-17 14:57:05 +02005889 /* Go through the list of dicts and free items without the copyID. */
5890 did_free |= dict_free_nonref(copyID);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005891
Bram Moolenaarda861d62016-07-17 15:46:27 +02005892 /* Go through the list of lists and free items without the copyID. */
5893 did_free |= list_free_nonref(copyID);
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005894
5895#ifdef FEAT_JOB_CHANNEL
5896 /* Go through the list of jobs and free items without the copyID. This
5897 * must happen before doing channels, because jobs refer to channels, but
5898 * the reference from the channel to the job isn't tracked. */
5899 did_free |= free_unused_jobs_contents(copyID, COPYID_MASK);
5900
5901 /* Go through the list of channels and free items without the copyID. */
5902 did_free |= free_unused_channels_contents(copyID, COPYID_MASK);
5903#endif
5904
5905 /*
5906 * PASS 2: free the items themselves.
5907 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02005908 dict_free_items(copyID);
Bram Moolenaarda861d62016-07-17 15:46:27 +02005909 list_free_items(copyID);
Bram Moolenaar835dc632016-02-07 14:27:38 +01005910
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005911#ifdef FEAT_JOB_CHANNEL
5912 /* Go through the list of jobs and free items without the copyID. This
5913 * must happen before doing channels, because jobs refer to channels, but
5914 * the reference from the channel to the job isn't tracked. */
5915 free_unused_jobs(copyID, COPYID_MASK);
5916
5917 /* Go through the list of channels and free items without the copyID. */
5918 free_unused_channels(copyID, COPYID_MASK);
5919#endif
5920
5921 in_free_unref_items = FALSE;
5922
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005923 return did_free;
5924}
5925
5926/*
5927 * Mark all lists and dicts referenced through hashtab "ht" with "copyID".
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005928 * "list_stack" is used to add lists to be marked. Can be NULL.
5929 *
5930 * Returns TRUE if setting references failed somehow.
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005931 */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005932 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005933set_ref_in_ht(hashtab_T *ht, int copyID, list_stack_T **list_stack)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005934{
5935 int todo;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005936 int abort = FALSE;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005937 hashitem_T *hi;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005938 hashtab_T *cur_ht;
5939 ht_stack_T *ht_stack = NULL;
5940 ht_stack_T *tempitem;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005941
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005942 cur_ht = ht;
5943 for (;;)
5944 {
5945 if (!abort)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005946 {
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005947 /* Mark each item in the hashtab. If the item contains a hashtab
5948 * it is added to ht_stack, if it contains a list it is added to
5949 * list_stack. */
5950 todo = (int)cur_ht->ht_used;
5951 for (hi = cur_ht->ht_array; todo > 0; ++hi)
5952 if (!HASHITEM_EMPTY(hi))
5953 {
5954 --todo;
5955 abort = abort || set_ref_in_item(&HI2DI(hi)->di_tv, copyID,
5956 &ht_stack, list_stack);
5957 }
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005958 }
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005959
5960 if (ht_stack == NULL)
5961 break;
5962
5963 /* take an item from the stack */
5964 cur_ht = ht_stack->ht;
5965 tempitem = ht_stack;
5966 ht_stack = ht_stack->prev;
5967 free(tempitem);
5968 }
5969
5970 return abort;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005971}
5972
5973/*
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02005974 * Mark a dict and its items with "copyID".
5975 * Returns TRUE if setting references failed somehow.
5976 */
5977 int
5978set_ref_in_dict(dict_T *d, int copyID)
5979{
5980 if (d != NULL && d->dv_copyID != copyID)
5981 {
5982 d->dv_copyID = copyID;
5983 return set_ref_in_ht(&d->dv_hashtab, copyID, NULL);
5984 }
5985 return FALSE;
5986}
5987
5988/*
5989 * Mark a list and its items with "copyID".
5990 * Returns TRUE if setting references failed somehow.
5991 */
5992 int
5993set_ref_in_list(list_T *ll, int copyID)
5994{
5995 if (ll != NULL && ll->lv_copyID != copyID)
5996 {
5997 ll->lv_copyID = copyID;
5998 return set_ref_in_list_items(ll, copyID, NULL);
5999 }
6000 return FALSE;
6001}
6002
6003/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006004 * Mark all lists and dicts referenced through list "l" with "copyID".
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006005 * "ht_stack" is used to add hashtabs to be marked. Can be NULL.
6006 *
6007 * Returns TRUE if setting references failed somehow.
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006008 */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006009 int
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02006010set_ref_in_list_items(list_T *l, int copyID, ht_stack_T **ht_stack)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006011{
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006012 listitem_T *li;
6013 int abort = FALSE;
6014 list_T *cur_l;
6015 list_stack_T *list_stack = NULL;
6016 list_stack_T *tempitem;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006017
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006018 cur_l = l;
6019 for (;;)
6020 {
6021 if (!abort)
6022 /* Mark each item in the list. If the item contains a hashtab
6023 * it is added to ht_stack, if it contains a list it is added to
6024 * list_stack. */
6025 for (li = cur_l->lv_first; !abort && li != NULL; li = li->li_next)
6026 abort = abort || set_ref_in_item(&li->li_tv, copyID,
6027 ht_stack, &list_stack);
6028 if (list_stack == NULL)
6029 break;
6030
6031 /* take an item from the stack */
6032 cur_l = list_stack->list;
6033 tempitem = list_stack;
6034 list_stack = list_stack->prev;
6035 free(tempitem);
6036 }
6037
6038 return abort;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006039}
6040
6041/*
6042 * Mark all lists and dicts referenced through typval "tv" with "copyID".
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006043 * "list_stack" is used to add lists to be marked. Can be NULL.
6044 * "ht_stack" is used to add hashtabs to be marked. Can be NULL.
6045 *
6046 * Returns TRUE if setting references failed somehow.
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006047 */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006048 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006049set_ref_in_item(
6050 typval_T *tv,
6051 int copyID,
6052 ht_stack_T **ht_stack,
6053 list_stack_T **list_stack)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006054{
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006055 int abort = FALSE;
Bram Moolenaard9fba312005-06-26 22:34:35 +00006056
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006057 if (tv->v_type == VAR_DICT)
Bram Moolenaard9fba312005-06-26 22:34:35 +00006058 {
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006059 dict_T *dd = tv->vval.v_dict;
6060
Bram Moolenaara03f2332016-02-06 18:09:59 +01006061 if (dd != NULL && dd->dv_copyID != copyID)
6062 {
6063 /* Didn't see this dict yet. */
6064 dd->dv_copyID = copyID;
6065 if (ht_stack == NULL)
Bram Moolenaard9fba312005-06-26 22:34:35 +00006066 {
Bram Moolenaara03f2332016-02-06 18:09:59 +01006067 abort = set_ref_in_ht(&dd->dv_hashtab, copyID, list_stack);
6068 }
6069 else
6070 {
6071 ht_stack_T *newitem = (ht_stack_T*)malloc(sizeof(ht_stack_T));
6072 if (newitem == NULL)
6073 abort = TRUE;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006074 else
6075 {
Bram Moolenaara03f2332016-02-06 18:09:59 +01006076 newitem->ht = &dd->dv_hashtab;
6077 newitem->prev = *ht_stack;
6078 *ht_stack = newitem;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006079 }
Bram Moolenaard9fba312005-06-26 22:34:35 +00006080 }
Bram Moolenaara03f2332016-02-06 18:09:59 +01006081 }
6082 }
6083 else if (tv->v_type == VAR_LIST)
6084 {
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006085 list_T *ll = tv->vval.v_list;
6086
Bram Moolenaara03f2332016-02-06 18:09:59 +01006087 if (ll != NULL && ll->lv_copyID != copyID)
6088 {
6089 /* Didn't see this list yet. */
6090 ll->lv_copyID = copyID;
6091 if (list_stack == NULL)
Bram Moolenaard9fba312005-06-26 22:34:35 +00006092 {
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02006093 abort = set_ref_in_list_items(ll, copyID, ht_stack);
Bram Moolenaara03f2332016-02-06 18:09:59 +01006094 }
6095 else
6096 {
6097 list_stack_T *newitem = (list_stack_T*)malloc(
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006098 sizeof(list_stack_T));
Bram Moolenaara03f2332016-02-06 18:09:59 +01006099 if (newitem == NULL)
6100 abort = TRUE;
6101 else
6102 {
6103 newitem->list = ll;
6104 newitem->prev = *list_stack;
6105 *list_stack = newitem;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006106 }
Bram Moolenaard9fba312005-06-26 22:34:35 +00006107 }
Bram Moolenaara03f2332016-02-06 18:09:59 +01006108 }
Bram Moolenaard9fba312005-06-26 22:34:35 +00006109 }
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02006110 else if (tv->v_type == VAR_FUNC)
6111 {
Bram Moolenaar437bafe2016-08-01 15:40:54 +02006112 abort = set_ref_in_func(tv->vval.v_string, NULL, copyID);
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02006113 }
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006114 else if (tv->v_type == VAR_PARTIAL)
6115 {
6116 partial_T *pt = tv->vval.v_partial;
6117 int i;
6118
6119 /* A partial does not have a copyID, because it cannot contain itself.
6120 */
6121 if (pt != NULL)
6122 {
Bram Moolenaar437bafe2016-08-01 15:40:54 +02006123 abort = set_ref_in_func(pt->pt_name, pt->pt_func, copyID);
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02006124
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006125 if (pt->pt_dict != NULL)
6126 {
6127 typval_T dtv;
6128
6129 dtv.v_type = VAR_DICT;
6130 dtv.vval.v_dict = pt->pt_dict;
6131 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
6132 }
6133
6134 for (i = 0; i < pt->pt_argc; ++i)
6135 abort = abort || set_ref_in_item(&pt->pt_argv[i], copyID,
6136 ht_stack, list_stack);
6137 }
6138 }
6139#ifdef FEAT_JOB_CHANNEL
6140 else if (tv->v_type == VAR_JOB)
6141 {
6142 job_T *job = tv->vval.v_job;
6143 typval_T dtv;
6144
6145 if (job != NULL && job->jv_copyID != copyID)
6146 {
Bram Moolenaar0239acb2016-04-11 21:02:54 +02006147 job->jv_copyID = copyID;
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006148 if (job->jv_channel != NULL)
6149 {
6150 dtv.v_type = VAR_CHANNEL;
6151 dtv.vval.v_channel = job->jv_channel;
6152 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
6153 }
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006154 if (job->jv_exit_cb.cb_partial != NULL)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006155 {
6156 dtv.v_type = VAR_PARTIAL;
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006157 dtv.vval.v_partial = job->jv_exit_cb.cb_partial;
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006158 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
6159 }
6160 }
6161 }
6162 else if (tv->v_type == VAR_CHANNEL)
6163 {
6164 channel_T *ch =tv->vval.v_channel;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02006165 ch_part_T part;
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006166 typval_T dtv;
6167 jsonq_T *jq;
6168 cbq_T *cq;
6169
6170 if (ch != NULL && ch->ch_copyID != copyID)
6171 {
Bram Moolenaar0239acb2016-04-11 21:02:54 +02006172 ch->ch_copyID = copyID;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02006173 for (part = PART_SOCK; part < PART_COUNT; ++part)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006174 {
6175 for (jq = ch->ch_part[part].ch_json_head.jq_next; jq != NULL;
6176 jq = jq->jq_next)
6177 set_ref_in_item(jq->jq_value, copyID, ht_stack, list_stack);
6178 for (cq = ch->ch_part[part].ch_cb_head.cq_next; cq != NULL;
6179 cq = cq->cq_next)
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006180 if (cq->cq_callback.cb_partial != NULL)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006181 {
6182 dtv.v_type = VAR_PARTIAL;
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006183 dtv.vval.v_partial = cq->cq_callback.cb_partial;
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006184 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
6185 }
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006186 if (ch->ch_part[part].ch_callback.cb_partial != NULL)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006187 {
6188 dtv.v_type = VAR_PARTIAL;
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006189 dtv.vval.v_partial =
6190 ch->ch_part[part].ch_callback.cb_partial;
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006191 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
6192 }
6193 }
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006194 if (ch->ch_callback.cb_partial != NULL)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006195 {
6196 dtv.v_type = VAR_PARTIAL;
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006197 dtv.vval.v_partial = ch->ch_callback.cb_partial;
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006198 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
6199 }
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006200 if (ch->ch_close_cb.cb_partial != NULL)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006201 {
6202 dtv.v_type = VAR_PARTIAL;
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006203 dtv.vval.v_partial = ch->ch_close_cb.cb_partial;
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006204 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
6205 }
6206 }
6207 }
6208#endif
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006209 return abort;
Bram Moolenaard9fba312005-06-26 22:34:35 +00006210}
6211
Bram Moolenaar17a13432016-01-24 14:22:10 +01006212 static char *
6213get_var_special_name(int nr)
6214{
6215 switch (nr)
6216 {
Bram Moolenaarf48aa162016-01-24 17:54:24 +01006217 case VVAL_FALSE: return "v:false";
Bram Moolenaar65edff82016-02-21 16:40:11 +01006218 case VVAL_TRUE: return "v:true";
6219 case VVAL_NONE: return "v:none";
6220 case VVAL_NULL: return "v:null";
Bram Moolenaar17a13432016-01-24 14:22:10 +01006221 }
Bram Moolenaar95f09602016-11-10 20:01:45 +01006222 internal_error("get_var_special_name()");
Bram Moolenaar17a13432016-01-24 14:22:10 +01006223 return "42";
6224}
6225
Bram Moolenaar8c711452005-01-14 21:53:12 +00006226/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006227 * Return a string with the string representation of a variable.
6228 * If the memory is allocated "tofree" is set to it, otherwise NULL.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006229 * "numbuf" is used for a number.
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006230 * When "copyID" is not NULL replace recursive lists and dicts with "...".
Bram Moolenaar35422f42017-08-05 16:33:56 +02006231 * When both "echo_style" and "composite_val" are FALSE, put quotes around
6232 * stings as "string()", otherwise does not put quotes around strings, as
6233 * ":echo" displays values.
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006234 * When "restore_copyID" is FALSE, repeated items in dictionaries and lists
6235 * are replaced with "...".
Bram Moolenaar92c5aba2007-08-14 20:29:31 +00006236 * May return NULL.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006237 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02006238 char_u *
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006239echo_string_core(
Bram Moolenaar7454a062016-01-30 15:14:10 +01006240 typval_T *tv,
6241 char_u **tofree,
6242 char_u *numbuf,
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006243 int copyID,
6244 int echo_style,
6245 int restore_copyID,
Bram Moolenaar35422f42017-08-05 16:33:56 +02006246 int composite_val)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006247{
Bram Moolenaare9a41262005-01-15 22:18:47 +00006248 static int recurse = 0;
6249 char_u *r = NULL;
6250
Bram Moolenaar33570922005-01-25 22:26:29 +00006251 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006252 {
Bram Moolenaar8502c702014-06-17 12:51:16 +02006253 if (!did_echo_string_emsg)
6254 {
6255 /* Only give this message once for a recursive call to avoid
6256 * flooding the user with errors. And stop iterating over lists
6257 * and dicts. */
6258 did_echo_string_emsg = TRUE;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01006259 emsg(_("E724: variable nested too deep for displaying"));
Bram Moolenaar8502c702014-06-17 12:51:16 +02006260 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006261 *tofree = NULL;
Bram Moolenaar8502c702014-06-17 12:51:16 +02006262 return (char_u *)"{E724}";
Bram Moolenaare9a41262005-01-15 22:18:47 +00006263 }
6264 ++recurse;
6265
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006266 switch (tv->v_type)
6267 {
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006268 case VAR_STRING:
Bram Moolenaar35422f42017-08-05 16:33:56 +02006269 if (echo_style && !composite_val)
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006270 {
6271 *tofree = NULL;
Bram Moolenaar35422f42017-08-05 16:33:56 +02006272 r = tv->vval.v_string;
6273 if (r == NULL)
6274 r = (char_u *)"";
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006275 }
6276 else
6277 {
6278 *tofree = string_quote(tv->vval.v_string, FALSE);
6279 r = *tofree;
6280 }
6281 break;
6282
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006283 case VAR_FUNC:
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006284 if (echo_style)
6285 {
6286 *tofree = NULL;
6287 r = tv->vval.v_string;
6288 }
6289 else
6290 {
6291 *tofree = string_quote(tv->vval.v_string, TRUE);
6292 r = *tofree;
6293 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006294 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006295
Bram Moolenaar1735bc92016-03-14 23:05:14 +01006296 case VAR_PARTIAL:
Bram Moolenaar24c77a12016-03-24 21:23:06 +01006297 {
6298 partial_T *pt = tv->vval.v_partial;
6299 char_u *fname = string_quote(pt == NULL ? NULL
Bram Moolenaar437bafe2016-08-01 15:40:54 +02006300 : partial_name(pt), FALSE);
Bram Moolenaar24c77a12016-03-24 21:23:06 +01006301 garray_T ga;
6302 int i;
6303 char_u *tf;
6304
6305 ga_init2(&ga, 1, 100);
6306 ga_concat(&ga, (char_u *)"function(");
6307 if (fname != NULL)
6308 {
6309 ga_concat(&ga, fname);
6310 vim_free(fname);
6311 }
6312 if (pt != NULL && pt->pt_argc > 0)
6313 {
6314 ga_concat(&ga, (char_u *)", [");
6315 for (i = 0; i < pt->pt_argc; ++i)
6316 {
6317 if (i > 0)
6318 ga_concat(&ga, (char_u *)", ");
6319 ga_concat(&ga,
6320 tv2string(&pt->pt_argv[i], &tf, numbuf, copyID));
6321 vim_free(tf);
6322 }
6323 ga_concat(&ga, (char_u *)"]");
6324 }
6325 if (pt != NULL && pt->pt_dict != NULL)
6326 {
6327 typval_T dtv;
6328
6329 ga_concat(&ga, (char_u *)", ");
6330 dtv.v_type = VAR_DICT;
6331 dtv.vval.v_dict = pt->pt_dict;
6332 ga_concat(&ga, tv2string(&dtv, &tf, numbuf, copyID));
6333 vim_free(tf);
6334 }
6335 ga_concat(&ga, (char_u *)")");
6336
6337 *tofree = ga.ga_data;
6338 r = *tofree;
6339 break;
6340 }
Bram Moolenaar1735bc92016-03-14 23:05:14 +01006341
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01006342 case VAR_BLOB:
Bram Moolenaar8c8b8bb2019-01-13 17:48:04 +01006343 r = blob2string(tv->vval.v_blob, tofree, numbuf);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01006344 break;
6345
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006346 case VAR_LIST:
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006347 if (tv->vval.v_list == NULL)
6348 {
6349 *tofree = NULL;
6350 r = NULL;
6351 }
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006352 else if (copyID != 0 && tv->vval.v_list->lv_copyID == copyID
6353 && tv->vval.v_list->lv_len > 0)
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006354 {
6355 *tofree = NULL;
6356 r = (char_u *)"[...]";
6357 }
6358 else
6359 {
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006360 int old_copyID = tv->vval.v_list->lv_copyID;
6361
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006362 tv->vval.v_list->lv_copyID = copyID;
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006363 *tofree = list2string(tv, copyID, restore_copyID);
6364 if (restore_copyID)
6365 tv->vval.v_list->lv_copyID = old_copyID;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006366 r = *tofree;
6367 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006368 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006369
Bram Moolenaar8c711452005-01-14 21:53:12 +00006370 case VAR_DICT:
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006371 if (tv->vval.v_dict == NULL)
6372 {
6373 *tofree = NULL;
6374 r = NULL;
6375 }
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006376 else if (copyID != 0 && tv->vval.v_dict->dv_copyID == copyID
6377 && tv->vval.v_dict->dv_hashtab.ht_used != 0)
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006378 {
6379 *tofree = NULL;
6380 r = (char_u *)"{...}";
6381 }
6382 else
6383 {
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006384 int old_copyID = tv->vval.v_dict->dv_copyID;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006385 tv->vval.v_dict->dv_copyID = copyID;
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006386 *tofree = dict2string(tv, copyID, restore_copyID);
6387 if (restore_copyID)
6388 tv->vval.v_dict->dv_copyID = old_copyID;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006389 r = *tofree;
6390 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006391 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006392
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006393 case VAR_NUMBER:
Bram Moolenaara03f2332016-02-06 18:09:59 +01006394 case VAR_UNKNOWN:
Bram Moolenaar35422f42017-08-05 16:33:56 +02006395 *tofree = NULL;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01006396 r = tv_get_string_buf(tv, numbuf);
Bram Moolenaar35422f42017-08-05 16:33:56 +02006397 break;
6398
Bram Moolenaar835dc632016-02-07 14:27:38 +01006399 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01006400 case VAR_CHANNEL:
Bram Moolenaare9a41262005-01-15 22:18:47 +00006401 *tofree = NULL;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01006402 r = tv_get_string_buf(tv, numbuf);
Bram Moolenaar35422f42017-08-05 16:33:56 +02006403 if (composite_val)
6404 {
6405 *tofree = string_quote(r, FALSE);
6406 r = *tofree;
6407 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006408 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006409
Bram Moolenaar8c8de832008-06-24 22:58:06 +00006410 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01006411#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +00006412 *tofree = NULL;
6413 vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv->vval.v_float);
6414 r = numbuf;
6415 break;
6416#endif
6417
Bram Moolenaar520e1e42016-01-23 19:46:28 +01006418 case VAR_SPECIAL:
6419 *tofree = NULL;
Bram Moolenaar17a13432016-01-24 14:22:10 +01006420 r = (char_u *)get_var_special_name(tv->vval.v_number);
Bram Moolenaar520e1e42016-01-23 19:46:28 +01006421 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006422 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006423
Bram Moolenaar8502c702014-06-17 12:51:16 +02006424 if (--recurse == 0)
6425 did_echo_string_emsg = FALSE;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006426 return r;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006427}
6428
6429/*
6430 * Return a string with the string representation of a variable.
6431 * If the memory is allocated "tofree" is set to it, otherwise NULL.
6432 * "numbuf" is used for a number.
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006433 * Does not put quotes around strings, as ":echo" displays values.
6434 * When "copyID" is not NULL replace recursive lists and dicts with "...".
6435 * May return NULL.
6436 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02006437 char_u *
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006438echo_string(
6439 typval_T *tv,
6440 char_u **tofree,
6441 char_u *numbuf,
6442 int copyID)
6443{
6444 return echo_string_core(tv, tofree, numbuf, copyID, TRUE, FALSE, FALSE);
6445}
6446
6447/*
6448 * Return a string with the string representation of a variable.
6449 * If the memory is allocated "tofree" is set to it, otherwise NULL.
6450 * "numbuf" is used for a number.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006451 * Puts quotes around strings, so that they can be parsed back by eval().
Bram Moolenaar92c5aba2007-08-14 20:29:31 +00006452 * May return NULL.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006453 */
Bram Moolenaar8110a092016-04-14 15:56:09 +02006454 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006455tv2string(
6456 typval_T *tv,
6457 char_u **tofree,
6458 char_u *numbuf,
6459 int copyID)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006460{
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006461 return echo_string_core(tv, tofree, numbuf, copyID, FALSE, TRUE, FALSE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006462}
6463
6464/*
Bram Moolenaar33570922005-01-25 22:26:29 +00006465 * Return string "str" in ' quotes, doubling ' characters.
6466 * If "str" is NULL an empty string is assumed.
Bram Moolenaar8c711452005-01-14 21:53:12 +00006467 * If "function" is TRUE make it function('string').
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006468 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02006469 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006470string_quote(char_u *str, int function)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006471{
Bram Moolenaar33570922005-01-25 22:26:29 +00006472 unsigned len;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006473 char_u *p, *r, *s;
6474
Bram Moolenaar33570922005-01-25 22:26:29 +00006475 len = (function ? 13 : 3);
6476 if (str != NULL)
6477 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00006478 len += (unsigned)STRLEN(str);
Bram Moolenaar91acfff2017-03-12 19:22:36 +01006479 for (p = str; *p != NUL; MB_PTR_ADV(p))
Bram Moolenaar33570922005-01-25 22:26:29 +00006480 if (*p == '\'')
6481 ++len;
6482 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006483 s = r = alloc(len);
6484 if (r != NULL)
6485 {
6486 if (function)
6487 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00006488 STRCPY(r, "function('");
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006489 r += 10;
6490 }
6491 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00006492 *r++ = '\'';
Bram Moolenaar33570922005-01-25 22:26:29 +00006493 if (str != NULL)
6494 for (p = str; *p != NUL; )
6495 {
6496 if (*p == '\'')
6497 *r++ = '\'';
6498 MB_COPY_CHAR(p, r);
6499 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006500 *r++ = '\'';
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006501 if (function)
6502 *r++ = ')';
6503 *r++ = NUL;
6504 }
6505 return s;
6506}
6507
Bram Moolenaar520e1e42016-01-23 19:46:28 +01006508#if defined(FEAT_FLOAT) || defined(PROTO)
Bram Moolenaar8c8de832008-06-24 22:58:06 +00006509/*
6510 * Convert the string "text" to a floating point number.
6511 * This uses strtod(). setlocale(LC_NUMERIC, "C") has been used to make sure
6512 * this always uses a decimal point.
6513 * Returns the length of the text that was consumed.
6514 */
Bram Moolenaar520e1e42016-01-23 19:46:28 +01006515 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006516string2float(
6517 char_u *text,
6518 float_T *value) /* result stored here */
Bram Moolenaar8c8de832008-06-24 22:58:06 +00006519{
6520 char *s = (char *)text;
6521 float_T f;
6522
Bram Moolenaar62473612017-01-08 19:25:40 +01006523 /* MS-Windows does not deal with "inf" and "nan" properly. */
6524 if (STRNICMP(text, "inf", 3) == 0)
6525 {
6526 *value = INFINITY;
6527 return 3;
6528 }
6529 if (STRNICMP(text, "-inf", 3) == 0)
6530 {
6531 *value = -INFINITY;
6532 return 4;
6533 }
6534 if (STRNICMP(text, "nan", 3) == 0)
6535 {
6536 *value = NAN;
6537 return 3;
6538 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00006539 f = strtod(s, &s);
6540 *value = f;
6541 return (int)((char_u *)s - text);
6542}
6543#endif
6544
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006545/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006546 * Get the value of an environment variable.
6547 * "arg" is pointing to the '$'. It is advanced to after the name.
6548 * If the environment variable was not set, silently assume it is empty.
Bram Moolenaare512c8c2014-04-29 17:41:22 +02006549 * Return FAIL if the name is invalid.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006550 */
6551 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006552get_env_tv(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006553{
6554 char_u *string = NULL;
6555 int len;
6556 int cc;
6557 char_u *name;
Bram Moolenaar05159a02005-02-26 23:04:13 +00006558 int mustfree = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006559
6560 ++*arg;
6561 name = *arg;
6562 len = get_env_len(arg);
6563 if (evaluate)
6564 {
Bram Moolenaare512c8c2014-04-29 17:41:22 +02006565 if (len == 0)
Bram Moolenaar615b9972015-01-14 17:15:05 +01006566 return FAIL; /* invalid empty name */
Bram Moolenaar05159a02005-02-26 23:04:13 +00006567
Bram Moolenaare512c8c2014-04-29 17:41:22 +02006568 cc = name[len];
6569 name[len] = NUL;
6570 /* first try vim_getenv(), fast for normal environment vars */
6571 string = vim_getenv(name, &mustfree);
6572 if (string != NULL && *string != NUL)
6573 {
6574 if (!mustfree)
6575 string = vim_strsave(string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006576 }
Bram Moolenaare512c8c2014-04-29 17:41:22 +02006577 else
6578 {
6579 if (mustfree)
6580 vim_free(string);
6581
6582 /* next try expanding things like $VIM and ${HOME} */
6583 string = expand_env_save(name - 1);
6584 if (string != NULL && *string == '$')
Bram Moolenaard23a8232018-02-10 18:45:26 +01006585 VIM_CLEAR(string);
Bram Moolenaare512c8c2014-04-29 17:41:22 +02006586 }
6587 name[len] = cc;
6588
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006589 rettv->v_type = VAR_STRING;
6590 rettv->vval.v_string = string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006591 }
6592
6593 return OK;
6594}
6595
Bram Moolenaard6e256c2011-12-14 15:32:50 +01006596
6597
6598/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006599 * Translate a String variable into a position.
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006600 * Returns NULL when there is an error.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006601 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006602 pos_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006603var2fpos(
6604 typval_T *varp,
6605 int dollar_lnum, /* TRUE when $ is last line */
6606 int *fnum) /* set to fnum for '0, 'A, etc. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006607{
Bram Moolenaar261bfea2006-03-01 22:12:31 +00006608 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006609 static pos_T pos;
Bram Moolenaar261bfea2006-03-01 22:12:31 +00006610 pos_T *pp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006611
Bram Moolenaara5525202006-03-02 22:52:09 +00006612 /* Argument can be [lnum, col, coladd]. */
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006613 if (varp->v_type == VAR_LIST)
6614 {
6615 list_T *l;
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006616 int len;
Bram Moolenaara5525202006-03-02 22:52:09 +00006617 int error = FALSE;
Bram Moolenaar477933c2007-07-17 14:32:23 +00006618 listitem_T *li;
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006619
6620 l = varp->vval.v_list;
6621 if (l == NULL)
6622 return NULL;
6623
6624 /* Get the line number */
Bram Moolenaara5525202006-03-02 22:52:09 +00006625 pos.lnum = list_find_nr(l, 0L, &error);
6626 if (error || pos.lnum <= 0 || pos.lnum > curbuf->b_ml.ml_line_count)
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006627 return NULL; /* invalid line number */
6628
6629 /* Get the column number */
Bram Moolenaara5525202006-03-02 22:52:09 +00006630 pos.col = list_find_nr(l, 1L, &error);
6631 if (error)
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006632 return NULL;
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006633 len = (long)STRLEN(ml_get(pos.lnum));
Bram Moolenaar477933c2007-07-17 14:32:23 +00006634
6635 /* We accept "$" for the column number: last column. */
6636 li = list_find(l, 1L);
6637 if (li != NULL && li->li_tv.v_type == VAR_STRING
6638 && li->li_tv.vval.v_string != NULL
6639 && STRCMP(li->li_tv.vval.v_string, "$") == 0)
6640 pos.col = len + 1;
6641
Bram Moolenaara5525202006-03-02 22:52:09 +00006642 /* Accept a position up to the NUL after the line. */
Bram Moolenaar4c3f5362006-04-11 21:38:50 +00006643 if (pos.col == 0 || (int)pos.col > len + 1)
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006644 return NULL; /* invalid column number */
Bram Moolenaara5525202006-03-02 22:52:09 +00006645 --pos.col;
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006646
Bram Moolenaara5525202006-03-02 22:52:09 +00006647 /* Get the virtual offset. Defaults to zero. */
6648 pos.coladd = list_find_nr(l, 2L, &error);
6649 if (error)
6650 pos.coladd = 0;
Bram Moolenaara5525202006-03-02 22:52:09 +00006651
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006652 return &pos;
6653 }
6654
Bram Moolenaard155d7a2018-12-21 16:04:21 +01006655 name = tv_get_string_chk(varp);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006656 if (name == NULL)
6657 return NULL;
Bram Moolenaar9ecd0232008-06-20 15:31:51 +00006658 if (name[0] == '.') /* cursor */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006659 return &curwin->w_cursor;
Bram Moolenaar9ecd0232008-06-20 15:31:51 +00006660 if (name[0] == 'v' && name[1] == NUL) /* Visual start */
6661 {
6662 if (VIsual_active)
6663 return &VIsual;
6664 return &curwin->w_cursor;
6665 }
Bram Moolenaar9ecd0232008-06-20 15:31:51 +00006666 if (name[0] == '\'') /* mark */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006667 {
Bram Moolenaar9d182dd2013-01-23 15:53:15 +01006668 pp = getmark_buf_fnum(curbuf, name[1], FALSE, fnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006669 if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
6670 return NULL;
6671 return pp;
6672 }
Bram Moolenaara5525202006-03-02 22:52:09 +00006673
Bram Moolenaara5525202006-03-02 22:52:09 +00006674 pos.coladd = 0;
Bram Moolenaara5525202006-03-02 22:52:09 +00006675
Bram Moolenaar477933c2007-07-17 14:32:23 +00006676 if (name[0] == 'w' && dollar_lnum)
Bram Moolenaarf52c7252006-02-10 23:23:57 +00006677 {
6678 pos.col = 0;
6679 if (name[1] == '0') /* "w0": first visible line */
6680 {
Bram Moolenaarf740b292006-02-16 22:11:02 +00006681 update_topline();
Bram Moolenaara1d5fa62017-04-03 22:02:55 +02006682 /* In silent Ex mode topline is zero, but that's not a valid line
6683 * number; use one instead. */
6684 pos.lnum = curwin->w_topline > 0 ? curwin->w_topline : 1;
Bram Moolenaarf52c7252006-02-10 23:23:57 +00006685 return &pos;
6686 }
6687 else if (name[1] == '$') /* "w$": last visible line */
6688 {
Bram Moolenaarf740b292006-02-16 22:11:02 +00006689 validate_botline();
Bram Moolenaara1d5fa62017-04-03 22:02:55 +02006690 /* In silent Ex mode botline is zero, return zero then. */
6691 pos.lnum = curwin->w_botline > 0 ? curwin->w_botline - 1 : 0;
Bram Moolenaarf52c7252006-02-10 23:23:57 +00006692 return &pos;
6693 }
6694 }
6695 else if (name[0] == '$') /* last column or line */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006696 {
Bram Moolenaar477933c2007-07-17 14:32:23 +00006697 if (dollar_lnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006698 {
6699 pos.lnum = curbuf->b_ml.ml_line_count;
6700 pos.col = 0;
6701 }
6702 else
6703 {
6704 pos.lnum = curwin->w_cursor.lnum;
6705 pos.col = (colnr_T)STRLEN(ml_get_curline());
6706 }
6707 return &pos;
6708 }
6709 return NULL;
6710}
6711
6712/*
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006713 * Convert list in "arg" into a position and optional file number.
6714 * When "fnump" is NULL there is no file number, only 3 items.
6715 * Note that the column is passed on as-is, the caller may want to decrement
6716 * it to use 1 for the first column.
6717 * Return FAIL when conversion is not possible, doesn't check the position for
6718 * validity.
6719 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006720 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006721list2fpos(
6722 typval_T *arg,
6723 pos_T *posp,
6724 int *fnump,
6725 colnr_T *curswantp)
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006726{
6727 list_T *l = arg->vval.v_list;
6728 long i = 0;
6729 long n;
6730
Bram Moolenaar493c1782014-05-28 14:34:46 +02006731 /* List must be: [fnum, lnum, col, coladd, curswant], where "fnum" is only
6732 * there when "fnump" isn't NULL; "coladd" and "curswant" are optional. */
Bram Moolenaarbde35262006-07-23 20:12:24 +00006733 if (arg->v_type != VAR_LIST
6734 || l == NULL
6735 || l->lv_len < (fnump == NULL ? 2 : 3)
Bram Moolenaar493c1782014-05-28 14:34:46 +02006736 || l->lv_len > (fnump == NULL ? 4 : 5))
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006737 return FAIL;
6738
6739 if (fnump != NULL)
6740 {
6741 n = list_find_nr(l, i++, NULL); /* fnum */
6742 if (n < 0)
6743 return FAIL;
6744 if (n == 0)
6745 n = curbuf->b_fnum; /* current buffer */
6746 *fnump = n;
6747 }
6748
6749 n = list_find_nr(l, i++, NULL); /* lnum */
6750 if (n < 0)
6751 return FAIL;
6752 posp->lnum = n;
6753
6754 n = list_find_nr(l, i++, NULL); /* col */
6755 if (n < 0)
6756 return FAIL;
6757 posp->col = n;
6758
Bram Moolenaar493c1782014-05-28 14:34:46 +02006759 n = list_find_nr(l, i, NULL); /* off */
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006760 if (n < 0)
Bram Moolenaarbde35262006-07-23 20:12:24 +00006761 posp->coladd = 0;
6762 else
6763 posp->coladd = n;
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006764
Bram Moolenaar493c1782014-05-28 14:34:46 +02006765 if (curswantp != NULL)
6766 *curswantp = list_find_nr(l, i + 1, NULL); /* curswant */
6767
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006768 return OK;
6769}
6770
6771/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006772 * Get the length of an environment variable name.
6773 * Advance "arg" to the first character after the name.
6774 * Return 0 for error.
6775 */
6776 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006777get_env_len(char_u **arg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006778{
6779 char_u *p;
6780 int len;
6781
6782 for (p = *arg; vim_isIDc(*p); ++p)
6783 ;
6784 if (p == *arg) /* no name found */
6785 return 0;
6786
6787 len = (int)(p - *arg);
6788 *arg = p;
6789 return len;
6790}
6791
6792/*
6793 * Get the length of the name of a function or internal variable.
6794 * "arg" is advanced to the first non-white character after the name.
6795 * Return 0 if something is wrong.
6796 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02006797 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006798get_id_len(char_u **arg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006799{
6800 char_u *p;
6801 int len;
6802
6803 /* Find the end of the name. */
6804 for (p = *arg; eval_isnamec(*p); ++p)
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01006805 {
6806 if (*p == ':')
6807 {
6808 /* "s:" is start of "s:var", but "n:" is not and can be used in
6809 * slice "[n:]". Also "xx:" is not a namespace. */
6810 len = (int)(p - *arg);
6811 if ((len == 1 && vim_strchr(NAMESPACE_CHAR, **arg) == NULL)
6812 || len > 1)
6813 break;
6814 }
6815 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006816 if (p == *arg) /* no name found */
6817 return 0;
6818
6819 len = (int)(p - *arg);
6820 *arg = skipwhite(p);
6821
6822 return len;
6823}
6824
6825/*
Bram Moolenaara7043832005-01-21 11:56:39 +00006826 * Get the length of the name of a variable or function.
6827 * Only the name is recognized, does not handle ".key" or "[idx]".
Bram Moolenaar071d4272004-06-13 20:20:40 +00006828 * "arg" is advanced to the first non-white character after the name.
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006829 * Return -1 if curly braces expansion failed.
6830 * Return 0 if something else is wrong.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006831 * If the name contains 'magic' {}'s, expand them and return the
6832 * expanded name in an allocated string via 'alias' - caller must free.
6833 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006834 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006835get_name_len(
6836 char_u **arg,
6837 char_u **alias,
6838 int evaluate,
6839 int verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006840{
6841 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006842 char_u *p;
6843 char_u *expr_start;
6844 char_u *expr_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006845
6846 *alias = NULL; /* default to no alias */
6847
6848 if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
6849 && (*arg)[2] == (int)KE_SNR)
6850 {
6851 /* hard coded <SNR>, already translated */
6852 *arg += 3;
6853 return get_id_len(arg) + 3;
6854 }
6855 len = eval_fname_script(*arg);
6856 if (len > 0)
6857 {
6858 /* literal "<SID>", "s:" or "<SNR>" */
6859 *arg += len;
6860 }
6861
Bram Moolenaar071d4272004-06-13 20:20:40 +00006862 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006863 * Find the end of the name; check for {} construction.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006864 */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00006865 p = find_name_end(*arg, &expr_start, &expr_end,
6866 len > 0 ? 0 : FNE_CHECK_START);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006867 if (expr_start != NULL)
6868 {
6869 char_u *temp_string;
6870
6871 if (!evaluate)
6872 {
6873 len += (int)(p - *arg);
6874 *arg = skipwhite(p);
6875 return len;
6876 }
6877
6878 /*
6879 * Include any <SID> etc in the expanded string:
6880 * Thus the -len here.
6881 */
6882 temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
6883 if (temp_string == NULL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006884 return -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006885 *alias = temp_string;
6886 *arg = skipwhite(p);
6887 return (int)STRLEN(temp_string);
6888 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006889
6890 len += get_id_len(arg);
Bram Moolenaar8309b052019-01-13 16:46:22 +01006891 // Only give an error when there is something, otherwise it will be
6892 // reported at a higher level.
6893 if (len == 0 && verbose && **arg != NUL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01006894 semsg(_(e_invexpr2), *arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006895
6896 return len;
6897}
6898
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006899/*
6900 * Find the end of a variable or function name, taking care of magic braces.
6901 * If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the
6902 * start and end of the first magic braces item.
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00006903 * "flags" can have FNE_INCL_BR and FNE_CHECK_START.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006904 * Return a pointer to just after the name. Equal to "arg" if there is no
6905 * valid name.
6906 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02006907 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006908find_name_end(
6909 char_u *arg,
6910 char_u **expr_start,
6911 char_u **expr_end,
6912 int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006913{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006914 int mb_nest = 0;
6915 int br_nest = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006916 char_u *p;
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01006917 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006918
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006919 if (expr_start != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006920 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006921 *expr_start = NULL;
6922 *expr_end = NULL;
6923 }
6924
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00006925 /* Quick check for valid starting character. */
6926 if ((flags & FNE_CHECK_START) && !eval_isnamec1(*arg) && *arg != '{')
6927 return arg;
6928
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006929 for (p = arg; *p != NUL
6930 && (eval_isnamec(*p)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006931 || *p == '{'
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00006932 || ((flags & FNE_INCL_BR) && (*p == '[' || *p == '.'))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006933 || mb_nest != 0
Bram Moolenaar91acfff2017-03-12 19:22:36 +01006934 || br_nest != 0); MB_PTR_ADV(p))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006935 {
Bram Moolenaar8af24422005-08-08 22:06:28 +00006936 if (*p == '\'')
6937 {
6938 /* skip over 'string' to avoid counting [ and ] inside it. */
Bram Moolenaar91acfff2017-03-12 19:22:36 +01006939 for (p = p + 1; *p != NUL && *p != '\''; MB_PTR_ADV(p))
Bram Moolenaar8af24422005-08-08 22:06:28 +00006940 ;
6941 if (*p == NUL)
6942 break;
6943 }
6944 else if (*p == '"')
6945 {
6946 /* skip over "str\"ing" to avoid counting [ and ] inside it. */
Bram Moolenaar91acfff2017-03-12 19:22:36 +01006947 for (p = p + 1; *p != NUL && *p != '"'; MB_PTR_ADV(p))
Bram Moolenaar8af24422005-08-08 22:06:28 +00006948 if (*p == '\\' && p[1] != NUL)
6949 ++p;
6950 if (*p == NUL)
6951 break;
6952 }
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01006953 else if (br_nest == 0 && mb_nest == 0 && *p == ':')
6954 {
6955 /* "s:" is start of "s:var", but "n:" is not and can be used in
Bram Moolenaar4119cf82016-01-17 14:59:01 +01006956 * slice "[n:]". Also "xx:" is not a namespace. But {ns}: is. */
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01006957 len = (int)(p - arg);
6958 if ((len == 1 && vim_strchr(NAMESPACE_CHAR, *arg) == NULL)
Bram Moolenaar4119cf82016-01-17 14:59:01 +01006959 || (len > 1 && p[-1] != '}'))
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01006960 break;
6961 }
Bram Moolenaar8af24422005-08-08 22:06:28 +00006962
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006963 if (mb_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006964 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006965 if (*p == '[')
6966 ++br_nest;
6967 else if (*p == ']')
6968 --br_nest;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006969 }
Bram Moolenaar8af24422005-08-08 22:06:28 +00006970
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006971 if (br_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006972 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006973 if (*p == '{')
6974 {
6975 mb_nest++;
6976 if (expr_start != NULL && *expr_start == NULL)
6977 *expr_start = p;
6978 }
6979 else if (*p == '}')
6980 {
6981 mb_nest--;
6982 if (expr_start != NULL && mb_nest == 0 && *expr_end == NULL)
6983 *expr_end = p;
6984 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006985 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006986 }
6987
6988 return p;
6989}
6990
6991/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006992 * Expands out the 'magic' {}'s in a variable/function name.
6993 * Note that this can call itself recursively, to deal with
6994 * constructs like foo{bar}{baz}{bam}
6995 * The four pointer arguments point to "foo{expre}ss{ion}bar"
6996 * "in_start" ^
6997 * "expr_start" ^
6998 * "expr_end" ^
6999 * "in_end" ^
7000 *
7001 * Returns a new allocated string, which the caller must free.
7002 * Returns NULL for failure.
7003 */
7004 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007005make_expanded_name(
7006 char_u *in_start,
7007 char_u *expr_start,
7008 char_u *expr_end,
7009 char_u *in_end)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007010{
7011 char_u c1;
7012 char_u *retval = NULL;
7013 char_u *temp_result;
7014 char_u *nextcmd = NULL;
7015
7016 if (expr_end == NULL || in_end == NULL)
7017 return NULL;
7018 *expr_start = NUL;
7019 *expr_end = NUL;
7020 c1 = *in_end;
7021 *in_end = NUL;
7022
Bram Moolenaar362e1a32006-03-06 23:29:24 +00007023 temp_result = eval_to_string(expr_start + 1, &nextcmd, FALSE);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007024 if (temp_result != NULL && nextcmd == NULL)
7025 {
Bram Moolenaar964b3742019-05-24 18:54:09 +02007026 retval = alloc(STRLEN(temp_result) + (expr_start - in_start)
7027 + (in_end - expr_end) + 1);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007028 if (retval != NULL)
7029 {
7030 STRCPY(retval, in_start);
7031 STRCAT(retval, temp_result);
7032 STRCAT(retval, expr_end + 1);
7033 }
7034 }
7035 vim_free(temp_result);
7036
7037 *in_end = c1; /* put char back for error messages */
7038 *expr_start = '{';
7039 *expr_end = '}';
7040
7041 if (retval != NULL)
7042 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00007043 temp_result = find_name_end(retval, &expr_start, &expr_end, 0);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007044 if (expr_start != NULL)
7045 {
7046 /* Further expansion! */
7047 temp_result = make_expanded_name(retval, expr_start,
7048 expr_end, temp_result);
7049 vim_free(retval);
7050 retval = temp_result;
7051 }
7052 }
7053
7054 return retval;
7055}
7056
7057/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007058 * Return TRUE if character "c" can be used in a variable or function name.
Bram Moolenaare9a41262005-01-15 22:18:47 +00007059 * Does not include '{' or '}' for magic braces.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007060 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02007061 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007062eval_isnamec(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007063{
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00007064 return (ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR);
7065}
7066
7067/*
7068 * Return TRUE if character "c" can be used as the first character in a
7069 * variable or function name (excluding '{' and '}').
7070 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02007071 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007072eval_isnamec1(int c)
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00007073{
7074 return (ASCII_ISALPHA(c) || c == '_');
Bram Moolenaar071d4272004-06-13 20:20:40 +00007075}
7076
7077/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007078 * Set number v: variable to "val".
7079 */
7080 void
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02007081set_vim_var_nr(int idx, varnumber_T val)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007082{
Bram Moolenaare9a41262005-01-15 22:18:47 +00007083 vimvars[idx].vv_nr = val;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007084}
7085
7086/*
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02007087 * Get typval_T v: variable value.
7088 */
7089 typval_T *
7090get_vim_var_tv(int idx)
7091{
7092 return &vimvars[idx].vv_tv;
7093}
7094
7095/*
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007096 * Get number v: variable value.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007097 */
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02007098 varnumber_T
Bram Moolenaar7454a062016-01-30 15:14:10 +01007099get_vim_var_nr(int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007100{
Bram Moolenaare9a41262005-01-15 22:18:47 +00007101 return vimvars[idx].vv_nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007102}
7103
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007104/*
7105 * Get string v: variable value. Uses a static buffer, can only be used once.
Bram Moolenaar6e65d592017-12-07 22:11:27 +01007106 * If the String variable has never been set, return an empty string.
7107 * Never returns NULL;
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007108 */
7109 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007110get_vim_var_str(int idx)
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007111{
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007112 return tv_get_string(&vimvars[idx].vv_tv);
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007113}
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007114
Bram Moolenaar071d4272004-06-13 20:20:40 +00007115/*
Bram Moolenaard812df62008-11-09 12:46:09 +00007116 * Get List v: variable value. Caller must take care of reference count when
7117 * needed.
7118 */
7119 list_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007120get_vim_var_list(int idx)
Bram Moolenaard812df62008-11-09 12:46:09 +00007121{
7122 return vimvars[idx].vv_list;
7123}
7124
7125/*
Bram Moolenaar7e1652c2017-12-16 18:27:02 +01007126 * Get Dict v: variable value. Caller must take care of reference count when
7127 * needed.
7128 */
7129 dict_T *
7130get_vim_var_dict(int idx)
7131{
7132 return vimvars[idx].vv_dict;
7133}
7134
7135/*
Bram Moolenaarda9591e2009-09-30 13:17:02 +00007136 * Set v:char to character "c".
7137 */
7138 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007139set_vim_var_char(int c)
Bram Moolenaarda9591e2009-09-30 13:17:02 +00007140{
Bram Moolenaar9a920d82012-06-01 15:21:02 +02007141 char_u buf[MB_MAXBYTES + 1];
Bram Moolenaarda9591e2009-09-30 13:17:02 +00007142
Bram Moolenaarda9591e2009-09-30 13:17:02 +00007143 if (has_mbyte)
7144 buf[(*mb_char2bytes)(c, buf)] = NUL;
7145 else
Bram Moolenaarda9591e2009-09-30 13:17:02 +00007146 {
7147 buf[0] = c;
7148 buf[1] = NUL;
7149 }
7150 set_vim_var_string(VV_CHAR, buf, -1);
7151}
7152
7153/*
Bram Moolenaar8df74be2008-11-20 15:12:02 +00007154 * Set v:count to "count" and v:count1 to "count1".
7155 * When "set_prevcount" is TRUE first set v:prevcount from v:count.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007156 */
7157 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007158set_vcount(
7159 long count,
7160 long count1,
7161 int set_prevcount)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007162{
Bram Moolenaar8df74be2008-11-20 15:12:02 +00007163 if (set_prevcount)
7164 vimvars[VV_PREVCOUNT].vv_nr = vimvars[VV_COUNT].vv_nr;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007165 vimvars[VV_COUNT].vv_nr = count;
7166 vimvars[VV_COUNT1].vv_nr = count1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007167}
7168
7169/*
Bram Moolenaarb0f42ba2018-05-12 15:38:26 +02007170 * Save variables that might be changed as a side effect. Used when executing
7171 * a timer callback.
7172 */
7173 void
7174save_vimvars(vimvars_save_T *vvsave)
7175{
7176 vvsave->vv_prevcount = vimvars[VV_PREVCOUNT].vv_nr;
7177 vvsave->vv_count = vimvars[VV_COUNT].vv_nr;
7178 vvsave->vv_count1 = vimvars[VV_COUNT1].vv_nr;
7179}
7180
7181/*
7182 * Restore variables saved by save_vimvars().
7183 */
7184 void
7185restore_vimvars(vimvars_save_T *vvsave)
7186{
7187 vimvars[VV_PREVCOUNT].vv_nr = vvsave->vv_prevcount;
7188 vimvars[VV_COUNT].vv_nr = vvsave->vv_count;
7189 vimvars[VV_COUNT1].vv_nr = vvsave->vv_count1;
7190}
7191
7192/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007193 * Set string v: variable to a copy of "val".
7194 */
7195 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007196set_vim_var_string(
7197 int idx,
7198 char_u *val,
7199 int len) /* length of "val" to use or -1 (whole string) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007200{
Bram Moolenaara542c682016-01-31 16:28:04 +01007201 clear_tv(&vimvars[idx].vv_di.di_tv);
7202 vimvars[idx].vv_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007203 if (val == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007204 vimvars[idx].vv_str = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007205 else if (len == -1)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007206 vimvars[idx].vv_str = vim_strsave(val);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007207 else
Bram Moolenaare9a41262005-01-15 22:18:47 +00007208 vimvars[idx].vv_str = vim_strnsave(val, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007209}
7210
7211/*
Bram Moolenaard812df62008-11-09 12:46:09 +00007212 * Set List v: variable to "val".
7213 */
7214 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007215set_vim_var_list(int idx, list_T *val)
Bram Moolenaard812df62008-11-09 12:46:09 +00007216{
Bram Moolenaara542c682016-01-31 16:28:04 +01007217 clear_tv(&vimvars[idx].vv_di.di_tv);
7218 vimvars[idx].vv_type = VAR_LIST;
Bram Moolenaard812df62008-11-09 12:46:09 +00007219 vimvars[idx].vv_list = val;
7220 if (val != NULL)
7221 ++val->lv_refcount;
7222}
7223
7224/*
Bram Moolenaar42a45122015-07-10 17:56:23 +02007225 * Set Dictionary v: variable to "val".
7226 */
7227 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007228set_vim_var_dict(int idx, dict_T *val)
Bram Moolenaar42a45122015-07-10 17:56:23 +02007229{
Bram Moolenaara542c682016-01-31 16:28:04 +01007230 clear_tv(&vimvars[idx].vv_di.di_tv);
7231 vimvars[idx].vv_type = VAR_DICT;
Bram Moolenaar42a45122015-07-10 17:56:23 +02007232 vimvars[idx].vv_dict = val;
7233 if (val != NULL)
7234 {
7235 ++val->dv_refcount;
Bram Moolenaar7e1652c2017-12-16 18:27:02 +01007236 dict_set_items_ro(val);
Bram Moolenaar42a45122015-07-10 17:56:23 +02007237 }
7238}
7239
7240/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007241 * Set v:register if needed.
7242 */
7243 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007244set_reg_var(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007245{
7246 char_u regname;
7247
7248 if (c == 0 || c == ' ')
7249 regname = '"';
7250 else
7251 regname = c;
7252 /* Avoid free/alloc when the value is already right. */
Bram Moolenaare9a41262005-01-15 22:18:47 +00007253 if (vimvars[VV_REG].vv_str == NULL || vimvars[VV_REG].vv_str[0] != c)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007254 set_vim_var_string(VV_REG, &regname, 1);
7255}
7256
7257/*
7258 * Get or set v:exception. If "oldval" == NULL, return the current value.
7259 * Otherwise, restore the value to "oldval" and return NULL.
7260 * Must always be called in pairs to save and restore v:exception! Does not
7261 * take care of memory allocations.
7262 */
7263 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007264v_exception(char_u *oldval)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007265{
7266 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007267 return vimvars[VV_EXCEPTION].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007268
Bram Moolenaare9a41262005-01-15 22:18:47 +00007269 vimvars[VV_EXCEPTION].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007270 return NULL;
7271}
7272
7273/*
7274 * Get or set v:throwpoint. If "oldval" == NULL, return the current value.
7275 * Otherwise, restore the value to "oldval" and return NULL.
7276 * Must always be called in pairs to save and restore v:throwpoint! Does not
7277 * take care of memory allocations.
7278 */
7279 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007280v_throwpoint(char_u *oldval)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007281{
7282 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007283 return vimvars[VV_THROWPOINT].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007284
Bram Moolenaare9a41262005-01-15 22:18:47 +00007285 vimvars[VV_THROWPOINT].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007286 return NULL;
7287}
7288
Bram Moolenaar071d4272004-06-13 20:20:40 +00007289/*
7290 * Set v:cmdarg.
7291 * If "eap" != NULL, use "eap" to generate the value and return the old value.
7292 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
7293 * Must always be called in pairs!
7294 */
7295 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007296set_cmdarg(exarg_T *eap, char_u *oldarg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007297{
7298 char_u *oldval;
7299 char_u *newval;
7300 unsigned len;
7301
Bram Moolenaare9a41262005-01-15 22:18:47 +00007302 oldval = vimvars[VV_CMDARG].vv_str;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007303 if (eap == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007304 {
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007305 vim_free(oldval);
Bram Moolenaare9a41262005-01-15 22:18:47 +00007306 vimvars[VV_CMDARG].vv_str = oldarg;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007307 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007308 }
7309
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007310 if (eap->force_bin == FORCE_BIN)
7311 len = 6;
7312 else if (eap->force_bin == FORCE_NOBIN)
7313 len = 8;
7314 else
7315 len = 0;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00007316
7317 if (eap->read_edit)
7318 len += 7;
7319
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007320 if (eap->force_ff != 0)
Bram Moolenaar333b80a2018-04-04 22:57:29 +02007321 len += 10; /* " ++ff=unix" */
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007322 if (eap->force_enc != 0)
7323 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
Bram Moolenaar34b4daf2010-05-16 13:26:25 +02007324 if (eap->bad_char != 0)
7325 len += 7 + 4; /* " ++bad=" + "keep" or "drop" */
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007326
7327 newval = alloc(len + 1);
7328 if (newval == NULL)
7329 return NULL;
7330
7331 if (eap->force_bin == FORCE_BIN)
7332 sprintf((char *)newval, " ++bin");
7333 else if (eap->force_bin == FORCE_NOBIN)
7334 sprintf((char *)newval, " ++nobin");
7335 else
7336 *newval = NUL;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00007337
7338 if (eap->read_edit)
7339 STRCAT(newval, " ++edit");
7340
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007341 if (eap->force_ff != 0)
7342 sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
Bram Moolenaar333b80a2018-04-04 22:57:29 +02007343 eap->force_ff == 'u' ? "unix"
7344 : eap->force_ff == 'd' ? "dos"
7345 : "mac");
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007346 if (eap->force_enc != 0)
7347 sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
7348 eap->cmd + eap->force_enc);
Bram Moolenaar34b4daf2010-05-16 13:26:25 +02007349 if (eap->bad_char == BAD_KEEP)
7350 STRCPY(newval + STRLEN(newval), " ++bad=keep");
7351 else if (eap->bad_char == BAD_DROP)
7352 STRCPY(newval + STRLEN(newval), " ++bad=drop");
7353 else if (eap->bad_char != 0)
7354 sprintf((char *)newval + STRLEN(newval), " ++bad=%c", eap->bad_char);
Bram Moolenaare9a41262005-01-15 22:18:47 +00007355 vimvars[VV_CMDARG].vv_str = newval;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007356 return oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007357}
Bram Moolenaar071d4272004-06-13 20:20:40 +00007358
7359/*
7360 * Get the value of internal variable "name".
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01007361 * Return OK or FAIL. If OK is returned "rettv" must be cleared.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007362 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007363 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007364get_var_tv(
7365 char_u *name,
7366 int len, /* length of "name" */
7367 typval_T *rettv, /* NULL when only checking existence */
7368 dictitem_T **dip, /* non-NULL when typval's dict item is needed */
7369 int verbose, /* may give error message */
7370 int no_autoload) /* do not use script autoloading */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007371{
7372 int ret = OK;
Bram Moolenaar33570922005-01-25 22:26:29 +00007373 typval_T *tv = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00007374 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007375 int cc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007376
7377 /* truncate the name, so that we can use strcmp() */
7378 cc = name[len];
7379 name[len] = NUL;
7380
7381 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007382 * Check for user-defined variables.
7383 */
Bram Moolenaar79518e22017-02-17 16:31:35 +01007384 v = find_var(name, NULL, no_autoload);
7385 if (v != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007386 {
Bram Moolenaar79518e22017-02-17 16:31:35 +01007387 tv = &v->di_tv;
7388 if (dip != NULL)
7389 *dip = v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007390 }
7391
Bram Moolenaare9a41262005-01-15 22:18:47 +00007392 if (tv == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007393 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007394 if (rettv != NULL && verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007395 semsg(_(e_undefvar), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007396 ret = FAIL;
7397 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007398 else if (rettv != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007399 copy_tv(tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007400
7401 name[len] = cc;
7402
7403 return ret;
7404}
7405
7406/*
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02007407 * Check if variable "name[len]" is a local variable or an argument.
7408 * If so, "*eval_lavars_used" is set to TRUE.
7409 */
7410 static void
7411check_vars(char_u *name, int len)
7412{
7413 int cc;
7414 char_u *varname;
7415 hashtab_T *ht;
7416
7417 if (eval_lavars_used == NULL)
7418 return;
7419
7420 /* truncate the name, so that we can use strcmp() */
7421 cc = name[len];
7422 name[len] = NUL;
7423
7424 ht = find_var_ht(name, &varname);
7425 if (ht == get_funccal_local_ht() || ht == get_funccal_args_ht())
7426 {
7427 if (find_var(name, NULL, TRUE) != NULL)
7428 *eval_lavars_used = TRUE;
7429 }
7430
7431 name[len] = cc;
7432}
7433
7434/*
Bram Moolenaarac92e252019-08-03 21:58:38 +02007435 * Handle:
7436 * - expr[expr], expr[expr:expr] subscript
7437 * - ".name" lookup
7438 * - function call with Funcref variable: func(expr)
7439 * - method call: var->method()
7440 *
7441 * Can all be combined in any order: dict.func(expr)[idx]['func'](expr)->len()
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007442 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02007443 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007444handle_subscript(
7445 char_u **arg,
7446 typval_T *rettv,
7447 int evaluate, /* do more than finding the end */
7448 int verbose) /* give error messages */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007449{
7450 int ret = OK;
7451 dict_T *selfdict = NULL;
7452 char_u *s;
Bram Moolenaard9fba312005-06-26 22:34:35 +00007453 typval_T functv;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007454
Bram Moolenaar61343f02019-07-20 21:11:13 +02007455 // "." is ".name" lookup when we found a dict or when evaluating and
7456 // scriptversion is at least 2, where string concatenation is "..".
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007457 while (ret == OK
Bram Moolenaarac92e252019-08-03 21:58:38 +02007458 && (((**arg == '['
7459 || (**arg == '.' && (rettv->v_type == VAR_DICT
Bram Moolenaar61343f02019-07-20 21:11:13 +02007460 || (!evaluate
7461 && (*arg)[1] != '.'
7462 && current_sctx.sc_version >= 2)))
Bram Moolenaarac92e252019-08-03 21:58:38 +02007463 || (**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007464 || rettv->v_type == VAR_PARTIAL)))
Bram Moolenaarac92e252019-08-03 21:58:38 +02007465 && !VIM_ISWHITE(*(*arg - 1)))
7466 || (**arg == '-' && (*arg)[1] == '>')))
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007467 {
7468 if (**arg == '(')
7469 {
Bram Moolenaar3f242a82016-03-18 19:39:25 +01007470 partial_T *pt = NULL;
Bram Moolenaarc6538bc2019-08-03 18:17:11 +02007471 funcexe_T funcexe;
Bram Moolenaar3f242a82016-03-18 19:39:25 +01007472
Bram Moolenaard9fba312005-06-26 22:34:35 +00007473 /* need to copy the funcref so that we can clear rettv */
Bram Moolenaar0f8de8d2013-11-11 04:25:53 +01007474 if (evaluate)
7475 {
7476 functv = *rettv;
7477 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007478
Bram Moolenaar0f8de8d2013-11-11 04:25:53 +01007479 /* Invoke the function. Recursive! */
Bram Moolenaarab1fa392016-03-15 19:33:34 +01007480 if (functv.v_type == VAR_PARTIAL)
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007481 {
7482 pt = functv.vval.v_partial;
Bram Moolenaar437bafe2016-08-01 15:40:54 +02007483 s = partial_name(pt);
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007484 }
7485 else
7486 s = functv.vval.v_string;
Bram Moolenaar0f8de8d2013-11-11 04:25:53 +01007487 }
7488 else
7489 s = (char_u *)"";
Bram Moolenaarc6538bc2019-08-03 18:17:11 +02007490
Bram Moolenaarac92e252019-08-03 21:58:38 +02007491 vim_memset(&funcexe, 0, sizeof(funcexe));
Bram Moolenaarc6538bc2019-08-03 18:17:11 +02007492 funcexe.firstline = curwin->w_cursor.lnum;
7493 funcexe.lastline = curwin->w_cursor.lnum;
Bram Moolenaarc6538bc2019-08-03 18:17:11 +02007494 funcexe.evaluate = evaluate;
7495 funcexe.partial = pt;
7496 funcexe.selfdict = selfdict;
7497 ret = get_func_tv(s, -1, rettv, arg, &funcexe);
Bram Moolenaard9fba312005-06-26 22:34:35 +00007498
7499 /* Clear the funcref afterwards, so that deleting it while
7500 * evaluating the arguments is possible (see test55). */
Bram Moolenaar0f8de8d2013-11-11 04:25:53 +01007501 if (evaluate)
7502 clear_tv(&functv);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007503
7504 /* Stop the expression evaluation when immediately aborting on
7505 * error, or when an interrupt occurred or an exception was thrown
7506 * but not caught. */
7507 if (aborting())
7508 {
7509 if (ret == OK)
7510 clear_tv(rettv);
7511 ret = FAIL;
7512 }
7513 dict_unref(selfdict);
7514 selfdict = NULL;
7515 }
Bram Moolenaarac92e252019-08-03 21:58:38 +02007516 else if (**arg == '-')
7517 {
7518 if (eval_method(arg, rettv, evaluate, verbose) == FAIL)
7519 {
7520 clear_tv(rettv);
7521 ret = FAIL;
7522 }
7523 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007524 else /* **arg == '[' || **arg == '.' */
7525 {
7526 dict_unref(selfdict);
7527 if (rettv->v_type == VAR_DICT)
7528 {
7529 selfdict = rettv->vval.v_dict;
7530 if (selfdict != NULL)
7531 ++selfdict->dv_refcount;
7532 }
7533 else
7534 selfdict = NULL;
7535 if (eval_index(arg, rettv, evaluate, verbose) == FAIL)
7536 {
7537 clear_tv(rettv);
7538 ret = FAIL;
7539 }
7540 }
7541 }
Bram Moolenaarab1fa392016-03-15 19:33:34 +01007542
Bram Moolenaar1d429612016-05-24 15:44:17 +02007543 /* Turn "dict.Func" into a partial for "Func" bound to "dict".
7544 * Don't do this when "Func" is already a partial that was bound
7545 * explicitly (pt_auto is FALSE). */
7546 if (selfdict != NULL
7547 && (rettv->v_type == VAR_FUNC
7548 || (rettv->v_type == VAR_PARTIAL
7549 && (rettv->vval.v_partial->pt_auto
7550 || rettv->vval.v_partial->pt_dict == NULL))))
Bram Moolenaara9b579f2016-07-17 18:29:19 +02007551 selfdict = make_partial(selfdict, rettv);
Bram Moolenaarab1fa392016-03-15 19:33:34 +01007552
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007553 dict_unref(selfdict);
7554 return ret;
7555}
7556
7557/*
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007558 * Allocate memory for a variable type-value, and make it empty (0 or NULL
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007559 * value).
7560 */
Bram Moolenaar11e0afa2016-02-01 22:41:00 +01007561 typval_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007562alloc_tv(void)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007563{
Bram Moolenaarc799fe22019-05-28 23:08:19 +02007564 return ALLOC_CLEAR_ONE(typval_T);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007565}
7566
7567/*
7568 * Allocate memory for a variable type-value, and assign a string to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007569 * The string "s" must have been allocated, it is consumed.
7570 * Return NULL for out of memory, the variable otherwise.
7571 */
Bram Moolenaar33570922005-01-25 22:26:29 +00007572 static typval_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007573alloc_string_tv(char_u *s)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007574{
Bram Moolenaar33570922005-01-25 22:26:29 +00007575 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007576
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007577 rettv = alloc_tv();
7578 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007579 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007580 rettv->v_type = VAR_STRING;
7581 rettv->vval.v_string = s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007582 }
7583 else
7584 vim_free(s);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007585 return rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007586}
7587
7588/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007589 * Free the memory for a variable type-value.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007590 */
Bram Moolenaar4770d092006-01-12 23:22:24 +00007591 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007592free_tv(typval_T *varp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007593{
7594 if (varp != NULL)
7595 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007596 switch (varp->v_type)
7597 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007598 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007599 func_unref(varp->vval.v_string);
Bram Moolenaar2f40d122017-10-24 21:49:36 +02007600 /* FALLTHROUGH */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007601 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007602 vim_free(varp->vval.v_string);
7603 break;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007604 case VAR_PARTIAL:
7605 partial_unref(varp->vval.v_partial);
7606 break;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01007607 case VAR_BLOB:
7608 blob_unref(varp->vval.v_blob);
7609 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007610 case VAR_LIST:
7611 list_unref(varp->vval.v_list);
7612 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007613 case VAR_DICT:
7614 dict_unref(varp->vval.v_dict);
7615 break;
Bram Moolenaar835dc632016-02-07 14:27:38 +01007616 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007617#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +01007618 job_unref(varp->vval.v_job);
7619 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007620#endif
Bram Moolenaar77073442016-02-13 23:23:53 +01007621 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007622#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +01007623 channel_unref(varp->vval.v_channel);
7624 break;
7625#endif
Bram Moolenaar835dc632016-02-07 14:27:38 +01007626 case VAR_NUMBER:
7627 case VAR_FLOAT:
Bram Moolenaar758711c2005-02-02 23:11:38 +00007628 case VAR_UNKNOWN:
Bram Moolenaar6650a692016-01-26 19:59:10 +01007629 case VAR_SPECIAL:
Bram Moolenaar758711c2005-02-02 23:11:38 +00007630 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007631 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007632 vim_free(varp);
7633 }
7634}
7635
7636/*
7637 * Free the memory for a variable value and set the value to NULL or 0.
7638 */
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00007639 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007640clear_tv(typval_T *varp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007641{
7642 if (varp != NULL)
7643 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007644 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007645 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007646 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007647 func_unref(varp->vval.v_string);
Bram Moolenaar2f40d122017-10-24 21:49:36 +02007648 /* FALLTHROUGH */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007649 case VAR_STRING:
Bram Moolenaard23a8232018-02-10 18:45:26 +01007650 VIM_CLEAR(varp->vval.v_string);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007651 break;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007652 case VAR_PARTIAL:
7653 partial_unref(varp->vval.v_partial);
7654 varp->vval.v_partial = NULL;
7655 break;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01007656 case VAR_BLOB:
7657 blob_unref(varp->vval.v_blob);
7658 varp->vval.v_blob = NULL;
7659 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007660 case VAR_LIST:
7661 list_unref(varp->vval.v_list);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007662 varp->vval.v_list = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007663 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007664 case VAR_DICT:
7665 dict_unref(varp->vval.v_dict);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007666 varp->vval.v_dict = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007667 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007668 case VAR_NUMBER:
Bram Moolenaar520e1e42016-01-23 19:46:28 +01007669 case VAR_SPECIAL:
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007670 varp->vval.v_number = 0;
7671 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007672 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01007673#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007674 varp->vval.v_float = 0.0;
7675 break;
7676#endif
Bram Moolenaar835dc632016-02-07 14:27:38 +01007677 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007678#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +01007679 job_unref(varp->vval.v_job);
7680 varp->vval.v_job = NULL;
7681#endif
7682 break;
Bram Moolenaar77073442016-02-13 23:23:53 +01007683 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007684#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +01007685 channel_unref(varp->vval.v_channel);
7686 varp->vval.v_channel = NULL;
7687#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007688 case VAR_UNKNOWN:
7689 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007690 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007691 varp->v_lock = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007692 }
7693}
7694
7695/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007696 * Set the value of a variable to NULL without freeing items.
7697 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007698 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007699init_tv(typval_T *varp)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007700{
7701 if (varp != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +00007702 vim_memset(varp, 0, sizeof(typval_T));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007703}
7704
7705/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007706 * Get the number value of a variable.
7707 * If it is a String variable, uses vim_str2nr().
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007708 * For incompatible types, return 0.
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007709 * tv_get_number_chk() is similar to tv_get_number(), but informs the
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007710 * caller of incompatible types: it sets *denote to TRUE if "denote"
7711 * is not NULL or returns -1 otherwise.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007712 */
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02007713 varnumber_T
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007714tv_get_number(typval_T *varp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007715{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007716 int error = FALSE;
7717
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007718 return tv_get_number_chk(varp, &error); /* return 0L on error */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007719}
7720
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02007721 varnumber_T
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007722tv_get_number_chk(typval_T *varp, int *denote)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007723{
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02007724 varnumber_T n = 0L;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007725
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007726 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007727 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007728 case VAR_NUMBER:
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02007729 return varp->vval.v_number;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007730 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01007731#ifdef FEAT_FLOAT
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007732 emsg(_("E805: Using a Float as a Number"));
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007733 break;
7734#endif
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007735 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007736 case VAR_PARTIAL:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007737 emsg(_("E703: Using a Funcref as a Number"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007738 break;
7739 case VAR_STRING:
7740 if (varp->vval.v_string != NULL)
7741 vim_str2nr(varp->vval.v_string, NULL, NULL,
Bram Moolenaar16e9b852019-05-19 19:59:35 +02007742 STR2NR_ALL, &n, NULL, 0, FALSE);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007743 return n;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007744 case VAR_LIST:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007745 emsg(_("E745: Using a List as a Number"));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007746 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007747 case VAR_DICT:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007748 emsg(_("E728: Using a Dictionary as a Number"));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007749 break;
Bram Moolenaar17a13432016-01-24 14:22:10 +01007750 case VAR_SPECIAL:
7751 return varp->vval.v_number == VVAL_TRUE ? 1 : 0;
7752 break;
Bram Moolenaar835dc632016-02-07 14:27:38 +01007753 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007754#ifdef FEAT_JOB_CHANNEL
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007755 emsg(_("E910: Using a Job as a Number"));
Bram Moolenaar835dc632016-02-07 14:27:38 +01007756 break;
7757#endif
Bram Moolenaar77073442016-02-13 23:23:53 +01007758 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007759#ifdef FEAT_JOB_CHANNEL
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007760 emsg(_("E913: Using a Channel as a Number"));
Bram Moolenaar77073442016-02-13 23:23:53 +01007761 break;
7762#endif
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01007763 case VAR_BLOB:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007764 emsg(_("E974: Using a Blob as a Number"));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01007765 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +01007766 case VAR_UNKNOWN:
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007767 internal_error("tv_get_number(UNKNOWN)");
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007768 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007769 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007770 if (denote == NULL) /* useful for values that must be unsigned */
7771 n = -1;
7772 else
7773 *denote = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007774 return n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007775}
7776
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007777#ifdef FEAT_FLOAT
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007778 float_T
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007779tv_get_float(typval_T *varp)
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007780{
7781 switch (varp->v_type)
7782 {
7783 case VAR_NUMBER:
7784 return (float_T)(varp->vval.v_number);
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007785 case VAR_FLOAT:
7786 return varp->vval.v_float;
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007787 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007788 case VAR_PARTIAL:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007789 emsg(_("E891: Using a Funcref as a Float"));
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007790 break;
7791 case VAR_STRING:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007792 emsg(_("E892: Using a String as a Float"));
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007793 break;
7794 case VAR_LIST:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007795 emsg(_("E893: Using a List as a Float"));
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007796 break;
7797 case VAR_DICT:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007798 emsg(_("E894: Using a Dictionary as a Float"));
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007799 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +01007800 case VAR_SPECIAL:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007801 emsg(_("E907: Using a special value as a Float"));
Bram Moolenaara03f2332016-02-06 18:09:59 +01007802 break;
Bram Moolenaar835dc632016-02-07 14:27:38 +01007803 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007804# ifdef FEAT_JOB_CHANNEL
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007805 emsg(_("E911: Using a Job as a Float"));
Bram Moolenaar835dc632016-02-07 14:27:38 +01007806 break;
7807# endif
Bram Moolenaar77073442016-02-13 23:23:53 +01007808 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007809# ifdef FEAT_JOB_CHANNEL
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007810 emsg(_("E914: Using a Channel as a Float"));
Bram Moolenaar77073442016-02-13 23:23:53 +01007811 break;
7812# endif
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01007813 case VAR_BLOB:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007814 emsg(_("E975: Using a Blob as a Float"));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01007815 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +01007816 case VAR_UNKNOWN:
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007817 internal_error("tv_get_float(UNKNOWN)");
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007818 break;
7819 }
7820 return 0;
7821}
7822#endif
7823
Bram Moolenaar071d4272004-06-13 20:20:40 +00007824/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007825 * Get the string value of a variable.
7826 * If it is a Number variable, the number is converted into a string.
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007827 * tv_get_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
7828 * tv_get_string_buf() uses a given buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007829 * If the String variable has never been set, return an empty string.
7830 * Never returns NULL;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007831 * tv_get_string_chk() and tv_get_string_buf_chk() are similar, but return
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007832 * NULL on error.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007833 */
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01007834 char_u *
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007835tv_get_string(typval_T *varp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007836{
7837 static char_u mybuf[NUMBUFLEN];
7838
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007839 return tv_get_string_buf(varp, mybuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007840}
7841
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01007842 char_u *
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007843tv_get_string_buf(typval_T *varp, char_u *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007844{
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007845 char_u *res = tv_get_string_buf_chk(varp, buf);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007846
7847 return res != NULL ? res : (char_u *)"";
7848}
7849
Bram Moolenaar7d647822014-04-05 21:28:56 +02007850/*
7851 * Careful: This uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
7852 */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00007853 char_u *
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007854tv_get_string_chk(typval_T *varp)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007855{
7856 static char_u mybuf[NUMBUFLEN];
7857
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007858 return tv_get_string_buf_chk(varp, mybuf);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007859}
7860
Bram Moolenaar520e1e42016-01-23 19:46:28 +01007861 char_u *
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007862tv_get_string_buf_chk(typval_T *varp, char_u *buf)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007863{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007864 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007865 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007866 case VAR_NUMBER:
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02007867 vim_snprintf((char *)buf, NUMBUFLEN, "%lld",
Bram Moolenaar88c86eb2019-01-17 17:13:30 +01007868 (long_long_T)varp->vval.v_number);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007869 return buf;
7870 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007871 case VAR_PARTIAL:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007872 emsg(_("E729: using Funcref as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007873 break;
7874 case VAR_LIST:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007875 emsg(_("E730: using List as a String"));
Bram Moolenaar8c711452005-01-14 21:53:12 +00007876 break;
7877 case VAR_DICT:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007878 emsg(_("E731: using Dictionary as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007879 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007880 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01007881#ifdef FEAT_FLOAT
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007882 emsg(_(e_float_as_string));
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007883 break;
7884#endif
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007885 case VAR_STRING:
7886 if (varp->vval.v_string != NULL)
7887 return varp->vval.v_string;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007888 return (char_u *)"";
Bram Moolenaar17a13432016-01-24 14:22:10 +01007889 case VAR_SPECIAL:
7890 STRCPY(buf, get_var_special_name(varp->vval.v_number));
7891 return buf;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01007892 case VAR_BLOB:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007893 emsg(_("E976: using Blob as a String"));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01007894 break;
Bram Moolenaar835dc632016-02-07 14:27:38 +01007895 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007896#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +01007897 {
7898 job_T *job = varp->vval.v_job;
Bram Moolenaar839fd112016-03-06 21:34:03 +01007899 char *status;
7900
7901 if (job == NULL)
7902 return (char_u *)"no process";
7903 status = job->jv_status == JOB_FAILED ? "fail"
Bram Moolenaar7df915d2016-11-17 17:25:32 +01007904 : job->jv_status >= JOB_ENDED ? "dead"
Bram Moolenaar835dc632016-02-07 14:27:38 +01007905 : "run";
7906# ifdef UNIX
7907 vim_snprintf((char *)buf, NUMBUFLEN,
7908 "process %ld %s", (long)job->jv_pid, status);
Bram Moolenaar4f974752019-02-17 17:44:42 +01007909# elif defined(MSWIN)
Bram Moolenaar4d8747c2016-02-09 20:39:26 +01007910 vim_snprintf((char *)buf, NUMBUFLEN,
Bram Moolenaar76467df2016-02-12 19:30:26 +01007911 "process %ld %s",
7912 (long)job->jv_proc_info.dwProcessId,
Bram Moolenaar4d8747c2016-02-09 20:39:26 +01007913 status);
Bram Moolenaar835dc632016-02-07 14:27:38 +01007914# else
Bram Moolenaar4d8747c2016-02-09 20:39:26 +01007915 /* fall-back */
Bram Moolenaar835dc632016-02-07 14:27:38 +01007916 vim_snprintf((char *)buf, NUMBUFLEN, "process ? %s", status);
7917# endif
7918 return buf;
7919 }
7920#endif
7921 break;
Bram Moolenaar77073442016-02-13 23:23:53 +01007922 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007923#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +01007924 {
7925 channel_T *channel = varp->vval.v_channel;
Bram Moolenaar0e77b762016-09-26 22:58:58 +02007926 char *status = channel_status(channel, -1);
Bram Moolenaar77073442016-02-13 23:23:53 +01007927
Bram Moolenaar5cefd402016-02-16 12:44:26 +01007928 if (channel == NULL)
7929 vim_snprintf((char *)buf, NUMBUFLEN, "channel %s", status);
7930 else
7931 vim_snprintf((char *)buf, NUMBUFLEN,
Bram Moolenaar77073442016-02-13 23:23:53 +01007932 "channel %d %s", channel->ch_id, status);
7933 return buf;
7934 }
7935#endif
7936 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +01007937 case VAR_UNKNOWN:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007938 emsg(_("E908: using an invalid value as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007939 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007940 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007941 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007942}
7943
7944/*
Bram Moolenaar461a7fc2018-12-22 13:28:07 +01007945 * Turn a typeval into a string. Similar to tv_get_string_buf() but uses
7946 * string() on Dict, List, etc.
7947 */
7948 char_u *
7949tv_stringify(typval_T *varp, char_u *buf)
7950{
7951 if (varp->v_type == VAR_LIST
7952 || varp->v_type == VAR_DICT
7953 || varp->v_type == VAR_FUNC
7954 || varp->v_type == VAR_PARTIAL
7955 || varp->v_type == VAR_FLOAT)
7956 {
7957 typval_T tmp;
7958
7959 f_string(varp, &tmp);
7960 tv_get_string_buf(&tmp, buf);
7961 clear_tv(varp);
7962 *varp = tmp;
7963 return tmp.vval.v_string;
7964 }
7965 return tv_get_string_buf(varp, buf);
7966}
7967
7968/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007969 * Find variable "name" in the list of variables.
7970 * Return a pointer to it if found, NULL if not found.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007971 * Careful: "a:0" variables don't have a name.
Bram Moolenaara7043832005-01-21 11:56:39 +00007972 * When "htp" is not NULL we are writing to the variable, set "htp" to the
Bram Moolenaar33570922005-01-25 22:26:29 +00007973 * hashtab_T used.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007974 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02007975 dictitem_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007976find_var(char_u *name, hashtab_T **htp, int no_autoload)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007977{
Bram Moolenaar071d4272004-06-13 20:20:40 +00007978 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +00007979 hashtab_T *ht;
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02007980 dictitem_T *ret = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007981
Bram Moolenaara7043832005-01-21 11:56:39 +00007982 ht = find_var_ht(name, &varname);
7983 if (htp != NULL)
7984 *htp = ht;
7985 if (ht == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007986 return NULL;
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02007987 ret = find_var_in_ht(ht, *name, varname, no_autoload || htp != NULL);
7988 if (ret != NULL)
7989 return ret;
7990
7991 /* Search in parent scope for lambda */
Bram Moolenaarba96e9a2016-08-01 17:10:20 +02007992 return find_var_in_scoped_ht(name, no_autoload || htp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007993}
7994
7995/*
Bram Moolenaar332ac062013-04-15 13:06:21 +02007996 * Find variable "varname" in hashtab "ht" with name "htname".
Bram Moolenaara7043832005-01-21 11:56:39 +00007997 * Returns NULL if not found.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007998 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007999 dictitem_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01008000find_var_in_ht(
8001 hashtab_T *ht,
8002 int htname,
8003 char_u *varname,
8004 int no_autoload)
Bram Moolenaara7043832005-01-21 11:56:39 +00008005{
Bram Moolenaar33570922005-01-25 22:26:29 +00008006 hashitem_T *hi;
8007
8008 if (*varname == NUL)
8009 {
8010 /* Must be something like "s:", otherwise "ht" would be NULL. */
Bram Moolenaar332ac062013-04-15 13:06:21 +02008011 switch (htname)
Bram Moolenaar33570922005-01-25 22:26:29 +00008012 {
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02008013 case 's': return &SCRIPT_SV(current_sctx.sc_sid)->sv_var;
Bram Moolenaar33570922005-01-25 22:26:29 +00008014 case 'g': return &globvars_var;
8015 case 'v': return &vimvars_var;
8016 case 'b': return &curbuf->b_bufvar;
8017 case 'w': return &curwin->w_winvar;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00008018 case 't': return &curtab->tp_winvar;
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008019 case 'l': return get_funccal_local_var();
8020 case 'a': return get_funccal_args_var();
Bram Moolenaar33570922005-01-25 22:26:29 +00008021 }
8022 return NULL;
8023 }
Bram Moolenaara7043832005-01-21 11:56:39 +00008024
8025 hi = hash_find(ht, varname);
8026 if (HASHITEM_EMPTY(hi))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008027 {
8028 /* For global variables we may try auto-loading the script. If it
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00008029 * worked find the variable again. Don't auto-load a script if it was
8030 * loaded already, otherwise it would be loaded every time when
8031 * checking if a function name is a Funcref variable. */
Bram Moolenaar6d977d62014-01-14 15:24:39 +01008032 if (ht == &globvarht && !no_autoload)
Bram Moolenaar8000baf2011-11-30 15:19:28 +01008033 {
8034 /* Note: script_autoload() may make "hi" invalid. It must either
8035 * be obtained again or not used. */
8036 if (!script_autoload(varname, FALSE) || aborting())
8037 return NULL;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008038 hi = hash_find(ht, varname);
Bram Moolenaar8000baf2011-11-30 15:19:28 +01008039 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008040 if (HASHITEM_EMPTY(hi))
8041 return NULL;
8042 }
Bram Moolenaar33570922005-01-25 22:26:29 +00008043 return HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +00008044}
8045
8046/*
Bram Moolenaar33570922005-01-25 22:26:29 +00008047 * Find the hashtab used for a variable name.
Bram Moolenaar73627d02015-08-11 15:46:09 +02008048 * Return NULL if the name is not valid.
Bram Moolenaara7043832005-01-21 11:56:39 +00008049 * Set "varname" to the start of name without ':'.
8050 */
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02008051 hashtab_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01008052find_var_ht(char_u *name, char_u **varname)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008053{
Bram Moolenaar75c50c42005-06-04 22:06:24 +00008054 hashitem_T *hi;
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008055 hashtab_T *ht;
Bram Moolenaar75c50c42005-06-04 22:06:24 +00008056
Bram Moolenaar73627d02015-08-11 15:46:09 +02008057 if (name[0] == NUL)
8058 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008059 if (name[1] != ':')
8060 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00008061 /* The name must not start with a colon or #. */
8062 if (name[0] == ':' || name[0] == AUTOLOAD_CHAR)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008063 return NULL;
8064 *varname = name;
Bram Moolenaar532c7802005-01-27 14:44:31 +00008065
Bram Moolenaard2e716e2019-04-20 14:39:52 +02008066 // "version" is "v:version" in all scopes if scriptversion < 3.
8067 // Same for a few other variables marked with VV_COMPAT.
8068 if (current_sctx.sc_version < 3)
8069 {
8070 hi = hash_find(&compat_hashtab, name);
8071 if (!HASHITEM_EMPTY(hi))
8072 return &compat_hashtab;
8073 }
Bram Moolenaar532c7802005-01-27 14:44:31 +00008074
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008075 ht = get_funccal_local_ht();
8076 if (ht == NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +00008077 return &globvarht; /* global variable */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008078 return ht; /* local variable */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008079 }
8080 *varname = name + 2;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008081 if (*name == 'g') /* global variable */
8082 return &globvarht;
Bram Moolenaar4c6d9042019-07-16 22:04:02 +02008083 // There must be no ':' or '#' in the rest of the name, unless g: is used
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00008084 if (vim_strchr(name + 2, ':') != NULL
8085 || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008086 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008087 if (*name == 'b') /* buffer variable */
Bram Moolenaar429fa852013-04-15 12:27:36 +02008088 return &curbuf->b_vars->dv_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008089 if (*name == 'w') /* window variable */
Bram Moolenaar429fa852013-04-15 12:27:36 +02008090 return &curwin->w_vars->dv_hashtab;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00008091 if (*name == 't') /* tab page variable */
Bram Moolenaar429fa852013-04-15 12:27:36 +02008092 return &curtab->tp_vars->dv_hashtab;
Bram Moolenaar33570922005-01-25 22:26:29 +00008093 if (*name == 'v') /* v: variable */
8094 return &vimvarht;
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008095 if (*name == 'a') /* a: function argument */
8096 return get_funccal_args_ht();
8097 if (*name == 'l') /* l: local function variable */
8098 return get_funccal_local_ht();
Bram Moolenaar071d4272004-06-13 20:20:40 +00008099 if (*name == 's' /* script variable */
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02008100 && current_sctx.sc_sid > 0 && current_sctx.sc_sid <= ga_scripts.ga_len)
8101 return &SCRIPT_VARS(current_sctx.sc_sid);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008102 return NULL;
8103}
8104
8105/*
8106 * Get the string value of a (global/local) variable.
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008107 * Note: see tv_get_string() for how long the pointer remains valid.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008108 * Returns NULL when it doesn't exist.
8109 */
8110 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01008111get_var_value(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008112{
Bram Moolenaar33570922005-01-25 22:26:29 +00008113 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008114
Bram Moolenaar6d977d62014-01-14 15:24:39 +01008115 v = find_var(name, NULL, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008116 if (v == NULL)
8117 return NULL;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008118 return tv_get_string(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008119}
8120
8121/*
Bram Moolenaar33570922005-01-25 22:26:29 +00008122 * Allocate a new hashtab for a sourced script. It will be used while
Bram Moolenaar071d4272004-06-13 20:20:40 +00008123 * sourcing this script and when executing functions defined in the script.
8124 */
8125 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008126new_script_vars(scid_T id)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008127{
Bram Moolenaara7043832005-01-21 11:56:39 +00008128 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00008129 hashtab_T *ht;
8130 scriptvar_T *sv;
Bram Moolenaara7043832005-01-21 11:56:39 +00008131
Bram Moolenaar071d4272004-06-13 20:20:40 +00008132 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
8133 {
Bram Moolenaara7043832005-01-21 11:56:39 +00008134 /* Re-allocating ga_data means that an ht_array pointing to
8135 * ht_smallarray becomes invalid. We can recognize this: ht_mask is
Bram Moolenaar33570922005-01-25 22:26:29 +00008136 * at its init value. Also reset "v_dict", it's always the same. */
Bram Moolenaara7043832005-01-21 11:56:39 +00008137 for (i = 1; i <= ga_scripts.ga_len; ++i)
8138 {
8139 ht = &SCRIPT_VARS(i);
8140 if (ht->ht_mask == HT_INIT_SIZE - 1)
8141 ht->ht_array = ht->ht_smallarray;
Bram Moolenaar9577c3e2010-05-14 12:16:25 +02008142 sv = SCRIPT_SV(i);
Bram Moolenaar33570922005-01-25 22:26:29 +00008143 sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict;
Bram Moolenaara7043832005-01-21 11:56:39 +00008144 }
8145
Bram Moolenaar071d4272004-06-13 20:20:40 +00008146 while (ga_scripts.ga_len < id)
8147 {
Bram Moolenaar2c704a72010-06-03 21:17:25 +02008148 sv = SCRIPT_SV(ga_scripts.ga_len + 1) =
Bram Moolenaarc799fe22019-05-28 23:08:19 +02008149 ALLOC_CLEAR_ONE(scriptvar_T);
Bram Moolenaarbdb62052012-07-16 17:31:53 +02008150 init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008151 ++ga_scripts.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008152 }
8153 }
8154}
8155
8156/*
Bram Moolenaar33570922005-01-25 22:26:29 +00008157 * Initialize dictionary "dict" as a scope and set variable "dict_var" to
8158 * point to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008159 */
8160 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008161init_var_dict(dict_T *dict, dictitem_T *dict_var, int scope)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008162{
Bram Moolenaar33570922005-01-25 22:26:29 +00008163 hash_init(&dict->dv_hashtab);
Bram Moolenaared465602012-06-20 14:13:06 +02008164 dict->dv_lock = 0;
Bram Moolenaarbdb62052012-07-16 17:31:53 +02008165 dict->dv_scope = scope;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +00008166 dict->dv_refcount = DO_NOT_FREE_CNT;
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00008167 dict->dv_copyID = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00008168 dict_var->di_tv.vval.v_dict = dict;
8169 dict_var->di_tv.v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008170 dict_var->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +00008171 dict_var->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
8172 dict_var->di_key[0] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008173}
8174
8175/*
Bram Moolenaar429fa852013-04-15 12:27:36 +02008176 * Unreference a dictionary initialized by init_var_dict().
8177 */
8178 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008179unref_var_dict(dict_T *dict)
Bram Moolenaar429fa852013-04-15 12:27:36 +02008180{
8181 /* Now the dict needs to be freed if no one else is using it, go back to
8182 * normal reference counting. */
8183 dict->dv_refcount -= DO_NOT_FREE_CNT - 1;
8184 dict_unref(dict);
8185}
8186
8187/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008188 * Clean up a list of internal variables.
Bram Moolenaar33570922005-01-25 22:26:29 +00008189 * Frees all allocated variables and the value they contain.
8190 * Clears hashtab "ht", does not free it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008191 */
8192 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008193vars_clear(hashtab_T *ht)
Bram Moolenaar33570922005-01-25 22:26:29 +00008194{
8195 vars_clear_ext(ht, TRUE);
8196}
8197
8198/*
8199 * Like vars_clear(), but only free the value if "free_val" is TRUE.
8200 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008201 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008202vars_clear_ext(hashtab_T *ht, int free_val)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008203{
Bram Moolenaara7043832005-01-21 11:56:39 +00008204 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00008205 hashitem_T *hi;
8206 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008207
Bram Moolenaar33570922005-01-25 22:26:29 +00008208 hash_lock(ht);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008209 todo = (int)ht->ht_used;
Bram Moolenaara7043832005-01-21 11:56:39 +00008210 for (hi = ht->ht_array; todo > 0; ++hi)
8211 {
8212 if (!HASHITEM_EMPTY(hi))
8213 {
8214 --todo;
8215
Bram Moolenaar33570922005-01-25 22:26:29 +00008216 /* Free the variable. Don't remove it from the hashtab,
Bram Moolenaara7043832005-01-21 11:56:39 +00008217 * ht_array might change then. hash_clear() takes care of it
8218 * later. */
Bram Moolenaar33570922005-01-25 22:26:29 +00008219 v = HI2DI(hi);
8220 if (free_val)
8221 clear_tv(&v->di_tv);
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02008222 if (v->di_flags & DI_FLAGS_ALLOC)
Bram Moolenaar33570922005-01-25 22:26:29 +00008223 vim_free(v);
Bram Moolenaara7043832005-01-21 11:56:39 +00008224 }
8225 }
8226 hash_clear(ht);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00008227 ht->ht_used = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008228}
8229
Bram Moolenaara7043832005-01-21 11:56:39 +00008230/*
Bram Moolenaar33570922005-01-25 22:26:29 +00008231 * Delete a variable from hashtab "ht" at item "hi".
8232 * Clear the variable value and free the dictitem.
Bram Moolenaara7043832005-01-21 11:56:39 +00008233 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008234 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008235delete_var(hashtab_T *ht, hashitem_T *hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008236{
Bram Moolenaar33570922005-01-25 22:26:29 +00008237 dictitem_T *di = HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +00008238
8239 hash_remove(ht, hi);
Bram Moolenaar33570922005-01-25 22:26:29 +00008240 clear_tv(&di->di_tv);
8241 vim_free(di);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008242}
8243
8244/*
8245 * List the value of one internal variable.
8246 */
8247 static void
Bram Moolenaar32526b32019-01-19 17:43:09 +01008248list_one_var(dictitem_T *v, char *prefix, int *first)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008249{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008250 char_u *tofree;
8251 char_u *s;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008252 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008253
Bram Moolenaar520e1e42016-01-23 19:46:28 +01008254 s = echo_string(&v->di_tv, &tofree, numbuf, get_copyID());
Bram Moolenaar33570922005-01-25 22:26:29 +00008255 list_one_var_a(prefix, v->di_key, v->di_tv.v_type,
Bram Moolenaar7d61a922007-08-30 09:12:23 +00008256 s == NULL ? (char_u *)"" : s, first);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008257 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008258}
8259
Bram Moolenaar071d4272004-06-13 20:20:40 +00008260 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008261list_one_var_a(
Bram Moolenaar32526b32019-01-19 17:43:09 +01008262 char *prefix,
Bram Moolenaar7454a062016-01-30 15:14:10 +01008263 char_u *name,
8264 int type,
8265 char_u *string,
8266 int *first) /* when TRUE clear rest of screen and set to FALSE */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008267{
Bram Moolenaar31859182007-08-14 20:41:13 +00008268 /* don't use msg() or msg_attr() to avoid overwriting "v:statusmsg" */
8269 msg_start();
8270 msg_puts(prefix);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008271 if (name != NULL) /* "a:" vars don't have a name stored */
Bram Moolenaar32526b32019-01-19 17:43:09 +01008272 msg_puts((char *)name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008273 msg_putchar(' ');
8274 msg_advance(22);
8275 if (type == VAR_NUMBER)
8276 msg_putchar('#');
Bram Moolenaar1735bc92016-03-14 23:05:14 +01008277 else if (type == VAR_FUNC || type == VAR_PARTIAL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008278 msg_putchar('*');
8279 else if (type == VAR_LIST)
8280 {
8281 msg_putchar('[');
8282 if (*string == '[')
8283 ++string;
8284 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00008285 else if (type == VAR_DICT)
8286 {
8287 msg_putchar('{');
8288 if (*string == '{')
8289 ++string;
8290 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008291 else
8292 msg_putchar(' ');
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008293
Bram Moolenaar071d4272004-06-13 20:20:40 +00008294 msg_outtrans(string);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008295
Bram Moolenaar1735bc92016-03-14 23:05:14 +01008296 if (type == VAR_FUNC || type == VAR_PARTIAL)
Bram Moolenaar32526b32019-01-19 17:43:09 +01008297 msg_puts("()");
Bram Moolenaar7d61a922007-08-30 09:12:23 +00008298 if (*first)
8299 {
8300 msg_clr_eos();
8301 *first = FALSE;
8302 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008303}
8304
8305/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008306 * Set variable "name" to value in "tv".
Bram Moolenaar071d4272004-06-13 20:20:40 +00008307 * If the variable already exists, the value is updated.
8308 * Otherwise the variable is created.
8309 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008310 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008311set_var(
8312 char_u *name,
8313 typval_T *tv,
Bram Moolenaar9937a052019-06-15 15:45:06 +02008314 int copy) // make copy of value in "tv"
8315{
8316 set_var_const(name, tv, copy, FALSE);
8317}
8318
8319/*
8320 * Set variable "name" to value in "tv".
8321 * If the variable already exists and "is_const" is FALSE the value is updated.
8322 * Otherwise the variable is created.
8323 */
8324 static void
8325set_var_const(
8326 char_u *name,
8327 typval_T *tv,
8328 int copy, // make copy of value in "tv"
8329 int is_const) // disallow to modify existing variable
Bram Moolenaar071d4272004-06-13 20:20:40 +00008330{
Bram Moolenaar33570922005-01-25 22:26:29 +00008331 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008332 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +00008333 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008334
Bram Moolenaarbaff0fe2010-03-17 19:53:49 +01008335 ht = find_var_ht(name, &varname);
8336 if (ht == NULL || *varname == NUL)
8337 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008338 semsg(_(e_illvar), name);
Bram Moolenaarbaff0fe2010-03-17 19:53:49 +01008339 return;
8340 }
Bram Moolenaar332ac062013-04-15 13:06:21 +02008341 v = find_var_in_ht(ht, 0, varname, TRUE);
Bram Moolenaarbaff0fe2010-03-17 19:53:49 +01008342
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02008343 /* Search in parent scope which is possible to reference from lambda */
8344 if (v == NULL)
Bram Moolenaarba96e9a2016-08-01 17:10:20 +02008345 v = find_var_in_scoped_ht(name, TRUE);
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02008346
Bram Moolenaar1735bc92016-03-14 23:05:14 +01008347 if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL)
8348 && var_check_func_name(name, v == NULL))
Bram Moolenaar4228bec2011-03-27 16:03:15 +02008349 return;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008350
Bram Moolenaar33570922005-01-25 22:26:29 +00008351 if (v != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008352 {
Bram Moolenaar9937a052019-06-15 15:45:06 +02008353 if (is_const)
8354 {
8355 emsg(_(e_cannot_mod));
8356 return;
8357 }
8358
Bram Moolenaar33570922005-01-25 22:26:29 +00008359 /* existing variable, need to clear the value */
Bram Moolenaar77354e72015-04-21 16:49:05 +02008360 if (var_check_ro(v->di_flags, name, FALSE)
Bram Moolenaar05c00c02019-02-11 22:00:11 +01008361 || var_check_lock(v->di_tv.v_lock, name, FALSE))
Bram Moolenaar33570922005-01-25 22:26:29 +00008362 return;
Bram Moolenaar33570922005-01-25 22:26:29 +00008363
8364 /*
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02008365 * Handle setting internal v: variables separately where needed to
8366 * prevent changing the type.
Bram Moolenaar33570922005-01-25 22:26:29 +00008367 */
8368 if (ht == &vimvarht)
8369 {
8370 if (v->di_tv.v_type == VAR_STRING)
8371 {
Bram Moolenaar4b9e91f2019-01-24 13:58:11 +01008372 VIM_CLEAR(v->di_tv.vval.v_string);
Bram Moolenaar33570922005-01-25 22:26:29 +00008373 if (copy || tv->v_type != VAR_STRING)
Bram Moolenaar4b9e91f2019-01-24 13:58:11 +01008374 {
8375 char_u *val = tv_get_string(tv);
8376
8377 // Careful: when assigning to v:errmsg and tv_get_string()
8378 // causes an error message the variable will alrady be set.
8379 if (v->di_tv.vval.v_string == NULL)
8380 v->di_tv.vval.v_string = vim_strsave(val);
8381 }
Bram Moolenaar33570922005-01-25 22:26:29 +00008382 else
8383 {
8384 /* Take over the string to avoid an extra alloc/free. */
8385 v->di_tv.vval.v_string = tv->vval.v_string;
8386 tv->vval.v_string = NULL;
8387 }
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02008388 return;
Bram Moolenaar33570922005-01-25 22:26:29 +00008389 }
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02008390 else if (v->di_tv.v_type == VAR_NUMBER)
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008391 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008392 v->di_tv.vval.v_number = tv_get_number(tv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008393 if (STRCMP(varname, "searchforward") == 0)
8394 set_search_direction(v->di_tv.vval.v_number ? '/' : '?');
Bram Moolenaar8050efa2013-11-08 04:30:20 +01008395#ifdef FEAT_SEARCH_EXTRA
8396 else if (STRCMP(varname, "hlsearch") == 0)
8397 {
8398 no_hlsearch = !v->di_tv.vval.v_number;
8399 redraw_all_later(SOME_VALID);
8400 }
8401#endif
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02008402 return;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008403 }
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02008404 else if (v->di_tv.v_type != tv->v_type)
Bram Moolenaar88b53fd2018-12-05 18:43:28 +01008405 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008406 semsg(_("E963: setting %s to value with wrong type"), name);
Bram Moolenaar88b53fd2018-12-05 18:43:28 +01008407 return;
8408 }
Bram Moolenaar33570922005-01-25 22:26:29 +00008409 }
8410
8411 clear_tv(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008412 }
8413 else /* add a new variable */
8414 {
Bram Moolenaar31b81602019-02-10 22:14:27 +01008415 // Can't add "v:" or "a:" variable.
8416 if (ht == &vimvarht || ht == get_funccal_args_ht())
Bram Moolenaar5fcc3fe2006-06-22 15:35:14 +00008417 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008418 semsg(_(e_illvar), name);
Bram Moolenaar5fcc3fe2006-06-22 15:35:14 +00008419 return;
8420 }
8421
Bram Moolenaar31b81602019-02-10 22:14:27 +01008422 // Make sure the variable name is valid.
Bram Moolenaar4228bec2011-03-27 16:03:15 +02008423 if (!valid_varname(varname))
8424 return;
Bram Moolenaar92124a32005-06-17 22:03:40 +00008425
Bram Moolenaarc799fe22019-05-28 23:08:19 +02008426 v = alloc(sizeof(dictitem_T) + STRLEN(varname));
Bram Moolenaara7043832005-01-21 11:56:39 +00008427 if (v == NULL)
8428 return;
Bram Moolenaar33570922005-01-25 22:26:29 +00008429 STRCPY(v->di_key, varname);
Bram Moolenaar33570922005-01-25 22:26:29 +00008430 if (hash_add(ht, DI2HIKEY(v)) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008431 {
Bram Moolenaara7043832005-01-21 11:56:39 +00008432 vim_free(v);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008433 return;
8434 }
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02008435 v->di_flags = DI_FLAGS_ALLOC;
Bram Moolenaar9937a052019-06-15 15:45:06 +02008436 if (is_const)
8437 v->di_flags |= DI_FLAGS_LOCK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008438 }
Bram Moolenaara7043832005-01-21 11:56:39 +00008439
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008440 if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT)
Bram Moolenaar33570922005-01-25 22:26:29 +00008441 copy_tv(tv, &v->di_tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +00008442 else
8443 {
Bram Moolenaar33570922005-01-25 22:26:29 +00008444 v->di_tv = *tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008445 v->di_tv.v_lock = 0;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008446 init_tv(tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +00008447 }
Bram Moolenaar9937a052019-06-15 15:45:06 +02008448
8449 if (is_const)
8450 v->di_tv.v_lock |= VAR_LOCKED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008451}
8452
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008453/*
Bram Moolenaar4e957af2006-09-02 11:41:07 +00008454 * Return TRUE if di_flags "flags" indicates variable "name" is read-only.
Bram Moolenaar33570922005-01-25 22:26:29 +00008455 * Also give an error message.
8456 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02008457 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01008458var_check_ro(int flags, char_u *name, int use_gettext)
Bram Moolenaar33570922005-01-25 22:26:29 +00008459{
8460 if (flags & DI_FLAGS_RO)
8461 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008462 semsg(_(e_readonlyvar), use_gettext ? (char_u *)_(name) : name);
Bram Moolenaar33570922005-01-25 22:26:29 +00008463 return TRUE;
8464 }
8465 if ((flags & DI_FLAGS_RO_SBX) && sandbox)
8466 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008467 semsg(_(e_readonlysbx), use_gettext ? (char_u *)_(name) : name);
Bram Moolenaar33570922005-01-25 22:26:29 +00008468 return TRUE;
8469 }
8470 return FALSE;
8471}
8472
8473/*
Bram Moolenaar4e957af2006-09-02 11:41:07 +00008474 * Return TRUE if di_flags "flags" indicates variable "name" is fixed.
8475 * Also give an error message.
8476 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008477 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01008478var_check_fixed(int flags, char_u *name, int use_gettext)
Bram Moolenaar4e957af2006-09-02 11:41:07 +00008479{
8480 if (flags & DI_FLAGS_FIX)
8481 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008482 semsg(_("E795: Cannot delete variable %s"),
Bram Moolenaar77354e72015-04-21 16:49:05 +02008483 use_gettext ? (char_u *)_(name) : name);
Bram Moolenaar4e957af2006-09-02 11:41:07 +00008484 return TRUE;
8485 }
8486 return FALSE;
8487}
8488
8489/*
Bram Moolenaar4228bec2011-03-27 16:03:15 +02008490 * Check if a funcref is assigned to a valid variable name.
8491 * Return TRUE and give an error if not.
8492 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02008493 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01008494var_check_func_name(
8495 char_u *name, /* points to start of variable name */
8496 int new_var) /* TRUE when creating the variable */
Bram Moolenaar4228bec2011-03-27 16:03:15 +02008497{
Bram Moolenaarcbc67722014-05-22 14:19:56 +02008498 /* Allow for w: b: s: and t:. */
8499 if (!(vim_strchr((char_u *)"wbst", name[0]) != NULL && name[1] == ':')
Bram Moolenaar4228bec2011-03-27 16:03:15 +02008500 && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
8501 ? name[2] : name[0]))
8502 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008503 semsg(_("E704: Funcref variable name must start with a capital: %s"),
Bram Moolenaar4228bec2011-03-27 16:03:15 +02008504 name);
8505 return TRUE;
8506 }
8507 /* Don't allow hiding a function. When "v" is not NULL we might be
8508 * assigning another function to the same var, the type is checked
8509 * below. */
Bram Moolenaarb54c3ff2016-07-31 14:11:58 +02008510 if (new_var && function_exists(name, FALSE))
Bram Moolenaar4228bec2011-03-27 16:03:15 +02008511 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008512 semsg(_("E705: Variable name conflicts with existing function: %s"),
Bram Moolenaar4228bec2011-03-27 16:03:15 +02008513 name);
8514 return TRUE;
8515 }
8516 return FALSE;
8517}
8518
8519/*
Bram Moolenaar05c00c02019-02-11 22:00:11 +01008520 * Return TRUE if "flags" indicates variable "name" is locked (immutable).
Bram Moolenaar77354e72015-04-21 16:49:05 +02008521 * Also give an error message, using "name" or _("name") when use_gettext is
8522 * TRUE.
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008523 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02008524 int
Bram Moolenaar05c00c02019-02-11 22:00:11 +01008525var_check_lock(int lock, char_u *name, int use_gettext)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008526{
8527 if (lock & VAR_LOCKED)
8528 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008529 semsg(_("E741: Value is locked: %s"),
Bram Moolenaar77354e72015-04-21 16:49:05 +02008530 name == NULL ? (char_u *)_("Unknown")
8531 : use_gettext ? (char_u *)_(name)
8532 : name);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008533 return TRUE;
8534 }
8535 if (lock & VAR_FIXED)
8536 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008537 semsg(_("E742: Cannot change value of %s"),
Bram Moolenaar77354e72015-04-21 16:49:05 +02008538 name == NULL ? (char_u *)_("Unknown")
8539 : use_gettext ? (char_u *)_(name)
8540 : name);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008541 return TRUE;
8542 }
8543 return FALSE;
8544}
8545
8546/*
Bram Moolenaar05c00c02019-02-11 22:00:11 +01008547 * Return TRUE if typeval "tv" and its value are set to be locked (immutable).
8548 * Also give an error message, using "name" or _("name") when use_gettext is
8549 * TRUE.
8550 */
8551 static int
8552tv_check_lock(typval_T *tv, char_u *name, int use_gettext)
8553{
8554 int lock = 0;
8555
8556 switch (tv->v_type)
8557 {
8558 case VAR_BLOB:
8559 if (tv->vval.v_blob != NULL)
8560 lock = tv->vval.v_blob->bv_lock;
8561 break;
8562 case VAR_LIST:
8563 if (tv->vval.v_list != NULL)
8564 lock = tv->vval.v_list->lv_lock;
8565 break;
8566 case VAR_DICT:
8567 if (tv->vval.v_dict != NULL)
8568 lock = tv->vval.v_dict->dv_lock;
8569 break;
8570 default:
8571 break;
8572 }
8573 return var_check_lock(tv->v_lock, name, use_gettext)
8574 || (lock != 0 && var_check_lock(lock, name, use_gettext));
8575}
8576
8577/*
8578 * Check if a variable name is valid.
8579 * Return FALSE and give an error if not.
8580 */
8581 int
8582valid_varname(char_u *varname)
8583{
8584 char_u *p;
8585
8586 for (p = varname; *p != NUL; ++p)
8587 if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p))
8588 && *p != AUTOLOAD_CHAR)
8589 {
8590 semsg(_(e_illvar), varname);
8591 return FALSE;
8592 }
8593 return TRUE;
8594}
8595
8596/*
Bram Moolenaar33570922005-01-25 22:26:29 +00008597 * Copy the values from typval_T "from" to typval_T "to".
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008598 * When needed allocates string or increases reference count.
Bram Moolenaardd29ea12019-01-23 21:56:21 +01008599 * Does not make a copy of a list, blob or dict but copies the reference!
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +00008600 * It is OK for "from" and "to" to point to the same item. This is used to
8601 * make a copy later.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008602 */
Bram Moolenaar7e506b62010-01-19 15:55:06 +01008603 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008604copy_tv(typval_T *from, typval_T *to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008605{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008606 to->v_type = from->v_type;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008607 to->v_lock = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008608 switch (from->v_type)
8609 {
8610 case VAR_NUMBER:
Bram Moolenaar520e1e42016-01-23 19:46:28 +01008611 case VAR_SPECIAL:
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008612 to->vval.v_number = from->vval.v_number;
8613 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008614 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01008615#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008616 to->vval.v_float = from->vval.v_float;
8617 break;
8618#endif
Bram Moolenaar835dc632016-02-07 14:27:38 +01008619 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01008620#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +01008621 to->vval.v_job = from->vval.v_job;
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01008622 if (to->vval.v_job != NULL)
8623 ++to->vval.v_job->jv_refcount;
Bram Moolenaar835dc632016-02-07 14:27:38 +01008624 break;
8625#endif
Bram Moolenaar77073442016-02-13 23:23:53 +01008626 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01008627#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +01008628 to->vval.v_channel = from->vval.v_channel;
Bram Moolenaar5cefd402016-02-16 12:44:26 +01008629 if (to->vval.v_channel != NULL)
8630 ++to->vval.v_channel->ch_refcount;
Bram Moolenaar77073442016-02-13 23:23:53 +01008631 break;
8632#endif
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008633 case VAR_STRING:
8634 case VAR_FUNC:
8635 if (from->vval.v_string == NULL)
8636 to->vval.v_string = NULL;
8637 else
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00008638 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008639 to->vval.v_string = vim_strsave(from->vval.v_string);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00008640 if (from->v_type == VAR_FUNC)
8641 func_ref(to->vval.v_string);
8642 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008643 break;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01008644 case VAR_PARTIAL:
8645 if (from->vval.v_partial == NULL)
8646 to->vval.v_partial = NULL;
8647 else
8648 {
8649 to->vval.v_partial = from->vval.v_partial;
8650 ++to->vval.v_partial->pt_refcount;
8651 }
8652 break;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01008653 case VAR_BLOB:
8654 if (from->vval.v_blob == NULL)
8655 to->vval.v_blob = NULL;
8656 else
8657 {
8658 to->vval.v_blob = from->vval.v_blob;
8659 ++to->vval.v_blob->bv_refcount;
8660 }
8661 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008662 case VAR_LIST:
8663 if (from->vval.v_list == NULL)
8664 to->vval.v_list = NULL;
8665 else
8666 {
8667 to->vval.v_list = from->vval.v_list;
8668 ++to->vval.v_list->lv_refcount;
8669 }
8670 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00008671 case VAR_DICT:
8672 if (from->vval.v_dict == NULL)
8673 to->vval.v_dict = NULL;
8674 else
8675 {
8676 to->vval.v_dict = from->vval.v_dict;
8677 ++to->vval.v_dict->dv_refcount;
8678 }
8679 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +01008680 case VAR_UNKNOWN:
Bram Moolenaar95f09602016-11-10 20:01:45 +01008681 internal_error("copy_tv(UNKNOWN)");
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008682 break;
8683 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008684}
8685
8686/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00008687 * Make a copy of an item.
8688 * Lists and Dictionaries are also copied. A deep copy if "deep" is set.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008689 * For deepcopy() "copyID" is zero for a full copy or the ID for when a
8690 * reference to an already copied list/dict can be used.
8691 * Returns FAIL or OK.
Bram Moolenaare9a41262005-01-15 22:18:47 +00008692 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02008693 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01008694item_copy(
8695 typval_T *from,
8696 typval_T *to,
8697 int deep,
8698 int copyID)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008699{
8700 static int recurse = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008701 int ret = OK;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008702
Bram Moolenaar33570922005-01-25 22:26:29 +00008703 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008704 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008705 emsg(_("E698: variable nested too deep for making a copy"));
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008706 return FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008707 }
8708 ++recurse;
8709
8710 switch (from->v_type)
8711 {
8712 case VAR_NUMBER:
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008713 case VAR_FLOAT:
Bram Moolenaare9a41262005-01-15 22:18:47 +00008714 case VAR_STRING:
8715 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01008716 case VAR_PARTIAL:
Bram Moolenaar15550002016-01-31 18:45:24 +01008717 case VAR_SPECIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01008718 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01008719 case VAR_CHANNEL:
Bram Moolenaare9a41262005-01-15 22:18:47 +00008720 copy_tv(from, to);
8721 break;
8722 case VAR_LIST:
8723 to->v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008724 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008725 if (from->vval.v_list == NULL)
8726 to->vval.v_list = NULL;
8727 else if (copyID != 0 && from->vval.v_list->lv_copyID == copyID)
8728 {
8729 /* use the copy made earlier */
8730 to->vval.v_list = from->vval.v_list->lv_copylist;
8731 ++to->vval.v_list->lv_refcount;
8732 }
8733 else
8734 to->vval.v_list = list_copy(from->vval.v_list, deep, copyID);
8735 if (to->vval.v_list == NULL)
8736 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008737 break;
Bram Moolenaar3d28b582019-01-15 22:44:17 +01008738 case VAR_BLOB:
Bram Moolenaardd29ea12019-01-23 21:56:21 +01008739 ret = blob_copy(from, to);
Bram Moolenaar3d28b582019-01-15 22:44:17 +01008740 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008741 case VAR_DICT:
8742 to->v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008743 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008744 if (from->vval.v_dict == NULL)
8745 to->vval.v_dict = NULL;
8746 else if (copyID != 0 && from->vval.v_dict->dv_copyID == copyID)
8747 {
8748 /* use the copy made earlier */
8749 to->vval.v_dict = from->vval.v_dict->dv_copydict;
8750 ++to->vval.v_dict->dv_refcount;
8751 }
8752 else
8753 to->vval.v_dict = dict_copy(from->vval.v_dict, deep, copyID);
8754 if (to->vval.v_dict == NULL)
8755 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008756 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +01008757 case VAR_UNKNOWN:
Bram Moolenaar95f09602016-11-10 20:01:45 +01008758 internal_error("item_copy(UNKNOWN)");
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008759 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008760 }
8761 --recurse;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008762 return ret;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008763}
8764
8765/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008766 * This function is used by f_input() and f_inputdialog() functions. The third
8767 * argument to f_input() specifies the type of completion to use at the
8768 * prompt. The third argument to f_inputdialog() specifies the value to return
8769 * when the user cancels the prompt.
8770 */
8771 void
8772get_user_input(
8773 typval_T *argvars,
8774 typval_T *rettv,
8775 int inputdialog,
8776 int secret)
8777{
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008778 char_u *prompt = tv_get_string_chk(&argvars[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008779 char_u *p = NULL;
8780 int c;
8781 char_u buf[NUMBUFLEN];
8782 int cmd_silent_save = cmd_silent;
8783 char_u *defstr = (char_u *)"";
8784 int xp_type = EXPAND_NOTHING;
8785 char_u *xp_arg = NULL;
8786
8787 rettv->v_type = VAR_STRING;
8788 rettv->vval.v_string = NULL;
8789
8790#ifdef NO_CONSOLE_INPUT
Bram Moolenaar91d348a2017-07-29 20:16:03 +02008791 /* While starting up, there is no place to enter text. When running tests
8792 * with --not-a-term we assume feedkeys() will be used. */
8793 if (no_console_input() && !is_not_a_term())
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008794 return;
8795#endif
8796
8797 cmd_silent = FALSE; /* Want to see the prompt. */
8798 if (prompt != NULL)
8799 {
8800 /* Only the part of the message after the last NL is considered as
8801 * prompt for the command line */
8802 p = vim_strrchr(prompt, '\n');
8803 if (p == NULL)
8804 p = prompt;
8805 else
8806 {
8807 ++p;
8808 c = *p;
8809 *p = NUL;
8810 msg_start();
8811 msg_clr_eos();
Bram Moolenaar32526b32019-01-19 17:43:09 +01008812 msg_puts_attr((char *)prompt, echo_attr);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008813 msg_didout = FALSE;
8814 msg_starthere();
8815 *p = c;
8816 }
8817 cmdline_row = msg_row;
8818
8819 if (argvars[1].v_type != VAR_UNKNOWN)
8820 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008821 defstr = tv_get_string_buf_chk(&argvars[1], buf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008822 if (defstr != NULL)
8823 stuffReadbuffSpec(defstr);
8824
8825 if (!inputdialog && argvars[2].v_type != VAR_UNKNOWN)
8826 {
8827 char_u *xp_name;
8828 int xp_namelen;
8829 long argt;
8830
8831 /* input() with a third argument: completion */
8832 rettv->vval.v_string = NULL;
8833
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008834 xp_name = tv_get_string_buf_chk(&argvars[2], buf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008835 if (xp_name == NULL)
8836 return;
8837
8838 xp_namelen = (int)STRLEN(xp_name);
8839
8840 if (parse_compl_arg(xp_name, xp_namelen, &xp_type, &argt,
8841 &xp_arg) == FAIL)
8842 return;
8843 }
8844 }
8845
8846 if (defstr != NULL)
8847 {
8848 int save_ex_normal_busy = ex_normal_busy;
Bram Moolenaar6dff58f2018-09-30 21:43:26 +02008849
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008850 ex_normal_busy = 0;
8851 rettv->vval.v_string =
8852 getcmdline_prompt(secret ? NUL : '@', p, echo_attr,
8853 xp_type, xp_arg);
8854 ex_normal_busy = save_ex_normal_busy;
8855 }
8856 if (inputdialog && rettv->vval.v_string == NULL
8857 && argvars[1].v_type != VAR_UNKNOWN
8858 && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008859 rettv->vval.v_string = vim_strsave(tv_get_string_buf(
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008860 &argvars[2], buf));
8861
8862 vim_free(xp_arg);
8863
8864 /* since the user typed this, no need to wait for return */
8865 need_wait_return = FALSE;
8866 msg_didout = FALSE;
8867 }
8868 cmd_silent = cmd_silent_save;
8869}
8870
8871/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008872 * ":echo expr1 ..." print each argument separated with a space, add a
8873 * newline at the end.
8874 * ":echon expr1 ..." print each argument plain.
8875 */
8876 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008877ex_echo(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008878{
8879 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00008880 typval_T rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008881 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008882 char_u *p;
8883 int needclr = TRUE;
8884 int atstart = TRUE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008885 char_u numbuf[NUMBUFLEN];
Bram Moolenaar76a63452018-11-28 20:38:37 +01008886 int did_emsg_before = did_emsg;
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01008887 int called_emsg_before = called_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008888
8889 if (eap->skip)
8890 ++emsg_skip;
8891 while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int)
8892 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008893 /* If eval1() causes an error message the text from the command may
8894 * still need to be cleared. E.g., "echo 22,44". */
8895 need_clr_eos = needclr;
8896
Bram Moolenaar071d4272004-06-13 20:20:40 +00008897 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008898 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008899 {
8900 /*
8901 * Report the invalid expression unless the expression evaluation
8902 * has been cancelled due to an aborting error, an interrupt, or an
8903 * exception.
8904 */
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01008905 if (!aborting() && did_emsg == did_emsg_before
8906 && called_emsg == called_emsg_before)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008907 semsg(_(e_invexpr2), p);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008908 need_clr_eos = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008909 break;
8910 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008911 need_clr_eos = FALSE;
8912
Bram Moolenaar071d4272004-06-13 20:20:40 +00008913 if (!eap->skip)
8914 {
8915 if (atstart)
8916 {
8917 atstart = FALSE;
8918 /* Call msg_start() after eval1(), evaluating the expression
8919 * may cause a message to appear. */
8920 if (eap->cmdidx == CMD_echo)
Bram Moolenaar12b02902012-03-23 15:18:24 +01008921 {
Bram Moolenaar6df5e5a2012-03-28 16:49:29 +02008922 /* Mark the saved text as finishing the line, so that what
8923 * follows is displayed on a new line when scrolling back
8924 * at the more prompt. */
8925 msg_sb_eol();
Bram Moolenaar071d4272004-06-13 20:20:40 +00008926 msg_start();
Bram Moolenaar12b02902012-03-23 15:18:24 +01008927 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008928 }
8929 else if (eap->cmdidx == CMD_echo)
Bram Moolenaar32526b32019-01-19 17:43:09 +01008930 msg_puts_attr(" ", echo_attr);
Bram Moolenaar520e1e42016-01-23 19:46:28 +01008931 p = echo_string(&rettv, &tofree, numbuf, get_copyID());
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008932 if (p != NULL)
8933 for ( ; *p != NUL && !got_int; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008934 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008935 if (*p == '\n' || *p == '\r' || *p == TAB)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008936 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008937 if (*p != TAB && needclr)
8938 {
8939 /* remove any text still there from the command */
8940 msg_clr_eos();
8941 needclr = FALSE;
8942 }
8943 msg_putchar_attr(*p, echo_attr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008944 }
8945 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008946 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008947 if (has_mbyte)
8948 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00008949 int i = (*mb_ptr2len)(p);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008950
8951 (void)msg_outtrans_len_attr(p, i, echo_attr);
8952 p += i - 1;
8953 }
8954 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008955 (void)msg_outtrans_len_attr(p, 1, echo_attr);
8956 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008957 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008958 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008959 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008960 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008961 arg = skipwhite(arg);
8962 }
8963 eap->nextcmd = check_nextcmd(arg);
8964
8965 if (eap->skip)
8966 --emsg_skip;
8967 else
8968 {
8969 /* remove text that may still be there from the command */
8970 if (needclr)
8971 msg_clr_eos();
8972 if (eap->cmdidx == CMD_echo)
8973 msg_end();
8974 }
8975}
8976
8977/*
8978 * ":echohl {name}".
8979 */
8980 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008981ex_echohl(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008982{
Bram Moolenaar1b9645d2017-09-17 23:03:31 +02008983 echo_attr = syn_name2attr(eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008984}
8985
8986/*
8987 * ":execute expr1 ..." execute the result of an expression.
8988 * ":echomsg expr1 ..." Print a message
8989 * ":echoerr expr1 ..." Print an error
8990 * Each gets spaces around each argument and a newline at the end for
8991 * echo commands
8992 */
8993 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008994ex_execute(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008995{
8996 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00008997 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008998 int ret = OK;
8999 char_u *p;
9000 garray_T ga;
9001 int len;
Bram Moolenaar2c519cf2019-03-21 21:45:34 +01009002 int save_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009003
9004 ga_init2(&ga, 1, 80);
9005
9006 if (eap->skip)
9007 ++emsg_skip;
9008 while (*arg != NUL && *arg != '|' && *arg != '\n')
9009 {
Bram Moolenaarce9d50d2019-01-14 22:22:29 +01009010 ret = eval1_emsg(&arg, &rettv, !eap->skip);
9011 if (ret == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009012 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009013
9014 if (!eap->skip)
9015 {
Bram Moolenaar461a7fc2018-12-22 13:28:07 +01009016 char_u buf[NUMBUFLEN];
9017
9018 if (eap->cmdidx == CMD_execute)
9019 p = tv_get_string_buf(&rettv, buf);
9020 else
9021 p = tv_stringify(&rettv, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009022 len = (int)STRLEN(p);
9023 if (ga_grow(&ga, len + 2) == FAIL)
9024 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009025 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009026 ret = FAIL;
9027 break;
9028 }
9029 if (ga.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009030 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
Bram Moolenaar071d4272004-06-13 20:20:40 +00009031 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009032 ga.ga_len += len;
9033 }
9034
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009035 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009036 arg = skipwhite(arg);
9037 }
9038
9039 if (ret != FAIL && ga.ga_data != NULL)
9040 {
Bram Moolenaar57002ad2017-03-16 19:04:19 +01009041 if (eap->cmdidx == CMD_echomsg || eap->cmdidx == CMD_echoerr)
9042 {
9043 /* Mark the already saved text as finishing the line, so that what
9044 * follows is displayed on a new line when scrolling back at the
9045 * more prompt. */
9046 msg_sb_eol();
Bram Moolenaar57002ad2017-03-16 19:04:19 +01009047 }
9048
Bram Moolenaar071d4272004-06-13 20:20:40 +00009049 if (eap->cmdidx == CMD_echomsg)
Bram Moolenaar4770d092006-01-12 23:22:24 +00009050 {
Bram Moolenaar32526b32019-01-19 17:43:09 +01009051 msg_attr(ga.ga_data, echo_attr);
Bram Moolenaar4770d092006-01-12 23:22:24 +00009052 out_flush();
9053 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009054 else if (eap->cmdidx == CMD_echoerr)
9055 {
9056 /* We don't want to abort following commands, restore did_emsg. */
9057 save_did_emsg = did_emsg;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01009058 emsg(ga.ga_data);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009059 if (!force_abort)
9060 did_emsg = save_did_emsg;
9061 }
9062 else if (eap->cmdidx == CMD_execute)
9063 do_cmdline((char_u *)ga.ga_data,
9064 eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE);
9065 }
9066
9067 ga_clear(&ga);
9068
9069 if (eap->skip)
9070 --emsg_skip;
9071
9072 eap->nextcmd = check_nextcmd(arg);
9073}
9074
9075/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009076 * Find window specified by "vp" in tabpage "tp".
9077 */
9078 win_T *
9079find_win_by_nr(
9080 typval_T *vp,
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009081 tabpage_T *tp) /* NULL for current tab page */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009082{
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009083 win_T *wp;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009084 int nr = (int)tv_get_number_chk(vp, NULL);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009085
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009086 if (nr < 0)
9087 return NULL;
9088 if (nr == 0)
9089 return curwin;
9090
Bram Moolenaar29323592016-07-24 22:04:11 +02009091 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
9092 {
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009093 if (nr >= LOWEST_WIN_ID)
9094 {
9095 if (wp->w_id == nr)
9096 return wp;
9097 }
9098 else if (--nr <= 0)
9099 break;
Bram Moolenaar29323592016-07-24 22:04:11 +02009100 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009101 if (nr >= LOWEST_WIN_ID)
Bram Moolenaar4d784b22019-05-25 19:51:39 +02009102 {
9103#ifdef FEAT_TEXT_PROP
Bram Moolenaar9c27b1c2019-05-26 18:48:13 +02009104 // check tab-local popup windows
9105 for (wp = tp->tp_first_popupwin; wp != NULL; wp = wp->w_next)
Bram Moolenaar4d784b22019-05-25 19:51:39 +02009106 if (wp->w_id == nr)
9107 return wp;
Bram Moolenaar9c27b1c2019-05-26 18:48:13 +02009108 // check global popup windows
Bram Moolenaar4d784b22019-05-25 19:51:39 +02009109 for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
9110 if (wp->w_id == nr)
9111 return wp;
9112#endif
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009113 return NULL;
Bram Moolenaar4d784b22019-05-25 19:51:39 +02009114 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009115 return wp;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009116}
9117
9118/*
Bram Moolenaare6e39892018-10-25 12:32:11 +02009119 * Find a window: When using a Window ID in any tab page, when using a number
9120 * in the current tab page.
9121 */
9122 win_T *
9123find_win_by_nr_or_id(typval_T *vp)
9124{
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009125 int nr = (int)tv_get_number_chk(vp, NULL);
Bram Moolenaare6e39892018-10-25 12:32:11 +02009126
9127 if (nr >= LOWEST_WIN_ID)
Bram Moolenaareeb1b9c2019-02-10 22:59:04 +01009128 return win_id2wp(tv_get_number(vp));
Bram Moolenaare6e39892018-10-25 12:32:11 +02009129 return find_win_by_nr(vp, NULL);
9130}
9131
9132/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009133 * Find window specified by "wvp" in tabpage "tvp".
Bram Moolenaar00aa0692019-04-27 20:37:57 +02009134 * Returns the tab page in 'ptp'
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009135 */
9136 win_T *
9137find_tabwin(
Bram Moolenaar00aa0692019-04-27 20:37:57 +02009138 typval_T *wvp, // VAR_UNKNOWN for current window
9139 typval_T *tvp, // VAR_UNKNOWN for current tab page
9140 tabpage_T **ptp)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009141{
9142 win_T *wp = NULL;
9143 tabpage_T *tp = NULL;
9144 long n;
9145
9146 if (wvp->v_type != VAR_UNKNOWN)
9147 {
9148 if (tvp->v_type != VAR_UNKNOWN)
9149 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009150 n = (long)tv_get_number(tvp);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009151 if (n >= 0)
9152 tp = find_tabpage(n);
9153 }
9154 else
9155 tp = curtab;
9156
9157 if (tp != NULL)
Bram Moolenaar00aa0692019-04-27 20:37:57 +02009158 {
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009159 wp = find_win_by_nr(wvp, tp);
Bram Moolenaar00aa0692019-04-27 20:37:57 +02009160 if (wp == NULL && wvp->v_type == VAR_NUMBER
9161 && wvp->vval.v_number != -1)
9162 // A window with the specified number is not found
9163 tp = NULL;
9164 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009165 }
9166 else
Bram Moolenaar00aa0692019-04-27 20:37:57 +02009167 {
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009168 wp = curwin;
Bram Moolenaar00aa0692019-04-27 20:37:57 +02009169 tp = curtab;
9170 }
9171
9172 if (ptp != NULL)
9173 *ptp = tp;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009174
9175 return wp;
9176}
9177
9178/*
9179 * getwinvar() and gettabwinvar()
9180 */
9181 void
9182getwinvar(
9183 typval_T *argvars,
9184 typval_T *rettv,
9185 int off) /* 1 for gettabwinvar() */
9186{
9187 win_T *win;
9188 char_u *varname;
9189 dictitem_T *v;
9190 tabpage_T *tp = NULL;
9191 int done = FALSE;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009192 win_T *oldcurwin;
9193 tabpage_T *oldtabpage;
9194 int need_switch_win;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009195
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009196 if (off == 1)
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009197 tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009198 else
9199 tp = curtab;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009200 win = find_win_by_nr(&argvars[off], tp);
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009201 varname = tv_get_string_chk(&argvars[off + 1]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009202 ++emsg_off;
9203
9204 rettv->v_type = VAR_STRING;
9205 rettv->vval.v_string = NULL;
9206
9207 if (win != NULL && varname != NULL)
9208 {
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009209 /* Set curwin to be our win, temporarily. Also set the tabpage,
9210 * otherwise the window is not valid. Only do this when needed,
9211 * autocommands get blocked. */
9212 need_switch_win = !(tp == curtab && win == curwin);
9213 if (!need_switch_win
9214 || switch_win(&oldcurwin, &oldtabpage, win, tp, TRUE) == OK)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009215 {
Bram Moolenaar30567352016-08-27 21:25:44 +02009216 if (*varname == '&')
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009217 {
Bram Moolenaar30567352016-08-27 21:25:44 +02009218 if (varname[1] == NUL)
9219 {
9220 /* get all window-local options in a dict */
9221 dict_T *opts = get_winbuf_options(FALSE);
9222
9223 if (opts != NULL)
9224 {
Bram Moolenaar45cf6e92017-04-30 20:25:19 +02009225 rettv_dict_set(rettv, opts);
Bram Moolenaar30567352016-08-27 21:25:44 +02009226 done = TRUE;
9227 }
9228 }
9229 else if (get_option_tv(&varname, rettv, 1) == OK)
9230 /* window-local-option */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009231 done = TRUE;
9232 }
9233 else
9234 {
9235 /* Look up the variable. */
9236 /* Let getwinvar({nr}, "") return the "w:" dictionary. */
9237 v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w',
9238 varname, FALSE);
9239 if (v != NULL)
9240 {
9241 copy_tv(&v->di_tv, rettv);
9242 done = TRUE;
9243 }
9244 }
9245 }
9246
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009247 if (need_switch_win)
9248 /* restore previous notion of curwin */
9249 restore_win(oldcurwin, oldtabpage, TRUE);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009250 }
9251
9252 if (!done && argvars[off + 2].v_type != VAR_UNKNOWN)
9253 /* use the default return value */
9254 copy_tv(&argvars[off + 2], rettv);
9255
9256 --emsg_off;
9257}
9258
9259/*
9260 * "setwinvar()" and "settabwinvar()" functions
9261 */
9262 void
9263setwinvar(typval_T *argvars, typval_T *rettv UNUSED, int off)
9264{
9265 win_T *win;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009266 win_T *save_curwin;
9267 tabpage_T *save_curtab;
9268 int need_switch_win;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009269 char_u *varname, *winvarname;
9270 typval_T *varp;
9271 char_u nbuf[NUMBUFLEN];
9272 tabpage_T *tp = NULL;
9273
Bram Moolenaare0fb7d12019-02-12 20:48:10 +01009274 if (check_secure())
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009275 return;
9276
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009277 if (off == 1)
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009278 tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009279 else
9280 tp = curtab;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009281 win = find_win_by_nr(&argvars[off], tp);
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009282 varname = tv_get_string_chk(&argvars[off + 1]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009283 varp = &argvars[off + 2];
9284
9285 if (win != NULL && varname != NULL && varp != NULL)
9286 {
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009287 need_switch_win = !(tp == curtab && win == curwin);
9288 if (!need_switch_win
9289 || switch_win(&save_curwin, &save_curtab, win, tp, TRUE) == OK)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009290 {
9291 if (*varname == '&')
9292 {
9293 long numval;
9294 char_u *strval;
9295 int error = FALSE;
9296
9297 ++varname;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009298 numval = (long)tv_get_number_chk(varp, &error);
9299 strval = tv_get_string_buf_chk(varp, nbuf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009300 if (!error && strval != NULL)
9301 set_option_value(varname, numval, strval, OPT_LOCAL);
9302 }
9303 else
9304 {
Bram Moolenaar964b3742019-05-24 18:54:09 +02009305 winvarname = alloc(STRLEN(varname) + 3);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009306 if (winvarname != NULL)
9307 {
9308 STRCPY(winvarname, "w:");
9309 STRCPY(winvarname + 2, varname);
9310 set_var(winvarname, varp, TRUE);
9311 vim_free(winvarname);
9312 }
9313 }
9314 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009315 if (need_switch_win)
9316 restore_win(save_curwin, save_curtab, TRUE);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009317 }
9318}
9319
9320/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009321 * Skip over the name of an option: "&option", "&g:option" or "&l:option".
9322 * "arg" points to the "&" or '+' when called, to "option" when returning.
9323 * Returns NULL when no option name found. Otherwise pointer to the char
9324 * after the option name.
9325 */
9326 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01009327find_option_end(char_u **arg, int *opt_flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009328{
9329 char_u *p = *arg;
9330
9331 ++p;
9332 if (*p == 'g' && p[1] == ':')
9333 {
9334 *opt_flags = OPT_GLOBAL;
9335 p += 2;
9336 }
9337 else if (*p == 'l' && p[1] == ':')
9338 {
9339 *opt_flags = OPT_LOCAL;
9340 p += 2;
9341 }
9342 else
9343 *opt_flags = 0;
9344
9345 if (!ASCII_ISALPHA(*p))
9346 return NULL;
9347 *arg = p;
9348
9349 if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL)
9350 p += 4; /* termcap option */
9351 else
9352 while (ASCII_ISALPHA(*p))
9353 ++p;
9354 return p;
9355}
9356
9357/*
Bram Moolenaara9b579f2016-07-17 18:29:19 +02009358 * Return the autoload script name for a function or variable name.
9359 * Returns NULL when out of memory.
Bram Moolenaar28fc2472019-07-05 22:14:16 +02009360 * Caller must make sure that "name" contains AUTOLOAD_CHAR.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009361 */
Bram Moolenaara1544c02013-05-30 12:35:52 +02009362 char_u *
Bram Moolenaara9b579f2016-07-17 18:29:19 +02009363autoload_name(char_u *name)
Bram Moolenaara1544c02013-05-30 12:35:52 +02009364{
Bram Moolenaar28fc2472019-07-05 22:14:16 +02009365 char_u *p, *q = NULL;
Bram Moolenaara9b579f2016-07-17 18:29:19 +02009366 char_u *scriptname;
Bram Moolenaara1544c02013-05-30 12:35:52 +02009367
Bram Moolenaar28fc2472019-07-05 22:14:16 +02009368 // Get the script file name: replace '#' with '/', append ".vim".
Bram Moolenaar964b3742019-05-24 18:54:09 +02009369 scriptname = alloc(STRLEN(name) + 14);
Bram Moolenaara9b579f2016-07-17 18:29:19 +02009370 if (scriptname == NULL)
Bram Moolenaar9bdfb002014-04-23 17:43:42 +02009371 return FALSE;
Bram Moolenaara9b579f2016-07-17 18:29:19 +02009372 STRCPY(scriptname, "autoload/");
9373 STRCAT(scriptname, name);
Bram Moolenaar28fc2472019-07-05 22:14:16 +02009374 for (p = scriptname + 9; (p = vim_strchr(p, AUTOLOAD_CHAR)) != NULL;
9375 q = p, ++p)
Bram Moolenaara9b579f2016-07-17 18:29:19 +02009376 *p = '/';
Bram Moolenaar28fc2472019-07-05 22:14:16 +02009377 STRCPY(q, ".vim");
Bram Moolenaara9b579f2016-07-17 18:29:19 +02009378 return scriptname;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00009379}
9380
9381/*
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00009382 * If "name" has a package name try autoloading the script for it.
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00009383 * Return TRUE if a package was loaded.
9384 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02009385 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01009386script_autoload(
9387 char_u *name,
9388 int reload) /* load script again when already loaded */
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00009389{
9390 char_u *p;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00009391 char_u *scriptname, *tofree;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00009392 int ret = FALSE;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00009393 int i;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00009394
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00009395 /* If there is no '#' after name[0] there is no package name. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00009396 p = vim_strchr(name, AUTOLOAD_CHAR);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00009397 if (p == NULL || p == name)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00009398 return FALSE;
9399
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00009400 tofree = scriptname = autoload_name(name);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00009401
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00009402 /* Find the name in the list of previously loaded package names. Skip
9403 * "autoload/", it's always the same. */
9404 for (i = 0; i < ga_loaded.ga_len; ++i)
9405 if (STRCMP(((char_u **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0)
9406 break;
9407 if (!reload && i < ga_loaded.ga_len)
9408 ret = FALSE; /* was loaded already */
9409 else
9410 {
9411 /* Remember the name if it wasn't loaded already. */
9412 if (i == ga_loaded.ga_len && ga_grow(&ga_loaded, 1) == OK)
9413 {
9414 ((char_u **)ga_loaded.ga_data)[ga_loaded.ga_len++] = scriptname;
9415 tofree = NULL;
9416 }
9417
9418 /* Try loading the package from $VIMRUNTIME/autoload/<name>.vim */
Bram Moolenaar7f8989d2016-03-12 22:11:39 +01009419 if (source_runtime(scriptname, 0) == OK)
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00009420 ret = TRUE;
9421 }
9422
9423 vim_free(tofree);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00009424 return ret;
9425}
9426
Bram Moolenaar661b1822005-07-28 22:36:45 +00009427/*
9428 * Display script name where an item was last set.
9429 * Should only be invoked when 'verbose' is non-zero.
9430 */
9431 void
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02009432last_set_msg(sctx_T script_ctx)
Bram Moolenaar661b1822005-07-28 22:36:45 +00009433{
Bram Moolenaarcafda4f2005-09-06 19:25:11 +00009434 char_u *p;
9435
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02009436 if (script_ctx.sc_sid != 0)
Bram Moolenaar661b1822005-07-28 22:36:45 +00009437 {
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02009438 p = home_replace_save(NULL, get_scriptname(script_ctx.sc_sid));
Bram Moolenaarcafda4f2005-09-06 19:25:11 +00009439 if (p != NULL)
9440 {
9441 verbose_enter();
Bram Moolenaar32526b32019-01-19 17:43:09 +01009442 msg_puts(_("\n\tLast set from "));
9443 msg_puts((char *)p);
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02009444 if (script_ctx.sc_lnum > 0)
9445 {
Bram Moolenaar32526b32019-01-19 17:43:09 +01009446 msg_puts(_(" line "));
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02009447 msg_outnum((long)script_ctx.sc_lnum);
9448 }
Bram Moolenaarcafda4f2005-09-06 19:25:11 +00009449 verbose_leave();
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02009450 vim_free(p);
Bram Moolenaarcafda4f2005-09-06 19:25:11 +00009451 }
Bram Moolenaar661b1822005-07-28 22:36:45 +00009452 }
9453}
9454
Bram Moolenaar61be3762019-03-19 23:04:17 +01009455/*
Bram Moolenaard7c96872019-06-15 17:12:48 +02009456 * reset v:option_new, v:option_old, v:option_oldlocal, v:option_oldglobal,
9457 * v:option_type, and v:option_command.
Bram Moolenaar61be3762019-03-19 23:04:17 +01009458 */
Bram Moolenaar53744302015-07-17 17:38:22 +02009459 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009460reset_v_option_vars(void)
Bram Moolenaar53744302015-07-17 17:38:22 +02009461{
9462 set_vim_var_string(VV_OPTION_NEW, NULL, -1);
9463 set_vim_var_string(VV_OPTION_OLD, NULL, -1);
Bram Moolenaard7c96872019-06-15 17:12:48 +02009464 set_vim_var_string(VV_OPTION_OLDLOCAL, NULL, -1);
9465 set_vim_var_string(VV_OPTION_OLDGLOBAL, NULL, -1);
Bram Moolenaar53744302015-07-17 17:38:22 +02009466 set_vim_var_string(VV_OPTION_TYPE, NULL, -1);
Bram Moolenaard7c96872019-06-15 17:12:48 +02009467 set_vim_var_string(VV_OPTION_COMMAND, NULL, -1);
Bram Moolenaar53744302015-07-17 17:38:22 +02009468}
9469
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009470/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009471 * Add an assert error to v:errors.
9472 */
9473 void
9474assert_error(garray_T *gap)
9475{
9476 struct vimvar *vp = &vimvars[VV_ERRORS];
9477
9478 if (vp->vv_type != VAR_LIST || vimvars[VV_ERRORS].vv_list == NULL)
9479 /* Make sure v:errors is a list. */
9480 set_vim_var_list(VV_ERRORS, list_alloc());
9481 list_append_string(vimvars[VV_ERRORS].vv_list, gap->ga_data, gap->ga_len);
9482}
Bram Moolenaar31988702018-02-13 12:57:42 +01009483/*
9484 * Compare "typ1" and "typ2". Put the result in "typ1".
9485 */
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009486 int
9487typval_compare(
9488 typval_T *typ1, /* first operand */
9489 typval_T *typ2, /* second operand */
9490 exptype_T type, /* operator */
9491 int type_is, /* TRUE for "is" and "isnot" */
Bram Moolenaar31988702018-02-13 12:57:42 +01009492 int ic) /* ignore case */
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009493{
9494 int i;
9495 varnumber_T n1, n2;
9496 char_u *s1, *s2;
9497 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
9498
Bram Moolenaar31988702018-02-13 12:57:42 +01009499 if (type_is && typ1->v_type != typ2->v_type)
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009500 {
Bram Moolenaar31988702018-02-13 12:57:42 +01009501 /* For "is" a different type always means FALSE, for "notis"
9502 * it means TRUE. */
9503 n1 = (type == TYPE_NEQUAL);
9504 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01009505 else if (typ1->v_type == VAR_BLOB || typ2->v_type == VAR_BLOB)
9506 {
9507 if (type_is)
9508 {
9509 n1 = (typ1->v_type == typ2->v_type
9510 && typ1->vval.v_blob == typ2->vval.v_blob);
9511 if (type == TYPE_NEQUAL)
9512 n1 = !n1;
9513 }
9514 else if (typ1->v_type != typ2->v_type
9515 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
9516 {
9517 if (typ1->v_type != typ2->v_type)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01009518 emsg(_("E977: Can only compare Blob with Blob"));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01009519 else
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01009520 emsg(_(e_invalblob));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01009521 clear_tv(typ1);
9522 return FAIL;
9523 }
9524 else
9525 {
9526 // Compare two Blobs for being equal or unequal.
9527 n1 = blob_equal(typ1->vval.v_blob, typ2->vval.v_blob);
9528 if (type == TYPE_NEQUAL)
9529 n1 = !n1;
9530 }
9531 }
Bram Moolenaar31988702018-02-13 12:57:42 +01009532 else if (typ1->v_type == VAR_LIST || typ2->v_type == VAR_LIST)
9533 {
9534 if (type_is)
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009535 {
Bram Moolenaar31988702018-02-13 12:57:42 +01009536 n1 = (typ1->v_type == typ2->v_type
9537 && typ1->vval.v_list == typ2->vval.v_list);
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009538 if (type == TYPE_NEQUAL)
9539 n1 = !n1;
9540 }
Bram Moolenaar31988702018-02-13 12:57:42 +01009541 else if (typ1->v_type != typ2->v_type
9542 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009543 {
Bram Moolenaar31988702018-02-13 12:57:42 +01009544 if (typ1->v_type != typ2->v_type)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01009545 emsg(_("E691: Can only compare List with List"));
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009546 else
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01009547 emsg(_("E692: Invalid operation for List"));
Bram Moolenaar31988702018-02-13 12:57:42 +01009548 clear_tv(typ1);
9549 return FAIL;
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009550 }
9551 else
9552 {
Bram Moolenaar31988702018-02-13 12:57:42 +01009553 /* Compare two Lists for being equal or unequal. */
9554 n1 = list_equal(typ1->vval.v_list, typ2->vval.v_list,
9555 ic, FALSE);
9556 if (type == TYPE_NEQUAL)
9557 n1 = !n1;
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009558 }
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009559 }
Bram Moolenaar31988702018-02-13 12:57:42 +01009560
9561 else if (typ1->v_type == VAR_DICT || typ2->v_type == VAR_DICT)
9562 {
9563 if (type_is)
9564 {
9565 n1 = (typ1->v_type == typ2->v_type
9566 && typ1->vval.v_dict == typ2->vval.v_dict);
9567 if (type == TYPE_NEQUAL)
9568 n1 = !n1;
9569 }
9570 else if (typ1->v_type != typ2->v_type
9571 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
9572 {
9573 if (typ1->v_type != typ2->v_type)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01009574 emsg(_("E735: Can only compare Dictionary with Dictionary"));
Bram Moolenaar31988702018-02-13 12:57:42 +01009575 else
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01009576 emsg(_("E736: Invalid operation for Dictionary"));
Bram Moolenaar31988702018-02-13 12:57:42 +01009577 clear_tv(typ1);
9578 return FAIL;
9579 }
9580 else
9581 {
9582 /* Compare two Dictionaries for being equal or unequal. */
9583 n1 = dict_equal(typ1->vval.v_dict, typ2->vval.v_dict,
9584 ic, FALSE);
9585 if (type == TYPE_NEQUAL)
9586 n1 = !n1;
9587 }
9588 }
9589
9590 else if (typ1->v_type == VAR_FUNC || typ2->v_type == VAR_FUNC
9591 || typ1->v_type == VAR_PARTIAL || typ2->v_type == VAR_PARTIAL)
9592 {
9593 if (type != TYPE_EQUAL && type != TYPE_NEQUAL)
9594 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01009595 emsg(_("E694: Invalid operation for Funcrefs"));
Bram Moolenaar31988702018-02-13 12:57:42 +01009596 clear_tv(typ1);
9597 return FAIL;
9598 }
9599 if ((typ1->v_type == VAR_PARTIAL
9600 && typ1->vval.v_partial == NULL)
9601 || (typ2->v_type == VAR_PARTIAL
9602 && typ2->vval.v_partial == NULL))
9603 /* when a partial is NULL assume not equal */
9604 n1 = FALSE;
9605 else if (type_is)
9606 {
9607 if (typ1->v_type == VAR_FUNC && typ2->v_type == VAR_FUNC)
9608 /* strings are considered the same if their value is
9609 * the same */
9610 n1 = tv_equal(typ1, typ2, ic, FALSE);
9611 else if (typ1->v_type == VAR_PARTIAL
9612 && typ2->v_type == VAR_PARTIAL)
9613 n1 = (typ1->vval.v_partial == typ2->vval.v_partial);
9614 else
9615 n1 = FALSE;
9616 }
9617 else
9618 n1 = tv_equal(typ1, typ2, ic, FALSE);
9619 if (type == TYPE_NEQUAL)
9620 n1 = !n1;
9621 }
9622
9623#ifdef FEAT_FLOAT
9624 /*
9625 * If one of the two variables is a float, compare as a float.
9626 * When using "=~" or "!~", always compare as string.
9627 */
9628 else if ((typ1->v_type == VAR_FLOAT || typ2->v_type == VAR_FLOAT)
9629 && type != TYPE_MATCH && type != TYPE_NOMATCH)
9630 {
9631 float_T f1, f2;
9632
Bram Moolenaar38f08e72019-02-20 22:04:32 +01009633 f1 = tv_get_float(typ1);
9634 f2 = tv_get_float(typ2);
Bram Moolenaar31988702018-02-13 12:57:42 +01009635 n1 = FALSE;
9636 switch (type)
9637 {
9638 case TYPE_EQUAL: n1 = (f1 == f2); break;
9639 case TYPE_NEQUAL: n1 = (f1 != f2); break;
9640 case TYPE_GREATER: n1 = (f1 > f2); break;
9641 case TYPE_GEQUAL: n1 = (f1 >= f2); break;
9642 case TYPE_SMALLER: n1 = (f1 < f2); break;
9643 case TYPE_SEQUAL: n1 = (f1 <= f2); break;
9644 case TYPE_UNKNOWN:
9645 case TYPE_MATCH:
9646 case TYPE_NOMATCH: break; /* avoid gcc warning */
9647 }
9648 }
9649#endif
9650
9651 /*
9652 * If one of the two variables is a number, compare as a number.
9653 * When using "=~" or "!~", always compare as string.
9654 */
9655 else if ((typ1->v_type == VAR_NUMBER || typ2->v_type == VAR_NUMBER)
9656 && type != TYPE_MATCH && type != TYPE_NOMATCH)
9657 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009658 n1 = tv_get_number(typ1);
9659 n2 = tv_get_number(typ2);
Bram Moolenaar31988702018-02-13 12:57:42 +01009660 switch (type)
9661 {
9662 case TYPE_EQUAL: n1 = (n1 == n2); break;
9663 case TYPE_NEQUAL: n1 = (n1 != n2); break;
9664 case TYPE_GREATER: n1 = (n1 > n2); break;
9665 case TYPE_GEQUAL: n1 = (n1 >= n2); break;
9666 case TYPE_SMALLER: n1 = (n1 < n2); break;
9667 case TYPE_SEQUAL: n1 = (n1 <= n2); break;
9668 case TYPE_UNKNOWN:
9669 case TYPE_MATCH:
9670 case TYPE_NOMATCH: break; /* avoid gcc warning */
9671 }
9672 }
9673 else
9674 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009675 s1 = tv_get_string_buf(typ1, buf1);
9676 s2 = tv_get_string_buf(typ2, buf2);
Bram Moolenaar31988702018-02-13 12:57:42 +01009677 if (type != TYPE_MATCH && type != TYPE_NOMATCH)
9678 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2);
9679 else
9680 i = 0;
9681 n1 = FALSE;
9682 switch (type)
9683 {
9684 case TYPE_EQUAL: n1 = (i == 0); break;
9685 case TYPE_NEQUAL: n1 = (i != 0); break;
9686 case TYPE_GREATER: n1 = (i > 0); break;
9687 case TYPE_GEQUAL: n1 = (i >= 0); break;
9688 case TYPE_SMALLER: n1 = (i < 0); break;
9689 case TYPE_SEQUAL: n1 = (i <= 0); break;
9690
9691 case TYPE_MATCH:
9692 case TYPE_NOMATCH:
9693 n1 = pattern_match(s2, s1, ic);
9694 if (type == TYPE_NOMATCH)
9695 n1 = !n1;
9696 break;
9697
9698 case TYPE_UNKNOWN: break; /* avoid gcc warning */
9699 }
9700 }
9701 clear_tv(typ1);
9702 typ1->v_type = VAR_NUMBER;
9703 typ1->vval.v_number = n1;
9704
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009705 return OK;
9706}
9707
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009708 char_u *
Bram Moolenaar6f8d2ac2018-07-25 19:49:45 +02009709typval_tostring(typval_T *arg)
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009710{
9711 char_u *tofree;
9712 char_u numbuf[NUMBUFLEN];
9713 char_u *ret = NULL;
9714
9715 if (arg == NULL)
9716 return vim_strsave((char_u *)"(does not exist)");
9717 ret = tv2string(arg, &tofree, numbuf, 0);
9718 /* Make a copy if we have a value but it's not in allocated memory. */
9719 if (ret != NULL && tofree == NULL)
9720 ret = vim_strsave(ret);
9721 return ret;
9722}
9723
9724 int
9725var_exists(char_u *var)
9726{
9727 char_u *name;
9728 char_u *tofree;
9729 typval_T tv;
9730 int len = 0;
9731 int n = FALSE;
9732
9733 /* get_name_len() takes care of expanding curly braces */
9734 name = var;
9735 len = get_name_len(&var, &tofree, TRUE, FALSE);
9736 if (len > 0)
9737 {
9738 if (tofree != NULL)
9739 name = tofree;
9740 n = (get_var_tv(name, len, &tv, NULL, FALSE, TRUE) == OK);
9741 if (n)
9742 {
9743 /* handle d.key, l[idx], f(expr) */
9744 n = (handle_subscript(&var, &tv, TRUE, FALSE) == OK);
9745 if (n)
9746 clear_tv(&tv);
9747 }
9748 }
9749 if (*var != NUL)
9750 n = FALSE;
9751
9752 vim_free(tofree);
9753 return n;
9754}
9755
Bram Moolenaar071d4272004-06-13 20:20:40 +00009756#endif /* FEAT_EVAL */
9757
Bram Moolenaar071d4272004-06-13 20:20:40 +00009758
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009759#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009760
Bram Moolenaar4f974752019-02-17 17:44:42 +01009761#ifdef MSWIN
Bram Moolenaar071d4272004-06-13 20:20:40 +00009762/*
9763 * Functions for ":8" filename modifier: get 8.3 version of a filename.
9764 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009765
9766/*
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009767 * Get the short path (8.3) for the filename in "fnamep".
9768 * Only works for a valid file name.
9769 * When the path gets longer "fnamep" is changed and the allocated buffer
9770 * is put in "bufp".
9771 * *fnamelen is the length of "fnamep" and set to 0 for a nonexistent path.
9772 * Returns OK on success, FAIL on failure.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009773 */
9774 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01009775get_short_pathname(char_u **fnamep, char_u **bufp, int *fnamelen)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009776{
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009777 int l, len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009778 char_u *newbuf;
9779
9780 len = *fnamelen;
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +01009781 l = GetShortPathName((LPSTR)*fnamep, (LPSTR)*fnamep, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009782 if (l > len - 1)
9783 {
9784 /* If that doesn't work (not enough space), then save the string
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009785 * and try again with a new buffer big enough. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009786 newbuf = vim_strnsave(*fnamep, l);
9787 if (newbuf == NULL)
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009788 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009789
9790 vim_free(*bufp);
9791 *fnamep = *bufp = newbuf;
9792
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009793 /* Really should always succeed, as the buffer is big enough. */
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +01009794 l = GetShortPathName((LPSTR)*fnamep, (LPSTR)*fnamep, l+1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009795 }
9796
9797 *fnamelen = l;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009798 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009799}
9800
9801/*
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009802 * Get the short path (8.3) for the filename in "fname". The converted
9803 * path is returned in "bufp".
9804 *
9805 * Some of the directories specified in "fname" may not exist. This function
9806 * will shorten the existing directories at the beginning of the path and then
9807 * append the remaining non-existing path.
9808 *
9809 * fname - Pointer to the filename to shorten. On return, contains the
Bram Moolenaar2c704a72010-06-03 21:17:25 +02009810 * pointer to the shortened pathname
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009811 * bufp - Pointer to an allocated buffer for the filename.
9812 * fnamelen - Length of the filename pointed to by fname
9813 *
9814 * Returns OK on success (or nothing done) and FAIL on failure (out of memory).
Bram Moolenaar071d4272004-06-13 20:20:40 +00009815 */
9816 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01009817shortpath_for_invalid_fname(
9818 char_u **fname,
9819 char_u **bufp,
9820 int *fnamelen)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009821{
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009822 char_u *short_fname, *save_fname, *pbuf_unused;
9823 char_u *endp, *save_endp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009824 char_u ch;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009825 int old_len, len;
9826 int new_len, sfx_len;
9827 int retval = OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009828
9829 /* Make a copy */
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009830 old_len = *fnamelen;
9831 save_fname = vim_strnsave(*fname, old_len);
9832 pbuf_unused = NULL;
9833 short_fname = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009834
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009835 endp = save_fname + old_len - 1; /* Find the end of the copy */
9836 save_endp = endp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009837
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009838 /*
9839 * Try shortening the supplied path till it succeeds by removing one
9840 * directory at a time from the tail of the path.
9841 */
9842 len = 0;
9843 for (;;)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009844 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009845 /* go back one path-separator */
9846 while (endp > save_fname && !after_pathsep(save_fname, endp + 1))
9847 --endp;
9848 if (endp <= save_fname)
9849 break; /* processed the complete path */
9850
9851 /*
9852 * Replace the path separator with a NUL and try to shorten the
9853 * resulting path.
9854 */
9855 ch = *endp;
9856 *endp = 0;
9857 short_fname = save_fname;
Bram Moolenaarc236c162008-07-13 17:41:49 +00009858 len = (int)STRLEN(short_fname) + 1;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009859 if (get_short_pathname(&short_fname, &pbuf_unused, &len) == FAIL)
9860 {
9861 retval = FAIL;
9862 goto theend;
9863 }
9864 *endp = ch; /* preserve the string */
9865
9866 if (len > 0)
9867 break; /* successfully shortened the path */
9868
9869 /* failed to shorten the path. Skip the path separator */
9870 --endp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009871 }
9872
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009873 if (len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009874 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009875 /*
9876 * Succeeded in shortening the path. Now concatenate the shortened
9877 * path with the remaining path at the tail.
9878 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009879
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009880 /* Compute the length of the new path. */
9881 sfx_len = (int)(save_endp - endp) + 1;
9882 new_len = len + sfx_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009883
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009884 *fnamelen = new_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009885 vim_free(*bufp);
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009886 if (new_len > old_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009887 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009888 /* There is not enough space in the currently allocated string,
9889 * copy it to a buffer big enough. */
9890 *fname = *bufp = vim_strnsave(short_fname, new_len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009891 if (*fname == NULL)
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009892 {
9893 retval = FAIL;
9894 goto theend;
9895 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009896 }
9897 else
9898 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009899 /* Transfer short_fname to the main buffer (it's big enough),
9900 * unless get_short_pathname() did its work in-place. */
9901 *fname = *bufp = save_fname;
9902 if (short_fname != save_fname)
9903 vim_strncpy(save_fname, short_fname, len);
9904 save_fname = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009905 }
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009906
9907 /* concat the not-shortened part of the path */
9908 vim_strncpy(*fname + len, endp, sfx_len);
9909 (*fname)[new_len] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009910 }
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009911
9912theend:
9913 vim_free(pbuf_unused);
9914 vim_free(save_fname);
9915
9916 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009917}
9918
9919/*
9920 * Get a pathname for a partial path.
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009921 * Returns OK for success, FAIL for failure.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009922 */
9923 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01009924shortpath_for_partial(
9925 char_u **fnamep,
9926 char_u **bufp,
9927 int *fnamelen)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009928{
9929 int sepcount, len, tflen;
9930 char_u *p;
9931 char_u *pbuf, *tfname;
9932 int hasTilde;
9933
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009934 /* Count up the path separators from the RHS.. so we know which part
9935 * of the path to return. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009936 sepcount = 0;
Bram Moolenaar91acfff2017-03-12 19:22:36 +01009937 for (p = *fnamep; p < *fnamep + *fnamelen; MB_PTR_ADV(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00009938 if (vim_ispathsep(*p))
9939 ++sepcount;
9940
9941 /* Need full path first (use expand_env() to remove a "~/") */
9942 hasTilde = (**fnamep == '~');
9943 if (hasTilde)
9944 pbuf = tfname = expand_env_save(*fnamep);
9945 else
9946 pbuf = tfname = FullName_save(*fnamep, FALSE);
9947
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00009948 len = tflen = (int)STRLEN(tfname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009949
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009950 if (get_short_pathname(&tfname, &pbuf, &len) == FAIL)
9951 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009952
9953 if (len == 0)
9954 {
9955 /* Don't have a valid filename, so shorten the rest of the
9956 * path if we can. This CAN give us invalid 8.3 filenames, but
9957 * there's not a lot of point in guessing what it might be.
9958 */
9959 len = tflen;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009960 if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == FAIL)
9961 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009962 }
9963
9964 /* Count the paths backward to find the beginning of the desired string. */
9965 for (p = tfname + len - 1; p >= tfname; --p)
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00009966 {
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00009967 if (has_mbyte)
9968 p -= mb_head_off(tfname, p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009969 if (vim_ispathsep(*p))
9970 {
9971 if (sepcount == 0 || (hasTilde && sepcount == 1))
9972 break;
9973 else
9974 sepcount --;
9975 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00009976 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009977 if (hasTilde)
9978 {
9979 --p;
9980 if (p >= tfname)
9981 *p = '~';
9982 else
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009983 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009984 }
9985 else
9986 ++p;
9987
9988 /* Copy in the string - p indexes into tfname - allocated at pbuf */
9989 vim_free(*bufp);
9990 *fnamelen = (int)STRLEN(p);
9991 *bufp = pbuf;
9992 *fnamep = p;
9993
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009994 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009995}
Bram Moolenaar4f974752019-02-17 17:44:42 +01009996#endif // MSWIN
Bram Moolenaar071d4272004-06-13 20:20:40 +00009997
9998/*
9999 * Adjust a filename, according to a string of modifiers.
10000 * *fnamep must be NUL terminated when called. When returning, the length is
10001 * determined by *fnamelen.
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000010002 * Returns VALID_ flags or -1 for failure.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010003 * When there is an error, *fnamep is set to NULL.
10004 */
10005 int
Bram Moolenaar7454a062016-01-30 15:14:10 +010010006modify_fname(
Bram Moolenaar00136dc2018-07-25 21:19:13 +020010007 char_u *src, // string with modifiers
10008 int tilde_file, // "~" is a file name, not $HOME
10009 int *usedlen, // characters after src that are used
10010 char_u **fnamep, // file name so far
10011 char_u **bufp, // buffer for allocated file name or NULL
10012 int *fnamelen) // length of fnamep
Bram Moolenaar071d4272004-06-13 20:20:40 +000010013{
10014 int valid = 0;
10015 char_u *tail;
10016 char_u *s, *p, *pbuf;
10017 char_u dirname[MAXPATHL];
10018 int c;
10019 int has_fullname = 0;
Bram Moolenaar4f974752019-02-17 17:44:42 +010010020#ifdef MSWIN
Bram Moolenaardc935552011-08-17 15:23:23 +020010021 char_u *fname_start = *fnamep;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010022 int has_shortname = 0;
10023#endif
10024
10025repeat:
10026 /* ":p" - full path/file_name */
10027 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p')
10028 {
10029 has_fullname = 1;
10030
10031 valid |= VALID_PATH;
10032 *usedlen += 2;
10033
10034 /* Expand "~/path" for all systems and "~user/path" for Unix and VMS */
10035 if ((*fnamep)[0] == '~'
10036#if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME))
10037 && ((*fnamep)[1] == '/'
10038# ifdef BACKSLASH_IN_FILENAME
10039 || (*fnamep)[1] == '\\'
10040# endif
10041 || (*fnamep)[1] == NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010042#endif
Bram Moolenaar00136dc2018-07-25 21:19:13 +020010043 && !(tilde_file && (*fnamep)[1] == NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010044 )
10045 {
10046 *fnamep = expand_env_save(*fnamep);
10047 vim_free(*bufp); /* free any allocated file name */
10048 *bufp = *fnamep;
10049 if (*fnamep == NULL)
10050 return -1;
10051 }
10052
10053 /* When "/." or "/.." is used: force expansion to get rid of it. */
Bram Moolenaar91acfff2017-03-12 19:22:36 +010010054 for (p = *fnamep; *p != NUL; MB_PTR_ADV(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000010055 {
10056 if (vim_ispathsep(*p)
10057 && p[1] == '.'
10058 && (p[2] == NUL
10059 || vim_ispathsep(p[2])
10060 || (p[2] == '.'
10061 && (p[3] == NUL || vim_ispathsep(p[3])))))
10062 break;
10063 }
10064
10065 /* FullName_save() is slow, don't use it when not needed. */
10066 if (*p != NUL || !vim_isAbsName(*fnamep))
10067 {
10068 *fnamep = FullName_save(*fnamep, *p != NUL);
10069 vim_free(*bufp); /* free any allocated file name */
10070 *bufp = *fnamep;
10071 if (*fnamep == NULL)
10072 return -1;
10073 }
10074
Bram Moolenaar4f974752019-02-17 17:44:42 +010010075#ifdef MSWIN
Bram Moolenaar9158f9e2012-06-20 14:02:27 +020010076# if _WIN32_WINNT >= 0x0500
10077 if (vim_strchr(*fnamep, '~') != NULL)
10078 {
Bram Moolenaar2d04a912019-03-30 20:04:08 +010010079 // Expand 8.3 filename to full path. Needed to make sure the same
10080 // file does not have two different names.
10081 // Note: problem does not occur if _WIN32_WINNT < 0x0500.
10082 WCHAR *wfname = enc_to_utf16(*fnamep, NULL);
10083 WCHAR buf[_MAX_PATH];
10084
10085 if (wfname != NULL)
Bram Moolenaar9158f9e2012-06-20 14:02:27 +020010086 {
Bram Moolenaar2d04a912019-03-30 20:04:08 +010010087 if (GetLongPathNameW(wfname, buf, _MAX_PATH))
Bram Moolenaar9158f9e2012-06-20 14:02:27 +020010088 {
Bram Moolenaar2d04a912019-03-30 20:04:08 +010010089 char_u *p = utf16_to_enc(buf, NULL);
10090
10091 if (p != NULL)
10092 {
10093 vim_free(*bufp); // free any allocated file name
10094 *bufp = *fnamep = p;
10095 }
Bram Moolenaar9158f9e2012-06-20 14:02:27 +020010096 }
Bram Moolenaar2d04a912019-03-30 20:04:08 +010010097 vim_free(wfname);
Bram Moolenaar9158f9e2012-06-20 14:02:27 +020010098 }
10099 }
10100# endif
10101#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010102 /* Append a path separator to a directory. */
10103 if (mch_isdir(*fnamep))
10104 {
10105 /* Make room for one or two extra characters. */
10106 *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2);
10107 vim_free(*bufp); /* free any allocated file name */
10108 *bufp = *fnamep;
10109 if (*fnamep == NULL)
10110 return -1;
10111 add_pathsep(*fnamep);
10112 }
10113 }
10114
10115 /* ":." - path relative to the current directory */
10116 /* ":~" - path relative to the home directory */
10117 /* ":8" - shortname path - postponed till after */
10118 while (src[*usedlen] == ':'
10119 && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8'))
10120 {
10121 *usedlen += 2;
10122 if (c == '8')
10123 {
Bram Moolenaar4f974752019-02-17 17:44:42 +010010124#ifdef MSWIN
Bram Moolenaar071d4272004-06-13 20:20:40 +000010125 has_shortname = 1; /* Postpone this. */
10126#endif
10127 continue;
10128 }
10129 pbuf = NULL;
10130 /* Need full path first (use expand_env() to remove a "~/") */
10131 if (!has_fullname)
10132 {
10133 if (c == '.' && **fnamep == '~')
10134 p = pbuf = expand_env_save(*fnamep);
10135 else
10136 p = pbuf = FullName_save(*fnamep, FALSE);
10137 }
10138 else
10139 p = *fnamep;
10140
10141 has_fullname = 0;
10142
10143 if (p != NULL)
10144 {
10145 if (c == '.')
10146 {
10147 mch_dirname(dirname, MAXPATHL);
10148 s = shorten_fname(p, dirname);
10149 if (s != NULL)
10150 {
10151 *fnamep = s;
10152 if (pbuf != NULL)
10153 {
10154 vim_free(*bufp); /* free any allocated file name */
10155 *bufp = pbuf;
10156 pbuf = NULL;
10157 }
10158 }
10159 }
10160 else
10161 {
10162 home_replace(NULL, p, dirname, MAXPATHL, TRUE);
10163 /* Only replace it when it starts with '~' */
10164 if (*dirname == '~')
10165 {
10166 s = vim_strsave(dirname);
10167 if (s != NULL)
10168 {
10169 *fnamep = s;
10170 vim_free(*bufp);
10171 *bufp = s;
10172 }
10173 }
10174 }
10175 vim_free(pbuf);
10176 }
10177 }
10178
10179 tail = gettail(*fnamep);
10180 *fnamelen = (int)STRLEN(*fnamep);
10181
10182 /* ":h" - head, remove "/file_name", can be repeated */
10183 /* Don't remove the first "/" or "c:\" */
10184 while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h')
10185 {
10186 valid |= VALID_HEAD;
10187 *usedlen += 2;
10188 s = get_past_head(*fnamep);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000010189 while (tail > s && after_pathsep(s, tail))
Bram Moolenaar91acfff2017-03-12 19:22:36 +010010190 MB_PTR_BACK(*fnamep, tail);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010191 *fnamelen = (int)(tail - *fnamep);
10192#ifdef VMS
10193 if (*fnamelen > 0)
10194 *fnamelen += 1; /* the path separator is part of the path */
10195#endif
Bram Moolenaar5461cfe2007-09-25 18:40:14 +000010196 if (*fnamelen == 0)
10197 {
10198 /* Result is empty. Turn it into "." to make ":cd %:h" work. */
10199 p = vim_strsave((char_u *)".");
10200 if (p == NULL)
10201 return -1;
10202 vim_free(*bufp);
10203 *bufp = *fnamep = tail = p;
10204 *fnamelen = 1;
10205 }
10206 else
10207 {
10208 while (tail > s && !after_pathsep(s, tail))
Bram Moolenaar91acfff2017-03-12 19:22:36 +010010209 MB_PTR_BACK(*fnamep, tail);
Bram Moolenaar5461cfe2007-09-25 18:40:14 +000010210 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010211 }
10212
10213 /* ":8" - shortname */
10214 if (src[*usedlen] == ':' && src[*usedlen + 1] == '8')
10215 {
10216 *usedlen += 2;
Bram Moolenaar4f974752019-02-17 17:44:42 +010010217#ifdef MSWIN
Bram Moolenaar071d4272004-06-13 20:20:40 +000010218 has_shortname = 1;
10219#endif
10220 }
10221
Bram Moolenaar4f974752019-02-17 17:44:42 +010010222#ifdef MSWIN
Bram Moolenaardc935552011-08-17 15:23:23 +020010223 /*
10224 * Handle ":8" after we have done 'heads' and before we do 'tails'.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010225 */
10226 if (has_shortname)
10227 {
Bram Moolenaardc935552011-08-17 15:23:23 +020010228 /* Copy the string if it is shortened by :h and when it wasn't copied
10229 * yet, because we are going to change it in place. Avoids changing
10230 * the buffer name for "%:8". */
10231 if (*fnamelen < (int)STRLEN(*fnamep) || *fnamep == fname_start)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010232 {
10233 p = vim_strnsave(*fnamep, *fnamelen);
Bram Moolenaardc935552011-08-17 15:23:23 +020010234 if (p == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010235 return -1;
10236 vim_free(*bufp);
10237 *bufp = *fnamep = p;
10238 }
10239
10240 /* Split into two implementations - makes it easier. First is where
Bram Moolenaardc935552011-08-17 15:23:23 +020010241 * there isn't a full name already, second is where there is. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010242 if (!has_fullname && !vim_isAbsName(*fnamep))
10243 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000010244 if (shortpath_for_partial(fnamep, bufp, fnamelen) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010245 return -1;
10246 }
10247 else
10248 {
Bram Moolenaardc935552011-08-17 15:23:23 +020010249 int l = *fnamelen;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010250
Bram Moolenaardc935552011-08-17 15:23:23 +020010251 /* Simple case, already have the full-name.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010252 * Nearly always shorter, so try first time. */
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000010253 if (get_short_pathname(fnamep, bufp, &l) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010254 return -1;
10255
10256 if (l == 0)
10257 {
Bram Moolenaardc935552011-08-17 15:23:23 +020010258 /* Couldn't find the filename, search the paths. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010259 l = *fnamelen;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000010260 if (shortpath_for_invalid_fname(fnamep, bufp, &l) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010261 return -1;
10262 }
10263 *fnamelen = l;
10264 }
10265 }
Bram Moolenaar4f974752019-02-17 17:44:42 +010010266#endif // MSWIN
Bram Moolenaar071d4272004-06-13 20:20:40 +000010267
10268 /* ":t" - tail, just the basename */
10269 if (src[*usedlen] == ':' && src[*usedlen + 1] == 't')
10270 {
10271 *usedlen += 2;
10272 *fnamelen -= (int)(tail - *fnamep);
10273 *fnamep = tail;
10274 }
10275
10276 /* ":e" - extension, can be repeated */
10277 /* ":r" - root, without extension, can be repeated */
10278 while (src[*usedlen] == ':'
10279 && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r'))
10280 {
10281 /* find a '.' in the tail:
10282 * - for second :e: before the current fname
10283 * - otherwise: The last '.'
10284 */
10285 if (src[*usedlen + 1] == 'e' && *fnamep > tail)
10286 s = *fnamep - 2;
10287 else
10288 s = *fnamep + *fnamelen - 1;
10289 for ( ; s > tail; --s)
10290 if (s[0] == '.')
10291 break;
10292 if (src[*usedlen + 1] == 'e') /* :e */
10293 {
10294 if (s > tail)
10295 {
10296 *fnamelen += (int)(*fnamep - (s + 1));
10297 *fnamep = s + 1;
10298#ifdef VMS
10299 /* cut version from the extension */
10300 s = *fnamep + *fnamelen - 1;
10301 for ( ; s > *fnamep; --s)
10302 if (s[0] == ';')
10303 break;
10304 if (s > *fnamep)
10305 *fnamelen = s - *fnamep;
10306#endif
10307 }
10308 else if (*fnamep <= tail)
10309 *fnamelen = 0;
10310 }
10311 else /* :r */
10312 {
10313 if (s > tail) /* remove one extension */
10314 *fnamelen = (int)(s - *fnamep);
10315 }
10316 *usedlen += 2;
10317 }
10318
10319 /* ":s?pat?foo?" - substitute */
10320 /* ":gs?pat?foo?" - global substitute */
10321 if (src[*usedlen] == ':'
10322 && (src[*usedlen + 1] == 's'
10323 || (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's')))
10324 {
10325 char_u *str;
10326 char_u *pat;
10327 char_u *sub;
10328 int sep;
10329 char_u *flags;
10330 int didit = FALSE;
10331
10332 flags = (char_u *)"";
10333 s = src + *usedlen + 2;
10334 if (src[*usedlen + 1] == 'g')
10335 {
10336 flags = (char_u *)"g";
10337 ++s;
10338 }
10339
10340 sep = *s++;
10341 if (sep)
10342 {
10343 /* find end of pattern */
10344 p = vim_strchr(s, sep);
10345 if (p != NULL)
10346 {
10347 pat = vim_strnsave(s, (int)(p - s));
10348 if (pat != NULL)
10349 {
10350 s = p + 1;
10351 /* find end of substitution */
10352 p = vim_strchr(s, sep);
10353 if (p != NULL)
10354 {
10355 sub = vim_strnsave(s, (int)(p - s));
10356 str = vim_strnsave(*fnamep, *fnamelen);
10357 if (sub != NULL && str != NULL)
10358 {
10359 *usedlen = (int)(p + 1 - src);
Bram Moolenaar72ab7292016-07-19 19:10:51 +020010360 s = do_string_sub(str, pat, sub, NULL, flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010361 if (s != NULL)
10362 {
10363 *fnamep = s;
10364 *fnamelen = (int)STRLEN(s);
10365 vim_free(*bufp);
10366 *bufp = s;
10367 didit = TRUE;
10368 }
10369 }
10370 vim_free(sub);
10371 vim_free(str);
10372 }
10373 vim_free(pat);
10374 }
10375 }
10376 /* after using ":s", repeat all the modifiers */
10377 if (didit)
10378 goto repeat;
10379 }
10380 }
10381
Bram Moolenaar26df0922014-02-23 23:39:13 +010010382 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'S')
10383 {
Bram Moolenaar5ca84ce2016-03-23 22:28:25 +010010384 /* vim_strsave_shellescape() needs a NUL terminated string. */
Bram Moolenaard4caf5c2016-03-24 19:14:35 +010010385 c = (*fnamep)[*fnamelen];
Bram Moolenaar52c6eaf2016-03-25 18:42:46 +010010386 if (c != NUL)
10387 (*fnamep)[*fnamelen] = NUL;
Bram Moolenaar26df0922014-02-23 23:39:13 +010010388 p = vim_strsave_shellescape(*fnamep, FALSE, FALSE);
Bram Moolenaar52c6eaf2016-03-25 18:42:46 +010010389 if (c != NUL)
10390 (*fnamep)[*fnamelen] = c;
Bram Moolenaar26df0922014-02-23 23:39:13 +010010391 if (p == NULL)
10392 return -1;
10393 vim_free(*bufp);
10394 *bufp = *fnamep = p;
10395 *fnamelen = (int)STRLEN(p);
10396 *usedlen += 2;
10397 }
10398
Bram Moolenaar071d4272004-06-13 20:20:40 +000010399 return valid;
10400}
10401
10402/*
10403 * Perform a substitution on "str" with pattern "pat" and substitute "sub".
Bram Moolenaar72ab7292016-07-19 19:10:51 +020010404 * When "sub" is NULL "expr" is used, must be a VAR_FUNC or VAR_PARTIAL.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010405 * "flags" can be "g" to do a global substitute.
10406 * Returns an allocated string, NULL for error.
10407 */
10408 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010010409do_string_sub(
10410 char_u *str,
10411 char_u *pat,
10412 char_u *sub,
Bram Moolenaar72ab7292016-07-19 19:10:51 +020010413 typval_T *expr,
Bram Moolenaar7454a062016-01-30 15:14:10 +010010414 char_u *flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010415{
10416 int sublen;
10417 regmatch_T regmatch;
10418 int i;
10419 int do_all;
10420 char_u *tail;
Bram Moolenaare90c8532014-11-05 16:03:44 +010010421 char_u *end;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010422 garray_T ga;
10423 char_u *ret;
10424 char_u *save_cpo;
Bram Moolenaar8af26912014-01-23 20:09:34 +010010425 char_u *zero_width = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010426
10427 /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */
10428 save_cpo = p_cpo;
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +000010429 p_cpo = empty_option;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010430
10431 ga_init2(&ga, 1, 200);
10432
10433 do_all = (flags[0] == 'g');
10434
10435 regmatch.rm_ic = p_ic;
10436 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
10437 if (regmatch.regprog != NULL)
10438 {
10439 tail = str;
Bram Moolenaare90c8532014-11-05 16:03:44 +010010440 end = str + STRLEN(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010441 while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
10442 {
Bram Moolenaar8af26912014-01-23 20:09:34 +010010443 /* Skip empty match except for first match. */
10444 if (regmatch.startp[0] == regmatch.endp[0])
10445 {
10446 if (zero_width == regmatch.startp[0])
10447 {
10448 /* avoid getting stuck on a match with an empty string */
Bram Moolenaar8e7048c2014-06-12 18:39:22 +020010449 i = MB_PTR2LEN(tail);
10450 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail,
10451 (size_t)i);
10452 ga.ga_len += i;
10453 tail += i;
Bram Moolenaar8af26912014-01-23 20:09:34 +010010454 continue;
10455 }
10456 zero_width = regmatch.startp[0];
10457 }
10458
Bram Moolenaar071d4272004-06-13 20:20:40 +000010459 /*
10460 * Get some space for a temporary buffer to do the substitution
10461 * into. It will contain:
10462 * - The text up to where the match is.
10463 * - The substituted text.
10464 * - The text after the match.
10465 */
Bram Moolenaar72ab7292016-07-19 19:10:51 +020010466 sublen = vim_regsub(&regmatch, sub, expr, tail, FALSE, TRUE, FALSE);
Bram Moolenaare90c8532014-11-05 16:03:44 +010010467 if (ga_grow(&ga, (int)((end - tail) + sublen -
Bram Moolenaar071d4272004-06-13 20:20:40 +000010468 (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
10469 {
10470 ga_clear(&ga);
10471 break;
10472 }
10473
10474 /* copy the text up to where the match is */
10475 i = (int)(regmatch.startp[0] - tail);
10476 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
10477 /* add the substituted text */
Bram Moolenaar72ab7292016-07-19 19:10:51 +020010478 (void)vim_regsub(&regmatch, sub, expr, (char_u *)ga.ga_data
Bram Moolenaar071d4272004-06-13 20:20:40 +000010479 + ga.ga_len + i, TRUE, TRUE, FALSE);
10480 ga.ga_len += i + sublen - 1;
Bram Moolenaarceb84af2013-09-29 21:11:05 +020010481 tail = regmatch.endp[0];
10482 if (*tail == NUL)
10483 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010484 if (!do_all)
10485 break;
10486 }
10487
10488 if (ga.ga_data != NULL)
10489 STRCPY((char *)ga.ga_data + ga.ga_len, tail);
10490
Bram Moolenaar473de612013-06-08 18:19:48 +020010491 vim_regfree(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010492 }
10493
10494 ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data);
10495 ga_clear(&ga);
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +000010496 if (p_cpo == empty_option)
10497 p_cpo = save_cpo;
10498 else
Bram Moolenaar72ab7292016-07-19 19:10:51 +020010499 /* Darn, evaluating {sub} expression or {expr} changed the value. */
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +000010500 free_string_option(save_cpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010501
10502 return ret;
10503}
10504
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010505 static int
10506filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)
10507{
10508 typval_T rettv;
10509 typval_T argv[3];
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010510 int retval = FAIL;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010511
10512 copy_tv(tv, &vimvars[VV_VAL].vv_tv);
10513 argv[0] = vimvars[VV_KEY].vv_tv;
10514 argv[1] = vimvars[VV_VAL].vv_tv;
Bram Moolenaar48570482017-10-30 21:48:41 +010010515 if (eval_expr_typval(expr, argv, 2, &rettv) == FAIL)
10516 goto theend;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010517 if (map)
10518 {
10519 /* map(): replace the list item value */
10520 clear_tv(tv);
10521 rettv.v_lock = 0;
10522 *tv = rettv;
10523 }
10524 else
10525 {
10526 int error = FALSE;
10527
10528 /* filter(): when expr is zero remove the item */
Bram Moolenaard155d7a2018-12-21 16:04:21 +010010529 *remp = (tv_get_number_chk(&rettv, &error) == 0);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010530 clear_tv(&rettv);
10531 /* On type error, nothing has been removed; return FAIL to stop the
Bram Moolenaard155d7a2018-12-21 16:04:21 +010010532 * loop. The error message was given by tv_get_number_chk(). */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010533 if (error)
10534 goto theend;
10535 }
10536 retval = OK;
10537theend:
10538 clear_tv(&vimvars[VV_VAL].vv_tv);
10539 return retval;
10540}
10541
10542
10543/*
10544 * Implementation of map() and filter().
10545 */
10546 void
10547filter_map(typval_T *argvars, typval_T *rettv, int map)
10548{
10549 typval_T *expr;
10550 listitem_T *li, *nli;
10551 list_T *l = NULL;
10552 dictitem_T *di;
10553 hashtab_T *ht;
10554 hashitem_T *hi;
10555 dict_T *d = NULL;
10556 typval_T save_val;
10557 typval_T save_key;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +010010558 blob_T *b = NULL;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010559 int rem;
10560 int todo;
10561 char_u *ermsg = (char_u *)(map ? "map()" : "filter()");
10562 char_u *arg_errmsg = (char_u *)(map ? N_("map() argument")
10563 : N_("filter() argument"));
10564 int save_did_emsg;
10565 int idx = 0;
10566
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +010010567 if (argvars[0].v_type == VAR_BLOB)
10568 {
10569 if ((b = argvars[0].vval.v_blob) == NULL)
10570 return;
10571 }
10572 else if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010573 {
10574 if ((l = argvars[0].vval.v_list) == NULL
Bram Moolenaar05c00c02019-02-11 22:00:11 +010010575 || (!map && var_check_lock(l->lv_lock, arg_errmsg, TRUE)))
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010576 return;
10577 }
10578 else if (argvars[0].v_type == VAR_DICT)
10579 {
10580 if ((d = argvars[0].vval.v_dict) == NULL
Bram Moolenaar05c00c02019-02-11 22:00:11 +010010581 || (!map && var_check_lock(d->dv_lock, arg_errmsg, TRUE)))
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010582 return;
10583 }
10584 else
10585 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +010010586 semsg(_(e_listdictarg), ermsg);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010587 return;
10588 }
10589
10590 expr = &argvars[1];
10591 /* On type errors, the preceding call has already displayed an error
10592 * message. Avoid a misleading error message for an empty string that
10593 * was not passed as argument. */
10594 if (expr->v_type != VAR_UNKNOWN)
10595 {
10596 prepare_vimvar(VV_VAL, &save_val);
10597
10598 /* We reset "did_emsg" to be able to detect whether an error
10599 * occurred during evaluation of the expression. */
10600 save_did_emsg = did_emsg;
10601 did_emsg = FALSE;
10602
10603 prepare_vimvar(VV_KEY, &save_key);
10604 if (argvars[0].v_type == VAR_DICT)
10605 {
10606 vimvars[VV_KEY].vv_type = VAR_STRING;
10607
10608 ht = &d->dv_hashtab;
10609 hash_lock(ht);
10610 todo = (int)ht->ht_used;
10611 for (hi = ht->ht_array; todo > 0; ++hi)
10612 {
10613 if (!HASHITEM_EMPTY(hi))
10614 {
10615 int r;
10616
10617 --todo;
10618 di = HI2DI(hi);
Bram Moolenaar05c00c02019-02-11 22:00:11 +010010619 if (map && (var_check_lock(di->di_tv.v_lock,
10620 arg_errmsg, TRUE)
10621 || var_check_ro(di->di_flags,
10622 arg_errmsg, TRUE)))
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010623 break;
10624 vimvars[VV_KEY].vv_str = vim_strsave(di->di_key);
10625 r = filter_map_one(&di->di_tv, expr, map, &rem);
10626 clear_tv(&vimvars[VV_KEY].vv_tv);
10627 if (r == FAIL || did_emsg)
10628 break;
10629 if (!map && rem)
10630 {
10631 if (var_check_fixed(di->di_flags, arg_errmsg, TRUE)
10632 || var_check_ro(di->di_flags, arg_errmsg, TRUE))
10633 break;
10634 dictitem_remove(d, di);
10635 }
10636 }
10637 }
10638 hash_unlock(ht);
10639 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +010010640 else if (argvars[0].v_type == VAR_BLOB)
10641 {
10642 int i;
10643 typval_T tv;
10644
10645 vimvars[VV_KEY].vv_type = VAR_NUMBER;
10646 for (i = 0; i < b->bv_ga.ga_len; i++)
10647 {
10648 tv.v_type = VAR_NUMBER;
10649 tv.vval.v_number = blob_get(b, i);
10650 vimvars[VV_KEY].vv_nr = idx;
10651 if (filter_map_one(&tv, expr, map, &rem) == FAIL || did_emsg)
10652 break;
10653 if (tv.v_type != VAR_NUMBER)
10654 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +010010655 emsg(_(e_invalblob));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +010010656 return;
10657 }
10658 tv.v_type = VAR_NUMBER;
10659 blob_set(b, i, tv.vval.v_number);
10660 if (!map && rem)
10661 {
10662 char_u *p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data;
10663
10664 mch_memmove(p + idx, p + i + 1,
10665 (size_t)b->bv_ga.ga_len - i - 1);
10666 --b->bv_ga.ga_len;
10667 --i;
10668 }
10669 }
10670 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010671 else
10672 {
Bram Moolenaarce9d50d2019-01-14 22:22:29 +010010673 // argvars[0].v_type == VAR_LIST
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010674 vimvars[VV_KEY].vv_type = VAR_NUMBER;
10675
10676 for (li = l->lv_first; li != NULL; li = nli)
10677 {
Bram Moolenaar05c00c02019-02-11 22:00:11 +010010678 if (map && var_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE))
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010679 break;
10680 nli = li->li_next;
10681 vimvars[VV_KEY].vv_nr = idx;
10682 if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL
10683 || did_emsg)
10684 break;
10685 if (!map && rem)
10686 listitem_remove(l, li);
10687 ++idx;
10688 }
10689 }
10690
10691 restore_vimvar(VV_KEY, &save_key);
10692 restore_vimvar(VV_VAL, &save_val);
10693
10694 did_emsg |= save_did_emsg;
10695 }
10696
10697 copy_tv(&argvars[0], rettv);
10698}
10699
Bram Moolenaar071d4272004-06-13 20:20:40 +000010700#endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */