blob: f70d03b369e9aac58a7b41b0d9ce96d678bad793 [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 Moolenaar8c0e3222013-06-16 17:32:40 +020031#ifdef FEAT_FLOAT
Bram Moolenaar2a876e42013-06-12 22:08:58 +020032static char *e_float_as_string = N_("E806: using Float as a String");
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020033#endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +000034
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +010035#define NAMESPACE_CHAR (char_u *)"abglstvw"
36
Bram Moolenaar230bb3f2013-04-24 14:07:45 +020037static dictitem_T globvars_var; /* variable used for g: */
Bram Moolenaar33570922005-01-25 22:26:29 +000038#define globvarht globvardict.dv_hashtab
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 */
81} forinfo_T;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000082
Bram Moolenaara7043832005-01-21 11:56:39 +000083
84/*
Bram Moolenaar33570922005-01-25 22:26:29 +000085 * Array to hold the value of v: variables.
86 * The value is in a dictitem, so that it can also be used in the v: scope.
87 * The reason to use this table anyway is for very quick access to the
88 * variables with the VV_ defines.
89 */
Bram Moolenaar33570922005-01-25 22:26:29 +000090
91/* values for vv_flags: */
92#define VV_COMPAT 1 /* compatible, also used without "v:" */
93#define VV_RO 2 /* read-only */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000094#define VV_RO_SBX 4 /* read-only in the sandbox */
Bram Moolenaar33570922005-01-25 22:26:29 +000095
Bram Moolenaarbee6c0c2016-03-25 15:40:50 +010096#define VV_NAME(s, t) s, {{t, 0, {0}}, 0, {0}}
Bram Moolenaar33570922005-01-25 22:26:29 +000097
98static struct vimvar
99{
100 char *vv_name; /* name of variable, without v: */
Bram Moolenaarbee6c0c2016-03-25 15:40:50 +0100101 dictitem16_T vv_di; /* value and name for key (max 16 chars!) */
Bram Moolenaar33570922005-01-25 22:26:29 +0000102 char vv_flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */
103} vimvars[VV_LEN] =
104{
105 /*
106 * The order here must match the VV_ defines in vim.h!
107 * Initializing a union does not work, leave tv.vval empty to get zero's.
108 */
109 {VV_NAME("count", VAR_NUMBER), VV_COMPAT+VV_RO},
110 {VV_NAME("count1", VAR_NUMBER), VV_RO},
111 {VV_NAME("prevcount", VAR_NUMBER), VV_RO},
112 {VV_NAME("errmsg", VAR_STRING), VV_COMPAT},
113 {VV_NAME("warningmsg", VAR_STRING), 0},
114 {VV_NAME("statusmsg", VAR_STRING), 0},
115 {VV_NAME("shell_error", VAR_NUMBER), VV_COMPAT+VV_RO},
116 {VV_NAME("this_session", VAR_STRING), VV_COMPAT},
117 {VV_NAME("version", VAR_NUMBER), VV_COMPAT+VV_RO},
118 {VV_NAME("lnum", VAR_NUMBER), VV_RO_SBX},
119 {VV_NAME("termresponse", VAR_STRING), VV_RO},
120 {VV_NAME("fname", VAR_STRING), VV_RO},
121 {VV_NAME("lang", VAR_STRING), VV_RO},
122 {VV_NAME("lc_time", VAR_STRING), VV_RO},
123 {VV_NAME("ctype", VAR_STRING), VV_RO},
124 {VV_NAME("charconvert_from", VAR_STRING), VV_RO},
125 {VV_NAME("charconvert_to", VAR_STRING), VV_RO},
126 {VV_NAME("fname_in", VAR_STRING), VV_RO},
127 {VV_NAME("fname_out", VAR_STRING), VV_RO},
128 {VV_NAME("fname_new", VAR_STRING), VV_RO},
129 {VV_NAME("fname_diff", VAR_STRING), VV_RO},
130 {VV_NAME("cmdarg", VAR_STRING), VV_RO},
131 {VV_NAME("foldstart", VAR_NUMBER), VV_RO_SBX},
132 {VV_NAME("foldend", VAR_NUMBER), VV_RO_SBX},
133 {VV_NAME("folddashes", VAR_STRING), VV_RO_SBX},
134 {VV_NAME("foldlevel", VAR_NUMBER), VV_RO_SBX},
135 {VV_NAME("progname", VAR_STRING), VV_RO},
136 {VV_NAME("servername", VAR_STRING), VV_RO},
137 {VV_NAME("dying", VAR_NUMBER), VV_RO},
138 {VV_NAME("exception", VAR_STRING), VV_RO},
139 {VV_NAME("throwpoint", VAR_STRING), VV_RO},
140 {VV_NAME("register", VAR_STRING), VV_RO},
141 {VV_NAME("cmdbang", VAR_NUMBER), VV_RO},
142 {VV_NAME("insertmode", VAR_STRING), VV_RO},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000143 {VV_NAME("val", VAR_UNKNOWN), VV_RO},
144 {VV_NAME("key", VAR_UNKNOWN), VV_RO},
Bram Moolenaar05159a02005-02-26 23:04:13 +0000145 {VV_NAME("profiling", VAR_NUMBER), VV_RO},
Bram Moolenaar19a09a12005-03-04 23:39:37 +0000146 {VV_NAME("fcs_reason", VAR_STRING), VV_RO},
147 {VV_NAME("fcs_choice", VAR_STRING), 0},
Bram Moolenaare2ac10d2005-03-07 23:26:06 +0000148 {VV_NAME("beval_bufnr", VAR_NUMBER), VV_RO},
149 {VV_NAME("beval_winnr", VAR_NUMBER), VV_RO},
Bram Moolenaarc9721bd2016-06-04 17:41:03 +0200150 {VV_NAME("beval_winid", VAR_NUMBER), VV_RO},
Bram Moolenaare2ac10d2005-03-07 23:26:06 +0000151 {VV_NAME("beval_lnum", VAR_NUMBER), VV_RO},
152 {VV_NAME("beval_col", VAR_NUMBER), VV_RO},
153 {VV_NAME("beval_text", VAR_STRING), VV_RO},
Bram Moolenaar761b1132005-10-03 22:05:45 +0000154 {VV_NAME("scrollstart", VAR_STRING), 0},
Bram Moolenaard5bc83f2005-12-07 21:07:59 +0000155 {VV_NAME("swapname", VAR_STRING), VV_RO},
156 {VV_NAME("swapchoice", VAR_STRING), 0},
Bram Moolenaar63a121b2005-12-11 21:36:39 +0000157 {VV_NAME("swapcommand", VAR_STRING), VV_RO},
Bram Moolenaare659c952011-05-19 17:25:41 +0200158 {VV_NAME("char", VAR_STRING), 0},
Bram Moolenaar219b8702006-11-01 14:32:36 +0000159 {VV_NAME("mouse_win", VAR_NUMBER), 0},
Bram Moolenaar511972d2016-06-04 18:09:59 +0200160 {VV_NAME("mouse_winid", VAR_NUMBER), 0},
Bram Moolenaar219b8702006-11-01 14:32:36 +0000161 {VV_NAME("mouse_lnum", VAR_NUMBER), 0},
162 {VV_NAME("mouse_col", VAR_NUMBER), 0},
Bram Moolenaar8af1fbf2008-01-05 12:35:21 +0000163 {VV_NAME("operator", VAR_STRING), VV_RO},
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000164 {VV_NAME("searchforward", VAR_NUMBER), 0},
Bram Moolenaar8050efa2013-11-08 04:30:20 +0100165 {VV_NAME("hlsearch", VAR_NUMBER), 0},
Bram Moolenaard812df62008-11-09 12:46:09 +0000166 {VV_NAME("oldfiles", VAR_LIST), 0},
Bram Moolenaar727c8762010-10-20 19:17:48 +0200167 {VV_NAME("windowid", VAR_NUMBER), VV_RO},
Bram Moolenaara1706c92014-04-01 19:55:49 +0200168 {VV_NAME("progpath", VAR_STRING), VV_RO},
Bram Moolenaar42a45122015-07-10 17:56:23 +0200169 {VV_NAME("completed_item", VAR_DICT), VV_RO},
Bram Moolenaar53744302015-07-17 17:38:22 +0200170 {VV_NAME("option_new", VAR_STRING), VV_RO},
171 {VV_NAME("option_old", VAR_STRING), VV_RO},
172 {VV_NAME("option_type", VAR_STRING), VV_RO},
Bram Moolenaar43345542015-11-29 17:35:35 +0100173 {VV_NAME("errors", VAR_LIST), 0},
Bram Moolenaar520e1e42016-01-23 19:46:28 +0100174 {VV_NAME("false", VAR_SPECIAL), VV_RO},
175 {VV_NAME("true", VAR_SPECIAL), VV_RO},
176 {VV_NAME("null", VAR_SPECIAL), VV_RO},
177 {VV_NAME("none", VAR_SPECIAL), VV_RO},
Bram Moolenaar14735512016-03-26 21:00:08 +0100178 {VV_NAME("vim_did_enter", VAR_NUMBER), VV_RO},
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +0200179 {VV_NAME("testing", VAR_NUMBER), 0},
Bram Moolenaarf562e722016-07-19 17:25:25 +0200180 {VV_NAME("t_number", VAR_NUMBER), VV_RO},
181 {VV_NAME("t_string", VAR_NUMBER), VV_RO},
182 {VV_NAME("t_func", VAR_NUMBER), VV_RO},
183 {VV_NAME("t_list", VAR_NUMBER), VV_RO},
184 {VV_NAME("t_dict", VAR_NUMBER), VV_RO},
185 {VV_NAME("t_float", VAR_NUMBER), VV_RO},
186 {VV_NAME("t_bool", VAR_NUMBER), VV_RO},
187 {VV_NAME("t_none", VAR_NUMBER), VV_RO},
188 {VV_NAME("t_job", VAR_NUMBER), VV_RO},
189 {VV_NAME("t_channel", VAR_NUMBER), VV_RO},
Bram Moolenaar33570922005-01-25 22:26:29 +0000190};
191
192/* shorthand */
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000193#define vv_type vv_di.di_tv.v_type
194#define vv_nr vv_di.di_tv.vval.v_number
195#define vv_float vv_di.di_tv.vval.v_float
196#define vv_str vv_di.di_tv.vval.v_string
Bram Moolenaard812df62008-11-09 12:46:09 +0000197#define vv_list vv_di.di_tv.vval.v_list
Bram Moolenaar42a45122015-07-10 17:56:23 +0200198#define vv_dict vv_di.di_tv.vval.v_dict
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000199#define vv_tv vv_di.di_tv
Bram Moolenaar33570922005-01-25 22:26:29 +0000200
Bram Moolenaar230bb3f2013-04-24 14:07:45 +0200201static dictitem_T vimvars_var; /* variable used for v: */
Bram Moolenaar33570922005-01-25 22:26:29 +0000202#define vimvarht vimvardict.dv_hashtab
203
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100204static int ex_let_vars(char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, char_u *nextchars);
205static char_u *skip_var_list(char_u *arg, int *var_count, int *semicolon);
206static char_u *skip_var_one(char_u *arg);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100207static void list_glob_vars(int *first);
208static void list_buf_vars(int *first);
209static void list_win_vars(int *first);
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000210#ifdef FEAT_WINDOWS
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100211static void list_tab_vars(int *first);
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000212#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100213static void list_vim_vars(int *first);
214static void list_script_vars(int *first);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100215static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first);
216static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, char_u *endchars, char_u *op);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100217static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op);
218static int tv_op(typval_T *tv1, typval_T *tv2, char_u *op);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100219static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep);
220static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit);
221static int do_lock_var(lval_T *lp, char_u *name_end, int deep, int lock);
222static void item_lock(typval_T *tv, int deep, int lock);
Bram Moolenaara40058a2005-07-11 22:42:07 +0000223
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100224static int eval2(char_u **arg, typval_T *rettv, int evaluate);
225static int eval3(char_u **arg, typval_T *rettv, int evaluate);
226static int eval4(char_u **arg, typval_T *rettv, int evaluate);
227static int eval5(char_u **arg, typval_T *rettv, int evaluate);
228static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string);
229static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string);
Bram Moolenaara40058a2005-07-11 22:42:07 +0000230
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100231static int eval_index(char_u **arg, typval_T *rettv, int evaluate, int verbose);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100232static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate);
233static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100234static int free_unref_items(int copyID);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100235static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100236static int get_env_len(char_u **arg);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100237static 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 +0200238static void check_vars(char_u *name, int len);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100239static typval_T *alloc_string_tv(char_u *string);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100240static void delete_var(hashtab_T *ht, hashitem_T *hi);
241static void list_one_var(dictitem_T *v, char_u *prefix, int *first);
242static void list_one_var_a(char_u *prefix, char_u *name, int type, char_u *string, int *first);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100243static char_u *find_option_end(char_u **arg, int *opt_flags);
Bram Moolenaar2c704a72010-06-03 21:17:25 +0200244
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200245/* for VIM_VERSION_ defines */
246#include "version.h"
247
Bram Moolenaara1fa8922017-01-12 20:06:33 +0100248
249#if defined(EBCDIC) || defined(PROTO)
250/*
251 * Compare struct fst by function name.
252 */
253 static int
254compare_func_name(const void *s1, const void *s2)
255{
256 struct fst *p1 = (struct fst *)s1;
257 struct fst *p2 = (struct fst *)s2;
258
259 return STRCMP(p1->f_name, p2->f_name);
260}
261
262/*
263 * Sort the function table by function name.
264 * The sorting of the table above is ASCII dependant.
265 * On machines using EBCDIC we have to sort it.
266 */
267 static void
268sortFunctions(void)
269{
270 int funcCnt = (int)(sizeof(functions) / sizeof(struct fst)) - 1;
271
272 qsort(functions, (size_t)funcCnt, sizeof(struct fst), compare_func_name);
273}
274#endif
275
276
Bram Moolenaar33570922005-01-25 22:26:29 +0000277/*
278 * Initialize the global and v: variables.
Bram Moolenaara7043832005-01-21 11:56:39 +0000279 */
280 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100281eval_init(void)
Bram Moolenaara7043832005-01-21 11:56:39 +0000282{
Bram Moolenaar33570922005-01-25 22:26:29 +0000283 int i;
284 struct vimvar *p;
285
Bram Moolenaarbdb62052012-07-16 17:31:53 +0200286 init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE);
287 init_var_dict(&vimvardict, &vimvars_var, VAR_SCOPE);
Bram Moolenaar32f649e2011-04-11 13:46:13 +0200288 vimvardict.dv_lock = VAR_FIXED;
Bram Moolenaar532c7802005-01-27 14:44:31 +0000289 hash_init(&compat_hashtab);
Bram Moolenaara9b579f2016-07-17 18:29:19 +0200290 func_init();
Bram Moolenaar33570922005-01-25 22:26:29 +0000291
292 for (i = 0; i < VV_LEN; ++i)
293 {
294 p = &vimvars[i];
Bram Moolenaaref9d9b92016-03-28 22:44:50 +0200295 if (STRLEN(p->vv_name) > 16)
296 {
Bram Moolenaarde330112017-01-08 20:50:52 +0100297 IEMSG("INTERNAL: name too long, increase size of dictitem16_T");
Bram Moolenaaref9d9b92016-03-28 22:44:50 +0200298 getout(1);
299 }
Bram Moolenaar33570922005-01-25 22:26:29 +0000300 STRCPY(p->vv_di.di_key, p->vv_name);
301 if (p->vv_flags & VV_RO)
302 p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
303 else if (p->vv_flags & VV_RO_SBX)
304 p->vv_di.di_flags = DI_FLAGS_RO_SBX | DI_FLAGS_FIX;
305 else
306 p->vv_di.di_flags = DI_FLAGS_FIX;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000307
308 /* add to v: scope dict, unless the value is not always available */
309 if (p->vv_type != VAR_UNKNOWN)
310 hash_add(&vimvarht, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000311 if (p->vv_flags & VV_COMPAT)
Bram Moolenaar532c7802005-01-27 14:44:31 +0000312 /* add to compat scope dict */
313 hash_add(&compat_hashtab, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000314 }
Bram Moolenaara542c682016-01-31 16:28:04 +0100315 vimvars[VV_VERSION].vv_nr = VIM_VERSION_100;
316
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000317 set_vim_var_nr(VV_SEARCHFORWARD, 1L);
Bram Moolenaar8050efa2013-11-08 04:30:20 +0100318 set_vim_var_nr(VV_HLSEARCH, 1L);
Bram Moolenaar42a45122015-07-10 17:56:23 +0200319 set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
Bram Moolenaar4649ded2015-12-03 14:55:55 +0100320 set_vim_var_list(VV_ERRORS, list_alloc());
Bram Moolenaar520e1e42016-01-23 19:46:28 +0100321
322 set_vim_var_nr(VV_FALSE, VVAL_FALSE);
323 set_vim_var_nr(VV_TRUE, VVAL_TRUE);
324 set_vim_var_nr(VV_NONE, VVAL_NONE);
325 set_vim_var_nr(VV_NULL, VVAL_NULL);
326
Bram Moolenaarf562e722016-07-19 17:25:25 +0200327 set_vim_var_nr(VV_TYPE_NUMBER, VAR_TYPE_NUMBER);
328 set_vim_var_nr(VV_TYPE_STRING, VAR_TYPE_STRING);
329 set_vim_var_nr(VV_TYPE_FUNC, VAR_TYPE_FUNC);
330 set_vim_var_nr(VV_TYPE_LIST, VAR_TYPE_LIST);
331 set_vim_var_nr(VV_TYPE_DICT, VAR_TYPE_DICT);
332 set_vim_var_nr(VV_TYPE_FLOAT, VAR_TYPE_FLOAT);
333 set_vim_var_nr(VV_TYPE_BOOL, VAR_TYPE_BOOL);
334 set_vim_var_nr(VV_TYPE_NONE, VAR_TYPE_NONE);
335 set_vim_var_nr(VV_TYPE_JOB, VAR_TYPE_JOB);
336 set_vim_var_nr(VV_TYPE_CHANNEL, VAR_TYPE_CHANNEL);
337
Bram Moolenaarb429cde2012-04-25 18:24:29 +0200338 set_reg_var(0); /* default for v:register is not 0 but '"' */
Bram Moolenaar2c704a72010-06-03 21:17:25 +0200339
340#ifdef EBCDIC
341 /*
Bram Moolenaar195ea0f2011-11-30 14:57:31 +0100342 * Sort the function table, to enable binary search.
Bram Moolenaar2c704a72010-06-03 21:17:25 +0200343 */
344 sortFunctions();
345#endif
Bram Moolenaara7043832005-01-21 11:56:39 +0000346}
347
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000348#if defined(EXITFREE) || defined(PROTO)
349 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100350eval_clear(void)
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000351{
352 int i;
353 struct vimvar *p;
354
355 for (i = 0; i < VV_LEN; ++i)
356 {
357 p = &vimvars[i];
358 if (p->vv_di.di_tv.v_type == VAR_STRING)
Bram Moolenaard9fba312005-06-26 22:34:35 +0000359 {
Bram Moolenaar12193212008-11-09 16:22:01 +0000360 vim_free(p->vv_str);
361 p->vv_str = NULL;
Bram Moolenaard812df62008-11-09 12:46:09 +0000362 }
363 else if (p->vv_di.di_tv.v_type == VAR_LIST)
364 {
365 list_unref(p->vv_list);
366 p->vv_list = NULL;
Bram Moolenaard9fba312005-06-26 22:34:35 +0000367 }
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000368 }
369 hash_clear(&vimvarht);
Bram Moolenaar0f71c6d2008-11-12 14:29:28 +0000370 hash_init(&vimvarht); /* garbage_collect() will access it */
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000371 hash_clear(&compat_hashtab);
372
Bram Moolenaard9fba312005-06-26 22:34:35 +0000373 free_scriptnames();
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +0100374# if defined(FEAT_CMDL_COMPL)
Bram Moolenaar9b486ca2011-05-19 18:26:40 +0200375 free_locales();
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +0100376# endif
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000377
378 /* global variables */
379 vars_clear(&globvarht);
Bram Moolenaard9fba312005-06-26 22:34:35 +0000380
Bram Moolenaaraa35dd12006-04-29 22:03:41 +0000381 /* autoloaded script names */
382 ga_clear_strings(&ga_loaded);
383
Bram Moolenaarcca74132013-09-25 21:00:28 +0200384 /* Script-local variables. First clear all the variables and in a second
385 * loop free the scriptvar_T, because a variable in one script might hold
386 * a reference to the whole scope of another script. */
Bram Moolenaar9577c3e2010-05-14 12:16:25 +0200387 for (i = 1; i <= ga_scripts.ga_len; ++i)
Bram Moolenaar9577c3e2010-05-14 12:16:25 +0200388 vars_clear(&SCRIPT_VARS(i));
Bram Moolenaarcca74132013-09-25 21:00:28 +0200389 for (i = 1; i <= ga_scripts.ga_len; ++i)
Bram Moolenaar9577c3e2010-05-14 12:16:25 +0200390 vim_free(SCRIPT_SV(i));
Bram Moolenaar9577c3e2010-05-14 12:16:25 +0200391 ga_clear(&ga_scripts);
392
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000393 /* unreferenced lists and dicts */
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +0200394 (void)garbage_collect(FALSE);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000395
396 /* functions */
397 free_all_functions();
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000398}
399#endif
400
Bram Moolenaar071d4272004-06-13 20:20:40 +0000401
402/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000403 * Set an internal variable to a string value. Creates the variable if it does
404 * not already exist.
405 */
406 void
Bram Moolenaarb7604cc2016-01-15 21:23:22 +0100407set_internal_string_var(char_u *name, char_u *value)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000408{
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000409 char_u *val;
Bram Moolenaar33570922005-01-25 22:26:29 +0000410 typval_T *tvp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000411
412 val = vim_strsave(value);
413 if (val != NULL)
414 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000415 tvp = alloc_string_tv(val);
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000416 if (tvp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000417 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000418 set_var(name, tvp, FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000419 free_tv(tvp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000420 }
421 }
422}
423
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000424static lval_T *redir_lval = NULL;
Bram Moolenaar1e5e1232016-07-07 17:33:02 +0200425#define EVALCMD_BUSY (redir_lval == (lval_T *)&redir_lval)
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000426static garray_T redir_ga; /* only valid when redir_lval is not NULL */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000427static char_u *redir_endp = NULL;
428static char_u *redir_varname = NULL;
429
430/*
431 * Start recording command output to a variable
Bram Moolenaarb7604cc2016-01-15 21:23:22 +0100432 * When "append" is TRUE append to an existing variable.
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000433 * Returns OK if successfully completed the setup. FAIL otherwise.
434 */
435 int
Bram Moolenaarb7604cc2016-01-15 21:23:22 +0100436var_redir_start(char_u *name, int append)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000437{
438 int save_emsg;
439 int err;
440 typval_T tv;
441
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000442 /* Catch a bad name early. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000443 if (!eval_isnamec1(*name))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000444 {
445 EMSG(_(e_invarg));
446 return FAIL;
447 }
448
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000449 /* Make a copy of the name, it is used in redir_lval until redir ends. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000450 redir_varname = vim_strsave(name);
451 if (redir_varname == NULL)
452 return FAIL;
453
454 redir_lval = (lval_T *)alloc_clear((unsigned)sizeof(lval_T));
455 if (redir_lval == NULL)
456 {
457 var_redir_stop();
458 return FAIL;
459 }
460
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000461 /* The output is stored in growarray "redir_ga" until redirection ends. */
462 ga_init2(&redir_ga, (int)sizeof(char), 500);
463
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000464 /* Parse the variable name (can be a dict or list entry). */
Bram Moolenaar6d977d62014-01-14 15:24:39 +0100465 redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, 0,
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000466 FNE_CHECK_START);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000467 if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != NUL)
468 {
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +0200469 clear_lval(redir_lval);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000470 if (redir_endp != NULL && *redir_endp != NUL)
471 /* Trailing characters are present after the variable name */
472 EMSG(_(e_trailing));
473 else
474 EMSG(_(e_invarg));
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000475 redir_endp = NULL; /* don't store a value, only cleanup */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000476 var_redir_stop();
477 return FAIL;
478 }
479
480 /* check if we can write to the variable: set it to or append an empty
481 * string */
482 save_emsg = did_emsg;
483 did_emsg = FALSE;
484 tv.v_type = VAR_STRING;
485 tv.vval.v_string = (char_u *)"";
486 if (append)
487 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)".");
488 else
489 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)"=");
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +0200490 clear_lval(redir_lval);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000491 err = did_emsg;
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000492 did_emsg |= save_emsg;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000493 if (err)
494 {
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000495 redir_endp = NULL; /* don't store a value, only cleanup */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000496 var_redir_stop();
497 return FAIL;
498 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000499
500 return OK;
501}
502
503/*
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000504 * Append "value[value_len]" to the variable set by var_redir_start().
505 * The actual appending is postponed until redirection ends, because the value
506 * appended may in fact be the string we write to, changing it may cause freed
507 * memory to be used:
508 * :redir => foo
509 * :let foo
510 * :redir END
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000511 */
512 void
Bram Moolenaarb7604cc2016-01-15 21:23:22 +0100513var_redir_str(char_u *value, int value_len)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000514{
Bram Moolenaar5fdec472007-07-24 08:45:13 +0000515 int len;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000516
517 if (redir_lval == NULL)
518 return;
519
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000520 if (value_len == -1)
Bram Moolenaar5fdec472007-07-24 08:45:13 +0000521 len = (int)STRLEN(value); /* Append the entire string */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000522 else
Bram Moolenaar5fdec472007-07-24 08:45:13 +0000523 len = value_len; /* Append only "value_len" characters */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000524
Bram Moolenaar5fdec472007-07-24 08:45:13 +0000525 if (ga_grow(&redir_ga, len) == OK)
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000526 {
527 mch_memmove((char *)redir_ga.ga_data + redir_ga.ga_len, value, len);
Bram Moolenaar5fdec472007-07-24 08:45:13 +0000528 redir_ga.ga_len += len;
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000529 }
530 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000531 var_redir_stop();
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000532}
533
534/*
535 * Stop redirecting command output to a variable.
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000536 * Frees the allocated memory.
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000537 */
538 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100539var_redir_stop(void)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000540{
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000541 typval_T tv;
542
Bram Moolenaar1e5e1232016-07-07 17:33:02 +0200543 if (EVALCMD_BUSY)
544 {
545 redir_lval = NULL;
546 return;
547 }
548
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000549 if (redir_lval != NULL)
550 {
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000551 /* If there was no error: assign the text to the variable. */
552 if (redir_endp != NULL)
553 {
554 ga_append(&redir_ga, NUL); /* Append the trailing NUL. */
555 tv.v_type = VAR_STRING;
556 tv.vval.v_string = redir_ga.ga_data;
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +0200557 /* Call get_lval() again, if it's inside a Dict or List it may
558 * have changed. */
559 redir_endp = get_lval(redir_varname, NULL, redir_lval,
Bram Moolenaar6d977d62014-01-14 15:24:39 +0100560 FALSE, FALSE, 0, FNE_CHECK_START);
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +0200561 if (redir_endp != NULL && redir_lval->ll_name != NULL)
562 set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)".");
563 clear_lval(redir_lval);
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000564 }
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000565
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000566 /* free the collected output */
567 vim_free(redir_ga.ga_data);
568 redir_ga.ga_data = NULL;
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000569
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000570 vim_free(redir_lval);
571 redir_lval = NULL;
572 }
573 vim_free(redir_varname);
574 redir_varname = NULL;
575}
576
Bram Moolenaar071d4272004-06-13 20:20:40 +0000577# if defined(FEAT_MBYTE) || defined(PROTO)
578 int
Bram Moolenaarb7604cc2016-01-15 21:23:22 +0100579eval_charconvert(
580 char_u *enc_from,
581 char_u *enc_to,
582 char_u *fname_from,
583 char_u *fname_to)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000584{
585 int err = FALSE;
586
587 set_vim_var_string(VV_CC_FROM, enc_from, -1);
588 set_vim_var_string(VV_CC_TO, enc_to, -1);
589 set_vim_var_string(VV_FNAME_IN, fname_from, -1);
590 set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
591 if (eval_to_bool(p_ccv, &err, NULL, FALSE))
592 err = TRUE;
593 set_vim_var_string(VV_CC_FROM, NULL, -1);
594 set_vim_var_string(VV_CC_TO, NULL, -1);
595 set_vim_var_string(VV_FNAME_IN, NULL, -1);
596 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
597
598 if (err)
599 return FAIL;
600 return OK;
601}
602# endif
603
604# if defined(FEAT_POSTSCRIPT) || defined(PROTO)
605 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100606eval_printexpr(char_u *fname, char_u *args)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000607{
608 int err = FALSE;
609
610 set_vim_var_string(VV_FNAME_IN, fname, -1);
611 set_vim_var_string(VV_CMDARG, args, -1);
612 if (eval_to_bool(p_pexpr, &err, NULL, FALSE))
613 err = TRUE;
614 set_vim_var_string(VV_FNAME_IN, NULL, -1);
615 set_vim_var_string(VV_CMDARG, NULL, -1);
616
617 if (err)
618 {
619 mch_remove(fname);
620 return FAIL;
621 }
622 return OK;
623}
624# endif
625
626# if defined(FEAT_DIFF) || defined(PROTO)
627 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100628eval_diff(
629 char_u *origfile,
630 char_u *newfile,
631 char_u *outfile)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000632{
633 int err = FALSE;
634
635 set_vim_var_string(VV_FNAME_IN, origfile, -1);
636 set_vim_var_string(VV_FNAME_NEW, newfile, -1);
637 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
638 (void)eval_to_bool(p_dex, &err, NULL, FALSE);
639 set_vim_var_string(VV_FNAME_IN, NULL, -1);
640 set_vim_var_string(VV_FNAME_NEW, NULL, -1);
641 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
642}
643
644 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100645eval_patch(
646 char_u *origfile,
647 char_u *difffile,
648 char_u *outfile)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000649{
650 int err;
651
652 set_vim_var_string(VV_FNAME_IN, origfile, -1);
653 set_vim_var_string(VV_FNAME_DIFF, difffile, -1);
654 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
655 (void)eval_to_bool(p_pex, &err, NULL, FALSE);
656 set_vim_var_string(VV_FNAME_IN, NULL, -1);
657 set_vim_var_string(VV_FNAME_DIFF, NULL, -1);
658 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
659}
660# endif
661
662/*
663 * Top level evaluation function, returning a boolean.
664 * Sets "error" to TRUE if there was an error.
665 * Return TRUE or FALSE.
666 */
667 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100668eval_to_bool(
669 char_u *arg,
670 int *error,
671 char_u **nextcmd,
672 int skip) /* only parse, don't execute */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000673{
Bram Moolenaar33570922005-01-25 22:26:29 +0000674 typval_T tv;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +0200675 varnumber_T retval = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000676
677 if (skip)
678 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000679 if (eval0(arg, &tv, nextcmd, !skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000680 *error = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000681 else
682 {
683 *error = FALSE;
684 if (!skip)
685 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +0000686 retval = (get_tv_number_chk(&tv, error) != 0);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000687 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000688 }
689 }
690 if (skip)
691 --emsg_skip;
692
Bram Moolenaar22fcfad2016-07-01 18:17:26 +0200693 return (int)retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000694}
695
696/*
697 * Top level evaluation function, returning a string. If "skip" is TRUE,
698 * only parsing to "nextcmd" is done, without reporting errors. Return
699 * pointer to allocated memory, or NULL for failure or when "skip" is TRUE.
700 */
701 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100702eval_to_string_skip(
703 char_u *arg,
704 char_u **nextcmd,
705 int skip) /* only parse, don't execute */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000706{
Bram Moolenaar33570922005-01-25 22:26:29 +0000707 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000708 char_u *retval;
709
710 if (skip)
711 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000712 if (eval0(arg, &tv, nextcmd, !skip) == FAIL || skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000713 retval = NULL;
714 else
715 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000716 retval = vim_strsave(get_tv_string(&tv));
717 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000718 }
719 if (skip)
720 --emsg_skip;
721
722 return retval;
723}
724
725/*
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000726 * Skip over an expression at "*pp".
727 * Return FAIL for an error, OK otherwise.
728 */
729 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100730skip_expr(char_u **pp)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000731{
Bram Moolenaar33570922005-01-25 22:26:29 +0000732 typval_T rettv;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000733
734 *pp = skipwhite(*pp);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000735 return eval1(pp, &rettv, FALSE);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000736}
737
738/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000739 * Top level evaluation function, returning a string.
Bram Moolenaara85fb752008-09-07 11:55:43 +0000740 * When "convert" is TRUE convert a List into a sequence of lines and convert
741 * a Float to a String.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000742 * Return pointer to allocated memory, or NULL for failure.
743 */
744 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100745eval_to_string(
746 char_u *arg,
747 char_u **nextcmd,
748 int convert)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000749{
Bram Moolenaar33570922005-01-25 22:26:29 +0000750 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000751 char_u *retval;
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000752 garray_T ga;
Bram Moolenaar798b30b2009-04-22 10:56:16 +0000753#ifdef FEAT_FLOAT
Bram Moolenaara85fb752008-09-07 11:55:43 +0000754 char_u numbuf[NUMBUFLEN];
Bram Moolenaar798b30b2009-04-22 10:56:16 +0000755#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000756
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000757 if (eval0(arg, &tv, nextcmd, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000758 retval = NULL;
759 else
760 {
Bram Moolenaara85fb752008-09-07 11:55:43 +0000761 if (convert && tv.v_type == VAR_LIST)
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000762 {
763 ga_init2(&ga, (int)sizeof(char), 80);
Bram Moolenaar9bf749b2008-07-27 13:57:29 +0000764 if (tv.vval.v_list != NULL)
Bram Moolenaar213b10a2011-08-10 12:38:08 +0200765 {
Bram Moolenaar18dfb442016-05-31 22:31:23 +0200766 list_join(&ga, tv.vval.v_list, (char_u *)"\n", TRUE, FALSE, 0);
Bram Moolenaar213b10a2011-08-10 12:38:08 +0200767 if (tv.vval.v_list->lv_len > 0)
768 ga_append(&ga, NL);
769 }
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000770 ga_append(&ga, NUL);
771 retval = (char_u *)ga.ga_data;
772 }
Bram Moolenaara85fb752008-09-07 11:55:43 +0000773#ifdef FEAT_FLOAT
774 else if (convert && tv.v_type == VAR_FLOAT)
775 {
776 vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv.vval.v_float);
777 retval = vim_strsave(numbuf);
778 }
779#endif
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000780 else
781 retval = vim_strsave(get_tv_string(&tv));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000782 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000783 }
784
785 return retval;
786}
787
788/*
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000789 * Call eval_to_string() without using current local variables and using
790 * textlock. When "use_sandbox" is TRUE use the sandbox.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000791 */
792 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100793eval_to_string_safe(
794 char_u *arg,
795 char_u **nextcmd,
796 int use_sandbox)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000797{
798 char_u *retval;
799 void *save_funccalp;
800
801 save_funccalp = save_funccal();
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000802 if (use_sandbox)
803 ++sandbox;
804 ++textlock;
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000805 retval = eval_to_string(arg, nextcmd, FALSE);
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000806 if (use_sandbox)
807 --sandbox;
808 --textlock;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000809 restore_funccal(save_funccalp);
810 return retval;
811}
812
Bram Moolenaar071d4272004-06-13 20:20:40 +0000813/*
814 * Top level evaluation function, returning a number.
815 * Evaluates "expr" silently.
816 * Returns -1 for an error.
817 */
Bram Moolenaar22fcfad2016-07-01 18:17:26 +0200818 varnumber_T
Bram Moolenaar7454a062016-01-30 15:14:10 +0100819eval_to_number(char_u *expr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000820{
Bram Moolenaar33570922005-01-25 22:26:29 +0000821 typval_T rettv;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +0200822 varnumber_T retval;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +0000823 char_u *p = skipwhite(expr);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000824
825 ++emsg_off;
826
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000827 if (eval1(&p, &rettv, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000828 retval = -1;
829 else
830 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +0000831 retval = get_tv_number_chk(&rettv, NULL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000832 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000833 }
834 --emsg_off;
835
836 return retval;
837}
838
Bram Moolenaara40058a2005-07-11 22:42:07 +0000839/*
840 * Prepare v: variable "idx" to be used.
841 * Save the current typeval in "save_tv".
842 * When not used yet add the variable to the v: hashtable.
843 */
844 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100845prepare_vimvar(int idx, typval_T *save_tv)
Bram Moolenaara40058a2005-07-11 22:42:07 +0000846{
847 *save_tv = vimvars[idx].vv_tv;
848 if (vimvars[idx].vv_type == VAR_UNKNOWN)
849 hash_add(&vimvarht, vimvars[idx].vv_di.di_key);
850}
851
852/*
853 * Restore v: variable "idx" to typeval "save_tv".
854 * When no longer defined, remove the variable from the v: hashtable.
855 */
856 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100857restore_vimvar(int idx, typval_T *save_tv)
Bram Moolenaara40058a2005-07-11 22:42:07 +0000858{
859 hashitem_T *hi;
860
Bram Moolenaara40058a2005-07-11 22:42:07 +0000861 vimvars[idx].vv_tv = *save_tv;
862 if (vimvars[idx].vv_type == VAR_UNKNOWN)
863 {
864 hi = hash_find(&vimvarht, vimvars[idx].vv_di.di_key);
865 if (HASHITEM_EMPTY(hi))
Bram Moolenaar95f09602016-11-10 20:01:45 +0100866 internal_error("restore_vimvar()");
Bram Moolenaara40058a2005-07-11 22:42:07 +0000867 else
868 hash_remove(&vimvarht, hi);
869 }
870}
871
Bram Moolenaar3c56a962006-03-12 22:19:04 +0000872#if defined(FEAT_SPELL) || defined(PROTO)
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +0000873/*
874 * Evaluate an expression to a list with suggestions.
875 * For the "expr:" part of 'spellsuggest'.
Bram Moolenaar9bf749b2008-07-27 13:57:29 +0000876 * Returns NULL when there is an error.
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +0000877 */
878 list_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100879eval_spell_expr(char_u *badword, char_u *expr)
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +0000880{
881 typval_T save_val;
882 typval_T rettv;
883 list_T *list = NULL;
884 char_u *p = skipwhite(expr);
885
886 /* Set "v:val" to the bad word. */
887 prepare_vimvar(VV_VAL, &save_val);
888 vimvars[VV_VAL].vv_type = VAR_STRING;
889 vimvars[VV_VAL].vv_str = badword;
890 if (p_verbose == 0)
891 ++emsg_off;
892
893 if (eval1(&p, &rettv, TRUE) == OK)
894 {
895 if (rettv.v_type != VAR_LIST)
896 clear_tv(&rettv);
897 else
898 list = rettv.vval.v_list;
899 }
900
901 if (p_verbose == 0)
902 --emsg_off;
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +0000903 restore_vimvar(VV_VAL, &save_val);
904
905 return list;
906}
907
908/*
909 * "list" is supposed to contain two items: a word and a number. Return the
910 * word in "pp" and the number as the return value.
911 * Return -1 if anything isn't right.
912 * Used to get the good word and score from the eval_spell_expr() result.
913 */
914 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100915get_spellword(list_T *list, char_u **pp)
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +0000916{
917 listitem_T *li;
918
919 li = list->lv_first;
920 if (li == NULL)
921 return -1;
922 *pp = get_tv_string(&li->li_tv);
923
924 li = li->li_next;
925 if (li == NULL)
926 return -1;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +0200927 return (int)get_tv_number(&li->li_tv);
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +0000928}
929#endif
930
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000931/*
Bram Moolenaar4770d092006-01-12 23:22:24 +0000932 * Top level evaluation function.
933 * Returns an allocated typval_T with the result.
934 * Returns NULL when there is an error.
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000935 */
936 typval_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100937eval_expr(char_u *arg, char_u **nextcmd)
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000938{
939 typval_T *tv;
940
941 tv = (typval_T *)alloc(sizeof(typval_T));
Bram Moolenaar4770d092006-01-12 23:22:24 +0000942 if (tv != NULL && eval0(arg, tv, nextcmd, TRUE) == FAIL)
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000943 {
944 vim_free(tv);
Bram Moolenaar4770d092006-01-12 23:22:24 +0000945 tv = NULL;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000946 }
947
948 return tv;
949}
950
951
Bram Moolenaar071d4272004-06-13 20:20:40 +0000952/*
Bram Moolenaard8e9bb22005-07-09 21:14:46 +0000953 * Call some vimL function and return the result in "*rettv".
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000954 * Uses argv[argc] for the function arguments. Only Number and String
955 * arguments are currently supported.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +0000956 * Returns OK or FAIL.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000957 */
Bram Moolenaar82139082011-09-14 16:52:09 +0200958 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100959call_vim_function(
960 char_u *func,
961 int argc,
962 char_u **argv,
963 int safe, /* use the sandbox */
964 int str_arg_only, /* all arguments are strings */
965 typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000966{
Bram Moolenaar33570922005-01-25 22:26:29 +0000967 typval_T *argvars;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +0200968 varnumber_T n;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000969 int len;
970 int i;
971 int doesrange;
972 void *save_funccalp = NULL;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +0000973 int ret;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000974
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000975 argvars = (typval_T *)alloc((unsigned)((argc + 1) * sizeof(typval_T)));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000976 if (argvars == NULL)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +0000977 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000978
979 for (i = 0; i < argc; i++)
980 {
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +0000981 /* Pass a NULL or empty argument as an empty string */
982 if (argv[i] == NULL || *argv[i] == NUL)
983 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000984 argvars[i].v_type = VAR_STRING;
985 argvars[i].vval.v_string = (char_u *)"";
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +0000986 continue;
987 }
988
Bram Moolenaar0cbba942012-07-25 16:47:03 +0200989 if (str_arg_only)
990 len = 0;
991 else
992 /* Recognize a number argument, the others must be strings. */
Bram Moolenaar887c1fe2016-01-02 17:56:35 +0100993 vim_str2nr(argv[i], NULL, &len, STR2NR_ALL, &n, NULL, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000994 if (len != 0 && len == (int)STRLEN(argv[i]))
995 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000996 argvars[i].v_type = VAR_NUMBER;
997 argvars[i].vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000998 }
999 else
1000 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001001 argvars[i].v_type = VAR_STRING;
1002 argvars[i].vval.v_string = argv[i];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001003 }
1004 }
1005
1006 if (safe)
1007 {
1008 save_funccalp = save_funccal();
1009 ++sandbox;
1010 }
1011
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001012 rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */
Bram Moolenaardf48fb42016-07-22 21:50:18 +02001013 ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars, NULL,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001014 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
Bram Moolenaar1735bc92016-03-14 23:05:14 +01001015 &doesrange, TRUE, NULL, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001016 if (safe)
1017 {
1018 --sandbox;
1019 restore_funccal(save_funccalp);
1020 }
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001021 vim_free(argvars);
1022
1023 if (ret == FAIL)
1024 clear_tv(rettv);
1025
1026 return ret;
1027}
1028
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001029/*
1030 * Call vimL function "func" and return the result as a number.
1031 * Returns -1 when calling the function fails.
1032 * Uses argv[argc] for the function arguments.
1033 */
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001034 varnumber_T
Bram Moolenaar7454a062016-01-30 15:14:10 +01001035call_func_retnr(
1036 char_u *func,
1037 int argc,
1038 char_u **argv,
1039 int safe) /* use the sandbox */
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001040{
1041 typval_T rettv;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001042 varnumber_T retval;
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001043
1044 /* All arguments are passed as strings, no conversion to number. */
1045 if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL)
1046 return -1;
1047
1048 retval = get_tv_number_chk(&rettv, NULL);
1049 clear_tv(&rettv);
1050 return retval;
1051}
1052
1053#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) \
1054 || defined(FEAT_COMPL_FUNC) || defined(PROTO)
1055
Bram Moolenaar4f688582007-07-24 12:34:30 +00001056# if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001057/*
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001058 * Call vimL function "func" and return the result as a string.
1059 * Returns NULL when calling the function fails.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001060 * Uses argv[argc] for the function arguments.
1061 */
1062 void *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001063call_func_retstr(
1064 char_u *func,
1065 int argc,
1066 char_u **argv,
1067 int safe) /* use the sandbox */
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001068{
1069 typval_T rettv;
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001070 char_u *retval;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001071
Bram Moolenaar0cbba942012-07-25 16:47:03 +02001072 /* All arguments are passed as strings, no conversion to number. */
1073 if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001074 return NULL;
1075
1076 retval = vim_strsave(get_tv_string(&rettv));
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001077 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001078 return retval;
1079}
Bram Moolenaar4f688582007-07-24 12:34:30 +00001080# endif
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001081
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001082/*
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00001083 * Call vimL function "func" and return the result as a List.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001084 * Uses argv[argc] for the function arguments.
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00001085 * Returns NULL when there is something wrong.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001086 */
1087 void *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001088call_func_retlist(
1089 char_u *func,
1090 int argc,
1091 char_u **argv,
1092 int safe) /* use the sandbox */
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001093{
1094 typval_T rettv;
1095
Bram Moolenaar0cbba942012-07-25 16:47:03 +02001096 /* All arguments are passed as strings, no conversion to number. */
1097 if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001098 return NULL;
1099
1100 if (rettv.v_type != VAR_LIST)
1101 {
1102 clear_tv(&rettv);
1103 return NULL;
1104 }
1105
1106 return rettv.vval.v_list;
1107}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001108#endif
1109
Bram Moolenaar05159a02005-02-26 23:04:13 +00001110
Bram Moolenaar071d4272004-06-13 20:20:40 +00001111#ifdef FEAT_FOLDING
1112/*
1113 * Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding
1114 * it in "*cp". Doesn't give error messages.
1115 */
1116 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001117eval_foldexpr(char_u *arg, int *cp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001118{
Bram Moolenaar33570922005-01-25 22:26:29 +00001119 typval_T tv;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001120 varnumber_T retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001121 char_u *s;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00001122 int use_sandbox = was_set_insecurely((char_u *)"foldexpr",
1123 OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001124
1125 ++emsg_off;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001126 if (use_sandbox)
1127 ++sandbox;
1128 ++textlock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001129 *cp = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001130 if (eval0(arg, &tv, NULL, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001131 retval = 0;
1132 else
1133 {
1134 /* If the result is a number, just return the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001135 if (tv.v_type == VAR_NUMBER)
1136 retval = tv.vval.v_number;
Bram Moolenaar758711c2005-02-02 23:11:38 +00001137 else if (tv.v_type != VAR_STRING || tv.vval.v_string == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001138 retval = 0;
1139 else
1140 {
1141 /* If the result is a string, check if there is a non-digit before
1142 * the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001143 s = tv.vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001144 if (!VIM_ISDIGIT(*s) && *s != '-')
1145 *cp = *s++;
1146 retval = atol((char *)s);
1147 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001148 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001149 }
1150 --emsg_off;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001151 if (use_sandbox)
1152 --sandbox;
1153 --textlock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001154
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001155 return (int)retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001156}
1157#endif
1158
Bram Moolenaar071d4272004-06-13 20:20:40 +00001159/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001160 * ":let" list all variable values
1161 * ":let var1 var2" list variable values
1162 * ":let var = expr" assignment command.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001163 * ":let var += expr" assignment command.
1164 * ":let var -= expr" assignment command.
1165 * ":let var .= expr" assignment command.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001166 * ":let [var1, var2] = expr" unpack list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001167 */
1168 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001169ex_let(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001170{
1171 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001172 char_u *expr = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00001173 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001174 int i;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001175 int var_count = 0;
1176 int semicolon = 0;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001177 char_u op[2];
Bram Moolenaardb552d602006-03-23 22:59:57 +00001178 char_u *argend;
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001179 int first = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001180
Bram Moolenaardb552d602006-03-23 22:59:57 +00001181 argend = skip_var_list(arg, &var_count, &semicolon);
1182 if (argend == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001183 return;
Bram Moolenaar76b92b22006-03-24 22:46:53 +00001184 if (argend > arg && argend[-1] == '.') /* for var.='str' */
1185 --argend;
Bram Moolenaara3920382014-03-30 16:49:09 +02001186 expr = skipwhite(argend);
1187 if (*expr != '=' && !(vim_strchr((char_u *)"+-.", *expr) != NULL
1188 && expr[1] == '='))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001189 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001190 /*
1191 * ":let" without "=": list variables
1192 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001193 if (*arg == '[')
1194 EMSG(_(e_invarg));
1195 else if (!ends_excmd(*arg))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001196 /* ":let var1 var2" */
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001197 arg = list_arg_vars(eap, arg, &first);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001198 else if (!eap->skip)
Bram Moolenaara7043832005-01-21 11:56:39 +00001199 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001200 /* ":let" */
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001201 list_glob_vars(&first);
1202 list_buf_vars(&first);
1203 list_win_vars(&first);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001204#ifdef FEAT_WINDOWS
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001205 list_tab_vars(&first);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001206#endif
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001207 list_script_vars(&first);
1208 list_func_vars(&first);
1209 list_vim_vars(&first);
Bram Moolenaara7043832005-01-21 11:56:39 +00001210 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001211 eap->nextcmd = check_nextcmd(arg);
1212 }
1213 else
1214 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001215 op[0] = '=';
1216 op[1] = NUL;
Bram Moolenaara3920382014-03-30 16:49:09 +02001217 if (*expr != '=')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001218 {
Bram Moolenaara3920382014-03-30 16:49:09 +02001219 if (vim_strchr((char_u *)"+-.", *expr) != NULL)
1220 op[0] = *expr; /* +=, -= or .= */
1221 expr = skipwhite(expr + 2);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001222 }
Bram Moolenaara3920382014-03-30 16:49:09 +02001223 else
1224 expr = skipwhite(expr + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001225
Bram Moolenaar071d4272004-06-13 20:20:40 +00001226 if (eap->skip)
1227 ++emsg_skip;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001228 i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001229 if (eap->skip)
1230 {
1231 if (i != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001232 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001233 --emsg_skip;
1234 }
1235 else if (i != FAIL)
1236 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001237 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001238 op);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001239 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001240 }
1241 }
1242}
1243
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001244/*
1245 * Assign the typevalue "tv" to the variable or variables at "arg_start".
1246 * Handles both "var" with any type and "[var, var; var]" with a list type.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001247 * When "nextchars" is not NULL it points to a string with characters that
1248 * must appear after the variable(s). Use "+", "-" or "." for add, subtract
1249 * or concatenate.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001250 * Returns OK or FAIL;
1251 */
1252 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001253ex_let_vars(
1254 char_u *arg_start,
1255 typval_T *tv,
1256 int copy, /* copy values from "tv", don't move */
1257 int semicolon, /* from skip_var_list() */
1258 int var_count, /* from skip_var_list() */
1259 char_u *nextchars)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001260{
1261 char_u *arg = arg_start;
Bram Moolenaar33570922005-01-25 22:26:29 +00001262 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001263 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00001264 listitem_T *item;
1265 typval_T ltv;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001266
1267 if (*arg != '[')
1268 {
1269 /*
1270 * ":let var = expr" or ":for var in list"
1271 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001272 if (ex_let_one(arg, tv, copy, nextchars, nextchars) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001273 return FAIL;
1274 return OK;
1275 }
1276
1277 /*
1278 * ":let [v1, v2] = list" or ":for [v1, v2] in listlist"
1279 */
Bram Moolenaar758711c2005-02-02 23:11:38 +00001280 if (tv->v_type != VAR_LIST || (l = tv->vval.v_list) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001281 {
1282 EMSG(_(e_listreq));
1283 return FAIL;
1284 }
1285
1286 i = list_len(l);
1287 if (semicolon == 0 && var_count < i)
1288 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00001289 EMSG(_("E687: Less targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001290 return FAIL;
1291 }
1292 if (var_count - semicolon > i)
1293 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00001294 EMSG(_("E688: More targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001295 return FAIL;
1296 }
1297
1298 item = l->lv_first;
1299 while (*arg != ']')
1300 {
1301 arg = skipwhite(arg + 1);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001302 arg = ex_let_one(arg, &item->li_tv, TRUE, (char_u *)",;]", nextchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001303 item = item->li_next;
1304 if (arg == NULL)
1305 return FAIL;
1306
1307 arg = skipwhite(arg);
1308 if (*arg == ';')
1309 {
1310 /* Put the rest of the list (may be empty) in the var after ';'.
1311 * Create a new list for this. */
1312 l = list_alloc();
1313 if (l == NULL)
1314 return FAIL;
1315 while (item != NULL)
1316 {
1317 list_append_tv(l, &item->li_tv);
1318 item = item->li_next;
1319 }
1320
1321 ltv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001322 ltv.v_lock = 0;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001323 ltv.vval.v_list = l;
1324 l->lv_refcount = 1;
1325
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001326 arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE,
1327 (char_u *)"]", nextchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001328 clear_tv(&ltv);
1329 if (arg == NULL)
1330 return FAIL;
1331 break;
1332 }
1333 else if (*arg != ',' && *arg != ']')
1334 {
Bram Moolenaar95f09602016-11-10 20:01:45 +01001335 internal_error("ex_let_vars()");
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001336 return FAIL;
1337 }
1338 }
1339
1340 return OK;
1341}
1342
1343/*
1344 * Skip over assignable variable "var" or list of variables "[var, var]".
1345 * Used for ":let varvar = expr" and ":for varvar in expr".
1346 * For "[var, var]" increment "*var_count" for each variable.
1347 * for "[var, var; var]" set "semicolon".
1348 * Return NULL for an error.
1349 */
1350 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001351skip_var_list(
1352 char_u *arg,
1353 int *var_count,
1354 int *semicolon)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001355{
1356 char_u *p, *s;
1357
1358 if (*arg == '[')
1359 {
1360 /* "[var, var]": find the matching ']'. */
1361 p = arg;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001362 for (;;)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001363 {
1364 p = skipwhite(p + 1); /* skip whites after '[', ';' or ',' */
1365 s = skip_var_one(p);
1366 if (s == p)
1367 {
1368 EMSG2(_(e_invarg2), p);
1369 return NULL;
1370 }
1371 ++*var_count;
1372
1373 p = skipwhite(s);
1374 if (*p == ']')
1375 break;
1376 else if (*p == ';')
1377 {
1378 if (*semicolon == 1)
1379 {
1380 EMSG(_("Double ; in list of variables"));
1381 return NULL;
1382 }
1383 *semicolon = 1;
1384 }
1385 else if (*p != ',')
1386 {
1387 EMSG2(_(e_invarg2), p);
1388 return NULL;
1389 }
1390 }
1391 return p + 1;
1392 }
1393 else
1394 return skip_var_one(arg);
1395}
1396
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001397/*
Bram Moolenaarbae0c162007-05-10 19:30:25 +00001398 * Skip one (assignable) variable name, including @r, $VAR, &option, d.key,
Bram Moolenaar92124a32005-06-17 22:03:40 +00001399 * l[idx].
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001400 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001401 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001402skip_var_one(char_u *arg)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001403{
Bram Moolenaar92124a32005-06-17 22:03:40 +00001404 if (*arg == '@' && arg[1] != NUL)
1405 return arg + 2;
1406 return find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg,
1407 NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001408}
1409
Bram Moolenaara7043832005-01-21 11:56:39 +00001410/*
Bram Moolenaar33570922005-01-25 22:26:29 +00001411 * List variables for hashtab "ht" with prefix "prefix".
1412 * If "empty" is TRUE also list NULL strings as empty strings.
Bram Moolenaara7043832005-01-21 11:56:39 +00001413 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02001414 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001415list_hashtable_vars(
1416 hashtab_T *ht,
1417 char_u *prefix,
1418 int empty,
1419 int *first)
Bram Moolenaara7043832005-01-21 11:56:39 +00001420{
Bram Moolenaar33570922005-01-25 22:26:29 +00001421 hashitem_T *hi;
1422 dictitem_T *di;
Bram Moolenaara7043832005-01-21 11:56:39 +00001423 int todo;
1424
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001425 todo = (int)ht->ht_used;
Bram Moolenaara7043832005-01-21 11:56:39 +00001426 for (hi = ht->ht_array; todo > 0 && !got_int; ++hi)
1427 {
1428 if (!HASHITEM_EMPTY(hi))
1429 {
1430 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00001431 di = HI2DI(hi);
1432 if (empty || di->di_tv.v_type != VAR_STRING
1433 || di->di_tv.vval.v_string != NULL)
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001434 list_one_var(di, prefix, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00001435 }
1436 }
1437}
1438
1439/*
1440 * List global variables.
1441 */
1442 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001443list_glob_vars(int *first)
Bram Moolenaara7043832005-01-21 11:56:39 +00001444{
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001445 list_hashtable_vars(&globvarht, (char_u *)"", TRUE, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00001446}
1447
1448/*
1449 * List buffer variables.
1450 */
1451 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001452list_buf_vars(int *first)
Bram Moolenaara7043832005-01-21 11:56:39 +00001453{
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001454 char_u numbuf[NUMBUFLEN];
1455
Bram Moolenaar429fa852013-04-15 12:27:36 +02001456 list_hashtable_vars(&curbuf->b_vars->dv_hashtab, (char_u *)"b:",
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001457 TRUE, first);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001458
1459 sprintf((char *)numbuf, "%ld", (long)curbuf->b_changedtick);
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001460 list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER,
1461 numbuf, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00001462}
1463
1464/*
1465 * List window variables.
1466 */
1467 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001468list_win_vars(int *first)
Bram Moolenaara7043832005-01-21 11:56:39 +00001469{
Bram Moolenaar429fa852013-04-15 12:27:36 +02001470 list_hashtable_vars(&curwin->w_vars->dv_hashtab,
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001471 (char_u *)"w:", TRUE, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00001472}
1473
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001474#ifdef FEAT_WINDOWS
1475/*
1476 * List tab page variables.
1477 */
1478 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001479list_tab_vars(int *first)
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001480{
Bram Moolenaar429fa852013-04-15 12:27:36 +02001481 list_hashtable_vars(&curtab->tp_vars->dv_hashtab,
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001482 (char_u *)"t:", TRUE, first);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001483}
1484#endif
1485
Bram Moolenaara7043832005-01-21 11:56:39 +00001486/*
1487 * List Vim variables.
1488 */
1489 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001490list_vim_vars(int *first)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001491{
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001492 list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE, first);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001493}
1494
1495/*
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00001496 * List script-local variables, if there is a script.
1497 */
1498 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001499list_script_vars(int *first)
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00001500{
1501 if (current_SID > 0 && current_SID <= ga_scripts.ga_len)
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001502 list_hashtable_vars(&SCRIPT_VARS(current_SID),
1503 (char_u *)"s:", FALSE, first);
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00001504}
1505
1506/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001507 * List variables in "arg".
1508 */
1509 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001510list_arg_vars(exarg_T *eap, char_u *arg, int *first)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001511{
1512 int error = FALSE;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001513 int len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001514 char_u *name;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001515 char_u *name_start;
1516 char_u *arg_subsc;
1517 char_u *tofree;
1518 typval_T tv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001519
1520 while (!ends_excmd(*arg) && !got_int)
1521 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001522 if (error || eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001523 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001524 arg = find_name_end(arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001525 if (!vim_iswhite(*arg) && !ends_excmd(*arg))
1526 {
1527 emsg_severe = TRUE;
1528 EMSG(_(e_trailing));
1529 break;
1530 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001531 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001532 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001533 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001534 /* get_name_len() takes care of expanding curly braces */
1535 name_start = name = arg;
1536 len = get_name_len(&arg, &tofree, TRUE, TRUE);
1537 if (len <= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001538 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001539 /* This is mainly to keep test 49 working: when expanding
1540 * curly braces fails overrule the exception error message. */
1541 if (len < 0 && !aborting())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001542 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001543 emsg_severe = TRUE;
1544 EMSG2(_(e_invarg2), arg);
1545 break;
1546 }
1547 error = TRUE;
1548 }
1549 else
1550 {
1551 if (tofree != NULL)
1552 name = tofree;
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02001553 if (get_var_tv(name, len, &tv, NULL, TRUE, FALSE) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001554 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001555 else
1556 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001557 /* handle d.key, l[idx], f(expr) */
1558 arg_subsc = arg;
1559 if (handle_subscript(&arg, &tv, TRUE, TRUE) == FAIL)
Bram Moolenaara7043832005-01-21 11:56:39 +00001560 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001561 else
Bram Moolenaara7043832005-01-21 11:56:39 +00001562 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001563 if (arg == arg_subsc && len == 2 && name[1] == ':')
Bram Moolenaara7043832005-01-21 11:56:39 +00001564 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001565 switch (*name)
Bram Moolenaara7043832005-01-21 11:56:39 +00001566 {
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001567 case 'g': list_glob_vars(first); break;
1568 case 'b': list_buf_vars(first); break;
1569 case 'w': list_win_vars(first); break;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001570#ifdef FEAT_WINDOWS
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001571 case 't': list_tab_vars(first); break;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001572#endif
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001573 case 'v': list_vim_vars(first); break;
1574 case 's': list_script_vars(first); break;
1575 case 'l': list_func_vars(first); break;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001576 default:
1577 EMSG2(_("E738: Can't list variables for %s"), name);
Bram Moolenaara7043832005-01-21 11:56:39 +00001578 }
Bram Moolenaara7043832005-01-21 11:56:39 +00001579 }
1580 else
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001581 {
1582 char_u numbuf[NUMBUFLEN];
1583 char_u *tf;
1584 int c;
1585 char_u *s;
1586
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001587 s = echo_string(&tv, &tf, numbuf, 0);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001588 c = *arg;
1589 *arg = NUL;
1590 list_one_var_a((char_u *)"",
1591 arg == arg_subsc ? name : name_start,
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001592 tv.v_type,
1593 s == NULL ? (char_u *)"" : s,
1594 first);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001595 *arg = c;
1596 vim_free(tf);
1597 }
1598 clear_tv(&tv);
Bram Moolenaara7043832005-01-21 11:56:39 +00001599 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001600 }
1601 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001602
1603 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001604 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001605
1606 arg = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001607 }
1608
1609 return arg;
1610}
1611
1612/*
1613 * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value.
1614 * Returns a pointer to the char just after the var name.
1615 * Returns NULL if there is an error.
1616 */
1617 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001618ex_let_one(
1619 char_u *arg, /* points to variable name */
1620 typval_T *tv, /* value to assign to variable */
1621 int copy, /* copy value from "tv" */
1622 char_u *endchars, /* valid chars after variable name or NULL */
1623 char_u *op) /* "+", "-", "." or NULL*/
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001624{
1625 int c1;
1626 char_u *name;
1627 char_u *p;
1628 char_u *arg_end = NULL;
1629 int len;
1630 int opt_flags;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001631 char_u *tofree = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001632
1633 /*
1634 * ":let $VAR = expr": Set environment variable.
1635 */
1636 if (*arg == '$')
1637 {
1638 /* Find the end of the name. */
1639 ++arg;
1640 name = arg;
1641 len = get_env_len(&arg);
1642 if (len == 0)
1643 EMSG2(_(e_invarg2), name - 1);
1644 else
1645 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001646 if (op != NULL && (*op == '+' || *op == '-'))
1647 EMSG2(_(e_letwrong), op);
1648 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001649 && vim_strchr(endchars, *skipwhite(arg)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001650 EMSG(_(e_letunexp));
Bram Moolenaard4ddfaf2010-12-02 14:48:14 +01001651 else if (!check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001652 {
1653 c1 = name[len];
1654 name[len] = NUL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001655 p = get_tv_string_chk(tv);
1656 if (p != NULL && op != NULL && *op == '.')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001657 {
1658 int mustfree = FALSE;
1659 char_u *s = vim_getenv(name, &mustfree);
1660
1661 if (s != NULL)
1662 {
1663 p = tofree = concat_str(s, p);
1664 if (mustfree)
1665 vim_free(s);
1666 }
1667 }
1668 if (p != NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001669 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001670 vim_setenv(name, p);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001671 if (STRICMP(name, "HOME") == 0)
1672 init_homedir();
1673 else if (didset_vim && STRICMP(name, "VIM") == 0)
1674 didset_vim = FALSE;
1675 else if (didset_vimruntime
1676 && STRICMP(name, "VIMRUNTIME") == 0)
1677 didset_vimruntime = FALSE;
1678 arg_end = arg;
1679 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001680 name[len] = c1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001681 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001682 }
1683 }
1684 }
1685
1686 /*
1687 * ":let &option = expr": Set option value.
1688 * ":let &l:option = expr": Set local option value.
1689 * ":let &g:option = expr": Set global option value.
1690 */
1691 else if (*arg == '&')
1692 {
1693 /* Find the end of the name. */
1694 p = find_option_end(&arg, &opt_flags);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001695 if (p == NULL || (endchars != NULL
1696 && vim_strchr(endchars, *skipwhite(p)) == NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001697 EMSG(_(e_letunexp));
1698 else
1699 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001700 long n;
1701 int opt_type;
1702 long numval;
1703 char_u *stringval = NULL;
1704 char_u *s;
1705
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001706 c1 = *p;
1707 *p = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001708
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001709 n = (long)get_tv_number(tv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001710 s = get_tv_string_chk(tv); /* != NULL if number or string */
1711 if (s != NULL && op != NULL && *op != '=')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001712 {
1713 opt_type = get_option_value(arg, &numval,
1714 &stringval, opt_flags);
1715 if ((opt_type == 1 && *op == '.')
1716 || (opt_type == 0 && *op != '.'))
1717 EMSG2(_(e_letwrong), op);
1718 else
1719 {
1720 if (opt_type == 1) /* number */
1721 {
1722 if (*op == '+')
1723 n = numval + n;
1724 else
1725 n = numval - n;
1726 }
1727 else if (opt_type == 0 && stringval != NULL) /* string */
1728 {
1729 s = concat_str(stringval, s);
1730 vim_free(stringval);
1731 stringval = s;
1732 }
1733 }
1734 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001735 if (s != NULL)
1736 {
1737 set_option_value(arg, n, s, opt_flags);
1738 arg_end = p;
1739 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001740 *p = c1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001741 vim_free(stringval);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001742 }
1743 }
1744
1745 /*
1746 * ":let @r = expr": Set register contents.
1747 */
1748 else if (*arg == '@')
1749 {
1750 ++arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001751 if (op != NULL && (*op == '+' || *op == '-'))
1752 EMSG2(_(e_letwrong), op);
1753 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001754 && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001755 EMSG(_(e_letunexp));
1756 else
1757 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00001758 char_u *ptofree = NULL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001759 char_u *s;
1760
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001761 p = get_tv_string_chk(tv);
1762 if (p != NULL && op != NULL && *op == '.')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001763 {
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +02001764 s = get_reg_contents(*arg == '@' ? '"' : *arg, GREG_EXPR_SRC);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001765 if (s != NULL)
1766 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00001767 p = ptofree = concat_str(s, p);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001768 vim_free(s);
1769 }
1770 }
1771 if (p != NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001772 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001773 write_reg_contents(*arg == '@' ? '"' : *arg, p, -1, FALSE);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001774 arg_end = arg + 1;
1775 }
Bram Moolenaar89d40322006-08-29 15:30:07 +00001776 vim_free(ptofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001777 }
1778 }
1779
1780 /*
1781 * ":let var = expr": Set internal variable.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001782 * ":let {expr} = expr": Idem, name made with curly braces
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001783 */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001784 else if (eval_isnamec1(*arg) || *arg == '{')
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001785 {
Bram Moolenaar33570922005-01-25 22:26:29 +00001786 lval_T lv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001787
Bram Moolenaar6d977d62014-01-14 15:24:39 +01001788 p = get_lval(arg, tv, &lv, FALSE, FALSE, 0, FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001789 if (p != NULL && lv.ll_name != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001790 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001791 if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL)
1792 EMSG(_(e_letunexp));
1793 else
1794 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001795 set_var_lval(&lv, p, tv, copy, op);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001796 arg_end = p;
1797 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001798 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001799 clear_lval(&lv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001800 }
1801
1802 else
1803 EMSG2(_(e_invarg2), arg);
1804
1805 return arg_end;
1806}
1807
1808/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00001809 * If "arg" is equal to "b:changedtick" give an error and return TRUE.
1810 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02001811 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001812check_changedtick(char_u *arg)
Bram Moolenaar8c711452005-01-14 21:53:12 +00001813{
1814 if (STRNCMP(arg, "b:changedtick", 13) == 0 && !eval_isnamec(arg[13]))
1815 {
1816 EMSG2(_(e_readonlyvar), arg);
1817 return TRUE;
1818 }
1819 return FALSE;
1820}
1821
1822/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001823 * Get an lval: variable, Dict item or List item that can be assigned a value
1824 * to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]",
1825 * "name.key", "name.key[expr]" etc.
1826 * Indexing only works if "name" is an existing List or Dictionary.
1827 * "name" points to the start of the name.
1828 * If "rettv" is not NULL it points to the value to be assigned.
1829 * "unlet" is TRUE for ":unlet": slightly different behavior when something is
1830 * wrong; must end in space or cmd separator.
1831 *
Bram Moolenaar6d977d62014-01-14 15:24:39 +01001832 * flags:
1833 * GLV_QUIET: do not give error messages
1834 * GLV_NO_AUTOLOAD: do not use script autoloading
1835 *
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001836 * Returns a pointer to just after the name, including indexes.
Bram Moolenaara7043832005-01-21 11:56:39 +00001837 * When an evaluation error occurs "lp->ll_name" is NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001838 * Returns NULL for a parsing error. Still need to free items in "lp"!
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001839 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02001840 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001841get_lval(
1842 char_u *name,
1843 typval_T *rettv,
1844 lval_T *lp,
1845 int unlet,
1846 int skip,
1847 int flags, /* GLV_ values */
1848 int fne_flags) /* flags for find_name_end() */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001849{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001850 char_u *p;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001851 char_u *expr_start, *expr_end;
1852 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00001853 dictitem_T *v;
1854 typval_T var1;
1855 typval_T var2;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001856 int empty1 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00001857 listitem_T *ni;
Bram Moolenaar8c711452005-01-14 21:53:12 +00001858 char_u *key = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00001859 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +00001860 hashtab_T *ht;
Bram Moolenaar6d977d62014-01-14 15:24:39 +01001861 int quiet = flags & GLV_QUIET;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001862
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001863 /* Clear everything in "lp". */
Bram Moolenaar33570922005-01-25 22:26:29 +00001864 vim_memset(lp, 0, sizeof(lval_T));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001865
1866 if (skip)
1867 {
1868 /* When skipping just find the end of the name. */
1869 lp->ll_name = name;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001870 return find_name_end(name, NULL, NULL, FNE_INCL_BR | fne_flags);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001871 }
1872
1873 /* Find the end of the name. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001874 p = find_name_end(name, &expr_start, &expr_end, fne_flags);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001875 if (expr_start != NULL)
1876 {
1877 /* Don't expand the name when we already know there is an error. */
1878 if (unlet && !vim_iswhite(*p) && !ends_excmd(*p)
1879 && *p != '[' && *p != '.')
1880 {
1881 EMSG(_(e_trailing));
1882 return NULL;
1883 }
1884
1885 lp->ll_exp_name = make_expanded_name(name, expr_start, expr_end, p);
1886 if (lp->ll_exp_name == NULL)
1887 {
1888 /* Report an invalid expression in braces, unless the
1889 * expression evaluation has been cancelled due to an
1890 * aborting error, an interrupt, or an exception. */
1891 if (!aborting() && !quiet)
1892 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00001893 emsg_severe = TRUE;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001894 EMSG2(_(e_invarg2), name);
1895 return NULL;
1896 }
1897 }
1898 lp->ll_name = lp->ll_exp_name;
1899 }
1900 else
1901 lp->ll_name = name;
1902
1903 /* Without [idx] or .key we are done. */
1904 if ((*p != '[' && *p != '.') || lp->ll_name == NULL)
1905 return p;
1906
1907 cc = *p;
1908 *p = NUL;
Bram Moolenaar6d977d62014-01-14 15:24:39 +01001909 v = find_var(lp->ll_name, &ht, flags & GLV_NO_AUTOLOAD);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001910 if (v == NULL && !quiet)
1911 EMSG2(_(e_undefvar), lp->ll_name);
1912 *p = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001913 if (v == NULL)
1914 return NULL;
1915
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001916 /*
1917 * Loop until no more [idx] or .key is following.
1918 */
Bram Moolenaar33570922005-01-25 22:26:29 +00001919 lp->ll_tv = &v->di_tv;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001920 while (*p == '[' || (*p == '.' && lp->ll_tv->v_type == VAR_DICT))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001921 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001922 if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL)
1923 && !(lp->ll_tv->v_type == VAR_DICT
1924 && lp->ll_tv->vval.v_dict != NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001925 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001926 if (!quiet)
1927 EMSG(_("E689: Can only index a List or Dictionary"));
1928 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001929 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001930 if (lp->ll_range)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001931 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001932 if (!quiet)
1933 EMSG(_("E708: [:] must come last"));
1934 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001935 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00001936
Bram Moolenaar8c711452005-01-14 21:53:12 +00001937 len = -1;
1938 if (*p == '.')
1939 {
1940 key = p + 1;
1941 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
1942 ;
1943 if (len == 0)
1944 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001945 if (!quiet)
1946 EMSG(_(e_emptykey));
1947 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00001948 }
1949 p = key + len;
1950 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00001951 else
1952 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00001953 /* Get the index [expr] or the first index [expr: ]. */
Bram Moolenaar6cc16192005-01-08 21:49:45 +00001954 p = skipwhite(p + 1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00001955 if (*p == ':')
1956 empty1 = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00001957 else
1958 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00001959 empty1 = FALSE;
1960 if (eval1(&p, &var1, TRUE) == FAIL) /* recursive! */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001961 return NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001962 if (get_tv_string_chk(&var1) == NULL)
1963 {
1964 /* not a number or string */
1965 clear_tv(&var1);
1966 return NULL;
1967 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00001968 }
1969
1970 /* Optionally get the second index [ :expr]. */
1971 if (*p == ':')
1972 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001973 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00001974 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001975 if (!quiet)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001976 EMSG(_(e_dictrange));
Bram Moolenaar6cc16192005-01-08 21:49:45 +00001977 if (!empty1)
1978 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001979 return NULL;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00001980 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001981 if (rettv != NULL && (rettv->v_type != VAR_LIST
1982 || rettv->vval.v_list == NULL))
Bram Moolenaar8c711452005-01-14 21:53:12 +00001983 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001984 if (!quiet)
1985 EMSG(_("E709: [:] requires a List value"));
Bram Moolenaar8c711452005-01-14 21:53:12 +00001986 if (!empty1)
1987 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001988 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00001989 }
1990 p = skipwhite(p + 1);
1991 if (*p == ']')
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001992 lp->ll_empty2 = TRUE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00001993 else
1994 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001995 lp->ll_empty2 = FALSE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00001996 if (eval1(&p, &var2, TRUE) == FAIL) /* recursive! */
1997 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00001998 if (!empty1)
1999 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002000 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002001 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002002 if (get_tv_string_chk(&var2) == NULL)
2003 {
2004 /* not a number or string */
2005 if (!empty1)
2006 clear_tv(&var1);
2007 clear_tv(&var2);
2008 return NULL;
2009 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002010 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002011 lp->ll_range = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002012 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002013 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002014 lp->ll_range = FALSE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002015
Bram Moolenaar8c711452005-01-14 21:53:12 +00002016 if (*p != ']')
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002017 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002018 if (!quiet)
2019 EMSG(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002020 if (!empty1)
2021 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002022 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002023 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002024 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002025 }
2026
2027 /* Skip to past ']'. */
2028 ++p;
2029 }
2030
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002031 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002032 {
2033 if (len == -1)
2034 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002035 /* "[key]": get key from "var1" */
Bram Moolenaar0921ecf2016-04-03 22:44:36 +02002036 key = get_tv_string_chk(&var1); /* is number or string */
2037 if (key == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002038 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002039 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002040 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002041 }
2042 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002043 lp->ll_list = NULL;
2044 lp->ll_dict = lp->ll_tv->vval.v_dict;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002045 lp->ll_di = dict_find(lp->ll_dict, key, len);
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002046
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002047 /* When assigning to a scope dictionary check that a function and
2048 * variable name is valid (only variable name unless it is l: or
2049 * g: dictionary). Disallow overwriting a builtin function. */
2050 if (rettv != NULL && lp->ll_dict->dv_scope != 0)
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002051 {
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002052 int prevval;
2053 int wrong;
2054
2055 if (len != -1)
2056 {
2057 prevval = key[len];
2058 key[len] = NUL;
2059 }
Bram Moolenaar4380d1e2013-06-09 20:51:00 +02002060 else
2061 prevval = 0; /* avoid compiler warning */
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002062 wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE
2063 && rettv->v_type == VAR_FUNC
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002064 && var_check_func_name(key, lp->ll_di == NULL))
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002065 || !valid_varname(key);
2066 if (len != -1)
2067 key[len] = prevval;
2068 if (wrong)
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002069 return NULL;
2070 }
2071
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002072 if (lp->ll_di == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002073 {
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002074 /* Can't add "v:" variable. */
2075 if (lp->ll_dict == &vimvardict)
2076 {
2077 EMSG2(_(e_illvar), name);
2078 return NULL;
2079 }
2080
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002081 /* Key does not exist in dict: may need to add it. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002082 if (*p == '[' || *p == '.' || unlet)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002083 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002084 if (!quiet)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002085 EMSG2(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002086 if (len == -1)
2087 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002088 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002089 }
2090 if (len == -1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002091 lp->ll_newkey = vim_strsave(key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002092 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002093 lp->ll_newkey = vim_strnsave(key, len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002094 if (len == -1)
2095 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002096 if (lp->ll_newkey == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002097 p = NULL;
2098 break;
2099 }
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002100 /* existing variable, need to check if it can be changed */
Bram Moolenaar77354e72015-04-21 16:49:05 +02002101 else if (var_check_ro(lp->ll_di->di_flags, name, FALSE))
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002102 return NULL;
2103
Bram Moolenaar8c711452005-01-14 21:53:12 +00002104 if (len == -1)
2105 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002106 lp->ll_tv = &lp->ll_di->di_tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002107 }
2108 else
2109 {
2110 /*
2111 * Get the number and item for the only or first index of the List.
2112 */
2113 if (empty1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002114 lp->ll_n1 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002115 else
2116 {
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02002117 lp->ll_n1 = (long)get_tv_number(&var1);
2118 /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002119 clear_tv(&var1);
2120 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002121 lp->ll_dict = NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002122 lp->ll_list = lp->ll_tv->vval.v_list;
2123 lp->ll_li = list_find(lp->ll_list, lp->ll_n1);
2124 if (lp->ll_li == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002125 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00002126 if (lp->ll_n1 < 0)
2127 {
2128 lp->ll_n1 = 0;
2129 lp->ll_li = list_find(lp->ll_list, lp->ll_n1);
2130 }
2131 }
2132 if (lp->ll_li == NULL)
2133 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002134 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002135 clear_tv(&var2);
Bram Moolenaare9623882011-04-21 14:27:28 +02002136 if (!quiet)
2137 EMSGN(_(e_listidx), lp->ll_n1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002138 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002139 }
2140
2141 /*
2142 * May need to find the item or absolute index for the second
2143 * index of a range.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002144 * When no index given: "lp->ll_empty2" is TRUE.
2145 * Otherwise "lp->ll_n2" is set to the second index.
Bram Moolenaar8c711452005-01-14 21:53:12 +00002146 */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002147 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002148 {
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02002149 lp->ll_n2 = (long)get_tv_number(&var2);
2150 /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002151 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002152 if (lp->ll_n2 < 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002153 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002154 ni = list_find(lp->ll_list, lp->ll_n2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002155 if (ni == NULL)
Bram Moolenaare9623882011-04-21 14:27:28 +02002156 {
2157 if (!quiet)
2158 EMSGN(_(e_listidx), lp->ll_n2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002159 return NULL;
Bram Moolenaare9623882011-04-21 14:27:28 +02002160 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002161 lp->ll_n2 = list_idx_of_item(lp->ll_list, ni);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002162 }
2163
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002164 /* Check that lp->ll_n2 isn't before lp->ll_n1. */
2165 if (lp->ll_n1 < 0)
2166 lp->ll_n1 = list_idx_of_item(lp->ll_list, lp->ll_li);
2167 if (lp->ll_n2 < lp->ll_n1)
Bram Moolenaare9623882011-04-21 14:27:28 +02002168 {
2169 if (!quiet)
2170 EMSGN(_(e_listidx), lp->ll_n2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002171 return NULL;
Bram Moolenaare9623882011-04-21 14:27:28 +02002172 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002173 }
2174
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002175 lp->ll_tv = &lp->ll_li->li_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002176 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002177 }
2178
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002179 return p;
2180}
2181
2182/*
Bram Moolenaar33570922005-01-25 22:26:29 +00002183 * Clear lval "lp" that was filled by get_lval().
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002184 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02002185 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002186clear_lval(lval_T *lp)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002187{
2188 vim_free(lp->ll_exp_name);
2189 vim_free(lp->ll_newkey);
2190}
2191
2192/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002193 * Set a variable that was parsed by get_lval() to "rettv".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002194 * "endp" points to just after the parsed name.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002195 * "op" is NULL, "+" for "+=", "-" for "-=", "." for ".=" or "=" for "=".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002196 */
2197 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002198set_var_lval(
2199 lval_T *lp,
2200 char_u *endp,
2201 typval_T *rettv,
2202 int copy,
2203 char_u *op)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002204{
2205 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00002206 listitem_T *ri;
2207 dictitem_T *di;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002208
2209 if (lp->ll_tv == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002210 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002211 if (!check_changedtick(lp->ll_name))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002212 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002213 cc = *endp;
2214 *endp = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002215 if (op != NULL && *op != '=')
2216 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002217 typval_T tv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002218
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002219 /* handle +=, -= and .= */
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02002220 di = NULL;
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00002221 if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02002222 &tv, &di, TRUE, FALSE) == OK)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002223 {
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02002224 if ((di == NULL
2225 || (!var_check_ro(di->di_flags, lp->ll_name, FALSE)
2226 && !tv_check_lock(di->di_tv.v_lock, lp->ll_name,
2227 FALSE)))
2228 && tv_op(&tv, rettv, op) == OK)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002229 set_var(lp->ll_name, &tv, FALSE);
2230 clear_tv(&tv);
2231 }
2232 }
2233 else
2234 set_var(lp->ll_name, rettv, copy);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002235 *endp = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002236 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002237 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002238 else if (tv_check_lock(lp->ll_newkey == NULL
2239 ? lp->ll_tv->v_lock
Bram Moolenaar77354e72015-04-21 16:49:05 +02002240 : lp->ll_tv->vval.v_dict->dv_lock, lp->ll_name, FALSE))
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002241 ;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002242 else if (lp->ll_range)
2243 {
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02002244 listitem_T *ll_li = lp->ll_li;
2245 int ll_n1 = lp->ll_n1;
2246
2247 /*
2248 * Check whether any of the list items is locked
2249 */
Bram Moolenaarb2a851f2014-12-07 00:18:33 +01002250 for (ri = rettv->vval.v_list->lv_first; ri != NULL && ll_li != NULL; )
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02002251 {
Bram Moolenaar77354e72015-04-21 16:49:05 +02002252 if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name, FALSE))
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02002253 return;
2254 ri = ri->li_next;
2255 if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == ll_n1))
2256 break;
2257 ll_li = ll_li->li_next;
2258 ++ll_n1;
2259 }
2260
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002261 /*
2262 * Assign the List values to the list items.
2263 */
2264 for (ri = rettv->vval.v_list->lv_first; ri != NULL; )
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002265 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002266 if (op != NULL && *op != '=')
2267 tv_op(&lp->ll_li->li_tv, &ri->li_tv, op);
2268 else
2269 {
2270 clear_tv(&lp->ll_li->li_tv);
2271 copy_tv(&ri->li_tv, &lp->ll_li->li_tv);
2272 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002273 ri = ri->li_next;
2274 if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == lp->ll_n1))
2275 break;
2276 if (lp->ll_li->li_next == NULL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002277 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002278 /* Need to add an empty item. */
Bram Moolenaar4463f292005-09-25 22:20:24 +00002279 if (list_append_number(lp->ll_list, 0) == FAIL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002280 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002281 ri = NULL;
2282 break;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002283 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002284 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002285 lp->ll_li = lp->ll_li->li_next;
2286 ++lp->ll_n1;
2287 }
2288 if (ri != NULL)
2289 EMSG(_("E710: List value has more items than target"));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002290 else if (lp->ll_empty2
2291 ? (lp->ll_li != NULL && lp->ll_li->li_next != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002292 : lp->ll_n1 != lp->ll_n2)
2293 EMSG(_("E711: List value has not enough items"));
2294 }
2295 else
2296 {
2297 /*
2298 * Assign to a List or Dictionary item.
2299 */
2300 if (lp->ll_newkey != NULL)
2301 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002302 if (op != NULL && *op != '=')
2303 {
2304 EMSG2(_(e_letwrong), op);
2305 return;
2306 }
2307
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002308 /* Need to add an item to the Dictionary. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002309 di = dictitem_alloc(lp->ll_newkey);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002310 if (di == NULL)
2311 return;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002312 if (dict_add(lp->ll_tv->vval.v_dict, di) == FAIL)
2313 {
2314 vim_free(di);
2315 return;
2316 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002317 lp->ll_tv = &di->di_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002318 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002319 else if (op != NULL && *op != '=')
2320 {
2321 tv_op(lp->ll_tv, rettv, op);
2322 return;
2323 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002324 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002325 clear_tv(lp->ll_tv);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002326
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002327 /*
2328 * Assign the value to the variable or list item.
2329 */
2330 if (copy)
2331 copy_tv(rettv, lp->ll_tv);
2332 else
2333 {
2334 *lp->ll_tv = *rettv;
Bram Moolenaar758711c2005-02-02 23:11:38 +00002335 lp->ll_tv->v_lock = 0;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002336 init_tv(rettv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002337 }
2338 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002339}
2340
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002341/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002342 * Handle "tv1 += tv2", "tv1 -= tv2" and "tv1 .= tv2"
2343 * Returns OK or FAIL.
2344 */
2345 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01002346tv_op(typval_T *tv1, typval_T *tv2, char_u *op)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002347{
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02002348 varnumber_T n;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002349 char_u numbuf[NUMBUFLEN];
2350 char_u *s;
2351
Bram Moolenaar520e1e42016-01-23 19:46:28 +01002352 /* Can't do anything with a Funcref, Dict, v:true on the right. */
2353 if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT
2354 && tv2->v_type != VAR_SPECIAL)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002355 {
2356 switch (tv1->v_type)
2357 {
Bram Moolenaar835dc632016-02-07 14:27:38 +01002358 case VAR_UNKNOWN:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002359 case VAR_DICT:
2360 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01002361 case VAR_PARTIAL:
Bram Moolenaar520e1e42016-01-23 19:46:28 +01002362 case VAR_SPECIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01002363 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01002364 case VAR_CHANNEL:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002365 break;
2366
2367 case VAR_LIST:
2368 if (*op != '+' || tv2->v_type != VAR_LIST)
2369 break;
2370 /* List += List */
2371 if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL)
2372 list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL);
2373 return OK;
2374
2375 case VAR_NUMBER:
2376 case VAR_STRING:
2377 if (tv2->v_type == VAR_LIST)
2378 break;
2379 if (*op == '+' || *op == '-')
2380 {
2381 /* nr += nr or nr -= nr*/
2382 n = get_tv_number(tv1);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002383#ifdef FEAT_FLOAT
2384 if (tv2->v_type == VAR_FLOAT)
2385 {
2386 float_T f = n;
2387
2388 if (*op == '+')
2389 f += tv2->vval.v_float;
2390 else
2391 f -= tv2->vval.v_float;
2392 clear_tv(tv1);
2393 tv1->v_type = VAR_FLOAT;
2394 tv1->vval.v_float = f;
2395 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002396 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002397#endif
2398 {
2399 if (*op == '+')
2400 n += get_tv_number(tv2);
2401 else
2402 n -= get_tv_number(tv2);
2403 clear_tv(tv1);
2404 tv1->v_type = VAR_NUMBER;
2405 tv1->vval.v_number = n;
2406 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002407 }
2408 else
2409 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002410 if (tv2->v_type == VAR_FLOAT)
2411 break;
2412
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002413 /* str .= str */
2414 s = get_tv_string(tv1);
2415 s = concat_str(s, get_tv_string_buf(tv2, numbuf));
2416 clear_tv(tv1);
2417 tv1->v_type = VAR_STRING;
2418 tv1->vval.v_string = s;
2419 }
2420 return OK;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002421
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002422 case VAR_FLOAT:
Bram Moolenaar5fac4672016-03-02 22:16:32 +01002423#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002424 {
2425 float_T f;
2426
2427 if (*op == '.' || (tv2->v_type != VAR_FLOAT
2428 && tv2->v_type != VAR_NUMBER
2429 && tv2->v_type != VAR_STRING))
2430 break;
2431 if (tv2->v_type == VAR_FLOAT)
2432 f = tv2->vval.v_float;
2433 else
2434 f = get_tv_number(tv2);
2435 if (*op == '+')
2436 tv1->vval.v_float += f;
2437 else
2438 tv1->vval.v_float -= f;
2439 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002440#endif
Bram Moolenaar5fac4672016-03-02 22:16:32 +01002441 return OK;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002442 }
2443 }
2444
2445 EMSG2(_(e_letwrong), op);
2446 return FAIL;
2447}
2448
2449/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002450 * Evaluate the expression used in a ":for var in expr" command.
2451 * "arg" points to "var".
2452 * Set "*errp" to TRUE for an error, FALSE otherwise;
2453 * Return a pointer that holds the info. Null when there is an error.
2454 */
2455 void *
Bram Moolenaar7454a062016-01-30 15:14:10 +01002456eval_for_line(
2457 char_u *arg,
2458 int *errp,
2459 char_u **nextcmdp,
2460 int skip)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002461{
Bram Moolenaar33570922005-01-25 22:26:29 +00002462 forinfo_T *fi;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002463 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +00002464 typval_T tv;
2465 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002466
2467 *errp = TRUE; /* default: there is an error */
2468
Bram Moolenaar33570922005-01-25 22:26:29 +00002469 fi = (forinfo_T *)alloc_clear(sizeof(forinfo_T));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002470 if (fi == NULL)
2471 return NULL;
2472
2473 expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
2474 if (expr == NULL)
2475 return fi;
2476
2477 expr = skipwhite(expr);
2478 if (expr[0] != 'i' || expr[1] != 'n' || !vim_iswhite(expr[2]))
2479 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00002480 EMSG(_("E690: Missing \"in\" after :for"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002481 return fi;
2482 }
2483
2484 if (skip)
2485 ++emsg_skip;
2486 if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK)
2487 {
2488 *errp = FALSE;
2489 if (!skip)
2490 {
2491 l = tv.vval.v_list;
Bram Moolenaard8585ed2016-05-01 23:05:53 +02002492 if (tv.v_type != VAR_LIST)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002493 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002494 EMSG(_(e_listreq));
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002495 clear_tv(&tv);
2496 }
Bram Moolenaard8585ed2016-05-01 23:05:53 +02002497 else if (l == NULL)
2498 {
2499 /* a null list is like an empty list: do nothing */
2500 clear_tv(&tv);
2501 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002502 else
2503 {
Bram Moolenaar7bb4c6e2005-09-07 21:22:27 +00002504 /* No need to increment the refcount, it's already set for the
2505 * list being used in "tv". */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002506 fi->fi_list = l;
2507 list_add_watch(l, &fi->fi_lw);
2508 fi->fi_lw.lw_item = l->lv_first;
2509 }
2510 }
2511 }
2512 if (skip)
2513 --emsg_skip;
2514
2515 return fi;
2516}
2517
2518/*
2519 * Use the first item in a ":for" list. Advance to the next.
2520 * Assign the values to the variable (list). "arg" points to the first one.
2521 * Return TRUE when a valid item was found, FALSE when at end of list or
2522 * something wrong.
2523 */
2524 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01002525next_for_item(void *fi_void, char_u *arg)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002526{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002527 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002528 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00002529 listitem_T *item;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002530
2531 item = fi->fi_lw.lw_item;
2532 if (item == NULL)
2533 result = FALSE;
2534 else
2535 {
2536 fi->fi_lw.lw_item = item->li_next;
2537 result = (ex_let_vars(arg, &item->li_tv, TRUE,
2538 fi->fi_semicolon, fi->fi_varcount, NULL) == OK);
2539 }
2540 return result;
2541}
2542
2543/*
2544 * Free the structure used to store info used by ":for".
2545 */
2546 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002547free_for_info(void *fi_void)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002548{
Bram Moolenaar33570922005-01-25 22:26:29 +00002549 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002550
Bram Moolenaarab7013c2005-01-09 21:23:56 +00002551 if (fi != NULL && fi->fi_list != NULL)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002552 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002553 list_rem_watch(fi->fi_list, &fi->fi_lw);
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002554 list_unref(fi->fi_list);
2555 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002556 vim_free(fi);
2557}
2558
Bram Moolenaar071d4272004-06-13 20:20:40 +00002559#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
2560
2561 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002562set_context_for_expression(
2563 expand_T *xp,
2564 char_u *arg,
2565 cmdidx_T cmdidx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002566{
2567 int got_eq = FALSE;
2568 int c;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002569 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002570
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002571 if (cmdidx == CMD_let)
2572 {
2573 xp->xp_context = EXPAND_USER_VARS;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002574 if (vim_strpbrk(arg, (char_u *)"\"'+-*/%.=!?~|&$([<>,#") == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002575 {
2576 /* ":let var1 var2 ...": find last space. */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002577 for (p = arg + STRLEN(arg); p >= arg; )
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002578 {
2579 xp->xp_pattern = p;
Bram Moolenaar33570922005-01-25 22:26:29 +00002580 mb_ptr_back(arg, p);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002581 if (vim_iswhite(*p))
2582 break;
2583 }
2584 return;
2585 }
2586 }
2587 else
2588 xp->xp_context = cmdidx == CMD_call ? EXPAND_FUNCTIONS
2589 : EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002590 while ((xp->xp_pattern = vim_strpbrk(arg,
2591 (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL)
2592 {
2593 c = *xp->xp_pattern;
2594 if (c == '&')
2595 {
2596 c = xp->xp_pattern[1];
2597 if (c == '&')
2598 {
2599 ++xp->xp_pattern;
2600 xp->xp_context = cmdidx != CMD_let || got_eq
2601 ? EXPAND_EXPRESSION : EXPAND_NOTHING;
2602 }
2603 else if (c != ' ')
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00002604 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002605 xp->xp_context = EXPAND_SETTINGS;
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00002606 if ((c == 'l' || c == 'g') && xp->xp_pattern[2] == ':')
2607 xp->xp_pattern += 2;
2608
2609 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002610 }
2611 else if (c == '$')
2612 {
2613 /* environment variable */
2614 xp->xp_context = EXPAND_ENV_VARS;
2615 }
2616 else if (c == '=')
2617 {
2618 got_eq = TRUE;
2619 xp->xp_context = EXPAND_EXPRESSION;
2620 }
Bram Moolenaara32095f2016-03-28 19:27:13 +02002621 else if (c == '#'
2622 && xp->xp_context == EXPAND_EXPRESSION)
2623 {
2624 /* Autoload function/variable contains '#'. */
2625 break;
2626 }
Bram Moolenaar8a349ff2014-11-12 20:09:06 +01002627 else if ((c == '<' || c == '#')
Bram Moolenaar071d4272004-06-13 20:20:40 +00002628 && xp->xp_context == EXPAND_FUNCTIONS
2629 && vim_strchr(xp->xp_pattern, '(') == NULL)
2630 {
Bram Moolenaar8a349ff2014-11-12 20:09:06 +01002631 /* Function name can start with "<SNR>" and contain '#'. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002632 break;
2633 }
2634 else if (cmdidx != CMD_let || got_eq)
2635 {
2636 if (c == '"') /* string */
2637 {
2638 while ((c = *++xp->xp_pattern) != NUL && c != '"')
2639 if (c == '\\' && xp->xp_pattern[1] != NUL)
2640 ++xp->xp_pattern;
2641 xp->xp_context = EXPAND_NOTHING;
2642 }
2643 else if (c == '\'') /* literal string */
2644 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002645 /* Trick: '' is like stopping and starting a literal string. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002646 while ((c = *++xp->xp_pattern) != NUL && c != '\'')
2647 /* skip */ ;
2648 xp->xp_context = EXPAND_NOTHING;
2649 }
2650 else if (c == '|')
2651 {
2652 if (xp->xp_pattern[1] == '|')
2653 {
2654 ++xp->xp_pattern;
2655 xp->xp_context = EXPAND_EXPRESSION;
2656 }
2657 else
2658 xp->xp_context = EXPAND_COMMANDS;
2659 }
2660 else
2661 xp->xp_context = EXPAND_EXPRESSION;
2662 }
2663 else
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002664 /* Doesn't look like something valid, expand as an expression
2665 * anyway. */
2666 xp->xp_context = EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002667 arg = xp->xp_pattern;
2668 if (*arg != NUL)
2669 while ((c = *++arg) != NUL && (c == ' ' || c == '\t'))
2670 /* skip */ ;
2671 }
2672 xp->xp_pattern = arg;
2673}
2674
2675#endif /* FEAT_CMDL_COMPL */
2676
2677/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00002678 * ":unlet[!] var1 ... " command.
2679 */
2680 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002681ex_unlet(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002682{
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002683 ex_unletlock(eap, eap->arg, 0);
2684}
2685
2686/*
2687 * ":lockvar" and ":unlockvar" commands
2688 */
2689 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002690ex_lockvar(exarg_T *eap)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002691{
Bram Moolenaar071d4272004-06-13 20:20:40 +00002692 char_u *arg = eap->arg;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002693 int deep = 2;
2694
2695 if (eap->forceit)
2696 deep = -1;
2697 else if (vim_isdigit(*arg))
2698 {
2699 deep = getdigits(&arg);
2700 arg = skipwhite(arg);
2701 }
2702
2703 ex_unletlock(eap, arg, deep);
2704}
2705
2706/*
2707 * ":unlet", ":lockvar" and ":unlockvar" are quite similar.
2708 */
2709 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002710ex_unletlock(
2711 exarg_T *eap,
2712 char_u *argstart,
2713 int deep)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002714{
2715 char_u *arg = argstart;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002716 char_u *name_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002717 int error = FALSE;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002718 lval_T lv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002719
2720 do
2721 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002722 /* Parse the name and find the end. */
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002723 name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error, 0,
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002724 FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002725 if (lv.ll_name == NULL)
2726 error = TRUE; /* error but continue parsing */
2727 if (name_end == NULL || (!vim_iswhite(*name_end)
2728 && !ends_excmd(*name_end)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002729 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002730 if (name_end != NULL)
2731 {
2732 emsg_severe = TRUE;
2733 EMSG(_(e_trailing));
2734 }
2735 if (!(eap->skip || error))
2736 clear_lval(&lv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002737 break;
2738 }
2739
2740 if (!error && !eap->skip)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002741 {
2742 if (eap->cmdidx == CMD_unlet)
2743 {
2744 if (do_unlet_var(&lv, name_end, eap->forceit) == FAIL)
2745 error = TRUE;
2746 }
2747 else
2748 {
2749 if (do_lock_var(&lv, name_end, deep,
2750 eap->cmdidx == CMD_lockvar) == FAIL)
2751 error = TRUE;
2752 }
2753 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002754
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002755 if (!eap->skip)
2756 clear_lval(&lv);
2757
Bram Moolenaar071d4272004-06-13 20:20:40 +00002758 arg = skipwhite(name_end);
2759 } while (!ends_excmd(*arg));
2760
2761 eap->nextcmd = check_nextcmd(arg);
2762}
2763
Bram Moolenaar8c711452005-01-14 21:53:12 +00002764 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01002765do_unlet_var(
2766 lval_T *lp,
2767 char_u *name_end,
2768 int forceit)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002769{
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002770 int ret = OK;
2771 int cc;
2772
2773 if (lp->ll_tv == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002774 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002775 cc = *name_end;
2776 *name_end = NUL;
2777
2778 /* Normal name or expanded name. */
2779 if (check_changedtick(lp->ll_name))
2780 ret = FAIL;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002781 else if (do_unlet(lp->ll_name, forceit) == FAIL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002782 ret = FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002783 *name_end = cc;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002784 }
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02002785 else if ((lp->ll_list != NULL
Bram Moolenaar77354e72015-04-21 16:49:05 +02002786 && tv_check_lock(lp->ll_list->lv_lock, lp->ll_name, FALSE))
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02002787 || (lp->ll_dict != NULL
Bram Moolenaar77354e72015-04-21 16:49:05 +02002788 && tv_check_lock(lp->ll_dict->dv_lock, lp->ll_name, FALSE)))
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002789 return FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002790 else if (lp->ll_range)
2791 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002792 listitem_T *li;
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02002793 listitem_T *ll_li = lp->ll_li;
Bram Moolenaarc9703302016-01-17 21:49:33 +01002794 int ll_n1 = lp->ll_n1;
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02002795
2796 while (ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= ll_n1))
2797 {
2798 li = ll_li->li_next;
Bram Moolenaar77354e72015-04-21 16:49:05 +02002799 if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name, FALSE))
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02002800 return FAIL;
2801 ll_li = li;
2802 ++ll_n1;
2803 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002804
2805 /* Delete a range of List items. */
2806 while (lp->ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
2807 {
2808 li = lp->ll_li->li_next;
2809 listitem_remove(lp->ll_list, lp->ll_li);
2810 lp->ll_li = li;
2811 ++lp->ll_n1;
2812 }
2813 }
2814 else
2815 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002816 if (lp->ll_list != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002817 /* unlet a List item. */
2818 listitem_remove(lp->ll_list, lp->ll_li);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002819 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002820 /* unlet a Dictionary item. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002821 dictitem_remove(lp->ll_dict, lp->ll_di);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002822 }
2823
2824 return ret;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002825}
2826
Bram Moolenaar071d4272004-06-13 20:20:40 +00002827/*
2828 * "unlet" a variable. Return OK if it existed, FAIL if not.
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002829 * When "forceit" is TRUE don't complain if the variable doesn't exist.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002830 */
2831 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01002832do_unlet(char_u *name, int forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002833{
Bram Moolenaar33570922005-01-25 22:26:29 +00002834 hashtab_T *ht;
2835 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00002836 char_u *varname;
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02002837 dict_T *d;
Bram Moolenaarafbdeb82008-01-05 21:16:31 +00002838 dictitem_T *di;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002839
Bram Moolenaar33570922005-01-25 22:26:29 +00002840 ht = find_var_ht(name, &varname);
2841 if (ht != NULL && *varname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002842 {
Bram Moolenaara9b579f2016-07-17 18:29:19 +02002843 d = get_current_funccal_dict(ht);
Bram Moolenaar71bcfdf2016-01-09 18:20:46 +01002844 if (d == NULL)
2845 {
Bram Moolenaara9b579f2016-07-17 18:29:19 +02002846 if (ht == &globvarht)
2847 d = &globvardict;
2848 else if (ht == &compat_hashtab)
2849 d = &vimvardict;
2850 else
2851 {
2852 di = find_var_in_ht(ht, *name, (char_u *)"", FALSE);
2853 d = di == NULL ? NULL : di->di_tv.vval.v_dict;
2854 }
2855 if (d == NULL)
2856 {
Bram Moolenaar95f09602016-11-10 20:01:45 +01002857 internal_error("do_unlet()");
Bram Moolenaara9b579f2016-07-17 18:29:19 +02002858 return FAIL;
2859 }
Bram Moolenaar71bcfdf2016-01-09 18:20:46 +01002860 }
Bram Moolenaar33570922005-01-25 22:26:29 +00002861 hi = hash_find(ht, varname);
Bram Moolenaar10ce39a2016-07-29 22:37:06 +02002862 if (HASHITEM_EMPTY(hi))
Bram Moolenaarba96e9a2016-08-01 17:10:20 +02002863 hi = find_hi_in_scoped_ht(name, &ht);
Bram Moolenaar10ce39a2016-07-29 22:37:06 +02002864 if (hi != NULL && !HASHITEM_EMPTY(hi))
Bram Moolenaara7043832005-01-21 11:56:39 +00002865 {
Bram Moolenaarafbdeb82008-01-05 21:16:31 +00002866 di = HI2DI(hi);
Bram Moolenaar77354e72015-04-21 16:49:05 +02002867 if (var_check_fixed(di->di_flags, name, FALSE)
Bram Moolenaar71bcfdf2016-01-09 18:20:46 +01002868 || var_check_ro(di->di_flags, name, FALSE)
2869 || tv_check_lock(d->dv_lock, name, FALSE))
Bram Moolenaaraf8af8b2016-01-04 22:05:24 +01002870 return FAIL;
2871
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002872 delete_var(ht, hi);
2873 return OK;
Bram Moolenaara7043832005-01-21 11:56:39 +00002874 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002875 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002876 if (forceit)
2877 return OK;
2878 EMSG2(_("E108: No such variable: \"%s\""), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002879 return FAIL;
2880}
2881
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002882/*
2883 * Lock or unlock variable indicated by "lp".
2884 * "deep" is the levels to go (-1 for unlimited);
2885 * "lock" is TRUE for ":lockvar", FALSE for ":unlockvar".
2886 */
2887 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01002888do_lock_var(
2889 lval_T *lp,
2890 char_u *name_end,
2891 int deep,
2892 int lock)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002893{
2894 int ret = OK;
2895 int cc;
2896 dictitem_T *di;
2897
2898 if (deep == 0) /* nothing to do */
2899 return OK;
2900
2901 if (lp->ll_tv == NULL)
2902 {
2903 cc = *name_end;
2904 *name_end = NUL;
2905
2906 /* Normal name or expanded name. */
2907 if (check_changedtick(lp->ll_name))
2908 ret = FAIL;
2909 else
2910 {
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002911 di = find_var(lp->ll_name, NULL, TRUE);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002912 if (di == NULL)
2913 ret = FAIL;
2914 else
2915 {
2916 if (lock)
2917 di->di_flags |= DI_FLAGS_LOCK;
2918 else
2919 di->di_flags &= ~DI_FLAGS_LOCK;
2920 item_lock(&di->di_tv, deep, lock);
2921 }
2922 }
2923 *name_end = cc;
2924 }
2925 else if (lp->ll_range)
2926 {
2927 listitem_T *li = lp->ll_li;
2928
2929 /* (un)lock a range of List items. */
2930 while (li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
2931 {
2932 item_lock(&li->li_tv, deep, lock);
2933 li = li->li_next;
2934 ++lp->ll_n1;
2935 }
2936 }
2937 else if (lp->ll_list != NULL)
2938 /* (un)lock a List item. */
2939 item_lock(&lp->ll_li->li_tv, deep, lock);
2940 else
Bram Moolenaar641e48c2015-06-25 16:09:26 +02002941 /* (un)lock a Dictionary item. */
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002942 item_lock(&lp->ll_di->di_tv, deep, lock);
2943
2944 return ret;
2945}
2946
2947/*
2948 * Lock or unlock an item. "deep" is nr of levels to go.
2949 */
2950 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002951item_lock(typval_T *tv, int deep, int lock)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002952{
2953 static int recurse = 0;
2954 list_T *l;
2955 listitem_T *li;
2956 dict_T *d;
2957 hashitem_T *hi;
2958 int todo;
2959
2960 if (recurse >= DICT_MAXNEST)
2961 {
2962 EMSG(_("E743: variable nested too deep for (un)lock"));
2963 return;
2964 }
2965 if (deep == 0)
2966 return;
2967 ++recurse;
2968
2969 /* lock/unlock the item itself */
2970 if (lock)
2971 tv->v_lock |= VAR_LOCKED;
2972 else
2973 tv->v_lock &= ~VAR_LOCKED;
2974
2975 switch (tv->v_type)
2976 {
Bram Moolenaara03f2332016-02-06 18:09:59 +01002977 case VAR_UNKNOWN:
2978 case VAR_NUMBER:
2979 case VAR_STRING:
2980 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01002981 case VAR_PARTIAL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01002982 case VAR_FLOAT:
2983 case VAR_SPECIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01002984 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01002985 case VAR_CHANNEL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01002986 break;
2987
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002988 case VAR_LIST:
2989 if ((l = tv->vval.v_list) != NULL)
2990 {
2991 if (lock)
2992 l->lv_lock |= VAR_LOCKED;
2993 else
2994 l->lv_lock &= ~VAR_LOCKED;
2995 if (deep < 0 || deep > 1)
2996 /* recursive: lock/unlock the items the List contains */
2997 for (li = l->lv_first; li != NULL; li = li->li_next)
2998 item_lock(&li->li_tv, deep - 1, lock);
2999 }
3000 break;
3001 case VAR_DICT:
3002 if ((d = tv->vval.v_dict) != NULL)
3003 {
3004 if (lock)
3005 d->dv_lock |= VAR_LOCKED;
3006 else
3007 d->dv_lock &= ~VAR_LOCKED;
3008 if (deep < 0 || deep > 1)
3009 {
3010 /* recursive: lock/unlock the items the List contains */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003011 todo = (int)d->dv_hashtab.ht_used;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003012 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
3013 {
3014 if (!HASHITEM_EMPTY(hi))
3015 {
3016 --todo;
3017 item_lock(&HI2DI(hi)->di_tv, deep - 1, lock);
3018 }
3019 }
3020 }
3021 }
3022 }
3023 --recurse;
3024}
3025
Bram Moolenaar071d4272004-06-13 20:20:40 +00003026#if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO)
3027/*
3028 * Delete all "menutrans_" variables.
3029 */
3030 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003031del_menutrans_vars(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003032{
Bram Moolenaar33570922005-01-25 22:26:29 +00003033 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003034 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003035
Bram Moolenaar33570922005-01-25 22:26:29 +00003036 hash_lock(&globvarht);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003037 todo = (int)globvarht.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00003038 for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaara7043832005-01-21 11:56:39 +00003039 {
3040 if (!HASHITEM_EMPTY(hi))
3041 {
3042 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00003043 if (STRNCMP(HI2DI(hi)->di_key, "menutrans_", 10) == 0)
3044 delete_var(&globvarht, hi);
Bram Moolenaara7043832005-01-21 11:56:39 +00003045 }
3046 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003047 hash_unlock(&globvarht);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003048}
3049#endif
3050
3051#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
3052
3053/*
3054 * Local string buffer for the next two functions to store a variable name
3055 * with its prefix. Allocated in cat_prefix_varname(), freed later in
3056 * get_user_var_name().
3057 */
3058
Bram Moolenaar48e697e2016-01-23 22:17:30 +01003059static char_u *cat_prefix_varname(int prefix, char_u *name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003060
3061static char_u *varnamebuf = NULL;
3062static int varnamebuflen = 0;
3063
3064/*
3065 * Function to concatenate a prefix and a variable name.
3066 */
3067 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01003068cat_prefix_varname(int prefix, char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003069{
3070 int len;
3071
3072 len = (int)STRLEN(name) + 3;
3073 if (len > varnamebuflen)
3074 {
3075 vim_free(varnamebuf);
3076 len += 10; /* some additional space */
3077 varnamebuf = alloc(len);
3078 if (varnamebuf == NULL)
3079 {
3080 varnamebuflen = 0;
3081 return NULL;
3082 }
3083 varnamebuflen = len;
3084 }
3085 *varnamebuf = prefix;
3086 varnamebuf[1] = ':';
3087 STRCPY(varnamebuf + 2, name);
3088 return varnamebuf;
3089}
3090
3091/*
3092 * Function given to ExpandGeneric() to obtain the list of user defined
3093 * (global/buffer/window/built-in) variable names.
3094 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003095 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01003096get_user_var_name(expand_T *xp, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003097{
Bram Moolenaar532c7802005-01-27 14:44:31 +00003098 static long_u gdone;
3099 static long_u bdone;
3100 static long_u wdone;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003101#ifdef FEAT_WINDOWS
3102 static long_u tdone;
3103#endif
Bram Moolenaar532c7802005-01-27 14:44:31 +00003104 static int vidx;
3105 static hashitem_T *hi;
3106 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003107
3108 if (idx == 0)
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003109 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003110 gdone = bdone = wdone = vidx = 0;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003111#ifdef FEAT_WINDOWS
3112 tdone = 0;
3113#endif
3114 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003115
3116 /* Global variables */
3117 if (gdone < globvarht.ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003118 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003119 if (gdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003120 hi = globvarht.ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003121 else
3122 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003123 while (HASHITEM_EMPTY(hi))
3124 ++hi;
3125 if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
3126 return cat_prefix_varname('g', hi->hi_key);
3127 return hi->hi_key;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003128 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003129
3130 /* b: variables */
Bram Moolenaar429fa852013-04-15 12:27:36 +02003131 ht = &curbuf->b_vars->dv_hashtab;
Bram Moolenaar33570922005-01-25 22:26:29 +00003132 if (bdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003133 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003134 if (bdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003135 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003136 else
3137 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003138 while (HASHITEM_EMPTY(hi))
3139 ++hi;
3140 return cat_prefix_varname('b', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003141 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003142 if (bdone == ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003143 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003144 ++bdone;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003145 return (char_u *)"b:changedtick";
3146 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003147
3148 /* w: variables */
Bram Moolenaar429fa852013-04-15 12:27:36 +02003149 ht = &curwin->w_vars->dv_hashtab;
Bram Moolenaar33570922005-01-25 22:26:29 +00003150 if (wdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003151 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00003152 if (wdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003153 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003154 else
3155 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003156 while (HASHITEM_EMPTY(hi))
3157 ++hi;
3158 return cat_prefix_varname('w', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003159 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003160
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003161#ifdef FEAT_WINDOWS
3162 /* t: variables */
Bram Moolenaar429fa852013-04-15 12:27:36 +02003163 ht = &curtab->tp_vars->dv_hashtab;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003164 if (tdone < ht->ht_used)
3165 {
3166 if (tdone++ == 0)
3167 hi = ht->ht_array;
3168 else
3169 ++hi;
3170 while (HASHITEM_EMPTY(hi))
3171 ++hi;
3172 return cat_prefix_varname('t', hi->hi_key);
3173 }
3174#endif
3175
Bram Moolenaar33570922005-01-25 22:26:29 +00003176 /* v: variables */
3177 if (vidx < VV_LEN)
3178 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].vv_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003179
3180 vim_free(varnamebuf);
3181 varnamebuf = NULL;
3182 varnamebuflen = 0;
3183 return NULL;
3184}
3185
3186#endif /* FEAT_CMDL_COMPL */
3187
3188/*
Bram Moolenaarea6553b2016-03-27 15:13:38 +02003189 * Return TRUE if "pat" matches "text".
3190 * Does not use 'cpo' and always uses 'magic'.
3191 */
3192 static int
3193pattern_match(char_u *pat, char_u *text, int ic)
3194{
3195 int matches = FALSE;
3196 char_u *save_cpo;
3197 regmatch_T regmatch;
3198
3199 /* avoid 'l' flag in 'cpoptions' */
3200 save_cpo = p_cpo;
3201 p_cpo = (char_u *)"";
3202 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
3203 if (regmatch.regprog != NULL)
3204 {
3205 regmatch.rm_ic = ic;
3206 matches = vim_regexec_nl(&regmatch, text, (colnr_T)0);
3207 vim_regfree(regmatch.regprog);
3208 }
3209 p_cpo = save_cpo;
3210 return matches;
3211}
3212
3213/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003214 * types for expressions.
3215 */
3216typedef enum
3217{
3218 TYPE_UNKNOWN = 0
3219 , TYPE_EQUAL /* == */
3220 , TYPE_NEQUAL /* != */
3221 , TYPE_GREATER /* > */
3222 , TYPE_GEQUAL /* >= */
3223 , TYPE_SMALLER /* < */
3224 , TYPE_SEQUAL /* <= */
3225 , TYPE_MATCH /* =~ */
3226 , TYPE_NOMATCH /* !~ */
3227} exptype_T;
3228
3229/*
3230 * The "evaluate" argument: When FALSE, the argument is only parsed but not
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003231 * executed. The function may return OK, but the rettv will be of type
Bram Moolenaar071d4272004-06-13 20:20:40 +00003232 * VAR_UNKNOWN. The function still returns FAIL for a syntax error.
3233 */
3234
3235/*
3236 * Handle zero level expression.
3237 * This calls eval1() and handles error message and nextcmd.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003238 * Put the result in "rettv" when returning OK and "evaluate" is TRUE.
Bram Moolenaar4463f292005-09-25 22:20:24 +00003239 * Note: "rettv.v_lock" is not set.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003240 * Return OK or FAIL.
3241 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02003242 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003243eval0(
3244 char_u *arg,
3245 typval_T *rettv,
3246 char_u **nextcmd,
3247 int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003248{
3249 int ret;
3250 char_u *p;
3251
3252 p = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003253 ret = eval1(&p, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003254 if (ret == FAIL || !ends_excmd(*p))
3255 {
3256 if (ret != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003257 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003258 /*
3259 * Report the invalid expression unless the expression evaluation has
3260 * been cancelled due to an aborting error, an interrupt, or an
3261 * exception.
3262 */
3263 if (!aborting())
3264 EMSG2(_(e_invexpr2), arg);
3265 ret = FAIL;
3266 }
3267 if (nextcmd != NULL)
3268 *nextcmd = check_nextcmd(p);
3269
3270 return ret;
3271}
3272
3273/*
3274 * Handle top level expression:
Bram Moolenaarb67cc162009-02-04 15:27:06 +00003275 * expr2 ? expr1 : expr1
Bram Moolenaar071d4272004-06-13 20:20:40 +00003276 *
3277 * "arg" must point to the first non-white of the expression.
3278 * "arg" is advanced to the next non-white after the recognized expression.
3279 *
Bram Moolenaar4463f292005-09-25 22:20:24 +00003280 * Note: "rettv.v_lock" is not set.
3281 *
Bram Moolenaar071d4272004-06-13 20:20:40 +00003282 * Return OK or FAIL.
3283 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02003284 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003285eval1(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003286{
3287 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00003288 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003289
3290 /*
3291 * Get the first variable.
3292 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003293 if (eval2(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003294 return FAIL;
3295
3296 if ((*arg)[0] == '?')
3297 {
3298 result = FALSE;
3299 if (evaluate)
3300 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003301 int error = FALSE;
3302
3303 if (get_tv_number_chk(rettv, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003304 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003305 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003306 if (error)
3307 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003308 }
3309
3310 /*
3311 * Get the second variable.
3312 */
3313 *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003314 if (eval1(arg, rettv, evaluate && result) == FAIL) /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003315 return FAIL;
3316
3317 /*
3318 * Check for the ":".
3319 */
3320 if ((*arg)[0] != ':')
3321 {
3322 EMSG(_("E109: Missing ':' after '?'"));
3323 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003324 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003325 return FAIL;
3326 }
3327
3328 /*
3329 * Get the third variable.
3330 */
3331 *arg = skipwhite(*arg + 1);
3332 if (eval1(arg, &var2, evaluate && !result) == FAIL) /* recursive! */
3333 {
3334 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003335 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003336 return FAIL;
3337 }
3338 if (evaluate && !result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003339 *rettv = var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003340 }
3341
3342 return OK;
3343}
3344
3345/*
3346 * Handle first level expression:
3347 * expr2 || expr2 || expr2 logical OR
3348 *
3349 * "arg" must point to the first non-white of the expression.
3350 * "arg" is advanced to the next non-white after the recognized expression.
3351 *
3352 * Return OK or FAIL.
3353 */
3354 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003355eval2(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003356{
Bram Moolenaar33570922005-01-25 22:26:29 +00003357 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003358 long result;
3359 int first;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003360 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003361
3362 /*
3363 * Get the first variable.
3364 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003365 if (eval3(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003366 return FAIL;
3367
3368 /*
3369 * Repeat until there is no following "||".
3370 */
3371 first = TRUE;
3372 result = FALSE;
3373 while ((*arg)[0] == '|' && (*arg)[1] == '|')
3374 {
3375 if (evaluate && first)
3376 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003377 if (get_tv_number_chk(rettv, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003378 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003379 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003380 if (error)
3381 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003382 first = FALSE;
3383 }
3384
3385 /*
3386 * Get the second variable.
3387 */
3388 *arg = skipwhite(*arg + 2);
3389 if (eval3(arg, &var2, evaluate && !result) == FAIL)
3390 return FAIL;
3391
3392 /*
3393 * Compute the result.
3394 */
3395 if (evaluate && !result)
3396 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003397 if (get_tv_number_chk(&var2, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003398 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003399 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003400 if (error)
3401 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003402 }
3403 if (evaluate)
3404 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003405 rettv->v_type = VAR_NUMBER;
3406 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003407 }
3408 }
3409
3410 return OK;
3411}
3412
3413/*
3414 * Handle second level expression:
3415 * expr3 && expr3 && expr3 logical AND
3416 *
3417 * "arg" must point to the first non-white of the expression.
3418 * "arg" is advanced to the next non-white after the recognized expression.
3419 *
3420 * Return OK or FAIL.
3421 */
3422 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003423eval3(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003424{
Bram Moolenaar33570922005-01-25 22:26:29 +00003425 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003426 long result;
3427 int first;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003428 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003429
3430 /*
3431 * Get the first variable.
3432 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003433 if (eval4(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003434 return FAIL;
3435
3436 /*
3437 * Repeat until there is no following "&&".
3438 */
3439 first = TRUE;
3440 result = TRUE;
3441 while ((*arg)[0] == '&' && (*arg)[1] == '&')
3442 {
3443 if (evaluate && first)
3444 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003445 if (get_tv_number_chk(rettv, &error) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003446 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003447 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003448 if (error)
3449 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003450 first = FALSE;
3451 }
3452
3453 /*
3454 * Get the second variable.
3455 */
3456 *arg = skipwhite(*arg + 2);
3457 if (eval4(arg, &var2, evaluate && result) == FAIL)
3458 return FAIL;
3459
3460 /*
3461 * Compute the result.
3462 */
3463 if (evaluate && result)
3464 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003465 if (get_tv_number_chk(&var2, &error) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003466 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003467 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003468 if (error)
3469 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003470 }
3471 if (evaluate)
3472 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003473 rettv->v_type = VAR_NUMBER;
3474 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003475 }
3476 }
3477
3478 return OK;
3479}
3480
3481/*
3482 * Handle third level expression:
3483 * var1 == var2
3484 * var1 =~ var2
3485 * var1 != var2
3486 * var1 !~ var2
3487 * var1 > var2
3488 * var1 >= var2
3489 * var1 < var2
3490 * var1 <= var2
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003491 * var1 is var2
3492 * var1 isnot var2
Bram Moolenaar071d4272004-06-13 20:20:40 +00003493 *
3494 * "arg" must point to the first non-white of the expression.
3495 * "arg" is advanced to the next non-white after the recognized expression.
3496 *
3497 * Return OK or FAIL.
3498 */
3499 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003500eval4(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003501{
Bram Moolenaar33570922005-01-25 22:26:29 +00003502 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003503 char_u *p;
3504 int i;
3505 exptype_T type = TYPE_UNKNOWN;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003506 int type_is = FALSE; /* TRUE for "is" and "isnot" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003507 int len = 2;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02003508 varnumber_T n1, n2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003509 char_u *s1, *s2;
3510 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +00003511 int ic;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003512
3513 /*
3514 * Get the first variable.
3515 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003516 if (eval5(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003517 return FAIL;
3518
3519 p = *arg;
3520 switch (p[0])
3521 {
3522 case '=': if (p[1] == '=')
3523 type = TYPE_EQUAL;
3524 else if (p[1] == '~')
3525 type = TYPE_MATCH;
3526 break;
3527 case '!': if (p[1] == '=')
3528 type = TYPE_NEQUAL;
3529 else if (p[1] == '~')
3530 type = TYPE_NOMATCH;
3531 break;
3532 case '>': if (p[1] != '=')
3533 {
3534 type = TYPE_GREATER;
3535 len = 1;
3536 }
3537 else
3538 type = TYPE_GEQUAL;
3539 break;
3540 case '<': if (p[1] != '=')
3541 {
3542 type = TYPE_SMALLER;
3543 len = 1;
3544 }
3545 else
3546 type = TYPE_SEQUAL;
3547 break;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003548 case 'i': if (p[1] == 's')
3549 {
3550 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3551 len = 5;
Bram Moolenaar37a8de12015-09-01 16:05:00 +02003552 i = p[len];
3553 if (!isalnum(i) && i != '_')
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003554 {
3555 type = len == 2 ? TYPE_EQUAL : TYPE_NEQUAL;
3556 type_is = TRUE;
3557 }
3558 }
3559 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003560 }
3561
3562 /*
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003563 * If there is a comparative operator, use it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003564 */
3565 if (type != TYPE_UNKNOWN)
3566 {
3567 /* extra question mark appended: ignore case */
3568 if (p[len] == '?')
3569 {
3570 ic = TRUE;
3571 ++len;
3572 }
3573 /* extra '#' appended: match case */
3574 else if (p[len] == '#')
3575 {
3576 ic = FALSE;
3577 ++len;
3578 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003579 /* nothing appended: use 'ignorecase' */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003580 else
3581 ic = p_ic;
3582
3583 /*
3584 * Get the second variable.
3585 */
3586 *arg = skipwhite(p + len);
3587 if (eval5(arg, &var2, evaluate) == FAIL)
3588 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003589 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003590 return FAIL;
3591 }
3592
3593 if (evaluate)
3594 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003595 if (type_is && rettv->v_type != var2.v_type)
3596 {
3597 /* For "is" a different type always means FALSE, for "notis"
3598 * it means TRUE. */
3599 n1 = (type == TYPE_NEQUAL);
3600 }
3601 else if (rettv->v_type == VAR_LIST || var2.v_type == VAR_LIST)
3602 {
3603 if (type_is)
3604 {
3605 n1 = (rettv->v_type == var2.v_type
3606 && rettv->vval.v_list == var2.vval.v_list);
3607 if (type == TYPE_NEQUAL)
3608 n1 = !n1;
3609 }
3610 else if (rettv->v_type != var2.v_type
3611 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
3612 {
3613 if (rettv->v_type != var2.v_type)
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003614 EMSG(_("E691: Can only compare List with List"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003615 else
Bram Moolenaar59838522014-05-13 13:46:33 +02003616 EMSG(_("E692: Invalid operation for List"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003617 clear_tv(rettv);
3618 clear_tv(&var2);
3619 return FAIL;
3620 }
3621 else
3622 {
3623 /* Compare two Lists for being equal or unequal. */
Bram Moolenaar67b3f992010-11-10 20:41:57 +01003624 n1 = list_equal(rettv->vval.v_list, var2.vval.v_list,
3625 ic, FALSE);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003626 if (type == TYPE_NEQUAL)
3627 n1 = !n1;
3628 }
3629 }
3630
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003631 else if (rettv->v_type == VAR_DICT || var2.v_type == VAR_DICT)
3632 {
3633 if (type_is)
3634 {
3635 n1 = (rettv->v_type == var2.v_type
3636 && rettv->vval.v_dict == var2.vval.v_dict);
3637 if (type == TYPE_NEQUAL)
3638 n1 = !n1;
3639 }
3640 else if (rettv->v_type != var2.v_type
3641 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
3642 {
3643 if (rettv->v_type != var2.v_type)
3644 EMSG(_("E735: Can only compare Dictionary with Dictionary"));
3645 else
3646 EMSG(_("E736: Invalid operation for Dictionary"));
3647 clear_tv(rettv);
3648 clear_tv(&var2);
3649 return FAIL;
3650 }
3651 else
3652 {
3653 /* Compare two Dictionaries for being equal or unequal. */
Bram Moolenaar67b3f992010-11-10 20:41:57 +01003654 n1 = dict_equal(rettv->vval.v_dict, var2.vval.v_dict,
3655 ic, FALSE);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003656 if (type == TYPE_NEQUAL)
3657 n1 = !n1;
3658 }
3659 }
3660
Bram Moolenaar1735bc92016-03-14 23:05:14 +01003661 else if (rettv->v_type == VAR_FUNC || var2.v_type == VAR_FUNC
3662 || rettv->v_type == VAR_PARTIAL || var2.v_type == VAR_PARTIAL)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003663 {
Bram Moolenaarf0e86a02016-03-19 19:38:12 +01003664 if (type != TYPE_EQUAL && type != TYPE_NEQUAL)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003665 {
Bram Moolenaarf0e86a02016-03-19 19:38:12 +01003666 EMSG(_("E694: Invalid operation for Funcrefs"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003667 clear_tv(rettv);
3668 clear_tv(&var2);
3669 return FAIL;
3670 }
Bram Moolenaar8e759ba2016-06-02 17:46:20 +02003671 if ((rettv->v_type == VAR_PARTIAL
3672 && rettv->vval.v_partial == NULL)
3673 || (var2.v_type == VAR_PARTIAL
3674 && var2.vval.v_partial == NULL))
3675 /* when a partial is NULL assume not equal */
3676 n1 = FALSE;
3677 else if (type_is)
3678 {
3679 if (rettv->v_type == VAR_FUNC && var2.v_type == VAR_FUNC)
3680 /* strings are considered the same if their value is
3681 * the same */
3682 n1 = tv_equal(rettv, &var2, ic, FALSE);
3683 else if (rettv->v_type == VAR_PARTIAL
3684 && var2.v_type == VAR_PARTIAL)
3685 n1 = (rettv->vval.v_partial == var2.vval.v_partial);
3686 else
3687 n1 = FALSE;
3688 }
3689 else
3690 n1 = tv_equal(rettv, &var2, ic, FALSE);
Bram Moolenaar1735bc92016-03-14 23:05:14 +01003691 if (type == TYPE_NEQUAL)
3692 n1 = !n1;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003693 }
3694
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003695#ifdef FEAT_FLOAT
3696 /*
3697 * If one of the two variables is a float, compare as a float.
3698 * When using "=~" or "!~", always compare as string.
3699 */
3700 else if ((rettv->v_type == VAR_FLOAT || var2.v_type == VAR_FLOAT)
3701 && type != TYPE_MATCH && type != TYPE_NOMATCH)
3702 {
3703 float_T f1, f2;
3704
3705 if (rettv->v_type == VAR_FLOAT)
3706 f1 = rettv->vval.v_float;
3707 else
3708 f1 = get_tv_number(rettv);
3709 if (var2.v_type == VAR_FLOAT)
3710 f2 = var2.vval.v_float;
3711 else
3712 f2 = get_tv_number(&var2);
3713 n1 = FALSE;
3714 switch (type)
3715 {
3716 case TYPE_EQUAL: n1 = (f1 == f2); break;
3717 case TYPE_NEQUAL: n1 = (f1 != f2); break;
3718 case TYPE_GREATER: n1 = (f1 > f2); break;
3719 case TYPE_GEQUAL: n1 = (f1 >= f2); break;
3720 case TYPE_SMALLER: n1 = (f1 < f2); break;
3721 case TYPE_SEQUAL: n1 = (f1 <= f2); break;
3722 case TYPE_UNKNOWN:
3723 case TYPE_MATCH:
3724 case TYPE_NOMATCH: break; /* avoid gcc warning */
3725 }
3726 }
3727#endif
3728
Bram Moolenaar071d4272004-06-13 20:20:40 +00003729 /*
3730 * If one of the two variables is a number, compare as a number.
3731 * When using "=~" or "!~", always compare as string.
3732 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003733 else if ((rettv->v_type == VAR_NUMBER || var2.v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003734 && type != TYPE_MATCH && type != TYPE_NOMATCH)
3735 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003736 n1 = get_tv_number(rettv);
3737 n2 = get_tv_number(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003738 switch (type)
3739 {
3740 case TYPE_EQUAL: n1 = (n1 == n2); break;
3741 case TYPE_NEQUAL: n1 = (n1 != n2); break;
3742 case TYPE_GREATER: n1 = (n1 > n2); break;
3743 case TYPE_GEQUAL: n1 = (n1 >= n2); break;
3744 case TYPE_SMALLER: n1 = (n1 < n2); break;
3745 case TYPE_SEQUAL: n1 = (n1 <= n2); break;
3746 case TYPE_UNKNOWN:
3747 case TYPE_MATCH:
3748 case TYPE_NOMATCH: break; /* avoid gcc warning */
3749 }
3750 }
3751 else
3752 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003753 s1 = get_tv_string_buf(rettv, buf1);
3754 s2 = get_tv_string_buf(&var2, buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003755 if (type != TYPE_MATCH && type != TYPE_NOMATCH)
3756 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2);
3757 else
3758 i = 0;
3759 n1 = FALSE;
3760 switch (type)
3761 {
3762 case TYPE_EQUAL: n1 = (i == 0); break;
3763 case TYPE_NEQUAL: n1 = (i != 0); break;
3764 case TYPE_GREATER: n1 = (i > 0); break;
3765 case TYPE_GEQUAL: n1 = (i >= 0); break;
3766 case TYPE_SMALLER: n1 = (i < 0); break;
3767 case TYPE_SEQUAL: n1 = (i <= 0); break;
3768
3769 case TYPE_MATCH:
3770 case TYPE_NOMATCH:
Bram Moolenaarea6553b2016-03-27 15:13:38 +02003771 n1 = pattern_match(s2, s1, ic);
3772 if (type == TYPE_NOMATCH)
3773 n1 = !n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003774 break;
3775
3776 case TYPE_UNKNOWN: break; /* avoid gcc warning */
3777 }
3778 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003779 clear_tv(rettv);
3780 clear_tv(&var2);
3781 rettv->v_type = VAR_NUMBER;
3782 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003783 }
3784 }
3785
3786 return OK;
3787}
3788
3789/*
3790 * Handle fourth level expression:
3791 * + number addition
3792 * - number subtraction
3793 * . string concatenation
3794 *
3795 * "arg" must point to the first non-white of the expression.
3796 * "arg" is advanced to the next non-white after the recognized expression.
3797 *
3798 * Return OK or FAIL.
3799 */
3800 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003801eval5(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003802{
Bram Moolenaar33570922005-01-25 22:26:29 +00003803 typval_T var2;
3804 typval_T var3;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003805 int op;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02003806 varnumber_T n1, n2;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003807#ifdef FEAT_FLOAT
3808 float_T f1 = 0, f2 = 0;
3809#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003810 char_u *s1, *s2;
3811 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
3812 char_u *p;
3813
3814 /*
3815 * Get the first variable.
3816 */
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00003817 if (eval6(arg, rettv, evaluate, FALSE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003818 return FAIL;
3819
3820 /*
3821 * Repeat computing, until no '+', '-' or '.' is following.
3822 */
3823 for (;;)
3824 {
3825 op = **arg;
3826 if (op != '+' && op != '-' && op != '.')
3827 break;
3828
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003829 if ((op != '+' || rettv->v_type != VAR_LIST)
3830#ifdef FEAT_FLOAT
3831 && (op == '.' || rettv->v_type != VAR_FLOAT)
3832#endif
3833 )
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003834 {
3835 /* For "list + ...", an illegal use of the first operand as
3836 * a number cannot be determined before evaluating the 2nd
3837 * operand: if this is also a list, all is ok.
3838 * For "something . ...", "something - ..." or "non-list + ...",
3839 * we know that the first operand needs to be a string or number
3840 * without evaluating the 2nd operand. So check before to avoid
3841 * side effects after an error. */
3842 if (evaluate && get_tv_string_chk(rettv) == NULL)
3843 {
3844 clear_tv(rettv);
3845 return FAIL;
3846 }
3847 }
3848
Bram Moolenaar071d4272004-06-13 20:20:40 +00003849 /*
3850 * Get the second variable.
3851 */
3852 *arg = skipwhite(*arg + 1);
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00003853 if (eval6(arg, &var2, evaluate, op == '.') == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003854 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003855 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003856 return FAIL;
3857 }
3858
3859 if (evaluate)
3860 {
3861 /*
3862 * Compute the result.
3863 */
3864 if (op == '.')
3865 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003866 s1 = get_tv_string_buf(rettv, buf1); /* already checked */
3867 s2 = get_tv_string_buf_chk(&var2, buf2);
3868 if (s2 == NULL) /* type error ? */
3869 {
3870 clear_tv(rettv);
3871 clear_tv(&var2);
3872 return FAIL;
3873 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003874 p = concat_str(s1, s2);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003875 clear_tv(rettv);
3876 rettv->v_type = VAR_STRING;
3877 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003878 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00003879 else if (op == '+' && rettv->v_type == VAR_LIST
3880 && var2.v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003881 {
3882 /* concatenate Lists */
3883 if (list_concat(rettv->vval.v_list, var2.vval.v_list,
3884 &var3) == FAIL)
3885 {
3886 clear_tv(rettv);
3887 clear_tv(&var2);
3888 return FAIL;
3889 }
3890 clear_tv(rettv);
3891 *rettv = var3;
3892 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003893 else
3894 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003895 int error = FALSE;
3896
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003897#ifdef FEAT_FLOAT
3898 if (rettv->v_type == VAR_FLOAT)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003899 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003900 f1 = rettv->vval.v_float;
3901 n1 = 0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003902 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003903 else
3904#endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003905 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003906 n1 = get_tv_number_chk(rettv, &error);
3907 if (error)
3908 {
3909 /* This can only happen for "list + non-list". For
3910 * "non-list + ..." or "something - ...", we returned
3911 * before evaluating the 2nd operand. */
3912 clear_tv(rettv);
3913 return FAIL;
3914 }
3915#ifdef FEAT_FLOAT
3916 if (var2.v_type == VAR_FLOAT)
3917 f1 = n1;
3918#endif
3919 }
3920#ifdef FEAT_FLOAT
3921 if (var2.v_type == VAR_FLOAT)
3922 {
3923 f2 = var2.vval.v_float;
3924 n2 = 0;
3925 }
3926 else
3927#endif
3928 {
3929 n2 = get_tv_number_chk(&var2, &error);
3930 if (error)
3931 {
3932 clear_tv(rettv);
3933 clear_tv(&var2);
3934 return FAIL;
3935 }
3936#ifdef FEAT_FLOAT
3937 if (rettv->v_type == VAR_FLOAT)
3938 f2 = n2;
3939#endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003940 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003941 clear_tv(rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003942
3943#ifdef FEAT_FLOAT
3944 /* If there is a float on either side the result is a float. */
3945 if (rettv->v_type == VAR_FLOAT || var2.v_type == VAR_FLOAT)
3946 {
3947 if (op == '+')
3948 f1 = f1 + f2;
3949 else
3950 f1 = f1 - f2;
3951 rettv->v_type = VAR_FLOAT;
3952 rettv->vval.v_float = f1;
3953 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003954 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003955#endif
3956 {
3957 if (op == '+')
3958 n1 = n1 + n2;
3959 else
3960 n1 = n1 - n2;
3961 rettv->v_type = VAR_NUMBER;
3962 rettv->vval.v_number = n1;
3963 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003964 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003965 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003966 }
3967 }
3968 return OK;
3969}
3970
3971/*
3972 * Handle fifth level expression:
3973 * * number multiplication
3974 * / number division
3975 * % number modulo
3976 *
3977 * "arg" must point to the first non-white of the expression.
3978 * "arg" is advanced to the next non-white after the recognized expression.
3979 *
3980 * Return OK or FAIL.
3981 */
3982 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003983eval6(
3984 char_u **arg,
3985 typval_T *rettv,
3986 int evaluate,
3987 int want_string) /* after "." operator */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003988{
Bram Moolenaar33570922005-01-25 22:26:29 +00003989 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003990 int op;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02003991 varnumber_T n1, n2;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003992#ifdef FEAT_FLOAT
3993 int use_float = FALSE;
3994 float_T f1 = 0, f2;
3995#endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003996 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003997
3998 /*
3999 * Get the first variable.
4000 */
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004001 if (eval7(arg, rettv, evaluate, want_string) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004002 return FAIL;
4003
4004 /*
4005 * Repeat computing, until no '*', '/' or '%' is following.
4006 */
4007 for (;;)
4008 {
4009 op = **arg;
4010 if (op != '*' && op != '/' && op != '%')
4011 break;
4012
4013 if (evaluate)
4014 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004015#ifdef FEAT_FLOAT
4016 if (rettv->v_type == VAR_FLOAT)
4017 {
4018 f1 = rettv->vval.v_float;
4019 use_float = TRUE;
4020 n1 = 0;
4021 }
4022 else
4023#endif
4024 n1 = get_tv_number_chk(rettv, &error);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004025 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004026 if (error)
4027 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004028 }
4029 else
4030 n1 = 0;
4031
4032 /*
4033 * Get the second variable.
4034 */
4035 *arg = skipwhite(*arg + 1);
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004036 if (eval7(arg, &var2, evaluate, FALSE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004037 return FAIL;
4038
4039 if (evaluate)
4040 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004041#ifdef FEAT_FLOAT
4042 if (var2.v_type == VAR_FLOAT)
4043 {
4044 if (!use_float)
4045 {
4046 f1 = n1;
4047 use_float = TRUE;
4048 }
4049 f2 = var2.vval.v_float;
4050 n2 = 0;
4051 }
4052 else
4053#endif
4054 {
4055 n2 = get_tv_number_chk(&var2, &error);
4056 clear_tv(&var2);
4057 if (error)
4058 return FAIL;
4059#ifdef FEAT_FLOAT
4060 if (use_float)
4061 f2 = n2;
4062#endif
4063 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004064
4065 /*
4066 * Compute the result.
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004067 * When either side is a float the result is a float.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004068 */
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004069#ifdef FEAT_FLOAT
4070 if (use_float)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004071 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004072 if (op == '*')
4073 f1 = f1 * f2;
4074 else if (op == '/')
4075 {
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004076# ifdef VMS
4077 /* VMS crashes on divide by zero, work around it */
4078 if (f2 == 0.0)
4079 {
4080 if (f1 == 0)
Bram Moolenaar314f11d2010-08-09 22:07:08 +02004081 f1 = -1 * __F_FLT_MAX - 1L; /* similar to NaN */
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004082 else if (f1 < 0)
Bram Moolenaar314f11d2010-08-09 22:07:08 +02004083 f1 = -1 * __F_FLT_MAX;
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004084 else
Bram Moolenaar314f11d2010-08-09 22:07:08 +02004085 f1 = __F_FLT_MAX;
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004086 }
4087 else
4088 f1 = f1 / f2;
4089# else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004090 /* We rely on the floating point library to handle divide
4091 * by zero to result in "inf" and not a crash. */
4092 f1 = f1 / f2;
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004093# endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004094 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004095 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004096 {
Bram Moolenaar1378fca2008-07-04 16:51:55 +00004097 EMSG(_("E804: Cannot use '%' with Float"));
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004098 return FAIL;
4099 }
4100 rettv->v_type = VAR_FLOAT;
4101 rettv->vval.v_float = f1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004102 }
4103 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004104#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004105 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004106 if (op == '*')
4107 n1 = n1 * n2;
4108 else if (op == '/')
4109 {
4110 if (n2 == 0) /* give an error message? */
4111 {
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02004112#ifdef FEAT_NUM64
4113 if (n1 == 0)
Bram Moolenaaraf9c4c92016-08-17 21:51:56 +02004114 n1 = -0x7fffffffffffffffLL - 1; /* similar to NaN */
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02004115 else if (n1 < 0)
Bram Moolenaaraf9c4c92016-08-17 21:51:56 +02004116 n1 = -0x7fffffffffffffffLL;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02004117 else
Bram Moolenaaraf9c4c92016-08-17 21:51:56 +02004118 n1 = 0x7fffffffffffffffLL;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02004119#else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004120 if (n1 == 0)
4121 n1 = -0x7fffffffL - 1L; /* similar to NaN */
4122 else if (n1 < 0)
4123 n1 = -0x7fffffffL;
4124 else
4125 n1 = 0x7fffffffL;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02004126#endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004127 }
4128 else
4129 n1 = n1 / n2;
4130 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004131 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004132 {
4133 if (n2 == 0) /* give an error message? */
4134 n1 = 0;
4135 else
4136 n1 = n1 % n2;
4137 }
4138 rettv->v_type = VAR_NUMBER;
4139 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004140 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004141 }
4142 }
4143
4144 return OK;
4145}
4146
4147/*
4148 * Handle sixth level expression:
4149 * number number constant
Bram Moolenaarbae0c162007-05-10 19:30:25 +00004150 * "string" string constant
4151 * 'string' literal string constant
Bram Moolenaar071d4272004-06-13 20:20:40 +00004152 * &option-name option value
4153 * @r register contents
4154 * identifier variable value
4155 * function() function call
4156 * $VAR environment variable
4157 * (expression) nested expression
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00004158 * [expr, expr] List
4159 * {key: val, key: val} Dictionary
Bram Moolenaar071d4272004-06-13 20:20:40 +00004160 *
4161 * Also handle:
4162 * ! in front logical NOT
4163 * - in front unary minus
4164 * + in front unary plus (ignored)
Bram Moolenaar8c711452005-01-14 21:53:12 +00004165 * trailing [] subscript in String or List
4166 * trailing .name entry in Dictionary
Bram Moolenaar071d4272004-06-13 20:20:40 +00004167 *
4168 * "arg" must point to the first non-white of the expression.
4169 * "arg" is advanced to the next non-white after the recognized expression.
4170 *
4171 * Return OK or FAIL.
4172 */
4173 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004174eval7(
4175 char_u **arg,
4176 typval_T *rettv,
4177 int evaluate,
4178 int want_string UNUSED) /* after "." operator */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004179{
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02004180 varnumber_T n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004181 int len;
4182 char_u *s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004183 char_u *start_leader, *end_leader;
4184 int ret = OK;
4185 char_u *alias;
4186
4187 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004188 * Initialise variable so that clear_tv() can't mistake this for a
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004189 * string and free a string that isn't there.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004190 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004191 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004192
4193 /*
Bram Moolenaaredf3f972016-08-29 22:49:24 +02004194 * Skip '!', '-' and '+' characters. They are handled later.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004195 */
4196 start_leader = *arg;
4197 while (**arg == '!' || **arg == '-' || **arg == '+')
4198 *arg = skipwhite(*arg + 1);
4199 end_leader = *arg;
4200
4201 switch (**arg)
4202 {
4203 /*
4204 * Number constant.
4205 */
4206 case '0':
4207 case '1':
4208 case '2':
4209 case '3':
4210 case '4':
4211 case '5':
4212 case '6':
4213 case '7':
4214 case '8':
4215 case '9':
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004216 {
4217#ifdef FEAT_FLOAT
4218 char_u *p = skipdigits(*arg + 1);
4219 int get_float = FALSE;
4220
4221 /* We accept a float when the format matches
4222 * "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004223 * strict to avoid backwards compatibility problems.
4224 * Don't look for a float after the "." operator, so that
4225 * ":let vers = 1.2.3" doesn't fail. */
4226 if (!want_string && p[0] == '.' && vim_isdigit(p[1]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004227 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004228 get_float = TRUE;
4229 p = skipdigits(p + 2);
4230 if (*p == 'e' || *p == 'E')
4231 {
4232 ++p;
4233 if (*p == '-' || *p == '+')
4234 ++p;
4235 if (!vim_isdigit(*p))
4236 get_float = FALSE;
4237 else
4238 p = skipdigits(p + 1);
4239 }
4240 if (ASCII_ISALPHA(*p) || *p == '.')
4241 get_float = FALSE;
4242 }
4243 if (get_float)
4244 {
4245 float_T f;
4246
4247 *arg += string2float(*arg, &f);
4248 if (evaluate)
4249 {
4250 rettv->v_type = VAR_FLOAT;
4251 rettv->vval.v_float = f;
4252 }
4253 }
4254 else
4255#endif
4256 {
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01004257 vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004258 *arg += len;
4259 if (evaluate)
4260 {
4261 rettv->v_type = VAR_NUMBER;
4262 rettv->vval.v_number = n;
4263 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004264 }
4265 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004266 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004267
4268 /*
4269 * String constant: "string".
4270 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004271 case '"': ret = get_string_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004272 break;
4273
4274 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004275 * Literal string constant: 'str''ing'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004276 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004277 case '\'': ret = get_lit_string_tv(arg, rettv, evaluate);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004278 break;
4279
4280 /*
4281 * List: [expr, expr]
4282 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004283 case '[': ret = get_list_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004284 break;
4285
4286 /*
Bram Moolenaar069c1e72016-07-15 21:25:08 +02004287 * Lambda: {arg, arg -> expr}
Bram Moolenaar8c711452005-01-14 21:53:12 +00004288 * Dictionary: {key: val, key: val}
4289 */
Bram Moolenaar069c1e72016-07-15 21:25:08 +02004290 case '{': ret = get_lambda_tv(arg, rettv, evaluate);
4291 if (ret == NOTDONE)
4292 ret = get_dict_tv(arg, rettv, evaluate);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004293 break;
4294
4295 /*
Bram Moolenaare9a41262005-01-15 22:18:47 +00004296 * Option value: &name
Bram Moolenaar071d4272004-06-13 20:20:40 +00004297 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00004298 case '&': ret = get_option_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004299 break;
4300
4301 /*
4302 * Environment variable: $VAR.
4303 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004304 case '$': ret = get_env_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004305 break;
4306
4307 /*
4308 * Register contents: @r.
4309 */
4310 case '@': ++*arg;
4311 if (evaluate)
4312 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004313 rettv->v_type = VAR_STRING;
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +02004314 rettv->vval.v_string = get_reg_contents(**arg,
4315 GREG_EXPR_SRC);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004316 }
4317 if (**arg != NUL)
4318 ++*arg;
4319 break;
4320
4321 /*
4322 * nested expression: (expression).
4323 */
4324 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004325 ret = eval1(arg, rettv, evaluate); /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004326 if (**arg == ')')
4327 ++*arg;
4328 else if (ret == OK)
4329 {
4330 EMSG(_("E110: Missing ')'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004331 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004332 ret = FAIL;
4333 }
4334 break;
4335
Bram Moolenaar8c711452005-01-14 21:53:12 +00004336 default: ret = NOTDONE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004337 break;
4338 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004339
4340 if (ret == NOTDONE)
4341 {
4342 /*
4343 * Must be a variable or function name.
4344 * Can also be a curly-braces kind of name: {expr}.
4345 */
4346 s = *arg;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004347 len = get_name_len(arg, &alias, evaluate, TRUE);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004348 if (alias != NULL)
4349 s = alias;
4350
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004351 if (len <= 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00004352 ret = FAIL;
4353 else
4354 {
4355 if (**arg == '(') /* recursive! */
4356 {
Bram Moolenaar1735bc92016-03-14 23:05:14 +01004357 partial_T *partial;
4358
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02004359 if (!evaluate)
4360 check_vars(s, len);
4361
Bram Moolenaar8c711452005-01-14 21:53:12 +00004362 /* If "s" is the name of a variable of type VAR_FUNC
4363 * use its contents. */
Bram Moolenaar1735bc92016-03-14 23:05:14 +01004364 s = deref_func_name(s, &len, &partial, !evaluate);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004365
Bram Moolenaar8a01f962016-11-14 21:50:00 +01004366 /* Need to make a copy, in case evaluating the arguments makes
4367 * the name invalid. */
4368 s = vim_strsave(s);
4369 if (s == NULL)
4370 ret = FAIL;
4371 else
4372 /* Invoke the function. */
4373 ret = get_func_tv(s, len, rettv, arg,
4374 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
4375 &len, evaluate, partial, NULL);
4376 vim_free(s);
Bram Moolenaare17c2602013-02-26 19:36:15 +01004377
4378 /* If evaluate is FALSE rettv->v_type was not set in
4379 * get_func_tv, but it's needed in handle_subscript() to parse
4380 * what follows. So set it here. */
4381 if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(')
4382 {
Bram Moolenaar9ad73232016-06-01 22:08:17 +02004383 rettv->vval.v_string = NULL;
Bram Moolenaare17c2602013-02-26 19:36:15 +01004384 rettv->v_type = VAR_FUNC;
4385 }
4386
Bram Moolenaar8c711452005-01-14 21:53:12 +00004387 /* Stop the expression evaluation when immediately
4388 * aborting on error, or when an interrupt occurred or
4389 * an exception was thrown but not caught. */
4390 if (aborting())
4391 {
4392 if (ret == OK)
4393 clear_tv(rettv);
4394 ret = FAIL;
4395 }
4396 }
4397 else if (evaluate)
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02004398 ret = get_var_tv(s, len, rettv, NULL, TRUE, FALSE);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004399 else
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02004400 {
4401 check_vars(s, len);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004402 ret = OK;
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02004403 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004404 }
Bram Moolenaar3c2d6532011-02-01 13:48:53 +01004405 vim_free(alias);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004406 }
4407
Bram Moolenaar071d4272004-06-13 20:20:40 +00004408 *arg = skipwhite(*arg);
4409
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004410 /* Handle following '[', '(' and '.' for expr[expr], expr.name,
4411 * expr(expr). */
4412 if (ret == OK)
4413 ret = handle_subscript(arg, rettv, evaluate, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004414
4415 /*
4416 * Apply logical NOT and unary '-', from right to left, ignore '+'.
4417 */
4418 if (ret == OK && evaluate && end_leader > start_leader)
4419 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004420 int error = FALSE;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02004421 varnumber_T val = 0;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004422#ifdef FEAT_FLOAT
4423 float_T f = 0.0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004424
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004425 if (rettv->v_type == VAR_FLOAT)
4426 f = rettv->vval.v_float;
4427 else
4428#endif
4429 val = get_tv_number_chk(rettv, &error);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004430 if (error)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004431 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004432 clear_tv(rettv);
4433 ret = FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004434 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004435 else
4436 {
4437 while (end_leader > start_leader)
4438 {
4439 --end_leader;
4440 if (*end_leader == '!')
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004441 {
4442#ifdef FEAT_FLOAT
4443 if (rettv->v_type == VAR_FLOAT)
4444 f = !f;
4445 else
4446#endif
4447 val = !val;
4448 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004449 else if (*end_leader == '-')
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004450 {
4451#ifdef FEAT_FLOAT
4452 if (rettv->v_type == VAR_FLOAT)
4453 f = -f;
4454 else
4455#endif
4456 val = -val;
4457 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004458 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004459#ifdef FEAT_FLOAT
4460 if (rettv->v_type == VAR_FLOAT)
4461 {
4462 clear_tv(rettv);
4463 rettv->vval.v_float = f;
4464 }
4465 else
4466#endif
4467 {
4468 clear_tv(rettv);
4469 rettv->v_type = VAR_NUMBER;
4470 rettv->vval.v_number = val;
4471 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004472 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004473 }
4474
4475 return ret;
4476}
4477
4478/*
Bram Moolenaar9e54a0e2006-04-14 20:42:25 +00004479 * Evaluate an "[expr]" or "[expr:expr]" index. Also "dict.key".
4480 * "*arg" points to the '[' or '.'.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004481 * Returns FAIL or OK. "*arg" is advanced to after the ']'.
4482 */
4483 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004484eval_index(
4485 char_u **arg,
4486 typval_T *rettv,
4487 int evaluate,
4488 int verbose) /* give error messages */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004489{
4490 int empty1 = FALSE, empty2 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00004491 typval_T var1, var2;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004492 long n1, n2 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004493 long len = -1;
4494 int range = FALSE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004495 char_u *s;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004496 char_u *key = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004497
Bram Moolenaara03f2332016-02-06 18:09:59 +01004498 switch (rettv->v_type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004499 {
Bram Moolenaara03f2332016-02-06 18:09:59 +01004500 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01004501 case VAR_PARTIAL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01004502 if (verbose)
4503 EMSG(_("E695: Cannot index a Funcref"));
4504 return FAIL;
4505 case VAR_FLOAT:
Bram Moolenaar2a876e42013-06-12 22:08:58 +02004506#ifdef FEAT_FLOAT
Bram Moolenaara03f2332016-02-06 18:09:59 +01004507 if (verbose)
4508 EMSG(_(e_float_as_string));
4509 return FAIL;
Bram Moolenaar2a876e42013-06-12 22:08:58 +02004510#endif
Bram Moolenaara03f2332016-02-06 18:09:59 +01004511 case VAR_SPECIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01004512 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01004513 case VAR_CHANNEL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01004514 if (verbose)
4515 EMSG(_("E909: Cannot index a special variable"));
4516 return FAIL;
4517 case VAR_UNKNOWN:
4518 if (evaluate)
4519 return FAIL;
4520 /* FALLTHROUGH */
4521
4522 case VAR_STRING:
4523 case VAR_NUMBER:
4524 case VAR_LIST:
4525 case VAR_DICT:
4526 break;
Bram Moolenaar520e1e42016-01-23 19:46:28 +01004527 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004528
Bram Moolenaar0a38dd22015-08-25 16:49:01 +02004529 init_tv(&var1);
4530 init_tv(&var2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004531 if (**arg == '.')
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004532 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004533 /*
4534 * dict.name
4535 */
4536 key = *arg + 1;
4537 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
4538 ;
4539 if (len == 0)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004540 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004541 *arg = skipwhite(key + len);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004542 }
4543 else
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004544 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004545 /*
4546 * something[idx]
4547 *
4548 * Get the (first) variable from inside the [].
4549 */
4550 *arg = skipwhite(*arg + 1);
4551 if (**arg == ':')
4552 empty1 = TRUE;
4553 else if (eval1(arg, &var1, evaluate) == FAIL) /* recursive! */
4554 return FAIL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004555 else if (evaluate && get_tv_string_chk(&var1) == NULL)
4556 {
4557 /* not a number or string */
4558 clear_tv(&var1);
4559 return FAIL;
4560 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004561
4562 /*
4563 * Get the second variable from inside the [:].
4564 */
4565 if (**arg == ':')
4566 {
4567 range = TRUE;
4568 *arg = skipwhite(*arg + 1);
4569 if (**arg == ']')
4570 empty2 = TRUE;
4571 else if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */
4572 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004573 if (!empty1)
4574 clear_tv(&var1);
4575 return FAIL;
4576 }
4577 else if (evaluate && get_tv_string_chk(&var2) == NULL)
4578 {
4579 /* not a number or string */
4580 if (!empty1)
4581 clear_tv(&var1);
4582 clear_tv(&var2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004583 return FAIL;
4584 }
4585 }
4586
4587 /* Check for the ']'. */
4588 if (**arg != ']')
4589 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004590 if (verbose)
4591 EMSG(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004592 clear_tv(&var1);
4593 if (range)
4594 clear_tv(&var2);
4595 return FAIL;
4596 }
4597 *arg = skipwhite(*arg + 1); /* skip the ']' */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004598 }
4599
4600 if (evaluate)
4601 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004602 n1 = 0;
4603 if (!empty1 && rettv->v_type != VAR_DICT)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004604 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004605 n1 = get_tv_number(&var1);
4606 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004607 }
4608 if (range)
4609 {
4610 if (empty2)
4611 n2 = -1;
4612 else
4613 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004614 n2 = get_tv_number(&var2);
4615 clear_tv(&var2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004616 }
4617 }
4618
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004619 switch (rettv->v_type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004620 {
Bram Moolenaar835dc632016-02-07 14:27:38 +01004621 case VAR_UNKNOWN:
Bram Moolenaara03f2332016-02-06 18:09:59 +01004622 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01004623 case VAR_PARTIAL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01004624 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01004625 case VAR_SPECIAL:
4626 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01004627 case VAR_CHANNEL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01004628 break; /* not evaluating, skipping over subscript */
4629
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004630 case VAR_NUMBER:
4631 case VAR_STRING:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004632 s = get_tv_string(rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004633 len = (long)STRLEN(s);
4634 if (range)
4635 {
4636 /* The resulting variable is a substring. If the indexes
4637 * are out of range the result is empty. */
4638 if (n1 < 0)
4639 {
4640 n1 = len + n1;
4641 if (n1 < 0)
4642 n1 = 0;
4643 }
4644 if (n2 < 0)
4645 n2 = len + n2;
4646 else if (n2 >= len)
4647 n2 = len;
4648 if (n1 >= len || n2 < 0 || n1 > n2)
4649 s = NULL;
4650 else
4651 s = vim_strnsave(s + n1, (int)(n2 - n1 + 1));
4652 }
4653 else
4654 {
4655 /* The resulting variable is a string of a single
4656 * character. If the index is too big or negative the
4657 * result is empty. */
4658 if (n1 >= len || n1 < 0)
4659 s = NULL;
4660 else
4661 s = vim_strnsave(s + n1, 1);
4662 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004663 clear_tv(rettv);
4664 rettv->v_type = VAR_STRING;
4665 rettv->vval.v_string = s;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004666 break;
4667
4668 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004669 len = list_len(rettv->vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004670 if (n1 < 0)
4671 n1 = len + n1;
4672 if (!empty1 && (n1 < 0 || n1 >= len))
4673 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00004674 /* For a range we allow invalid values and return an empty
4675 * list. A list index out of range is an error. */
4676 if (!range)
4677 {
4678 if (verbose)
4679 EMSGN(_(e_listidx), n1);
4680 return FAIL;
4681 }
4682 n1 = len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004683 }
4684 if (range)
4685 {
Bram Moolenaar33570922005-01-25 22:26:29 +00004686 list_T *l;
4687 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004688
4689 if (n2 < 0)
4690 n2 = len + n2;
Bram Moolenaar9e54a0e2006-04-14 20:42:25 +00004691 else if (n2 >= len)
4692 n2 = len - 1;
4693 if (!empty2 && (n2 < 0 || n2 + 1 < n1))
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00004694 n2 = -1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004695 l = list_alloc();
4696 if (l == NULL)
4697 return FAIL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004698 for (item = list_find(rettv->vval.v_list, n1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004699 n1 <= n2; ++n1)
4700 {
4701 if (list_append_tv(l, &item->li_tv) == FAIL)
4702 {
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02004703 list_free(l);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004704 return FAIL;
4705 }
4706 item = item->li_next;
4707 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004708 clear_tv(rettv);
4709 rettv->v_type = VAR_LIST;
4710 rettv->vval.v_list = l;
Bram Moolenaar0d660222005-01-07 21:51:51 +00004711 ++l->lv_refcount;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004712 }
4713 else
4714 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00004715 copy_tv(&list_find(rettv->vval.v_list, n1)->li_tv, &var1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004716 clear_tv(rettv);
4717 *rettv = var1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004718 }
4719 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004720
4721 case VAR_DICT:
4722 if (range)
4723 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004724 if (verbose)
4725 EMSG(_(e_dictrange));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004726 if (len == -1)
4727 clear_tv(&var1);
4728 return FAIL;
4729 }
4730 {
Bram Moolenaar33570922005-01-25 22:26:29 +00004731 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004732
4733 if (len == -1)
4734 {
Bram Moolenaar0921ecf2016-04-03 22:44:36 +02004735 key = get_tv_string_chk(&var1);
4736 if (key == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00004737 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004738 clear_tv(&var1);
4739 return FAIL;
4740 }
4741 }
4742
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00004743 item = dict_find(rettv->vval.v_dict, key, (int)len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004744
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004745 if (item == NULL && verbose)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004746 EMSG2(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004747 if (len == -1)
4748 clear_tv(&var1);
4749 if (item == NULL)
4750 return FAIL;
4751
4752 copy_tv(&item->di_tv, &var1);
4753 clear_tv(rettv);
4754 *rettv = var1;
4755 }
4756 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004757 }
4758 }
4759
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004760 return OK;
4761}
4762
4763/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00004764 * Get an option value.
4765 * "arg" points to the '&' or '+' before the option name.
4766 * "arg" is advanced to character after the option name.
4767 * Return OK or FAIL.
4768 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02004769 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004770get_option_tv(
4771 char_u **arg,
4772 typval_T *rettv, /* when NULL, only check if option exists */
4773 int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004774{
4775 char_u *option_end;
4776 long numval;
4777 char_u *stringval;
4778 int opt_type;
4779 int c;
4780 int working = (**arg == '+'); /* has("+option") */
4781 int ret = OK;
4782 int opt_flags;
4783
4784 /*
4785 * Isolate the option name and find its value.
4786 */
4787 option_end = find_option_end(arg, &opt_flags);
4788 if (option_end == NULL)
4789 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004790 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004791 EMSG2(_("E112: Option name missing: %s"), *arg);
4792 return FAIL;
4793 }
4794
4795 if (!evaluate)
4796 {
4797 *arg = option_end;
4798 return OK;
4799 }
4800
4801 c = *option_end;
4802 *option_end = NUL;
4803 opt_type = get_option_value(*arg, &numval,
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004804 rettv == NULL ? NULL : &stringval, opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004805
4806 if (opt_type == -3) /* invalid name */
4807 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004808 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004809 EMSG2(_("E113: Unknown option: %s"), *arg);
4810 ret = FAIL;
4811 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004812 else if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004813 {
4814 if (opt_type == -2) /* hidden string option */
4815 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004816 rettv->v_type = VAR_STRING;
4817 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004818 }
4819 else if (opt_type == -1) /* hidden number option */
4820 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004821 rettv->v_type = VAR_NUMBER;
4822 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004823 }
4824 else if (opt_type == 1) /* number option */
4825 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004826 rettv->v_type = VAR_NUMBER;
4827 rettv->vval.v_number = numval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004828 }
4829 else /* string option */
4830 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004831 rettv->v_type = VAR_STRING;
4832 rettv->vval.v_string = stringval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004833 }
4834 }
4835 else if (working && (opt_type == -2 || opt_type == -1))
4836 ret = FAIL;
4837
4838 *option_end = c; /* put back for error messages */
4839 *arg = option_end;
4840
4841 return ret;
4842}
4843
4844/*
4845 * Allocate a variable for a string constant.
4846 * Return OK or FAIL.
4847 */
4848 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004849get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004850{
4851 char_u *p;
4852 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004853 int extra = 0;
4854
4855 /*
4856 * Find the end of the string, skipping backslashed characters.
4857 */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004858 for (p = *arg + 1; *p != NUL && *p != '"'; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004859 {
4860 if (*p == '\\' && p[1] != NUL)
4861 {
4862 ++p;
4863 /* A "\<x>" form occupies at least 4 characters, and produces up
4864 * to 6 characters: reserve space for 2 extra */
4865 if (*p == '<')
4866 extra += 2;
4867 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004868 }
4869
4870 if (*p != '"')
4871 {
4872 EMSG2(_("E114: Missing quote: %s"), *arg);
4873 return FAIL;
4874 }
4875
4876 /* If only parsing, set *arg and return here */
4877 if (!evaluate)
4878 {
4879 *arg = p + 1;
4880 return OK;
4881 }
4882
4883 /*
4884 * Copy the string into allocated memory, handling backslashed
4885 * characters.
4886 */
4887 name = alloc((unsigned)(p - *arg + extra));
4888 if (name == NULL)
4889 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004890 rettv->v_type = VAR_STRING;
4891 rettv->vval.v_string = name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004892
Bram Moolenaar8c711452005-01-14 21:53:12 +00004893 for (p = *arg + 1; *p != NUL && *p != '"'; )
Bram Moolenaar071d4272004-06-13 20:20:40 +00004894 {
4895 if (*p == '\\')
4896 {
4897 switch (*++p)
4898 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004899 case 'b': *name++ = BS; ++p; break;
4900 case 'e': *name++ = ESC; ++p; break;
4901 case 'f': *name++ = FF; ++p; break;
4902 case 'n': *name++ = NL; ++p; break;
4903 case 'r': *name++ = CAR; ++p; break;
4904 case 't': *name++ = TAB; ++p; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004905
4906 case 'X': /* hex: "\x1", "\x12" */
4907 case 'x':
4908 case 'u': /* Unicode: "\u0023" */
4909 case 'U':
4910 if (vim_isxdigit(p[1]))
4911 {
4912 int n, nr;
4913 int c = toupper(*p);
4914
4915 if (c == 'X')
4916 n = 2;
Bram Moolenaaracc39882015-06-19 12:08:13 +02004917 else if (*p == 'u')
Bram Moolenaar071d4272004-06-13 20:20:40 +00004918 n = 4;
Bram Moolenaaracc39882015-06-19 12:08:13 +02004919 else
4920 n = 8;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004921 nr = 0;
4922 while (--n >= 0 && vim_isxdigit(p[1]))
4923 {
4924 ++p;
4925 nr = (nr << 4) + hex2nr(*p);
4926 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004927 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004928#ifdef FEAT_MBYTE
4929 /* For "\u" store the number according to
4930 * 'encoding'. */
4931 if (c != 'X')
Bram Moolenaar8c711452005-01-14 21:53:12 +00004932 name += (*mb_char2bytes)(nr, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004933 else
4934#endif
Bram Moolenaar8c711452005-01-14 21:53:12 +00004935 *name++ = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004936 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004937 break;
4938
4939 /* octal: "\1", "\12", "\123" */
4940 case '0':
4941 case '1':
4942 case '2':
4943 case '3':
4944 case '4':
4945 case '5':
4946 case '6':
Bram Moolenaar8c711452005-01-14 21:53:12 +00004947 case '7': *name = *p++ - '0';
4948 if (*p >= '0' && *p <= '7')
Bram Moolenaar071d4272004-06-13 20:20:40 +00004949 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004950 *name = (*name << 3) + *p++ - '0';
4951 if (*p >= '0' && *p <= '7')
4952 *name = (*name << 3) + *p++ - '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +00004953 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004954 ++name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004955 break;
4956
4957 /* Special key, e.g.: "\<C-W>" */
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +02004958 case '<': extra = trans_special(&p, name, TRUE, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004959 if (extra != 0)
4960 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004961 name += extra;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004962 break;
4963 }
4964 /* FALLTHROUGH */
4965
Bram Moolenaar8c711452005-01-14 21:53:12 +00004966 default: MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004967 break;
4968 }
4969 }
4970 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00004971 MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004972
Bram Moolenaar071d4272004-06-13 20:20:40 +00004973 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004974 *name = NUL;
Bram Moolenaardb249f22016-08-26 16:29:47 +02004975 if (*p != NUL) /* just in case */
4976 ++p;
4977 *arg = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004978
Bram Moolenaar071d4272004-06-13 20:20:40 +00004979 return OK;
4980}
4981
4982/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004983 * Allocate a variable for a 'str''ing' constant.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004984 * Return OK or FAIL.
4985 */
4986 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004987get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004988{
4989 char_u *p;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004990 char_u *str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004991 int reduce = 0;
4992
4993 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004994 * Find the end of the string, skipping ''.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004995 */
4996 for (p = *arg + 1; *p != NUL; mb_ptr_adv(p))
4997 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004998 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004999 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005000 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005001 break;
5002 ++reduce;
5003 ++p;
5004 }
5005 }
5006
Bram Moolenaar8c711452005-01-14 21:53:12 +00005007 if (*p != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005008 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005009 EMSG2(_("E115: Missing quote: %s"), *arg);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005010 return FAIL;
5011 }
5012
Bram Moolenaar8c711452005-01-14 21:53:12 +00005013 /* If only parsing return after setting "*arg" */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005014 if (!evaluate)
5015 {
5016 *arg = p + 1;
5017 return OK;
5018 }
5019
5020 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005021 * Copy the string into allocated memory, handling '' to ' reduction.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005022 */
5023 str = alloc((unsigned)((p - *arg) - reduce));
5024 if (str == NULL)
5025 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005026 rettv->v_type = VAR_STRING;
5027 rettv->vval.v_string = str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005028
Bram Moolenaar8c711452005-01-14 21:53:12 +00005029 for (p = *arg + 1; *p != NUL; )
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005030 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005031 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005032 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005033 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005034 break;
5035 ++p;
5036 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005037 MB_COPY_CHAR(p, str);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005038 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005039 *str = NUL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005040 *arg = p + 1;
5041
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005042 return OK;
5043}
5044
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005045/*
5046 * Return the function name of the partial.
5047 */
5048 char_u *
5049partial_name(partial_T *pt)
5050{
5051 if (pt->pt_name != NULL)
5052 return pt->pt_name;
5053 return pt->pt_func->uf_name;
5054}
5055
Bram Moolenaarddecc252016-04-06 22:59:37 +02005056 static void
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005057partial_free(partial_T *pt)
Bram Moolenaarddecc252016-04-06 22:59:37 +02005058{
5059 int i;
5060
5061 for (i = 0; i < pt->pt_argc; ++i)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005062 clear_tv(&pt->pt_argv[i]);
Bram Moolenaarddecc252016-04-06 22:59:37 +02005063 vim_free(pt->pt_argv);
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005064 dict_unref(pt->pt_dict);
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005065 if (pt->pt_name != NULL)
5066 {
5067 func_unref(pt->pt_name);
5068 vim_free(pt->pt_name);
5069 }
5070 else
5071 func_ptr_unref(pt->pt_func);
Bram Moolenaarddecc252016-04-06 22:59:37 +02005072 vim_free(pt);
5073}
5074
5075/*
5076 * Unreference a closure: decrement the reference count and free it when it
5077 * becomes zero.
5078 */
5079 void
5080partial_unref(partial_T *pt)
5081{
5082 if (pt != NULL && --pt->pt_refcount <= 0)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005083 partial_free(pt);
Bram Moolenaarddecc252016-04-06 22:59:37 +02005084}
5085
Bram Moolenaar67b3f992010-11-10 20:41:57 +01005086static int tv_equal_recurse_limit;
5087
Bram Moolenaar8e759ba2016-06-02 17:46:20 +02005088 static int
5089func_equal(
5090 typval_T *tv1,
5091 typval_T *tv2,
5092 int ic) /* ignore case */
5093{
5094 char_u *s1, *s2;
5095 dict_T *d1, *d2;
5096 int a1, a2;
5097 int i;
5098
5099 /* empty and NULL function name considered the same */
5100 s1 = tv1->v_type == VAR_FUNC ? tv1->vval.v_string
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005101 : partial_name(tv1->vval.v_partial);
Bram Moolenaar8e759ba2016-06-02 17:46:20 +02005102 if (s1 != NULL && *s1 == NUL)
5103 s1 = NULL;
5104 s2 = tv2->v_type == VAR_FUNC ? tv2->vval.v_string
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005105 : partial_name(tv2->vval.v_partial);
Bram Moolenaar8e759ba2016-06-02 17:46:20 +02005106 if (s2 != NULL && *s2 == NUL)
5107 s2 = NULL;
5108 if (s1 == NULL || s2 == NULL)
5109 {
5110 if (s1 != s2)
5111 return FALSE;
5112 }
5113 else if (STRCMP(s1, s2) != 0)
5114 return FALSE;
5115
5116 /* empty dict and NULL dict is different */
5117 d1 = tv1->v_type == VAR_FUNC ? NULL : tv1->vval.v_partial->pt_dict;
5118 d2 = tv2->v_type == VAR_FUNC ? NULL : tv2->vval.v_partial->pt_dict;
5119 if (d1 == NULL || d2 == NULL)
5120 {
5121 if (d1 != d2)
5122 return FALSE;
5123 }
5124 else if (!dict_equal(d1, d2, ic, TRUE))
5125 return FALSE;
5126
5127 /* empty list and no list considered the same */
5128 a1 = tv1->v_type == VAR_FUNC ? 0 : tv1->vval.v_partial->pt_argc;
5129 a2 = tv2->v_type == VAR_FUNC ? 0 : tv2->vval.v_partial->pt_argc;
5130 if (a1 != a2)
5131 return FALSE;
5132 for (i = 0; i < a1; ++i)
5133 if (!tv_equal(tv1->vval.v_partial->pt_argv + i,
5134 tv2->vval.v_partial->pt_argv + i, ic, TRUE))
5135 return FALSE;
5136
5137 return TRUE;
5138}
5139
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005140/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005141 * Return TRUE if "tv1" and "tv2" have the same value.
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005142 * Compares the items just like "==" would compare them, but strings and
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005143 * numbers are different. Floats and numbers are also different.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005144 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02005145 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005146tv_equal(
5147 typval_T *tv1,
5148 typval_T *tv2,
5149 int ic, /* ignore case */
5150 int recursive) /* TRUE when used recursively */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005151{
5152 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005153 char_u *s1, *s2;
Bram Moolenaar67b3f992010-11-10 20:41:57 +01005154 static int recursive_cnt = 0; /* catch recursive loops */
Bram Moolenaarb47a2402006-10-15 13:09:12 +00005155 int r;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005156
Bram Moolenaar8b402a02006-10-17 13:16:39 +00005157 /* Catch lists and dicts that have an endless loop by limiting
Bram Moolenaar67b3f992010-11-10 20:41:57 +01005158 * recursiveness to a limit. We guess they are equal then.
5159 * A fixed limit has the problem of still taking an awful long time.
5160 * Reduce the limit every time running into it. That should work fine for
5161 * deeply linked structures that are not recursively linked and catch
5162 * recursiveness quickly. */
5163 if (!recursive)
5164 tv_equal_recurse_limit = 1000;
5165 if (recursive_cnt >= tv_equal_recurse_limit)
5166 {
5167 --tv_equal_recurse_limit;
Bram Moolenaar8b402a02006-10-17 13:16:39 +00005168 return TRUE;
Bram Moolenaar67b3f992010-11-10 20:41:57 +01005169 }
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005170
Bram Moolenaarb33c7eb2016-07-04 22:29:49 +02005171 /* For VAR_FUNC and VAR_PARTIAL compare the function name, bound dict and
5172 * arguments. */
Bram Moolenaar8e759ba2016-06-02 17:46:20 +02005173 if ((tv1->v_type == VAR_FUNC
5174 || (tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial != NULL))
5175 && (tv2->v_type == VAR_FUNC
5176 || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial != NULL)))
5177 {
5178 ++recursive_cnt;
5179 r = func_equal(tv1, tv2, ic);
5180 --recursive_cnt;
5181 return r;
5182 }
5183
5184 if (tv1->v_type != tv2->v_type)
5185 return FALSE;
5186
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005187 switch (tv1->v_type)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005188 {
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005189 case VAR_LIST:
Bram Moolenaar67b3f992010-11-10 20:41:57 +01005190 ++recursive_cnt;
5191 r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic, TRUE);
5192 --recursive_cnt;
Bram Moolenaarb47a2402006-10-15 13:09:12 +00005193 return r;
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005194
5195 case VAR_DICT:
Bram Moolenaar67b3f992010-11-10 20:41:57 +01005196 ++recursive_cnt;
5197 r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, TRUE);
5198 --recursive_cnt;
Bram Moolenaarb47a2402006-10-15 13:09:12 +00005199 return r;
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005200
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005201 case VAR_NUMBER:
5202 return tv1->vval.v_number == tv2->vval.v_number;
5203
5204 case VAR_STRING:
5205 s1 = get_tv_string_buf(tv1, buf1);
5206 s2 = get_tv_string_buf(tv2, buf2);
5207 return ((ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2)) == 0);
Bram Moolenaar520e1e42016-01-23 19:46:28 +01005208
5209 case VAR_SPECIAL:
5210 return tv1->vval.v_number == tv2->vval.v_number;
Bram Moolenaar835dc632016-02-07 14:27:38 +01005211
5212 case VAR_FLOAT:
5213#ifdef FEAT_FLOAT
5214 return tv1->vval.v_float == tv2->vval.v_float;
5215#endif
5216 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01005217#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +01005218 return tv1->vval.v_job == tv2->vval.v_job;
5219#endif
Bram Moolenaar77073442016-02-13 23:23:53 +01005220 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01005221#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +01005222 return tv1->vval.v_channel == tv2->vval.v_channel;
5223#endif
Bram Moolenaarf0e86a02016-03-19 19:38:12 +01005224 case VAR_FUNC:
5225 case VAR_PARTIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01005226 case VAR_UNKNOWN:
5227 break;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005228 }
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005229
Bram Moolenaara03f2332016-02-06 18:09:59 +01005230 /* VAR_UNKNOWN can be the result of a invalid expression, let's say it
5231 * does not equal anything, not even itself. */
5232 return FALSE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005233}
5234
5235/*
Bram Moolenaar520e1e42016-01-23 19:46:28 +01005236 * Return the next (unique) copy ID.
5237 * Used for serializing nested structures.
5238 */
5239 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005240get_copyID(void)
Bram Moolenaar520e1e42016-01-23 19:46:28 +01005241{
5242 current_copyID += COPYID_INC;
5243 return current_copyID;
5244}
5245
5246/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005247 * Garbage collection for lists and dictionaries.
5248 *
5249 * We use reference counts to be able to free most items right away when they
5250 * are no longer used. But for composite items it's possible that it becomes
5251 * unused while the reference count is > 0: When there is a recursive
5252 * reference. Example:
5253 * :let l = [1, 2, 3]
5254 * :let d = {9: l}
5255 * :let l[1] = d
5256 *
5257 * Since this is quite unusual we handle this with garbage collection: every
5258 * once in a while find out which lists and dicts are not referenced from any
5259 * variable.
5260 *
5261 * Here is a good reference text about garbage collection (refers to Python
5262 * but it applies to all reference-counting mechanisms):
5263 * http://python.ca/nas/python/gc/
Bram Moolenaard9fba312005-06-26 22:34:35 +00005264 */
Bram Moolenaard9fba312005-06-26 22:34:35 +00005265
5266/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005267 * Do garbage collection for lists and dicts.
Bram Moolenaar574860b2016-05-24 17:33:34 +02005268 * When "testing" is TRUE this is called from test_garbagecollect_now().
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005269 * Return TRUE if some memory was freed.
Bram Moolenaard9fba312005-06-26 22:34:35 +00005270 */
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005271 int
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +02005272garbage_collect(int testing)
Bram Moolenaard9fba312005-06-26 22:34:35 +00005273{
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005274 int copyID;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005275 int abort = FALSE;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005276 buf_T *buf;
5277 win_T *wp;
5278 int i;
Bram Moolenaar934b1362015-02-04 23:06:45 +01005279 int did_free = FALSE;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00005280#ifdef FEAT_WINDOWS
5281 tabpage_T *tp;
5282#endif
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005283
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +02005284 if (!testing)
5285 {
5286 /* Only do this once. */
5287 want_garbage_collect = FALSE;
5288 may_garbage_collect = FALSE;
5289 garbage_collect_at_exit = FALSE;
5290 }
Bram Moolenaar9fecb462006-09-05 10:59:47 +00005291
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005292 /* We advance by two because we add one for items referenced through
5293 * previous_funccal. */
Bram Moolenaar520e1e42016-01-23 19:46:28 +01005294 copyID = get_copyID();
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005295
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005296 /*
5297 * 1. Go through all accessible variables and mark all lists and dicts
5298 * with copyID.
5299 */
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005300
5301 /* Don't free variables in the previous_funccal list unless they are only
5302 * referenced through previous_funccal. This must be first, because if
Bram Moolenaar2c2398c2009-06-03 11:22:45 +00005303 * the item is referenced elsewhere the funccal must not be freed. */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02005304 abort = abort || set_ref_in_previous_funccal(copyID);
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005305
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005306 /* script-local variables */
5307 for (i = 1; i <= ga_scripts.ga_len; ++i)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005308 abort = abort || set_ref_in_ht(&SCRIPT_VARS(i), copyID, NULL);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005309
5310 /* buffer-local variables */
Bram Moolenaar29323592016-07-24 22:04:11 +02005311 FOR_ALL_BUFFERS(buf)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005312 abort = abort || set_ref_in_item(&buf->b_bufvar.di_tv, copyID,
5313 NULL, NULL);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005314
5315 /* window-local variables */
Bram Moolenaar910f66f2006-04-05 20:41:53 +00005316 FOR_ALL_TAB_WINDOWS(tp, wp)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005317 abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
5318 NULL, NULL);
Bram Moolenaar3bb28552013-04-15 18:25:59 +02005319#ifdef FEAT_AUTOCMD
5320 if (aucmd_win != NULL)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005321 abort = abort || set_ref_in_item(&aucmd_win->w_winvar.di_tv, copyID,
5322 NULL, NULL);
Bram Moolenaar3bb28552013-04-15 18:25:59 +02005323#endif
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005324
Bram Moolenaar910f66f2006-04-05 20:41:53 +00005325#ifdef FEAT_WINDOWS
5326 /* tabpage-local variables */
Bram Moolenaar29323592016-07-24 22:04:11 +02005327 FOR_ALL_TABPAGES(tp)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005328 abort = abort || set_ref_in_item(&tp->tp_winvar.di_tv, copyID,
5329 NULL, NULL);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00005330#endif
5331
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005332 /* global variables */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005333 abort = abort || set_ref_in_ht(&globvarht, copyID, NULL);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005334
5335 /* function-local variables */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02005336 abort = abort || set_ref_in_call_stack(copyID);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005337
Bram Moolenaarbc7ce672016-08-01 22:49:22 +02005338 /* named functions (matters for closures) */
5339 abort = abort || set_ref_in_functions(copyID);
5340
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +02005341 /* function call arguments, if v:testing is set. */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02005342 abort = abort || set_ref_in_func_args(copyID);
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +02005343
Bram Moolenaard812df62008-11-09 12:46:09 +00005344 /* v: vars */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005345 abort = abort || set_ref_in_ht(&vimvarht, copyID, NULL);
Bram Moolenaard812df62008-11-09 12:46:09 +00005346
Bram Moolenaar1dced572012-04-05 16:54:08 +02005347#ifdef FEAT_LUA
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005348 abort = abort || set_ref_in_lua(copyID);
Bram Moolenaar1dced572012-04-05 16:54:08 +02005349#endif
5350
Bram Moolenaardb913952012-06-29 12:54:53 +02005351#ifdef FEAT_PYTHON
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005352 abort = abort || set_ref_in_python(copyID);
Bram Moolenaardb913952012-06-29 12:54:53 +02005353#endif
5354
5355#ifdef FEAT_PYTHON3
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005356 abort = abort || set_ref_in_python3(copyID);
Bram Moolenaardb913952012-06-29 12:54:53 +02005357#endif
5358
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01005359#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar3780bb92016-04-12 22:18:53 +02005360 abort = abort || set_ref_in_channel(copyID);
Bram Moolenaarb8d49052016-05-01 14:22:16 +02005361 abort = abort || set_ref_in_job(copyID);
Bram Moolenaar4b6a6dc2016-02-04 22:49:49 +01005362#endif
Bram Moolenaar3266c852016-04-30 18:07:05 +02005363#ifdef FEAT_NETBEANS_INTG
5364 abort = abort || set_ref_in_nb_channel(copyID);
5365#endif
Bram Moolenaar4b6a6dc2016-02-04 22:49:49 +01005366
Bram Moolenaare3188e22016-05-31 21:13:04 +02005367#ifdef FEAT_TIMERS
5368 abort = abort || set_ref_in_timer(copyID);
5369#endif
5370
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005371 if (!abort)
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005372 {
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005373 /*
5374 * 2. Free lists and dictionaries that are not referenced.
5375 */
5376 did_free = free_unref_items(copyID);
5377
5378 /*
5379 * 3. Check if any funccal can be freed now.
Bram Moolenaara9b579f2016-07-17 18:29:19 +02005380 * This may call us back recursively.
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005381 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02005382 free_unref_funccal(copyID, testing);
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005383 }
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005384 else if (p_verbose > 0)
5385 {
5386 verb_msg((char_u *)_("Not enough memory to set references, garbage collection aborted!"));
5387 }
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005388
5389 return did_free;
5390}
5391
5392/*
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005393 * Free lists, dictionaries, channels and jobs that are no longer referenced.
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005394 */
5395 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005396free_unref_items(int copyID)
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005397{
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005398 int did_free = FALSE;
5399
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005400 /* Let all "free" functions know that we are here. This means no
5401 * dictionaries, lists, channels or jobs are to be freed, because we will
5402 * do that here. */
5403 in_free_unref_items = TRUE;
5404
5405 /*
5406 * PASS 1: free the contents of the items. We don't free the items
5407 * themselves yet, so that it is possible to decrement refcount counters
5408 */
5409
Bram Moolenaarcd524592016-07-17 14:57:05 +02005410 /* Go through the list of dicts and free items without the copyID. */
5411 did_free |= dict_free_nonref(copyID);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005412
Bram Moolenaarda861d62016-07-17 15:46:27 +02005413 /* Go through the list of lists and free items without the copyID. */
5414 did_free |= list_free_nonref(copyID);
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005415
5416#ifdef FEAT_JOB_CHANNEL
5417 /* Go through the list of jobs and free items without the copyID. This
5418 * must happen before doing channels, because jobs refer to channels, but
5419 * the reference from the channel to the job isn't tracked. */
5420 did_free |= free_unused_jobs_contents(copyID, COPYID_MASK);
5421
5422 /* Go through the list of channels and free items without the copyID. */
5423 did_free |= free_unused_channels_contents(copyID, COPYID_MASK);
5424#endif
5425
5426 /*
5427 * PASS 2: free the items themselves.
5428 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02005429 dict_free_items(copyID);
Bram Moolenaarda861d62016-07-17 15:46:27 +02005430 list_free_items(copyID);
Bram Moolenaar835dc632016-02-07 14:27:38 +01005431
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005432#ifdef FEAT_JOB_CHANNEL
5433 /* Go through the list of jobs and free items without the copyID. This
5434 * must happen before doing channels, because jobs refer to channels, but
5435 * the reference from the channel to the job isn't tracked. */
5436 free_unused_jobs(copyID, COPYID_MASK);
5437
5438 /* Go through the list of channels and free items without the copyID. */
5439 free_unused_channels(copyID, COPYID_MASK);
5440#endif
5441
5442 in_free_unref_items = FALSE;
5443
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005444 return did_free;
5445}
5446
5447/*
5448 * Mark all lists and dicts referenced through hashtab "ht" with "copyID".
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005449 * "list_stack" is used to add lists to be marked. Can be NULL.
5450 *
5451 * Returns TRUE if setting references failed somehow.
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005452 */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005453 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005454set_ref_in_ht(hashtab_T *ht, int copyID, list_stack_T **list_stack)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005455{
5456 int todo;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005457 int abort = FALSE;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005458 hashitem_T *hi;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005459 hashtab_T *cur_ht;
5460 ht_stack_T *ht_stack = NULL;
5461 ht_stack_T *tempitem;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005462
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005463 cur_ht = ht;
5464 for (;;)
5465 {
5466 if (!abort)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005467 {
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005468 /* Mark each item in the hashtab. If the item contains a hashtab
5469 * it is added to ht_stack, if it contains a list it is added to
5470 * list_stack. */
5471 todo = (int)cur_ht->ht_used;
5472 for (hi = cur_ht->ht_array; todo > 0; ++hi)
5473 if (!HASHITEM_EMPTY(hi))
5474 {
5475 --todo;
5476 abort = abort || set_ref_in_item(&HI2DI(hi)->di_tv, copyID,
5477 &ht_stack, list_stack);
5478 }
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005479 }
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005480
5481 if (ht_stack == NULL)
5482 break;
5483
5484 /* take an item from the stack */
5485 cur_ht = ht_stack->ht;
5486 tempitem = ht_stack;
5487 ht_stack = ht_stack->prev;
5488 free(tempitem);
5489 }
5490
5491 return abort;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005492}
5493
5494/*
5495 * Mark all lists and dicts referenced through list "l" with "copyID".
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005496 * "ht_stack" is used to add hashtabs to be marked. Can be NULL.
5497 *
5498 * Returns TRUE if setting references failed somehow.
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005499 */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005500 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005501set_ref_in_list(list_T *l, int copyID, ht_stack_T **ht_stack)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005502{
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005503 listitem_T *li;
5504 int abort = FALSE;
5505 list_T *cur_l;
5506 list_stack_T *list_stack = NULL;
5507 list_stack_T *tempitem;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005508
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005509 cur_l = l;
5510 for (;;)
5511 {
5512 if (!abort)
5513 /* Mark each item in the list. If the item contains a hashtab
5514 * it is added to ht_stack, if it contains a list it is added to
5515 * list_stack. */
5516 for (li = cur_l->lv_first; !abort && li != NULL; li = li->li_next)
5517 abort = abort || set_ref_in_item(&li->li_tv, copyID,
5518 ht_stack, &list_stack);
5519 if (list_stack == NULL)
5520 break;
5521
5522 /* take an item from the stack */
5523 cur_l = list_stack->list;
5524 tempitem = list_stack;
5525 list_stack = list_stack->prev;
5526 free(tempitem);
5527 }
5528
5529 return abort;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005530}
5531
5532/*
5533 * Mark all lists and dicts referenced through typval "tv" with "copyID".
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005534 * "list_stack" is used to add lists to be marked. Can be NULL.
5535 * "ht_stack" is used to add hashtabs to be marked. Can be NULL.
5536 *
5537 * Returns TRUE if setting references failed somehow.
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005538 */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005539 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005540set_ref_in_item(
5541 typval_T *tv,
5542 int copyID,
5543 ht_stack_T **ht_stack,
5544 list_stack_T **list_stack)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005545{
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005546 int abort = FALSE;
Bram Moolenaard9fba312005-06-26 22:34:35 +00005547
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005548 if (tv->v_type == VAR_DICT)
Bram Moolenaard9fba312005-06-26 22:34:35 +00005549 {
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005550 dict_T *dd = tv->vval.v_dict;
5551
Bram Moolenaara03f2332016-02-06 18:09:59 +01005552 if (dd != NULL && dd->dv_copyID != copyID)
5553 {
5554 /* Didn't see this dict yet. */
5555 dd->dv_copyID = copyID;
5556 if (ht_stack == NULL)
Bram Moolenaard9fba312005-06-26 22:34:35 +00005557 {
Bram Moolenaara03f2332016-02-06 18:09:59 +01005558 abort = set_ref_in_ht(&dd->dv_hashtab, copyID, list_stack);
5559 }
5560 else
5561 {
5562 ht_stack_T *newitem = (ht_stack_T*)malloc(sizeof(ht_stack_T));
5563 if (newitem == NULL)
5564 abort = TRUE;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005565 else
5566 {
Bram Moolenaara03f2332016-02-06 18:09:59 +01005567 newitem->ht = &dd->dv_hashtab;
5568 newitem->prev = *ht_stack;
5569 *ht_stack = newitem;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005570 }
Bram Moolenaard9fba312005-06-26 22:34:35 +00005571 }
Bram Moolenaara03f2332016-02-06 18:09:59 +01005572 }
5573 }
5574 else if (tv->v_type == VAR_LIST)
5575 {
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005576 list_T *ll = tv->vval.v_list;
5577
Bram Moolenaara03f2332016-02-06 18:09:59 +01005578 if (ll != NULL && ll->lv_copyID != copyID)
5579 {
5580 /* Didn't see this list yet. */
5581 ll->lv_copyID = copyID;
5582 if (list_stack == NULL)
Bram Moolenaard9fba312005-06-26 22:34:35 +00005583 {
Bram Moolenaara03f2332016-02-06 18:09:59 +01005584 abort = set_ref_in_list(ll, copyID, ht_stack);
5585 }
5586 else
5587 {
5588 list_stack_T *newitem = (list_stack_T*)malloc(
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005589 sizeof(list_stack_T));
Bram Moolenaara03f2332016-02-06 18:09:59 +01005590 if (newitem == NULL)
5591 abort = TRUE;
5592 else
5593 {
5594 newitem->list = ll;
5595 newitem->prev = *list_stack;
5596 *list_stack = newitem;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005597 }
Bram Moolenaard9fba312005-06-26 22:34:35 +00005598 }
Bram Moolenaara03f2332016-02-06 18:09:59 +01005599 }
Bram Moolenaard9fba312005-06-26 22:34:35 +00005600 }
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02005601 else if (tv->v_type == VAR_FUNC)
5602 {
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005603 abort = set_ref_in_func(tv->vval.v_string, NULL, copyID);
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02005604 }
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005605 else if (tv->v_type == VAR_PARTIAL)
5606 {
5607 partial_T *pt = tv->vval.v_partial;
5608 int i;
5609
5610 /* A partial does not have a copyID, because it cannot contain itself.
5611 */
5612 if (pt != NULL)
5613 {
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005614 abort = set_ref_in_func(pt->pt_name, pt->pt_func, copyID);
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02005615
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005616 if (pt->pt_dict != NULL)
5617 {
5618 typval_T dtv;
5619
5620 dtv.v_type = VAR_DICT;
5621 dtv.vval.v_dict = pt->pt_dict;
5622 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5623 }
5624
5625 for (i = 0; i < pt->pt_argc; ++i)
5626 abort = abort || set_ref_in_item(&pt->pt_argv[i], copyID,
5627 ht_stack, list_stack);
5628 }
5629 }
5630#ifdef FEAT_JOB_CHANNEL
5631 else if (tv->v_type == VAR_JOB)
5632 {
5633 job_T *job = tv->vval.v_job;
5634 typval_T dtv;
5635
5636 if (job != NULL && job->jv_copyID != copyID)
5637 {
Bram Moolenaar0239acb2016-04-11 21:02:54 +02005638 job->jv_copyID = copyID;
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005639 if (job->jv_channel != NULL)
5640 {
5641 dtv.v_type = VAR_CHANNEL;
5642 dtv.vval.v_channel = job->jv_channel;
5643 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5644 }
5645 if (job->jv_exit_partial != NULL)
5646 {
5647 dtv.v_type = VAR_PARTIAL;
5648 dtv.vval.v_partial = job->jv_exit_partial;
5649 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5650 }
5651 }
5652 }
5653 else if (tv->v_type == VAR_CHANNEL)
5654 {
5655 channel_T *ch =tv->vval.v_channel;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02005656 ch_part_T part;
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005657 typval_T dtv;
5658 jsonq_T *jq;
5659 cbq_T *cq;
5660
5661 if (ch != NULL && ch->ch_copyID != copyID)
5662 {
Bram Moolenaar0239acb2016-04-11 21:02:54 +02005663 ch->ch_copyID = copyID;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02005664 for (part = PART_SOCK; part < PART_COUNT; ++part)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005665 {
5666 for (jq = ch->ch_part[part].ch_json_head.jq_next; jq != NULL;
5667 jq = jq->jq_next)
5668 set_ref_in_item(jq->jq_value, copyID, ht_stack, list_stack);
5669 for (cq = ch->ch_part[part].ch_cb_head.cq_next; cq != NULL;
5670 cq = cq->cq_next)
5671 if (cq->cq_partial != NULL)
5672 {
5673 dtv.v_type = VAR_PARTIAL;
5674 dtv.vval.v_partial = cq->cq_partial;
5675 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5676 }
5677 if (ch->ch_part[part].ch_partial != NULL)
5678 {
5679 dtv.v_type = VAR_PARTIAL;
5680 dtv.vval.v_partial = ch->ch_part[part].ch_partial;
5681 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5682 }
5683 }
5684 if (ch->ch_partial != NULL)
5685 {
5686 dtv.v_type = VAR_PARTIAL;
5687 dtv.vval.v_partial = ch->ch_partial;
5688 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5689 }
5690 if (ch->ch_close_partial != NULL)
5691 {
5692 dtv.v_type = VAR_PARTIAL;
5693 dtv.vval.v_partial = ch->ch_close_partial;
5694 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5695 }
5696 }
5697 }
5698#endif
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005699 return abort;
Bram Moolenaard9fba312005-06-26 22:34:35 +00005700}
5701
Bram Moolenaar17a13432016-01-24 14:22:10 +01005702 static char *
5703get_var_special_name(int nr)
5704{
5705 switch (nr)
5706 {
Bram Moolenaarf48aa162016-01-24 17:54:24 +01005707 case VVAL_FALSE: return "v:false";
Bram Moolenaar65edff82016-02-21 16:40:11 +01005708 case VVAL_TRUE: return "v:true";
5709 case VVAL_NONE: return "v:none";
5710 case VVAL_NULL: return "v:null";
Bram Moolenaar17a13432016-01-24 14:22:10 +01005711 }
Bram Moolenaar95f09602016-11-10 20:01:45 +01005712 internal_error("get_var_special_name()");
Bram Moolenaar17a13432016-01-24 14:22:10 +01005713 return "42";
5714}
5715
Bram Moolenaar8c711452005-01-14 21:53:12 +00005716/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005717 * Return a string with the string representation of a variable.
5718 * If the memory is allocated "tofree" is set to it, otherwise NULL.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005719 * "numbuf" is used for a number.
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005720 * When "copyID" is not NULL replace recursive lists and dicts with "...".
Bram Moolenaar18dfb442016-05-31 22:31:23 +02005721 * When both "echo_style" and "dict_val" are FALSE, put quotes around stings as
5722 * "string()", otherwise does not put quotes around strings, as ":echo"
5723 * displays values.
5724 * When "restore_copyID" is FALSE, repeated items in dictionaries and lists
5725 * are replaced with "...".
Bram Moolenaar92c5aba2007-08-14 20:29:31 +00005726 * May return NULL.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005727 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02005728 char_u *
Bram Moolenaar18dfb442016-05-31 22:31:23 +02005729echo_string_core(
Bram Moolenaar7454a062016-01-30 15:14:10 +01005730 typval_T *tv,
5731 char_u **tofree,
5732 char_u *numbuf,
Bram Moolenaar18dfb442016-05-31 22:31:23 +02005733 int copyID,
5734 int echo_style,
5735 int restore_copyID,
5736 int dict_val)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005737{
Bram Moolenaare9a41262005-01-15 22:18:47 +00005738 static int recurse = 0;
5739 char_u *r = NULL;
5740
Bram Moolenaar33570922005-01-25 22:26:29 +00005741 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +00005742 {
Bram Moolenaar8502c702014-06-17 12:51:16 +02005743 if (!did_echo_string_emsg)
5744 {
5745 /* Only give this message once for a recursive call to avoid
5746 * flooding the user with errors. And stop iterating over lists
5747 * and dicts. */
5748 did_echo_string_emsg = TRUE;
5749 EMSG(_("E724: variable nested too deep for displaying"));
5750 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005751 *tofree = NULL;
Bram Moolenaar8502c702014-06-17 12:51:16 +02005752 return (char_u *)"{E724}";
Bram Moolenaare9a41262005-01-15 22:18:47 +00005753 }
5754 ++recurse;
5755
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005756 switch (tv->v_type)
5757 {
Bram Moolenaar18dfb442016-05-31 22:31:23 +02005758 case VAR_STRING:
5759 if (echo_style && !dict_val)
5760 {
5761 *tofree = NULL;
5762 r = get_tv_string_buf(tv, numbuf);
5763 }
5764 else
5765 {
5766 *tofree = string_quote(tv->vval.v_string, FALSE);
5767 r = *tofree;
5768 }
5769 break;
5770
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005771 case VAR_FUNC:
Bram Moolenaar18dfb442016-05-31 22:31:23 +02005772 if (echo_style)
5773 {
5774 *tofree = NULL;
5775 r = tv->vval.v_string;
5776 }
5777 else
5778 {
5779 *tofree = string_quote(tv->vval.v_string, TRUE);
5780 r = *tofree;
5781 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005782 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005783
Bram Moolenaar1735bc92016-03-14 23:05:14 +01005784 case VAR_PARTIAL:
Bram Moolenaar24c77a12016-03-24 21:23:06 +01005785 {
5786 partial_T *pt = tv->vval.v_partial;
5787 char_u *fname = string_quote(pt == NULL ? NULL
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005788 : partial_name(pt), FALSE);
Bram Moolenaar24c77a12016-03-24 21:23:06 +01005789 garray_T ga;
5790 int i;
5791 char_u *tf;
5792
5793 ga_init2(&ga, 1, 100);
5794 ga_concat(&ga, (char_u *)"function(");
5795 if (fname != NULL)
5796 {
5797 ga_concat(&ga, fname);
5798 vim_free(fname);
5799 }
5800 if (pt != NULL && pt->pt_argc > 0)
5801 {
5802 ga_concat(&ga, (char_u *)", [");
5803 for (i = 0; i < pt->pt_argc; ++i)
5804 {
5805 if (i > 0)
5806 ga_concat(&ga, (char_u *)", ");
5807 ga_concat(&ga,
5808 tv2string(&pt->pt_argv[i], &tf, numbuf, copyID));
5809 vim_free(tf);
5810 }
5811 ga_concat(&ga, (char_u *)"]");
5812 }
5813 if (pt != NULL && pt->pt_dict != NULL)
5814 {
5815 typval_T dtv;
5816
5817 ga_concat(&ga, (char_u *)", ");
5818 dtv.v_type = VAR_DICT;
5819 dtv.vval.v_dict = pt->pt_dict;
5820 ga_concat(&ga, tv2string(&dtv, &tf, numbuf, copyID));
5821 vim_free(tf);
5822 }
5823 ga_concat(&ga, (char_u *)")");
5824
5825 *tofree = ga.ga_data;
5826 r = *tofree;
5827 break;
5828 }
Bram Moolenaar1735bc92016-03-14 23:05:14 +01005829
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005830 case VAR_LIST:
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005831 if (tv->vval.v_list == NULL)
5832 {
5833 *tofree = NULL;
5834 r = NULL;
5835 }
Bram Moolenaar18dfb442016-05-31 22:31:23 +02005836 else if (copyID != 0 && tv->vval.v_list->lv_copyID == copyID
5837 && tv->vval.v_list->lv_len > 0)
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005838 {
5839 *tofree = NULL;
5840 r = (char_u *)"[...]";
5841 }
5842 else
5843 {
Bram Moolenaar18dfb442016-05-31 22:31:23 +02005844 int old_copyID = tv->vval.v_list->lv_copyID;
5845
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005846 tv->vval.v_list->lv_copyID = copyID;
Bram Moolenaar18dfb442016-05-31 22:31:23 +02005847 *tofree = list2string(tv, copyID, restore_copyID);
5848 if (restore_copyID)
5849 tv->vval.v_list->lv_copyID = old_copyID;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005850 r = *tofree;
5851 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005852 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005853
Bram Moolenaar8c711452005-01-14 21:53:12 +00005854 case VAR_DICT:
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005855 if (tv->vval.v_dict == NULL)
5856 {
5857 *tofree = NULL;
5858 r = NULL;
5859 }
Bram Moolenaar18dfb442016-05-31 22:31:23 +02005860 else if (copyID != 0 && tv->vval.v_dict->dv_copyID == copyID
5861 && tv->vval.v_dict->dv_hashtab.ht_used != 0)
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005862 {
5863 *tofree = NULL;
5864 r = (char_u *)"{...}";
5865 }
5866 else
5867 {
Bram Moolenaar18dfb442016-05-31 22:31:23 +02005868 int old_copyID = tv->vval.v_dict->dv_copyID;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005869 tv->vval.v_dict->dv_copyID = copyID;
Bram Moolenaar18dfb442016-05-31 22:31:23 +02005870 *tofree = dict2string(tv, copyID, restore_copyID);
5871 if (restore_copyID)
5872 tv->vval.v_dict->dv_copyID = old_copyID;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005873 r = *tofree;
5874 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005875 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005876
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005877 case VAR_NUMBER:
Bram Moolenaara03f2332016-02-06 18:09:59 +01005878 case VAR_UNKNOWN:
Bram Moolenaar835dc632016-02-07 14:27:38 +01005879 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01005880 case VAR_CHANNEL:
Bram Moolenaare9a41262005-01-15 22:18:47 +00005881 *tofree = NULL;
5882 r = get_tv_string_buf(tv, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005883 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005884
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005885 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01005886#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005887 *tofree = NULL;
5888 vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv->vval.v_float);
5889 r = numbuf;
5890 break;
5891#endif
5892
Bram Moolenaar520e1e42016-01-23 19:46:28 +01005893 case VAR_SPECIAL:
5894 *tofree = NULL;
Bram Moolenaar17a13432016-01-24 14:22:10 +01005895 r = (char_u *)get_var_special_name(tv->vval.v_number);
Bram Moolenaar520e1e42016-01-23 19:46:28 +01005896 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005897 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005898
Bram Moolenaar8502c702014-06-17 12:51:16 +02005899 if (--recurse == 0)
5900 did_echo_string_emsg = FALSE;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005901 return r;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005902}
5903
5904/*
5905 * Return a string with the string representation of a variable.
5906 * If the memory is allocated "tofree" is set to it, otherwise NULL.
5907 * "numbuf" is used for a number.
Bram Moolenaar18dfb442016-05-31 22:31:23 +02005908 * Does not put quotes around strings, as ":echo" displays values.
5909 * When "copyID" is not NULL replace recursive lists and dicts with "...".
5910 * May return NULL.
5911 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02005912 char_u *
Bram Moolenaar18dfb442016-05-31 22:31:23 +02005913echo_string(
5914 typval_T *tv,
5915 char_u **tofree,
5916 char_u *numbuf,
5917 int copyID)
5918{
5919 return echo_string_core(tv, tofree, numbuf, copyID, TRUE, FALSE, FALSE);
5920}
5921
5922/*
5923 * Return a string with the string representation of a variable.
5924 * If the memory is allocated "tofree" is set to it, otherwise NULL.
5925 * "numbuf" is used for a number.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005926 * Puts quotes around strings, so that they can be parsed back by eval().
Bram Moolenaar92c5aba2007-08-14 20:29:31 +00005927 * May return NULL.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005928 */
Bram Moolenaar8110a092016-04-14 15:56:09 +02005929 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01005930tv2string(
5931 typval_T *tv,
5932 char_u **tofree,
5933 char_u *numbuf,
5934 int copyID)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005935{
Bram Moolenaar18dfb442016-05-31 22:31:23 +02005936 return echo_string_core(tv, tofree, numbuf, copyID, FALSE, TRUE, FALSE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005937}
5938
5939/*
Bram Moolenaar33570922005-01-25 22:26:29 +00005940 * Return string "str" in ' quotes, doubling ' characters.
5941 * If "str" is NULL an empty string is assumed.
Bram Moolenaar8c711452005-01-14 21:53:12 +00005942 * If "function" is TRUE make it function('string').
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005943 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02005944 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01005945string_quote(char_u *str, int function)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005946{
Bram Moolenaar33570922005-01-25 22:26:29 +00005947 unsigned len;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005948 char_u *p, *r, *s;
5949
Bram Moolenaar33570922005-01-25 22:26:29 +00005950 len = (function ? 13 : 3);
5951 if (str != NULL)
5952 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005953 len += (unsigned)STRLEN(str);
Bram Moolenaar33570922005-01-25 22:26:29 +00005954 for (p = str; *p != NUL; mb_ptr_adv(p))
5955 if (*p == '\'')
5956 ++len;
5957 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005958 s = r = alloc(len);
5959 if (r != NULL)
5960 {
5961 if (function)
5962 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005963 STRCPY(r, "function('");
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005964 r += 10;
5965 }
5966 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00005967 *r++ = '\'';
Bram Moolenaar33570922005-01-25 22:26:29 +00005968 if (str != NULL)
5969 for (p = str; *p != NUL; )
5970 {
5971 if (*p == '\'')
5972 *r++ = '\'';
5973 MB_COPY_CHAR(p, r);
5974 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005975 *r++ = '\'';
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005976 if (function)
5977 *r++ = ')';
5978 *r++ = NUL;
5979 }
5980 return s;
5981}
5982
Bram Moolenaar520e1e42016-01-23 19:46:28 +01005983#if defined(FEAT_FLOAT) || defined(PROTO)
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005984/*
5985 * Convert the string "text" to a floating point number.
5986 * This uses strtod(). setlocale(LC_NUMERIC, "C") has been used to make sure
5987 * this always uses a decimal point.
5988 * Returns the length of the text that was consumed.
5989 */
Bram Moolenaar520e1e42016-01-23 19:46:28 +01005990 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005991string2float(
5992 char_u *text,
5993 float_T *value) /* result stored here */
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005994{
5995 char *s = (char *)text;
5996 float_T f;
5997
Bram Moolenaar62473612017-01-08 19:25:40 +01005998 /* MS-Windows does not deal with "inf" and "nan" properly. */
5999 if (STRNICMP(text, "inf", 3) == 0)
6000 {
6001 *value = INFINITY;
6002 return 3;
6003 }
6004 if (STRNICMP(text, "-inf", 3) == 0)
6005 {
6006 *value = -INFINITY;
6007 return 4;
6008 }
6009 if (STRNICMP(text, "nan", 3) == 0)
6010 {
6011 *value = NAN;
6012 return 3;
6013 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00006014 f = strtod(s, &s);
6015 *value = f;
6016 return (int)((char_u *)s - text);
6017}
6018#endif
6019
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006020/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006021 * Get the value of an environment variable.
6022 * "arg" is pointing to the '$'. It is advanced to after the name.
6023 * If the environment variable was not set, silently assume it is empty.
Bram Moolenaare512c8c2014-04-29 17:41:22 +02006024 * Return FAIL if the name is invalid.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006025 */
6026 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006027get_env_tv(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006028{
6029 char_u *string = NULL;
6030 int len;
6031 int cc;
6032 char_u *name;
Bram Moolenaar05159a02005-02-26 23:04:13 +00006033 int mustfree = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006034
6035 ++*arg;
6036 name = *arg;
6037 len = get_env_len(arg);
6038 if (evaluate)
6039 {
Bram Moolenaare512c8c2014-04-29 17:41:22 +02006040 if (len == 0)
Bram Moolenaar615b9972015-01-14 17:15:05 +01006041 return FAIL; /* invalid empty name */
Bram Moolenaar05159a02005-02-26 23:04:13 +00006042
Bram Moolenaare512c8c2014-04-29 17:41:22 +02006043 cc = name[len];
6044 name[len] = NUL;
6045 /* first try vim_getenv(), fast for normal environment vars */
6046 string = vim_getenv(name, &mustfree);
6047 if (string != NULL && *string != NUL)
6048 {
6049 if (!mustfree)
6050 string = vim_strsave(string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006051 }
Bram Moolenaare512c8c2014-04-29 17:41:22 +02006052 else
6053 {
6054 if (mustfree)
6055 vim_free(string);
6056
6057 /* next try expanding things like $VIM and ${HOME} */
6058 string = expand_env_save(name - 1);
6059 if (string != NULL && *string == '$')
6060 {
6061 vim_free(string);
6062 string = NULL;
6063 }
6064 }
6065 name[len] = cc;
6066
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006067 rettv->v_type = VAR_STRING;
6068 rettv->vval.v_string = string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006069 }
6070
6071 return OK;
6072}
6073
Bram Moolenaard6e256c2011-12-14 15:32:50 +01006074
6075
6076/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006077 * Translate a String variable into a position.
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006078 * Returns NULL when there is an error.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006079 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006080 pos_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006081var2fpos(
6082 typval_T *varp,
6083 int dollar_lnum, /* TRUE when $ is last line */
6084 int *fnum) /* set to fnum for '0, 'A, etc. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006085{
Bram Moolenaar261bfea2006-03-01 22:12:31 +00006086 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006087 static pos_T pos;
Bram Moolenaar261bfea2006-03-01 22:12:31 +00006088 pos_T *pp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006089
Bram Moolenaara5525202006-03-02 22:52:09 +00006090 /* Argument can be [lnum, col, coladd]. */
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006091 if (varp->v_type == VAR_LIST)
6092 {
6093 list_T *l;
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006094 int len;
Bram Moolenaara5525202006-03-02 22:52:09 +00006095 int error = FALSE;
Bram Moolenaar477933c2007-07-17 14:32:23 +00006096 listitem_T *li;
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006097
6098 l = varp->vval.v_list;
6099 if (l == NULL)
6100 return NULL;
6101
6102 /* Get the line number */
Bram Moolenaara5525202006-03-02 22:52:09 +00006103 pos.lnum = list_find_nr(l, 0L, &error);
6104 if (error || pos.lnum <= 0 || pos.lnum > curbuf->b_ml.ml_line_count)
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006105 return NULL; /* invalid line number */
6106
6107 /* Get the column number */
Bram Moolenaara5525202006-03-02 22:52:09 +00006108 pos.col = list_find_nr(l, 1L, &error);
6109 if (error)
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006110 return NULL;
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006111 len = (long)STRLEN(ml_get(pos.lnum));
Bram Moolenaar477933c2007-07-17 14:32:23 +00006112
6113 /* We accept "$" for the column number: last column. */
6114 li = list_find(l, 1L);
6115 if (li != NULL && li->li_tv.v_type == VAR_STRING
6116 && li->li_tv.vval.v_string != NULL
6117 && STRCMP(li->li_tv.vval.v_string, "$") == 0)
6118 pos.col = len + 1;
6119
Bram Moolenaara5525202006-03-02 22:52:09 +00006120 /* Accept a position up to the NUL after the line. */
Bram Moolenaar4c3f5362006-04-11 21:38:50 +00006121 if (pos.col == 0 || (int)pos.col > len + 1)
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006122 return NULL; /* invalid column number */
Bram Moolenaara5525202006-03-02 22:52:09 +00006123 --pos.col;
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006124
Bram Moolenaara5525202006-03-02 22:52:09 +00006125#ifdef FEAT_VIRTUALEDIT
6126 /* Get the virtual offset. Defaults to zero. */
6127 pos.coladd = list_find_nr(l, 2L, &error);
6128 if (error)
6129 pos.coladd = 0;
6130#endif
6131
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006132 return &pos;
6133 }
6134
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006135 name = get_tv_string_chk(varp);
6136 if (name == NULL)
6137 return NULL;
Bram Moolenaar9ecd0232008-06-20 15:31:51 +00006138 if (name[0] == '.') /* cursor */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006139 return &curwin->w_cursor;
Bram Moolenaar9ecd0232008-06-20 15:31:51 +00006140 if (name[0] == 'v' && name[1] == NUL) /* Visual start */
6141 {
6142 if (VIsual_active)
6143 return &VIsual;
6144 return &curwin->w_cursor;
6145 }
Bram Moolenaar9ecd0232008-06-20 15:31:51 +00006146 if (name[0] == '\'') /* mark */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006147 {
Bram Moolenaar9d182dd2013-01-23 15:53:15 +01006148 pp = getmark_buf_fnum(curbuf, name[1], FALSE, fnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006149 if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
6150 return NULL;
6151 return pp;
6152 }
Bram Moolenaara5525202006-03-02 22:52:09 +00006153
6154#ifdef FEAT_VIRTUALEDIT
6155 pos.coladd = 0;
6156#endif
6157
Bram Moolenaar477933c2007-07-17 14:32:23 +00006158 if (name[0] == 'w' && dollar_lnum)
Bram Moolenaarf52c7252006-02-10 23:23:57 +00006159 {
6160 pos.col = 0;
6161 if (name[1] == '0') /* "w0": first visible line */
6162 {
Bram Moolenaarf740b292006-02-16 22:11:02 +00006163 update_topline();
Bram Moolenaarf52c7252006-02-10 23:23:57 +00006164 pos.lnum = curwin->w_topline;
6165 return &pos;
6166 }
6167 else if (name[1] == '$') /* "w$": last visible line */
6168 {
Bram Moolenaarf740b292006-02-16 22:11:02 +00006169 validate_botline();
Bram Moolenaarf52c7252006-02-10 23:23:57 +00006170 pos.lnum = curwin->w_botline - 1;
6171 return &pos;
6172 }
6173 }
6174 else if (name[0] == '$') /* last column or line */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006175 {
Bram Moolenaar477933c2007-07-17 14:32:23 +00006176 if (dollar_lnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006177 {
6178 pos.lnum = curbuf->b_ml.ml_line_count;
6179 pos.col = 0;
6180 }
6181 else
6182 {
6183 pos.lnum = curwin->w_cursor.lnum;
6184 pos.col = (colnr_T)STRLEN(ml_get_curline());
6185 }
6186 return &pos;
6187 }
6188 return NULL;
6189}
6190
6191/*
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006192 * Convert list in "arg" into a position and optional file number.
6193 * When "fnump" is NULL there is no file number, only 3 items.
6194 * Note that the column is passed on as-is, the caller may want to decrement
6195 * it to use 1 for the first column.
6196 * Return FAIL when conversion is not possible, doesn't check the position for
6197 * validity.
6198 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006199 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006200list2fpos(
6201 typval_T *arg,
6202 pos_T *posp,
6203 int *fnump,
6204 colnr_T *curswantp)
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006205{
6206 list_T *l = arg->vval.v_list;
6207 long i = 0;
6208 long n;
6209
Bram Moolenaar493c1782014-05-28 14:34:46 +02006210 /* List must be: [fnum, lnum, col, coladd, curswant], where "fnum" is only
6211 * there when "fnump" isn't NULL; "coladd" and "curswant" are optional. */
Bram Moolenaarbde35262006-07-23 20:12:24 +00006212 if (arg->v_type != VAR_LIST
6213 || l == NULL
6214 || l->lv_len < (fnump == NULL ? 2 : 3)
Bram Moolenaar493c1782014-05-28 14:34:46 +02006215 || l->lv_len > (fnump == NULL ? 4 : 5))
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006216 return FAIL;
6217
6218 if (fnump != NULL)
6219 {
6220 n = list_find_nr(l, i++, NULL); /* fnum */
6221 if (n < 0)
6222 return FAIL;
6223 if (n == 0)
6224 n = curbuf->b_fnum; /* current buffer */
6225 *fnump = n;
6226 }
6227
6228 n = list_find_nr(l, i++, NULL); /* lnum */
6229 if (n < 0)
6230 return FAIL;
6231 posp->lnum = n;
6232
6233 n = list_find_nr(l, i++, NULL); /* col */
6234 if (n < 0)
6235 return FAIL;
6236 posp->col = n;
6237
6238#ifdef FEAT_VIRTUALEDIT
Bram Moolenaar493c1782014-05-28 14:34:46 +02006239 n = list_find_nr(l, i, NULL); /* off */
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006240 if (n < 0)
Bram Moolenaarbde35262006-07-23 20:12:24 +00006241 posp->coladd = 0;
6242 else
6243 posp->coladd = n;
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006244#endif
6245
Bram Moolenaar493c1782014-05-28 14:34:46 +02006246 if (curswantp != NULL)
6247 *curswantp = list_find_nr(l, i + 1, NULL); /* curswant */
6248
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006249 return OK;
6250}
6251
6252/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006253 * Get the length of an environment variable name.
6254 * Advance "arg" to the first character after the name.
6255 * Return 0 for error.
6256 */
6257 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006258get_env_len(char_u **arg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006259{
6260 char_u *p;
6261 int len;
6262
6263 for (p = *arg; vim_isIDc(*p); ++p)
6264 ;
6265 if (p == *arg) /* no name found */
6266 return 0;
6267
6268 len = (int)(p - *arg);
6269 *arg = p;
6270 return len;
6271}
6272
6273/*
6274 * Get the length of the name of a function or internal variable.
6275 * "arg" is advanced to the first non-white character after the name.
6276 * Return 0 if something is wrong.
6277 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02006278 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006279get_id_len(char_u **arg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006280{
6281 char_u *p;
6282 int len;
6283
6284 /* Find the end of the name. */
6285 for (p = *arg; eval_isnamec(*p); ++p)
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01006286 {
6287 if (*p == ':')
6288 {
6289 /* "s:" is start of "s:var", but "n:" is not and can be used in
6290 * slice "[n:]". Also "xx:" is not a namespace. */
6291 len = (int)(p - *arg);
6292 if ((len == 1 && vim_strchr(NAMESPACE_CHAR, **arg) == NULL)
6293 || len > 1)
6294 break;
6295 }
6296 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006297 if (p == *arg) /* no name found */
6298 return 0;
6299
6300 len = (int)(p - *arg);
6301 *arg = skipwhite(p);
6302
6303 return len;
6304}
6305
6306/*
Bram Moolenaara7043832005-01-21 11:56:39 +00006307 * Get the length of the name of a variable or function.
6308 * Only the name is recognized, does not handle ".key" or "[idx]".
Bram Moolenaar071d4272004-06-13 20:20:40 +00006309 * "arg" is advanced to the first non-white character after the name.
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006310 * Return -1 if curly braces expansion failed.
6311 * Return 0 if something else is wrong.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006312 * If the name contains 'magic' {}'s, expand them and return the
6313 * expanded name in an allocated string via 'alias' - caller must free.
6314 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006315 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006316get_name_len(
6317 char_u **arg,
6318 char_u **alias,
6319 int evaluate,
6320 int verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006321{
6322 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006323 char_u *p;
6324 char_u *expr_start;
6325 char_u *expr_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006326
6327 *alias = NULL; /* default to no alias */
6328
6329 if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
6330 && (*arg)[2] == (int)KE_SNR)
6331 {
6332 /* hard coded <SNR>, already translated */
6333 *arg += 3;
6334 return get_id_len(arg) + 3;
6335 }
6336 len = eval_fname_script(*arg);
6337 if (len > 0)
6338 {
6339 /* literal "<SID>", "s:" or "<SNR>" */
6340 *arg += len;
6341 }
6342
Bram Moolenaar071d4272004-06-13 20:20:40 +00006343 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006344 * Find the end of the name; check for {} construction.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006345 */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00006346 p = find_name_end(*arg, &expr_start, &expr_end,
6347 len > 0 ? 0 : FNE_CHECK_START);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006348 if (expr_start != NULL)
6349 {
6350 char_u *temp_string;
6351
6352 if (!evaluate)
6353 {
6354 len += (int)(p - *arg);
6355 *arg = skipwhite(p);
6356 return len;
6357 }
6358
6359 /*
6360 * Include any <SID> etc in the expanded string:
6361 * Thus the -len here.
6362 */
6363 temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
6364 if (temp_string == NULL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006365 return -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006366 *alias = temp_string;
6367 *arg = skipwhite(p);
6368 return (int)STRLEN(temp_string);
6369 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006370
6371 len += get_id_len(arg);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006372 if (len == 0 && verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006373 EMSG2(_(e_invexpr2), *arg);
6374
6375 return len;
6376}
6377
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006378/*
6379 * Find the end of a variable or function name, taking care of magic braces.
6380 * If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the
6381 * start and end of the first magic braces item.
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00006382 * "flags" can have FNE_INCL_BR and FNE_CHECK_START.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006383 * Return a pointer to just after the name. Equal to "arg" if there is no
6384 * valid name.
6385 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02006386 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006387find_name_end(
6388 char_u *arg,
6389 char_u **expr_start,
6390 char_u **expr_end,
6391 int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006392{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006393 int mb_nest = 0;
6394 int br_nest = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006395 char_u *p;
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01006396 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006397
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006398 if (expr_start != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006399 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006400 *expr_start = NULL;
6401 *expr_end = NULL;
6402 }
6403
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00006404 /* Quick check for valid starting character. */
6405 if ((flags & FNE_CHECK_START) && !eval_isnamec1(*arg) && *arg != '{')
6406 return arg;
6407
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006408 for (p = arg; *p != NUL
6409 && (eval_isnamec(*p)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006410 || *p == '{'
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00006411 || ((flags & FNE_INCL_BR) && (*p == '[' || *p == '.'))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006412 || mb_nest != 0
Bram Moolenaar8af24422005-08-08 22:06:28 +00006413 || br_nest != 0); mb_ptr_adv(p))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006414 {
Bram Moolenaar8af24422005-08-08 22:06:28 +00006415 if (*p == '\'')
6416 {
6417 /* skip over 'string' to avoid counting [ and ] inside it. */
6418 for (p = p + 1; *p != NUL && *p != '\''; mb_ptr_adv(p))
6419 ;
6420 if (*p == NUL)
6421 break;
6422 }
6423 else if (*p == '"')
6424 {
6425 /* skip over "str\"ing" to avoid counting [ and ] inside it. */
6426 for (p = p + 1; *p != NUL && *p != '"'; mb_ptr_adv(p))
6427 if (*p == '\\' && p[1] != NUL)
6428 ++p;
6429 if (*p == NUL)
6430 break;
6431 }
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01006432 else if (br_nest == 0 && mb_nest == 0 && *p == ':')
6433 {
6434 /* "s:" is start of "s:var", but "n:" is not and can be used in
Bram Moolenaar4119cf82016-01-17 14:59:01 +01006435 * slice "[n:]". Also "xx:" is not a namespace. But {ns}: is. */
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01006436 len = (int)(p - arg);
6437 if ((len == 1 && vim_strchr(NAMESPACE_CHAR, *arg) == NULL)
Bram Moolenaar4119cf82016-01-17 14:59:01 +01006438 || (len > 1 && p[-1] != '}'))
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01006439 break;
6440 }
Bram Moolenaar8af24422005-08-08 22:06:28 +00006441
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006442 if (mb_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006443 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006444 if (*p == '[')
6445 ++br_nest;
6446 else if (*p == ']')
6447 --br_nest;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006448 }
Bram Moolenaar8af24422005-08-08 22:06:28 +00006449
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006450 if (br_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006451 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006452 if (*p == '{')
6453 {
6454 mb_nest++;
6455 if (expr_start != NULL && *expr_start == NULL)
6456 *expr_start = p;
6457 }
6458 else if (*p == '}')
6459 {
6460 mb_nest--;
6461 if (expr_start != NULL && mb_nest == 0 && *expr_end == NULL)
6462 *expr_end = p;
6463 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006464 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006465 }
6466
6467 return p;
6468}
6469
6470/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006471 * Expands out the 'magic' {}'s in a variable/function name.
6472 * Note that this can call itself recursively, to deal with
6473 * constructs like foo{bar}{baz}{bam}
6474 * The four pointer arguments point to "foo{expre}ss{ion}bar"
6475 * "in_start" ^
6476 * "expr_start" ^
6477 * "expr_end" ^
6478 * "in_end" ^
6479 *
6480 * Returns a new allocated string, which the caller must free.
6481 * Returns NULL for failure.
6482 */
6483 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006484make_expanded_name(
6485 char_u *in_start,
6486 char_u *expr_start,
6487 char_u *expr_end,
6488 char_u *in_end)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006489{
6490 char_u c1;
6491 char_u *retval = NULL;
6492 char_u *temp_result;
6493 char_u *nextcmd = NULL;
6494
6495 if (expr_end == NULL || in_end == NULL)
6496 return NULL;
6497 *expr_start = NUL;
6498 *expr_end = NUL;
6499 c1 = *in_end;
6500 *in_end = NUL;
6501
Bram Moolenaar362e1a32006-03-06 23:29:24 +00006502 temp_result = eval_to_string(expr_start + 1, &nextcmd, FALSE);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006503 if (temp_result != NULL && nextcmd == NULL)
6504 {
6505 retval = alloc((unsigned)(STRLEN(temp_result) + (expr_start - in_start)
6506 + (in_end - expr_end) + 1));
6507 if (retval != NULL)
6508 {
6509 STRCPY(retval, in_start);
6510 STRCAT(retval, temp_result);
6511 STRCAT(retval, expr_end + 1);
6512 }
6513 }
6514 vim_free(temp_result);
6515
6516 *in_end = c1; /* put char back for error messages */
6517 *expr_start = '{';
6518 *expr_end = '}';
6519
6520 if (retval != NULL)
6521 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00006522 temp_result = find_name_end(retval, &expr_start, &expr_end, 0);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006523 if (expr_start != NULL)
6524 {
6525 /* Further expansion! */
6526 temp_result = make_expanded_name(retval, expr_start,
6527 expr_end, temp_result);
6528 vim_free(retval);
6529 retval = temp_result;
6530 }
6531 }
6532
6533 return retval;
6534}
6535
6536/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006537 * Return TRUE if character "c" can be used in a variable or function name.
Bram Moolenaare9a41262005-01-15 22:18:47 +00006538 * Does not include '{' or '}' for magic braces.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006539 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02006540 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006541eval_isnamec(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006542{
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00006543 return (ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR);
6544}
6545
6546/*
6547 * Return TRUE if character "c" can be used as the first character in a
6548 * variable or function name (excluding '{' and '}').
6549 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02006550 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006551eval_isnamec1(int c)
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00006552{
6553 return (ASCII_ISALPHA(c) || c == '_');
Bram Moolenaar071d4272004-06-13 20:20:40 +00006554}
6555
6556/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006557 * Set number v: variable to "val".
6558 */
6559 void
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02006560set_vim_var_nr(int idx, varnumber_T val)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006561{
Bram Moolenaare9a41262005-01-15 22:18:47 +00006562 vimvars[idx].vv_nr = val;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006563}
6564
6565/*
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006566 * Get number v: variable value.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006567 */
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02006568 varnumber_T
Bram Moolenaar7454a062016-01-30 15:14:10 +01006569get_vim_var_nr(int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006570{
Bram Moolenaare9a41262005-01-15 22:18:47 +00006571 return vimvars[idx].vv_nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006572}
6573
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006574/*
6575 * Get string v: variable value. Uses a static buffer, can only be used once.
6576 */
6577 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006578get_vim_var_str(int idx)
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006579{
6580 return get_tv_string(&vimvars[idx].vv_tv);
6581}
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006582
Bram Moolenaar071d4272004-06-13 20:20:40 +00006583/*
Bram Moolenaard812df62008-11-09 12:46:09 +00006584 * Get List v: variable value. Caller must take care of reference count when
6585 * needed.
6586 */
6587 list_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006588get_vim_var_list(int idx)
Bram Moolenaard812df62008-11-09 12:46:09 +00006589{
6590 return vimvars[idx].vv_list;
6591}
6592
6593/*
Bram Moolenaarda9591e2009-09-30 13:17:02 +00006594 * Set v:char to character "c".
6595 */
6596 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01006597set_vim_var_char(int c)
Bram Moolenaarda9591e2009-09-30 13:17:02 +00006598{
Bram Moolenaar9a920d82012-06-01 15:21:02 +02006599 char_u buf[MB_MAXBYTES + 1];
Bram Moolenaarda9591e2009-09-30 13:17:02 +00006600
6601#ifdef FEAT_MBYTE
6602 if (has_mbyte)
6603 buf[(*mb_char2bytes)(c, buf)] = NUL;
6604 else
6605#endif
6606 {
6607 buf[0] = c;
6608 buf[1] = NUL;
6609 }
6610 set_vim_var_string(VV_CHAR, buf, -1);
6611}
6612
6613/*
Bram Moolenaar8df74be2008-11-20 15:12:02 +00006614 * Set v:count to "count" and v:count1 to "count1".
6615 * When "set_prevcount" is TRUE first set v:prevcount from v:count.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006616 */
6617 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01006618set_vcount(
6619 long count,
6620 long count1,
6621 int set_prevcount)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006622{
Bram Moolenaar8df74be2008-11-20 15:12:02 +00006623 if (set_prevcount)
6624 vimvars[VV_PREVCOUNT].vv_nr = vimvars[VV_COUNT].vv_nr;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006625 vimvars[VV_COUNT].vv_nr = count;
6626 vimvars[VV_COUNT1].vv_nr = count1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006627}
6628
6629/*
6630 * Set string v: variable to a copy of "val".
6631 */
6632 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01006633set_vim_var_string(
6634 int idx,
6635 char_u *val,
6636 int len) /* length of "val" to use or -1 (whole string) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006637{
Bram Moolenaara542c682016-01-31 16:28:04 +01006638 clear_tv(&vimvars[idx].vv_di.di_tv);
6639 vimvars[idx].vv_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006640 if (val == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006641 vimvars[idx].vv_str = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006642 else if (len == -1)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006643 vimvars[idx].vv_str = vim_strsave(val);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006644 else
Bram Moolenaare9a41262005-01-15 22:18:47 +00006645 vimvars[idx].vv_str = vim_strnsave(val, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006646}
6647
6648/*
Bram Moolenaard812df62008-11-09 12:46:09 +00006649 * Set List v: variable to "val".
6650 */
6651 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01006652set_vim_var_list(int idx, list_T *val)
Bram Moolenaard812df62008-11-09 12:46:09 +00006653{
Bram Moolenaara542c682016-01-31 16:28:04 +01006654 clear_tv(&vimvars[idx].vv_di.di_tv);
6655 vimvars[idx].vv_type = VAR_LIST;
Bram Moolenaard812df62008-11-09 12:46:09 +00006656 vimvars[idx].vv_list = val;
6657 if (val != NULL)
6658 ++val->lv_refcount;
6659}
6660
6661/*
Bram Moolenaar42a45122015-07-10 17:56:23 +02006662 * Set Dictionary v: variable to "val".
6663 */
6664 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01006665set_vim_var_dict(int idx, dict_T *val)
Bram Moolenaar42a45122015-07-10 17:56:23 +02006666{
6667 int todo;
6668 hashitem_T *hi;
6669
Bram Moolenaara542c682016-01-31 16:28:04 +01006670 clear_tv(&vimvars[idx].vv_di.di_tv);
6671 vimvars[idx].vv_type = VAR_DICT;
Bram Moolenaar42a45122015-07-10 17:56:23 +02006672 vimvars[idx].vv_dict = val;
6673 if (val != NULL)
6674 {
6675 ++val->dv_refcount;
6676
6677 /* Set readonly */
6678 todo = (int)val->dv_hashtab.ht_used;
6679 for (hi = val->dv_hashtab.ht_array; todo > 0 ; ++hi)
6680 {
6681 if (HASHITEM_EMPTY(hi))
6682 continue;
6683 --todo;
6684 HI2DI(hi)->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
6685 }
6686 }
6687}
6688
6689/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006690 * Set v:register if needed.
6691 */
6692 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01006693set_reg_var(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006694{
6695 char_u regname;
6696
6697 if (c == 0 || c == ' ')
6698 regname = '"';
6699 else
6700 regname = c;
6701 /* Avoid free/alloc when the value is already right. */
Bram Moolenaare9a41262005-01-15 22:18:47 +00006702 if (vimvars[VV_REG].vv_str == NULL || vimvars[VV_REG].vv_str[0] != c)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006703 set_vim_var_string(VV_REG, &regname, 1);
6704}
6705
6706/*
6707 * Get or set v:exception. If "oldval" == NULL, return the current value.
6708 * Otherwise, restore the value to "oldval" and return NULL.
6709 * Must always be called in pairs to save and restore v:exception! Does not
6710 * take care of memory allocations.
6711 */
6712 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006713v_exception(char_u *oldval)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006714{
6715 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006716 return vimvars[VV_EXCEPTION].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006717
Bram Moolenaare9a41262005-01-15 22:18:47 +00006718 vimvars[VV_EXCEPTION].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006719 return NULL;
6720}
6721
6722/*
6723 * Get or set v:throwpoint. If "oldval" == NULL, return the current value.
6724 * Otherwise, restore the value to "oldval" and return NULL.
6725 * Must always be called in pairs to save and restore v:throwpoint! Does not
6726 * take care of memory allocations.
6727 */
6728 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006729v_throwpoint(char_u *oldval)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006730{
6731 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006732 return vimvars[VV_THROWPOINT].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006733
Bram Moolenaare9a41262005-01-15 22:18:47 +00006734 vimvars[VV_THROWPOINT].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006735 return NULL;
6736}
6737
6738#if defined(FEAT_AUTOCMD) || defined(PROTO)
6739/*
6740 * Set v:cmdarg.
6741 * If "eap" != NULL, use "eap" to generate the value and return the old value.
6742 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
6743 * Must always be called in pairs!
6744 */
6745 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006746set_cmdarg(exarg_T *eap, char_u *oldarg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006747{
6748 char_u *oldval;
6749 char_u *newval;
6750 unsigned len;
6751
Bram Moolenaare9a41262005-01-15 22:18:47 +00006752 oldval = vimvars[VV_CMDARG].vv_str;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00006753 if (eap == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006754 {
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00006755 vim_free(oldval);
Bram Moolenaare9a41262005-01-15 22:18:47 +00006756 vimvars[VV_CMDARG].vv_str = oldarg;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00006757 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006758 }
6759
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00006760 if (eap->force_bin == FORCE_BIN)
6761 len = 6;
6762 else if (eap->force_bin == FORCE_NOBIN)
6763 len = 8;
6764 else
6765 len = 0;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00006766
6767 if (eap->read_edit)
6768 len += 7;
6769
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00006770 if (eap->force_ff != 0)
6771 len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6;
6772# ifdef FEAT_MBYTE
6773 if (eap->force_enc != 0)
6774 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
Bram Moolenaar34b4daf2010-05-16 13:26:25 +02006775 if (eap->bad_char != 0)
6776 len += 7 + 4; /* " ++bad=" + "keep" or "drop" */
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00006777# endif
6778
6779 newval = alloc(len + 1);
6780 if (newval == NULL)
6781 return NULL;
6782
6783 if (eap->force_bin == FORCE_BIN)
6784 sprintf((char *)newval, " ++bin");
6785 else if (eap->force_bin == FORCE_NOBIN)
6786 sprintf((char *)newval, " ++nobin");
6787 else
6788 *newval = NUL;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00006789
6790 if (eap->read_edit)
6791 STRCAT(newval, " ++edit");
6792
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00006793 if (eap->force_ff != 0)
6794 sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
6795 eap->cmd + eap->force_ff);
6796# ifdef FEAT_MBYTE
6797 if (eap->force_enc != 0)
6798 sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
6799 eap->cmd + eap->force_enc);
Bram Moolenaar34b4daf2010-05-16 13:26:25 +02006800 if (eap->bad_char == BAD_KEEP)
6801 STRCPY(newval + STRLEN(newval), " ++bad=keep");
6802 else if (eap->bad_char == BAD_DROP)
6803 STRCPY(newval + STRLEN(newval), " ++bad=drop");
6804 else if (eap->bad_char != 0)
6805 sprintf((char *)newval + STRLEN(newval), " ++bad=%c", eap->bad_char);
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00006806# endif
Bram Moolenaare9a41262005-01-15 22:18:47 +00006807 vimvars[VV_CMDARG].vv_str = newval;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00006808 return oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006809}
6810#endif
6811
6812/*
6813 * Get the value of internal variable "name".
6814 * Return OK or FAIL.
6815 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006816 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006817get_var_tv(
6818 char_u *name,
6819 int len, /* length of "name" */
6820 typval_T *rettv, /* NULL when only checking existence */
6821 dictitem_T **dip, /* non-NULL when typval's dict item is needed */
6822 int verbose, /* may give error message */
6823 int no_autoload) /* do not use script autoloading */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006824{
6825 int ret = OK;
Bram Moolenaar33570922005-01-25 22:26:29 +00006826 typval_T *tv = NULL;
6827 typval_T atv;
6828 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006829 int cc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006830
6831 /* truncate the name, so that we can use strcmp() */
6832 cc = name[len];
6833 name[len] = NUL;
6834
6835 /*
6836 * Check for "b:changedtick".
6837 */
6838 if (STRCMP(name, "b:changedtick") == 0)
6839 {
Bram Moolenaare9a41262005-01-15 22:18:47 +00006840 atv.v_type = VAR_NUMBER;
6841 atv.vval.v_number = curbuf->b_changedtick;
6842 tv = &atv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006843 }
6844
6845 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006846 * Check for user-defined variables.
6847 */
6848 else
6849 {
Bram Moolenaar6d977d62014-01-14 15:24:39 +01006850 v = find_var(name, NULL, no_autoload);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006851 if (v != NULL)
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02006852 {
Bram Moolenaar33570922005-01-25 22:26:29 +00006853 tv = &v->di_tv;
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02006854 if (dip != NULL)
6855 *dip = v;
6856 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006857 }
6858
Bram Moolenaare9a41262005-01-15 22:18:47 +00006859 if (tv == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006860 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006861 if (rettv != NULL && verbose)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006862 EMSG2(_(e_undefvar), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006863 ret = FAIL;
6864 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006865 else if (rettv != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006866 copy_tv(tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006867
6868 name[len] = cc;
6869
6870 return ret;
6871}
6872
6873/*
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02006874 * Check if variable "name[len]" is a local variable or an argument.
6875 * If so, "*eval_lavars_used" is set to TRUE.
6876 */
6877 static void
6878check_vars(char_u *name, int len)
6879{
6880 int cc;
6881 char_u *varname;
6882 hashtab_T *ht;
6883
6884 if (eval_lavars_used == NULL)
6885 return;
6886
6887 /* truncate the name, so that we can use strcmp() */
6888 cc = name[len];
6889 name[len] = NUL;
6890
6891 ht = find_var_ht(name, &varname);
6892 if (ht == get_funccal_local_ht() || ht == get_funccal_args_ht())
6893 {
6894 if (find_var(name, NULL, TRUE) != NULL)
6895 *eval_lavars_used = TRUE;
6896 }
6897
6898 name[len] = cc;
6899}
6900
6901/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006902 * Handle expr[expr], expr[expr:expr] subscript and .name lookup.
6903 * Also handle function call with Funcref variable: func(expr)
6904 * Can all be combined: dict.func(expr)[idx]['func'](expr)
6905 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02006906 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006907handle_subscript(
6908 char_u **arg,
6909 typval_T *rettv,
6910 int evaluate, /* do more than finding the end */
6911 int verbose) /* give error messages */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006912{
6913 int ret = OK;
6914 dict_T *selfdict = NULL;
6915 char_u *s;
6916 int len;
Bram Moolenaard9fba312005-06-26 22:34:35 +00006917 typval_T functv;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006918
6919 while (ret == OK
6920 && (**arg == '['
6921 || (**arg == '.' && rettv->v_type == VAR_DICT)
Bram Moolenaar1735bc92016-03-14 23:05:14 +01006922 || (**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC
6923 || rettv->v_type == VAR_PARTIAL)))
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006924 && !vim_iswhite(*(*arg - 1)))
6925 {
6926 if (**arg == '(')
6927 {
Bram Moolenaar3f242a82016-03-18 19:39:25 +01006928 partial_T *pt = NULL;
6929
Bram Moolenaard9fba312005-06-26 22:34:35 +00006930 /* need to copy the funcref so that we can clear rettv */
Bram Moolenaar0f8de8d2013-11-11 04:25:53 +01006931 if (evaluate)
6932 {
6933 functv = *rettv;
6934 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006935
Bram Moolenaar0f8de8d2013-11-11 04:25:53 +01006936 /* Invoke the function. Recursive! */
Bram Moolenaarab1fa392016-03-15 19:33:34 +01006937 if (functv.v_type == VAR_PARTIAL)
Bram Moolenaar1735bc92016-03-14 23:05:14 +01006938 {
6939 pt = functv.vval.v_partial;
Bram Moolenaar437bafe2016-08-01 15:40:54 +02006940 s = partial_name(pt);
Bram Moolenaar1735bc92016-03-14 23:05:14 +01006941 }
6942 else
6943 s = functv.vval.v_string;
Bram Moolenaar0f8de8d2013-11-11 04:25:53 +01006944 }
6945 else
6946 s = (char_u *)"";
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00006947 ret = get_func_tv(s, (int)STRLEN(s), rettv, arg,
Bram Moolenaard9fba312005-06-26 22:34:35 +00006948 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
Bram Moolenaar1735bc92016-03-14 23:05:14 +01006949 &len, evaluate, pt, selfdict);
Bram Moolenaard9fba312005-06-26 22:34:35 +00006950
6951 /* Clear the funcref afterwards, so that deleting it while
6952 * evaluating the arguments is possible (see test55). */
Bram Moolenaar0f8de8d2013-11-11 04:25:53 +01006953 if (evaluate)
6954 clear_tv(&functv);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006955
6956 /* Stop the expression evaluation when immediately aborting on
6957 * error, or when an interrupt occurred or an exception was thrown
6958 * but not caught. */
6959 if (aborting())
6960 {
6961 if (ret == OK)
6962 clear_tv(rettv);
6963 ret = FAIL;
6964 }
6965 dict_unref(selfdict);
6966 selfdict = NULL;
6967 }
6968 else /* **arg == '[' || **arg == '.' */
6969 {
6970 dict_unref(selfdict);
6971 if (rettv->v_type == VAR_DICT)
6972 {
6973 selfdict = rettv->vval.v_dict;
6974 if (selfdict != NULL)
6975 ++selfdict->dv_refcount;
6976 }
6977 else
6978 selfdict = NULL;
6979 if (eval_index(arg, rettv, evaluate, verbose) == FAIL)
6980 {
6981 clear_tv(rettv);
6982 ret = FAIL;
6983 }
6984 }
6985 }
Bram Moolenaarab1fa392016-03-15 19:33:34 +01006986
Bram Moolenaar1d429612016-05-24 15:44:17 +02006987 /* Turn "dict.Func" into a partial for "Func" bound to "dict".
6988 * Don't do this when "Func" is already a partial that was bound
6989 * explicitly (pt_auto is FALSE). */
6990 if (selfdict != NULL
6991 && (rettv->v_type == VAR_FUNC
6992 || (rettv->v_type == VAR_PARTIAL
6993 && (rettv->vval.v_partial->pt_auto
6994 || rettv->vval.v_partial->pt_dict == NULL))))
Bram Moolenaara9b579f2016-07-17 18:29:19 +02006995 selfdict = make_partial(selfdict, rettv);
Bram Moolenaarab1fa392016-03-15 19:33:34 +01006996
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006997 dict_unref(selfdict);
6998 return ret;
6999}
7000
7001/*
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007002 * Allocate memory for a variable type-value, and make it empty (0 or NULL
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007003 * value).
7004 */
Bram Moolenaar11e0afa2016-02-01 22:41:00 +01007005 typval_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007006alloc_tv(void)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007007{
Bram Moolenaar33570922005-01-25 22:26:29 +00007008 return (typval_T *)alloc_clear((unsigned)sizeof(typval_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007009}
7010
7011/*
7012 * Allocate memory for a variable type-value, and assign a string to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007013 * The string "s" must have been allocated, it is consumed.
7014 * Return NULL for out of memory, the variable otherwise.
7015 */
Bram Moolenaar33570922005-01-25 22:26:29 +00007016 static typval_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007017alloc_string_tv(char_u *s)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007018{
Bram Moolenaar33570922005-01-25 22:26:29 +00007019 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007020
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007021 rettv = alloc_tv();
7022 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007023 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007024 rettv->v_type = VAR_STRING;
7025 rettv->vval.v_string = s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007026 }
7027 else
7028 vim_free(s);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007029 return rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007030}
7031
7032/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007033 * Free the memory for a variable type-value.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007034 */
Bram Moolenaar4770d092006-01-12 23:22:24 +00007035 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007036free_tv(typval_T *varp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007037{
7038 if (varp != NULL)
7039 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007040 switch (varp->v_type)
7041 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007042 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007043 func_unref(varp->vval.v_string);
7044 /*FALLTHROUGH*/
7045 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007046 vim_free(varp->vval.v_string);
7047 break;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007048 case VAR_PARTIAL:
7049 partial_unref(varp->vval.v_partial);
7050 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007051 case VAR_LIST:
7052 list_unref(varp->vval.v_list);
7053 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007054 case VAR_DICT:
7055 dict_unref(varp->vval.v_dict);
7056 break;
Bram Moolenaar835dc632016-02-07 14:27:38 +01007057 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007058#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +01007059 job_unref(varp->vval.v_job);
7060 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007061#endif
Bram Moolenaar77073442016-02-13 23:23:53 +01007062 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007063#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +01007064 channel_unref(varp->vval.v_channel);
7065 break;
7066#endif
Bram Moolenaar835dc632016-02-07 14:27:38 +01007067 case VAR_NUMBER:
7068 case VAR_FLOAT:
Bram Moolenaar758711c2005-02-02 23:11:38 +00007069 case VAR_UNKNOWN:
Bram Moolenaar6650a692016-01-26 19:59:10 +01007070 case VAR_SPECIAL:
Bram Moolenaar758711c2005-02-02 23:11:38 +00007071 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007072 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007073 vim_free(varp);
7074 }
7075}
7076
7077/*
7078 * Free the memory for a variable value and set the value to NULL or 0.
7079 */
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00007080 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007081clear_tv(typval_T *varp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007082{
7083 if (varp != NULL)
7084 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007085 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007086 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007087 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007088 func_unref(varp->vval.v_string);
7089 /*FALLTHROUGH*/
7090 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007091 vim_free(varp->vval.v_string);
7092 varp->vval.v_string = NULL;
7093 break;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007094 case VAR_PARTIAL:
7095 partial_unref(varp->vval.v_partial);
7096 varp->vval.v_partial = NULL;
7097 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007098 case VAR_LIST:
7099 list_unref(varp->vval.v_list);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007100 varp->vval.v_list = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007101 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007102 case VAR_DICT:
7103 dict_unref(varp->vval.v_dict);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007104 varp->vval.v_dict = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007105 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007106 case VAR_NUMBER:
Bram Moolenaar520e1e42016-01-23 19:46:28 +01007107 case VAR_SPECIAL:
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007108 varp->vval.v_number = 0;
7109 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007110 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01007111#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007112 varp->vval.v_float = 0.0;
7113 break;
7114#endif
Bram Moolenaar835dc632016-02-07 14:27:38 +01007115 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007116#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +01007117 job_unref(varp->vval.v_job);
7118 varp->vval.v_job = NULL;
7119#endif
7120 break;
Bram Moolenaar77073442016-02-13 23:23:53 +01007121 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007122#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +01007123 channel_unref(varp->vval.v_channel);
7124 varp->vval.v_channel = NULL;
7125#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007126 case VAR_UNKNOWN:
7127 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007128 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007129 varp->v_lock = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007130 }
7131}
7132
7133/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007134 * Set the value of a variable to NULL without freeing items.
7135 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007136 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007137init_tv(typval_T *varp)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007138{
7139 if (varp != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +00007140 vim_memset(varp, 0, sizeof(typval_T));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007141}
7142
7143/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007144 * Get the number value of a variable.
7145 * If it is a String variable, uses vim_str2nr().
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007146 * For incompatible types, return 0.
7147 * get_tv_number_chk() is similar to get_tv_number(), but informs the
7148 * caller of incompatible types: it sets *denote to TRUE if "denote"
7149 * is not NULL or returns -1 otherwise.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007150 */
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02007151 varnumber_T
Bram Moolenaar7454a062016-01-30 15:14:10 +01007152get_tv_number(typval_T *varp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007153{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007154 int error = FALSE;
7155
7156 return get_tv_number_chk(varp, &error); /* return 0L on error */
7157}
7158
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02007159 varnumber_T
Bram Moolenaar7454a062016-01-30 15:14:10 +01007160get_tv_number_chk(typval_T *varp, int *denote)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007161{
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02007162 varnumber_T n = 0L;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007163
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007164 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007165 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007166 case VAR_NUMBER:
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02007167 return varp->vval.v_number;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007168 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01007169#ifdef FEAT_FLOAT
Bram Moolenaared0e7452008-06-27 19:17:34 +00007170 EMSG(_("E805: Using a Float as a Number"));
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007171 break;
7172#endif
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007173 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007174 case VAR_PARTIAL:
Bram Moolenaared0e7452008-06-27 19:17:34 +00007175 EMSG(_("E703: Using a Funcref as a Number"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007176 break;
7177 case VAR_STRING:
7178 if (varp->vval.v_string != NULL)
7179 vim_str2nr(varp->vval.v_string, NULL, NULL,
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01007180 STR2NR_ALL, &n, NULL, 0);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007181 return n;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007182 case VAR_LIST:
Bram Moolenaared0e7452008-06-27 19:17:34 +00007183 EMSG(_("E745: Using a List as a Number"));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007184 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007185 case VAR_DICT:
Bram Moolenaared0e7452008-06-27 19:17:34 +00007186 EMSG(_("E728: Using a Dictionary as a Number"));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007187 break;
Bram Moolenaar17a13432016-01-24 14:22:10 +01007188 case VAR_SPECIAL:
7189 return varp->vval.v_number == VVAL_TRUE ? 1 : 0;
7190 break;
Bram Moolenaar835dc632016-02-07 14:27:38 +01007191 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007192#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +01007193 EMSG(_("E910: Using a Job as a Number"));
7194 break;
7195#endif
Bram Moolenaar77073442016-02-13 23:23:53 +01007196 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007197#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +01007198 EMSG(_("E913: Using a Channel as a Number"));
7199 break;
7200#endif
Bram Moolenaara03f2332016-02-06 18:09:59 +01007201 case VAR_UNKNOWN:
Bram Moolenaar95f09602016-11-10 20:01:45 +01007202 internal_error("get_tv_number(UNKNOWN)");
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007203 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007204 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007205 if (denote == NULL) /* useful for values that must be unsigned */
7206 n = -1;
7207 else
7208 *denote = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007209 return n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007210}
7211
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007212#ifdef FEAT_FLOAT
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007213 float_T
Bram Moolenaar7454a062016-01-30 15:14:10 +01007214get_tv_float(typval_T *varp)
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007215{
7216 switch (varp->v_type)
7217 {
7218 case VAR_NUMBER:
7219 return (float_T)(varp->vval.v_number);
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007220 case VAR_FLOAT:
7221 return varp->vval.v_float;
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007222 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007223 case VAR_PARTIAL:
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007224 EMSG(_("E891: Using a Funcref as a Float"));
7225 break;
7226 case VAR_STRING:
7227 EMSG(_("E892: Using a String as a Float"));
7228 break;
7229 case VAR_LIST:
7230 EMSG(_("E893: Using a List as a Float"));
7231 break;
7232 case VAR_DICT:
7233 EMSG(_("E894: Using a Dictionary as a Float"));
7234 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +01007235 case VAR_SPECIAL:
7236 EMSG(_("E907: Using a special value as a Float"));
7237 break;
Bram Moolenaar835dc632016-02-07 14:27:38 +01007238 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007239# ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +01007240 EMSG(_("E911: Using a Job as a Float"));
7241 break;
7242# endif
Bram Moolenaar77073442016-02-13 23:23:53 +01007243 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007244# ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +01007245 EMSG(_("E914: Using a Channel as a Float"));
7246 break;
7247# endif
Bram Moolenaara03f2332016-02-06 18:09:59 +01007248 case VAR_UNKNOWN:
Bram Moolenaar95f09602016-11-10 20:01:45 +01007249 internal_error("get_tv_float(UNKNOWN)");
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007250 break;
7251 }
7252 return 0;
7253}
7254#endif
7255
Bram Moolenaar071d4272004-06-13 20:20:40 +00007256/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007257 * Get the string value of a variable.
7258 * If it is a Number variable, the number is converted into a string.
Bram Moolenaara7043832005-01-21 11:56:39 +00007259 * get_tv_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
7260 * get_tv_string_buf() uses a given buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007261 * If the String variable has never been set, return an empty string.
7262 * Never returns NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007263 * get_tv_string_chk() and get_tv_string_buf_chk() are similar, but return
7264 * NULL on error.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007265 */
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01007266 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007267get_tv_string(typval_T *varp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007268{
7269 static char_u mybuf[NUMBUFLEN];
7270
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007271 return get_tv_string_buf(varp, mybuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007272}
7273
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01007274 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007275get_tv_string_buf(typval_T *varp, char_u *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007276{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007277 char_u *res = get_tv_string_buf_chk(varp, buf);
7278
7279 return res != NULL ? res : (char_u *)"";
7280}
7281
Bram Moolenaar7d647822014-04-05 21:28:56 +02007282/*
7283 * Careful: This uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
7284 */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00007285 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007286get_tv_string_chk(typval_T *varp)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007287{
7288 static char_u mybuf[NUMBUFLEN];
7289
7290 return get_tv_string_buf_chk(varp, mybuf);
7291}
7292
Bram Moolenaar520e1e42016-01-23 19:46:28 +01007293 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007294get_tv_string_buf_chk(typval_T *varp, char_u *buf)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007295{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007296 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007297 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007298 case VAR_NUMBER:
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02007299 vim_snprintf((char *)buf, NUMBUFLEN, "%lld",
7300 (varnumber_T)varp->vval.v_number);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007301 return buf;
7302 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007303 case VAR_PARTIAL:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007304 EMSG(_("E729: using Funcref as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007305 break;
7306 case VAR_LIST:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007307 EMSG(_("E730: using List as a String"));
Bram Moolenaar8c711452005-01-14 21:53:12 +00007308 break;
7309 case VAR_DICT:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007310 EMSG(_("E731: using Dictionary as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007311 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007312 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01007313#ifdef FEAT_FLOAT
Bram Moolenaar2a876e42013-06-12 22:08:58 +02007314 EMSG(_(e_float_as_string));
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007315 break;
7316#endif
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007317 case VAR_STRING:
7318 if (varp->vval.v_string != NULL)
7319 return varp->vval.v_string;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007320 return (char_u *)"";
Bram Moolenaar17a13432016-01-24 14:22:10 +01007321 case VAR_SPECIAL:
7322 STRCPY(buf, get_var_special_name(varp->vval.v_number));
7323 return buf;
Bram Moolenaar835dc632016-02-07 14:27:38 +01007324 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007325#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +01007326 {
7327 job_T *job = varp->vval.v_job;
Bram Moolenaar839fd112016-03-06 21:34:03 +01007328 char *status;
7329
7330 if (job == NULL)
7331 return (char_u *)"no process";
7332 status = job->jv_status == JOB_FAILED ? "fail"
Bram Moolenaar7df915d2016-11-17 17:25:32 +01007333 : job->jv_status >= JOB_ENDED ? "dead"
Bram Moolenaar835dc632016-02-07 14:27:38 +01007334 : "run";
7335# ifdef UNIX
7336 vim_snprintf((char *)buf, NUMBUFLEN,
7337 "process %ld %s", (long)job->jv_pid, status);
Bram Moolenaar4d8747c2016-02-09 20:39:26 +01007338# elif defined(WIN32)
7339 vim_snprintf((char *)buf, NUMBUFLEN,
Bram Moolenaar76467df2016-02-12 19:30:26 +01007340 "process %ld %s",
7341 (long)job->jv_proc_info.dwProcessId,
Bram Moolenaar4d8747c2016-02-09 20:39:26 +01007342 status);
Bram Moolenaar835dc632016-02-07 14:27:38 +01007343# else
Bram Moolenaar4d8747c2016-02-09 20:39:26 +01007344 /* fall-back */
Bram Moolenaar835dc632016-02-07 14:27:38 +01007345 vim_snprintf((char *)buf, NUMBUFLEN, "process ? %s", status);
7346# endif
7347 return buf;
7348 }
7349#endif
7350 break;
Bram Moolenaar77073442016-02-13 23:23:53 +01007351 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007352#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +01007353 {
7354 channel_T *channel = varp->vval.v_channel;
Bram Moolenaar0e77b762016-09-26 22:58:58 +02007355 char *status = channel_status(channel, -1);
Bram Moolenaar77073442016-02-13 23:23:53 +01007356
Bram Moolenaar5cefd402016-02-16 12:44:26 +01007357 if (channel == NULL)
7358 vim_snprintf((char *)buf, NUMBUFLEN, "channel %s", status);
7359 else
7360 vim_snprintf((char *)buf, NUMBUFLEN,
Bram Moolenaar77073442016-02-13 23:23:53 +01007361 "channel %d %s", channel->ch_id, status);
7362 return buf;
7363 }
7364#endif
7365 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +01007366 case VAR_UNKNOWN:
7367 EMSG(_("E908: using an invalid value as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007368 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007369 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007370 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007371}
7372
7373/*
7374 * Find variable "name" in the list of variables.
7375 * Return a pointer to it if found, NULL if not found.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007376 * Careful: "a:0" variables don't have a name.
Bram Moolenaara7043832005-01-21 11:56:39 +00007377 * When "htp" is not NULL we are writing to the variable, set "htp" to the
Bram Moolenaar33570922005-01-25 22:26:29 +00007378 * hashtab_T used.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007379 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02007380 dictitem_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007381find_var(char_u *name, hashtab_T **htp, int no_autoload)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007382{
Bram Moolenaar071d4272004-06-13 20:20:40 +00007383 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +00007384 hashtab_T *ht;
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02007385 dictitem_T *ret = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007386
Bram Moolenaara7043832005-01-21 11:56:39 +00007387 ht = find_var_ht(name, &varname);
7388 if (htp != NULL)
7389 *htp = ht;
7390 if (ht == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007391 return NULL;
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02007392 ret = find_var_in_ht(ht, *name, varname, no_autoload || htp != NULL);
7393 if (ret != NULL)
7394 return ret;
7395
7396 /* Search in parent scope for lambda */
Bram Moolenaarba96e9a2016-08-01 17:10:20 +02007397 return find_var_in_scoped_ht(name, no_autoload || htp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007398}
7399
7400/*
Bram Moolenaar332ac062013-04-15 13:06:21 +02007401 * Find variable "varname" in hashtab "ht" with name "htname".
Bram Moolenaara7043832005-01-21 11:56:39 +00007402 * Returns NULL if not found.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007403 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007404 dictitem_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007405find_var_in_ht(
7406 hashtab_T *ht,
7407 int htname,
7408 char_u *varname,
7409 int no_autoload)
Bram Moolenaara7043832005-01-21 11:56:39 +00007410{
Bram Moolenaar33570922005-01-25 22:26:29 +00007411 hashitem_T *hi;
7412
7413 if (*varname == NUL)
7414 {
7415 /* Must be something like "s:", otherwise "ht" would be NULL. */
Bram Moolenaar332ac062013-04-15 13:06:21 +02007416 switch (htname)
Bram Moolenaar33570922005-01-25 22:26:29 +00007417 {
Bram Moolenaar9577c3e2010-05-14 12:16:25 +02007418 case 's': return &SCRIPT_SV(current_SID)->sv_var;
Bram Moolenaar33570922005-01-25 22:26:29 +00007419 case 'g': return &globvars_var;
7420 case 'v': return &vimvars_var;
7421 case 'b': return &curbuf->b_bufvar;
7422 case 'w': return &curwin->w_winvar;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00007423#ifdef FEAT_WINDOWS
7424 case 't': return &curtab->tp_winvar;
7425#endif
Bram Moolenaara9b579f2016-07-17 18:29:19 +02007426 case 'l': return get_funccal_local_var();
7427 case 'a': return get_funccal_args_var();
Bram Moolenaar33570922005-01-25 22:26:29 +00007428 }
7429 return NULL;
7430 }
Bram Moolenaara7043832005-01-21 11:56:39 +00007431
7432 hi = hash_find(ht, varname);
7433 if (HASHITEM_EMPTY(hi))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00007434 {
7435 /* For global variables we may try auto-loading the script. If it
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00007436 * worked find the variable again. Don't auto-load a script if it was
7437 * loaded already, otherwise it would be loaded every time when
7438 * checking if a function name is a Funcref variable. */
Bram Moolenaar6d977d62014-01-14 15:24:39 +01007439 if (ht == &globvarht && !no_autoload)
Bram Moolenaar8000baf2011-11-30 15:19:28 +01007440 {
7441 /* Note: script_autoload() may make "hi" invalid. It must either
7442 * be obtained again or not used. */
7443 if (!script_autoload(varname, FALSE) || aborting())
7444 return NULL;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00007445 hi = hash_find(ht, varname);
Bram Moolenaar8000baf2011-11-30 15:19:28 +01007446 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00007447 if (HASHITEM_EMPTY(hi))
7448 return NULL;
7449 }
Bram Moolenaar33570922005-01-25 22:26:29 +00007450 return HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +00007451}
7452
7453/*
Bram Moolenaar33570922005-01-25 22:26:29 +00007454 * Find the hashtab used for a variable name.
Bram Moolenaar73627d02015-08-11 15:46:09 +02007455 * Return NULL if the name is not valid.
Bram Moolenaara7043832005-01-21 11:56:39 +00007456 * Set "varname" to the start of name without ':'.
7457 */
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02007458 hashtab_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007459find_var_ht(char_u *name, char_u **varname)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007460{
Bram Moolenaar75c50c42005-06-04 22:06:24 +00007461 hashitem_T *hi;
Bram Moolenaara9b579f2016-07-17 18:29:19 +02007462 hashtab_T *ht;
Bram Moolenaar75c50c42005-06-04 22:06:24 +00007463
Bram Moolenaar73627d02015-08-11 15:46:09 +02007464 if (name[0] == NUL)
7465 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007466 if (name[1] != ':')
7467 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00007468 /* The name must not start with a colon or #. */
7469 if (name[0] == ':' || name[0] == AUTOLOAD_CHAR)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007470 return NULL;
7471 *varname = name;
Bram Moolenaar532c7802005-01-27 14:44:31 +00007472
7473 /* "version" is "v:version" in all scopes */
Bram Moolenaar75c50c42005-06-04 22:06:24 +00007474 hi = hash_find(&compat_hashtab, name);
7475 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar532c7802005-01-27 14:44:31 +00007476 return &compat_hashtab;
7477
Bram Moolenaara9b579f2016-07-17 18:29:19 +02007478 ht = get_funccal_local_ht();
7479 if (ht == NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +00007480 return &globvarht; /* global variable */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02007481 return ht; /* local variable */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007482 }
7483 *varname = name + 2;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00007484 if (*name == 'g') /* global variable */
7485 return &globvarht;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00007486 /* There must be no ':' or '#' in the rest of the name, unless g: is used
7487 */
7488 if (vim_strchr(name + 2, ':') != NULL
7489 || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00007490 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007491 if (*name == 'b') /* buffer variable */
Bram Moolenaar429fa852013-04-15 12:27:36 +02007492 return &curbuf->b_vars->dv_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007493 if (*name == 'w') /* window variable */
Bram Moolenaar429fa852013-04-15 12:27:36 +02007494 return &curwin->w_vars->dv_hashtab;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00007495#ifdef FEAT_WINDOWS
7496 if (*name == 't') /* tab page variable */
Bram Moolenaar429fa852013-04-15 12:27:36 +02007497 return &curtab->tp_vars->dv_hashtab;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00007498#endif
Bram Moolenaar33570922005-01-25 22:26:29 +00007499 if (*name == 'v') /* v: variable */
7500 return &vimvarht;
Bram Moolenaara9b579f2016-07-17 18:29:19 +02007501 if (*name == 'a') /* a: function argument */
7502 return get_funccal_args_ht();
7503 if (*name == 'l') /* l: local function variable */
7504 return get_funccal_local_ht();
Bram Moolenaar071d4272004-06-13 20:20:40 +00007505 if (*name == 's' /* script variable */
7506 && current_SID > 0 && current_SID <= ga_scripts.ga_len)
7507 return &SCRIPT_VARS(current_SID);
7508 return NULL;
7509}
7510
7511/*
7512 * Get the string value of a (global/local) variable.
Bram Moolenaar1950c352010-06-06 15:21:10 +02007513 * Note: see get_tv_string() for how long the pointer remains valid.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007514 * Returns NULL when it doesn't exist.
7515 */
7516 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007517get_var_value(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007518{
Bram Moolenaar33570922005-01-25 22:26:29 +00007519 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007520
Bram Moolenaar6d977d62014-01-14 15:24:39 +01007521 v = find_var(name, NULL, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007522 if (v == NULL)
7523 return NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00007524 return get_tv_string(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007525}
7526
7527/*
Bram Moolenaar33570922005-01-25 22:26:29 +00007528 * Allocate a new hashtab for a sourced script. It will be used while
Bram Moolenaar071d4272004-06-13 20:20:40 +00007529 * sourcing this script and when executing functions defined in the script.
7530 */
7531 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007532new_script_vars(scid_T id)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007533{
Bram Moolenaara7043832005-01-21 11:56:39 +00007534 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00007535 hashtab_T *ht;
7536 scriptvar_T *sv;
Bram Moolenaara7043832005-01-21 11:56:39 +00007537
Bram Moolenaar071d4272004-06-13 20:20:40 +00007538 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
7539 {
Bram Moolenaara7043832005-01-21 11:56:39 +00007540 /* Re-allocating ga_data means that an ht_array pointing to
7541 * ht_smallarray becomes invalid. We can recognize this: ht_mask is
Bram Moolenaar33570922005-01-25 22:26:29 +00007542 * at its init value. Also reset "v_dict", it's always the same. */
Bram Moolenaara7043832005-01-21 11:56:39 +00007543 for (i = 1; i <= ga_scripts.ga_len; ++i)
7544 {
7545 ht = &SCRIPT_VARS(i);
7546 if (ht->ht_mask == HT_INIT_SIZE - 1)
7547 ht->ht_array = ht->ht_smallarray;
Bram Moolenaar9577c3e2010-05-14 12:16:25 +02007548 sv = SCRIPT_SV(i);
Bram Moolenaar33570922005-01-25 22:26:29 +00007549 sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict;
Bram Moolenaara7043832005-01-21 11:56:39 +00007550 }
7551
Bram Moolenaar071d4272004-06-13 20:20:40 +00007552 while (ga_scripts.ga_len < id)
7553 {
Bram Moolenaar2c704a72010-06-03 21:17:25 +02007554 sv = SCRIPT_SV(ga_scripts.ga_len + 1) =
Bram Moolenaar9577c3e2010-05-14 12:16:25 +02007555 (scriptvar_T *)alloc_clear(sizeof(scriptvar_T));
Bram Moolenaarbdb62052012-07-16 17:31:53 +02007556 init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007557 ++ga_scripts.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007558 }
7559 }
7560}
7561
7562/*
Bram Moolenaar33570922005-01-25 22:26:29 +00007563 * Initialize dictionary "dict" as a scope and set variable "dict_var" to
7564 * point to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007565 */
7566 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007567init_var_dict(dict_T *dict, dictitem_T *dict_var, int scope)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007568{
Bram Moolenaar33570922005-01-25 22:26:29 +00007569 hash_init(&dict->dv_hashtab);
Bram Moolenaared465602012-06-20 14:13:06 +02007570 dict->dv_lock = 0;
Bram Moolenaarbdb62052012-07-16 17:31:53 +02007571 dict->dv_scope = scope;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +00007572 dict->dv_refcount = DO_NOT_FREE_CNT;
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00007573 dict->dv_copyID = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00007574 dict_var->di_tv.vval.v_dict = dict;
7575 dict_var->di_tv.v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007576 dict_var->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +00007577 dict_var->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
7578 dict_var->di_key[0] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007579}
7580
7581/*
Bram Moolenaar429fa852013-04-15 12:27:36 +02007582 * Unreference a dictionary initialized by init_var_dict().
7583 */
7584 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007585unref_var_dict(dict_T *dict)
Bram Moolenaar429fa852013-04-15 12:27:36 +02007586{
7587 /* Now the dict needs to be freed if no one else is using it, go back to
7588 * normal reference counting. */
7589 dict->dv_refcount -= DO_NOT_FREE_CNT - 1;
7590 dict_unref(dict);
7591}
7592
7593/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007594 * Clean up a list of internal variables.
Bram Moolenaar33570922005-01-25 22:26:29 +00007595 * Frees all allocated variables and the value they contain.
7596 * Clears hashtab "ht", does not free it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007597 */
7598 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007599vars_clear(hashtab_T *ht)
Bram Moolenaar33570922005-01-25 22:26:29 +00007600{
7601 vars_clear_ext(ht, TRUE);
7602}
7603
7604/*
7605 * Like vars_clear(), but only free the value if "free_val" is TRUE.
7606 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02007607 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007608vars_clear_ext(hashtab_T *ht, int free_val)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007609{
Bram Moolenaara7043832005-01-21 11:56:39 +00007610 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00007611 hashitem_T *hi;
7612 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007613
Bram Moolenaar33570922005-01-25 22:26:29 +00007614 hash_lock(ht);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007615 todo = (int)ht->ht_used;
Bram Moolenaara7043832005-01-21 11:56:39 +00007616 for (hi = ht->ht_array; todo > 0; ++hi)
7617 {
7618 if (!HASHITEM_EMPTY(hi))
7619 {
7620 --todo;
7621
Bram Moolenaar33570922005-01-25 22:26:29 +00007622 /* Free the variable. Don't remove it from the hashtab,
Bram Moolenaara7043832005-01-21 11:56:39 +00007623 * ht_array might change then. hash_clear() takes care of it
7624 * later. */
Bram Moolenaar33570922005-01-25 22:26:29 +00007625 v = HI2DI(hi);
7626 if (free_val)
7627 clear_tv(&v->di_tv);
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02007628 if (v->di_flags & DI_FLAGS_ALLOC)
Bram Moolenaar33570922005-01-25 22:26:29 +00007629 vim_free(v);
Bram Moolenaara7043832005-01-21 11:56:39 +00007630 }
7631 }
7632 hash_clear(ht);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007633 ht->ht_used = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007634}
7635
Bram Moolenaara7043832005-01-21 11:56:39 +00007636/*
Bram Moolenaar33570922005-01-25 22:26:29 +00007637 * Delete a variable from hashtab "ht" at item "hi".
7638 * Clear the variable value and free the dictitem.
Bram Moolenaara7043832005-01-21 11:56:39 +00007639 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007640 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007641delete_var(hashtab_T *ht, hashitem_T *hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007642{
Bram Moolenaar33570922005-01-25 22:26:29 +00007643 dictitem_T *di = HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +00007644
7645 hash_remove(ht, hi);
Bram Moolenaar33570922005-01-25 22:26:29 +00007646 clear_tv(&di->di_tv);
7647 vim_free(di);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007648}
7649
7650/*
7651 * List the value of one internal variable.
7652 */
7653 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007654list_one_var(dictitem_T *v, char_u *prefix, int *first)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007655{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007656 char_u *tofree;
7657 char_u *s;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007658 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007659
Bram Moolenaar520e1e42016-01-23 19:46:28 +01007660 s = echo_string(&v->di_tv, &tofree, numbuf, get_copyID());
Bram Moolenaar33570922005-01-25 22:26:29 +00007661 list_one_var_a(prefix, v->di_key, v->di_tv.v_type,
Bram Moolenaar7d61a922007-08-30 09:12:23 +00007662 s == NULL ? (char_u *)"" : s, first);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007663 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007664}
7665
Bram Moolenaar071d4272004-06-13 20:20:40 +00007666 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007667list_one_var_a(
7668 char_u *prefix,
7669 char_u *name,
7670 int type,
7671 char_u *string,
7672 int *first) /* when TRUE clear rest of screen and set to FALSE */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007673{
Bram Moolenaar31859182007-08-14 20:41:13 +00007674 /* don't use msg() or msg_attr() to avoid overwriting "v:statusmsg" */
7675 msg_start();
7676 msg_puts(prefix);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007677 if (name != NULL) /* "a:" vars don't have a name stored */
7678 msg_puts(name);
7679 msg_putchar(' ');
7680 msg_advance(22);
7681 if (type == VAR_NUMBER)
7682 msg_putchar('#');
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007683 else if (type == VAR_FUNC || type == VAR_PARTIAL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007684 msg_putchar('*');
7685 else if (type == VAR_LIST)
7686 {
7687 msg_putchar('[');
7688 if (*string == '[')
7689 ++string;
7690 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00007691 else if (type == VAR_DICT)
7692 {
7693 msg_putchar('{');
7694 if (*string == '{')
7695 ++string;
7696 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007697 else
7698 msg_putchar(' ');
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007699
Bram Moolenaar071d4272004-06-13 20:20:40 +00007700 msg_outtrans(string);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007701
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007702 if (type == VAR_FUNC || type == VAR_PARTIAL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007703 msg_puts((char_u *)"()");
Bram Moolenaar7d61a922007-08-30 09:12:23 +00007704 if (*first)
7705 {
7706 msg_clr_eos();
7707 *first = FALSE;
7708 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007709}
7710
7711/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007712 * Set variable "name" to value in "tv".
Bram Moolenaar071d4272004-06-13 20:20:40 +00007713 * If the variable already exists, the value is updated.
7714 * Otherwise the variable is created.
7715 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007716 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007717set_var(
7718 char_u *name,
7719 typval_T *tv,
7720 int copy) /* make copy of value in "tv" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007721{
Bram Moolenaar33570922005-01-25 22:26:29 +00007722 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007723 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +00007724 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007725
Bram Moolenaarbaff0fe2010-03-17 19:53:49 +01007726 ht = find_var_ht(name, &varname);
7727 if (ht == NULL || *varname == NUL)
7728 {
7729 EMSG2(_(e_illvar), name);
7730 return;
7731 }
Bram Moolenaar332ac062013-04-15 13:06:21 +02007732 v = find_var_in_ht(ht, 0, varname, TRUE);
Bram Moolenaarbaff0fe2010-03-17 19:53:49 +01007733
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02007734 /* Search in parent scope which is possible to reference from lambda */
7735 if (v == NULL)
Bram Moolenaarba96e9a2016-08-01 17:10:20 +02007736 v = find_var_in_scoped_ht(name, TRUE);
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02007737
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007738 if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL)
7739 && var_check_func_name(name, v == NULL))
Bram Moolenaar4228bec2011-03-27 16:03:15 +02007740 return;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007741
Bram Moolenaar33570922005-01-25 22:26:29 +00007742 if (v != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007743 {
Bram Moolenaar33570922005-01-25 22:26:29 +00007744 /* existing variable, need to clear the value */
Bram Moolenaar77354e72015-04-21 16:49:05 +02007745 if (var_check_ro(v->di_flags, name, FALSE)
7746 || tv_check_lock(v->di_tv.v_lock, name, FALSE))
Bram Moolenaar33570922005-01-25 22:26:29 +00007747 return;
Bram Moolenaar33570922005-01-25 22:26:29 +00007748
7749 /*
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02007750 * Handle setting internal v: variables separately where needed to
7751 * prevent changing the type.
Bram Moolenaar33570922005-01-25 22:26:29 +00007752 */
7753 if (ht == &vimvarht)
7754 {
7755 if (v->di_tv.v_type == VAR_STRING)
7756 {
7757 vim_free(v->di_tv.vval.v_string);
7758 if (copy || tv->v_type != VAR_STRING)
7759 v->di_tv.vval.v_string = vim_strsave(get_tv_string(tv));
7760 else
7761 {
7762 /* Take over the string to avoid an extra alloc/free. */
7763 v->di_tv.vval.v_string = tv->vval.v_string;
7764 tv->vval.v_string = NULL;
7765 }
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02007766 return;
Bram Moolenaar33570922005-01-25 22:26:29 +00007767 }
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02007768 else if (v->di_tv.v_type == VAR_NUMBER)
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007769 {
Bram Moolenaar33570922005-01-25 22:26:29 +00007770 v->di_tv.vval.v_number = get_tv_number(tv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007771 if (STRCMP(varname, "searchforward") == 0)
7772 set_search_direction(v->di_tv.vval.v_number ? '/' : '?');
Bram Moolenaar8050efa2013-11-08 04:30:20 +01007773#ifdef FEAT_SEARCH_EXTRA
7774 else if (STRCMP(varname, "hlsearch") == 0)
7775 {
7776 no_hlsearch = !v->di_tv.vval.v_number;
7777 redraw_all_later(SOME_VALID);
7778 }
7779#endif
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02007780 return;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007781 }
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02007782 else if (v->di_tv.v_type != tv->v_type)
Bram Moolenaar95f09602016-11-10 20:01:45 +01007783 internal_error("set_var()");
Bram Moolenaar33570922005-01-25 22:26:29 +00007784 }
7785
7786 clear_tv(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007787 }
7788 else /* add a new variable */
7789 {
Bram Moolenaar5fcc3fe2006-06-22 15:35:14 +00007790 /* Can't add "v:" variable. */
7791 if (ht == &vimvarht)
7792 {
7793 EMSG2(_(e_illvar), name);
7794 return;
7795 }
7796
Bram Moolenaar92124a32005-06-17 22:03:40 +00007797 /* Make sure the variable name is valid. */
Bram Moolenaar4228bec2011-03-27 16:03:15 +02007798 if (!valid_varname(varname))
7799 return;
Bram Moolenaar92124a32005-06-17 22:03:40 +00007800
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007801 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
7802 + STRLEN(varname)));
Bram Moolenaara7043832005-01-21 11:56:39 +00007803 if (v == NULL)
7804 return;
Bram Moolenaar33570922005-01-25 22:26:29 +00007805 STRCPY(v->di_key, varname);
Bram Moolenaar33570922005-01-25 22:26:29 +00007806 if (hash_add(ht, DI2HIKEY(v)) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007807 {
Bram Moolenaara7043832005-01-21 11:56:39 +00007808 vim_free(v);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007809 return;
7810 }
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02007811 v->di_flags = DI_FLAGS_ALLOC;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007812 }
Bram Moolenaara7043832005-01-21 11:56:39 +00007813
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007814 if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT)
Bram Moolenaar33570922005-01-25 22:26:29 +00007815 copy_tv(tv, &v->di_tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +00007816 else
7817 {
Bram Moolenaar33570922005-01-25 22:26:29 +00007818 v->di_tv = *tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007819 v->di_tv.v_lock = 0;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007820 init_tv(tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +00007821 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007822}
7823
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007824/*
Bram Moolenaar4e957af2006-09-02 11:41:07 +00007825 * Return TRUE if di_flags "flags" indicates variable "name" is read-only.
Bram Moolenaar33570922005-01-25 22:26:29 +00007826 * Also give an error message.
7827 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02007828 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007829var_check_ro(int flags, char_u *name, int use_gettext)
Bram Moolenaar33570922005-01-25 22:26:29 +00007830{
7831 if (flags & DI_FLAGS_RO)
7832 {
Bram Moolenaar77354e72015-04-21 16:49:05 +02007833 EMSG2(_(e_readonlyvar), use_gettext ? (char_u *)_(name) : name);
Bram Moolenaar33570922005-01-25 22:26:29 +00007834 return TRUE;
7835 }
7836 if ((flags & DI_FLAGS_RO_SBX) && sandbox)
7837 {
Bram Moolenaar77354e72015-04-21 16:49:05 +02007838 EMSG2(_(e_readonlysbx), use_gettext ? (char_u *)_(name) : name);
Bram Moolenaar33570922005-01-25 22:26:29 +00007839 return TRUE;
7840 }
7841 return FALSE;
7842}
7843
7844/*
Bram Moolenaar4e957af2006-09-02 11:41:07 +00007845 * Return TRUE if di_flags "flags" indicates variable "name" is fixed.
7846 * Also give an error message.
7847 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007848 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007849var_check_fixed(int flags, char_u *name, int use_gettext)
Bram Moolenaar4e957af2006-09-02 11:41:07 +00007850{
7851 if (flags & DI_FLAGS_FIX)
7852 {
Bram Moolenaar77354e72015-04-21 16:49:05 +02007853 EMSG2(_("E795: Cannot delete variable %s"),
7854 use_gettext ? (char_u *)_(name) : name);
Bram Moolenaar4e957af2006-09-02 11:41:07 +00007855 return TRUE;
7856 }
7857 return FALSE;
7858}
7859
7860/*
Bram Moolenaar4228bec2011-03-27 16:03:15 +02007861 * Check if a funcref is assigned to a valid variable name.
7862 * Return TRUE and give an error if not.
7863 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02007864 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007865var_check_func_name(
7866 char_u *name, /* points to start of variable name */
7867 int new_var) /* TRUE when creating the variable */
Bram Moolenaar4228bec2011-03-27 16:03:15 +02007868{
Bram Moolenaarcbc67722014-05-22 14:19:56 +02007869 /* Allow for w: b: s: and t:. */
7870 if (!(vim_strchr((char_u *)"wbst", name[0]) != NULL && name[1] == ':')
Bram Moolenaar4228bec2011-03-27 16:03:15 +02007871 && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
7872 ? name[2] : name[0]))
7873 {
7874 EMSG2(_("E704: Funcref variable name must start with a capital: %s"),
7875 name);
7876 return TRUE;
7877 }
7878 /* Don't allow hiding a function. When "v" is not NULL we might be
7879 * assigning another function to the same var, the type is checked
7880 * below. */
Bram Moolenaarb54c3ff2016-07-31 14:11:58 +02007881 if (new_var && function_exists(name, FALSE))
Bram Moolenaar4228bec2011-03-27 16:03:15 +02007882 {
7883 EMSG2(_("E705: Variable name conflicts with existing function: %s"),
7884 name);
7885 return TRUE;
7886 }
7887 return FALSE;
7888}
7889
7890/*
7891 * Check if a variable name is valid.
7892 * Return FALSE and give an error if not.
7893 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02007894 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007895valid_varname(char_u *varname)
Bram Moolenaar4228bec2011-03-27 16:03:15 +02007896{
7897 char_u *p;
7898
7899 for (p = varname; *p != NUL; ++p)
7900 if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p))
7901 && *p != AUTOLOAD_CHAR)
7902 {
7903 EMSG2(_(e_illvar), varname);
7904 return FALSE;
7905 }
7906 return TRUE;
7907}
7908
7909/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007910 * Return TRUE if typeval "tv" is set to be locked (immutable).
Bram Moolenaar77354e72015-04-21 16:49:05 +02007911 * Also give an error message, using "name" or _("name") when use_gettext is
7912 * TRUE.
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007913 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02007914 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007915tv_check_lock(int lock, char_u *name, int use_gettext)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007916{
7917 if (lock & VAR_LOCKED)
7918 {
7919 EMSG2(_("E741: Value is locked: %s"),
Bram Moolenaar77354e72015-04-21 16:49:05 +02007920 name == NULL ? (char_u *)_("Unknown")
7921 : use_gettext ? (char_u *)_(name)
7922 : name);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007923 return TRUE;
7924 }
7925 if (lock & VAR_FIXED)
7926 {
7927 EMSG2(_("E742: Cannot change value of %s"),
Bram Moolenaar77354e72015-04-21 16:49:05 +02007928 name == NULL ? (char_u *)_("Unknown")
7929 : use_gettext ? (char_u *)_(name)
7930 : name);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007931 return TRUE;
7932 }
7933 return FALSE;
7934}
7935
7936/*
Bram Moolenaar33570922005-01-25 22:26:29 +00007937 * Copy the values from typval_T "from" to typval_T "to".
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007938 * When needed allocates string or increases reference count.
Bram Moolenaare9a41262005-01-15 22:18:47 +00007939 * Does not make a copy of a list or dict but copies the reference!
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +00007940 * It is OK for "from" and "to" to point to the same item. This is used to
7941 * make a copy later.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007942 */
Bram Moolenaar7e506b62010-01-19 15:55:06 +01007943 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007944copy_tv(typval_T *from, typval_T *to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007945{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007946 to->v_type = from->v_type;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007947 to->v_lock = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007948 switch (from->v_type)
7949 {
7950 case VAR_NUMBER:
Bram Moolenaar520e1e42016-01-23 19:46:28 +01007951 case VAR_SPECIAL:
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007952 to->vval.v_number = from->vval.v_number;
7953 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007954 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01007955#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007956 to->vval.v_float = from->vval.v_float;
7957 break;
7958#endif
Bram Moolenaar835dc632016-02-07 14:27:38 +01007959 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007960#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +01007961 to->vval.v_job = from->vval.v_job;
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01007962 if (to->vval.v_job != NULL)
7963 ++to->vval.v_job->jv_refcount;
Bram Moolenaar835dc632016-02-07 14:27:38 +01007964 break;
7965#endif
Bram Moolenaar77073442016-02-13 23:23:53 +01007966 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007967#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +01007968 to->vval.v_channel = from->vval.v_channel;
Bram Moolenaar5cefd402016-02-16 12:44:26 +01007969 if (to->vval.v_channel != NULL)
7970 ++to->vval.v_channel->ch_refcount;
Bram Moolenaar77073442016-02-13 23:23:53 +01007971 break;
7972#endif
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007973 case VAR_STRING:
7974 case VAR_FUNC:
7975 if (from->vval.v_string == NULL)
7976 to->vval.v_string = NULL;
7977 else
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007978 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007979 to->vval.v_string = vim_strsave(from->vval.v_string);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007980 if (from->v_type == VAR_FUNC)
7981 func_ref(to->vval.v_string);
7982 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007983 break;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007984 case VAR_PARTIAL:
7985 if (from->vval.v_partial == NULL)
7986 to->vval.v_partial = NULL;
7987 else
7988 {
7989 to->vval.v_partial = from->vval.v_partial;
7990 ++to->vval.v_partial->pt_refcount;
7991 }
7992 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007993 case VAR_LIST:
7994 if (from->vval.v_list == NULL)
7995 to->vval.v_list = NULL;
7996 else
7997 {
7998 to->vval.v_list = from->vval.v_list;
7999 ++to->vval.v_list->lv_refcount;
8000 }
8001 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00008002 case VAR_DICT:
8003 if (from->vval.v_dict == NULL)
8004 to->vval.v_dict = NULL;
8005 else
8006 {
8007 to->vval.v_dict = from->vval.v_dict;
8008 ++to->vval.v_dict->dv_refcount;
8009 }
8010 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +01008011 case VAR_UNKNOWN:
Bram Moolenaar95f09602016-11-10 20:01:45 +01008012 internal_error("copy_tv(UNKNOWN)");
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008013 break;
8014 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008015}
8016
8017/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00008018 * Make a copy of an item.
8019 * Lists and Dictionaries are also copied. A deep copy if "deep" is set.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008020 * For deepcopy() "copyID" is zero for a full copy or the ID for when a
8021 * reference to an already copied list/dict can be used.
8022 * Returns FAIL or OK.
Bram Moolenaare9a41262005-01-15 22:18:47 +00008023 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02008024 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01008025item_copy(
8026 typval_T *from,
8027 typval_T *to,
8028 int deep,
8029 int copyID)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008030{
8031 static int recurse = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008032 int ret = OK;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008033
Bram Moolenaar33570922005-01-25 22:26:29 +00008034 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008035 {
8036 EMSG(_("E698: variable nested too deep for making a copy"));
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008037 return FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008038 }
8039 ++recurse;
8040
8041 switch (from->v_type)
8042 {
8043 case VAR_NUMBER:
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008044 case VAR_FLOAT:
Bram Moolenaare9a41262005-01-15 22:18:47 +00008045 case VAR_STRING:
8046 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01008047 case VAR_PARTIAL:
Bram Moolenaar15550002016-01-31 18:45:24 +01008048 case VAR_SPECIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01008049 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01008050 case VAR_CHANNEL:
Bram Moolenaare9a41262005-01-15 22:18:47 +00008051 copy_tv(from, to);
8052 break;
8053 case VAR_LIST:
8054 to->v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008055 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008056 if (from->vval.v_list == NULL)
8057 to->vval.v_list = NULL;
8058 else if (copyID != 0 && from->vval.v_list->lv_copyID == copyID)
8059 {
8060 /* use the copy made earlier */
8061 to->vval.v_list = from->vval.v_list->lv_copylist;
8062 ++to->vval.v_list->lv_refcount;
8063 }
8064 else
8065 to->vval.v_list = list_copy(from->vval.v_list, deep, copyID);
8066 if (to->vval.v_list == NULL)
8067 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008068 break;
8069 case VAR_DICT:
8070 to->v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008071 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008072 if (from->vval.v_dict == NULL)
8073 to->vval.v_dict = NULL;
8074 else if (copyID != 0 && from->vval.v_dict->dv_copyID == copyID)
8075 {
8076 /* use the copy made earlier */
8077 to->vval.v_dict = from->vval.v_dict->dv_copydict;
8078 ++to->vval.v_dict->dv_refcount;
8079 }
8080 else
8081 to->vval.v_dict = dict_copy(from->vval.v_dict, deep, copyID);
8082 if (to->vval.v_dict == NULL)
8083 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008084 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +01008085 case VAR_UNKNOWN:
Bram Moolenaar95f09602016-11-10 20:01:45 +01008086 internal_error("item_copy(UNKNOWN)");
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008087 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008088 }
8089 --recurse;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008090 return ret;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008091}
8092
8093/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008094 * This function is used by f_input() and f_inputdialog() functions. The third
8095 * argument to f_input() specifies the type of completion to use at the
8096 * prompt. The third argument to f_inputdialog() specifies the value to return
8097 * when the user cancels the prompt.
8098 */
8099 void
8100get_user_input(
8101 typval_T *argvars,
8102 typval_T *rettv,
8103 int inputdialog,
8104 int secret)
8105{
8106 char_u *prompt = get_tv_string_chk(&argvars[0]);
8107 char_u *p = NULL;
8108 int c;
8109 char_u buf[NUMBUFLEN];
8110 int cmd_silent_save = cmd_silent;
8111 char_u *defstr = (char_u *)"";
8112 int xp_type = EXPAND_NOTHING;
8113 char_u *xp_arg = NULL;
8114
8115 rettv->v_type = VAR_STRING;
8116 rettv->vval.v_string = NULL;
8117
8118#ifdef NO_CONSOLE_INPUT
8119 /* While starting up, there is no place to enter text. */
8120 if (no_console_input())
8121 return;
8122#endif
8123
8124 cmd_silent = FALSE; /* Want to see the prompt. */
8125 if (prompt != NULL)
8126 {
8127 /* Only the part of the message after the last NL is considered as
8128 * prompt for the command line */
8129 p = vim_strrchr(prompt, '\n');
8130 if (p == NULL)
8131 p = prompt;
8132 else
8133 {
8134 ++p;
8135 c = *p;
8136 *p = NUL;
8137 msg_start();
8138 msg_clr_eos();
8139 msg_puts_attr(prompt, echo_attr);
8140 msg_didout = FALSE;
8141 msg_starthere();
8142 *p = c;
8143 }
8144 cmdline_row = msg_row;
8145
8146 if (argvars[1].v_type != VAR_UNKNOWN)
8147 {
8148 defstr = get_tv_string_buf_chk(&argvars[1], buf);
8149 if (defstr != NULL)
8150 stuffReadbuffSpec(defstr);
8151
8152 if (!inputdialog && argvars[2].v_type != VAR_UNKNOWN)
8153 {
8154 char_u *xp_name;
8155 int xp_namelen;
8156 long argt;
8157
8158 /* input() with a third argument: completion */
8159 rettv->vval.v_string = NULL;
8160
8161 xp_name = get_tv_string_buf_chk(&argvars[2], buf);
8162 if (xp_name == NULL)
8163 return;
8164
8165 xp_namelen = (int)STRLEN(xp_name);
8166
8167 if (parse_compl_arg(xp_name, xp_namelen, &xp_type, &argt,
8168 &xp_arg) == FAIL)
8169 return;
8170 }
8171 }
8172
8173 if (defstr != NULL)
8174 {
8175 int save_ex_normal_busy = ex_normal_busy;
8176 ex_normal_busy = 0;
8177 rettv->vval.v_string =
8178 getcmdline_prompt(secret ? NUL : '@', p, echo_attr,
8179 xp_type, xp_arg);
8180 ex_normal_busy = save_ex_normal_busy;
8181 }
8182 if (inputdialog && rettv->vval.v_string == NULL
8183 && argvars[1].v_type != VAR_UNKNOWN
8184 && argvars[2].v_type != VAR_UNKNOWN)
8185 rettv->vval.v_string = vim_strsave(get_tv_string_buf(
8186 &argvars[2], buf));
8187
8188 vim_free(xp_arg);
8189
8190 /* since the user typed this, no need to wait for return */
8191 need_wait_return = FALSE;
8192 msg_didout = FALSE;
8193 }
8194 cmd_silent = cmd_silent_save;
8195}
8196
8197/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008198 * ":echo expr1 ..." print each argument separated with a space, add a
8199 * newline at the end.
8200 * ":echon expr1 ..." print each argument plain.
8201 */
8202 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008203ex_echo(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008204{
8205 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00008206 typval_T rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008207 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008208 char_u *p;
8209 int needclr = TRUE;
8210 int atstart = TRUE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008211 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +00008212
8213 if (eap->skip)
8214 ++emsg_skip;
8215 while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int)
8216 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008217 /* If eval1() causes an error message the text from the command may
8218 * still need to be cleared. E.g., "echo 22,44". */
8219 need_clr_eos = needclr;
8220
Bram Moolenaar071d4272004-06-13 20:20:40 +00008221 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008222 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008223 {
8224 /*
8225 * Report the invalid expression unless the expression evaluation
8226 * has been cancelled due to an aborting error, an interrupt, or an
8227 * exception.
8228 */
8229 if (!aborting())
8230 EMSG2(_(e_invexpr2), p);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008231 need_clr_eos = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008232 break;
8233 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008234 need_clr_eos = FALSE;
8235
Bram Moolenaar071d4272004-06-13 20:20:40 +00008236 if (!eap->skip)
8237 {
8238 if (atstart)
8239 {
8240 atstart = FALSE;
8241 /* Call msg_start() after eval1(), evaluating the expression
8242 * may cause a message to appear. */
8243 if (eap->cmdidx == CMD_echo)
Bram Moolenaar12b02902012-03-23 15:18:24 +01008244 {
Bram Moolenaar6df5e5a2012-03-28 16:49:29 +02008245 /* Mark the saved text as finishing the line, so that what
8246 * follows is displayed on a new line when scrolling back
8247 * at the more prompt. */
8248 msg_sb_eol();
Bram Moolenaar071d4272004-06-13 20:20:40 +00008249 msg_start();
Bram Moolenaar12b02902012-03-23 15:18:24 +01008250 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008251 }
8252 else if (eap->cmdidx == CMD_echo)
8253 msg_puts_attr((char_u *)" ", echo_attr);
Bram Moolenaar520e1e42016-01-23 19:46:28 +01008254 p = echo_string(&rettv, &tofree, numbuf, get_copyID());
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008255 if (p != NULL)
8256 for ( ; *p != NUL && !got_int; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008257 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008258 if (*p == '\n' || *p == '\r' || *p == TAB)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008259 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008260 if (*p != TAB && needclr)
8261 {
8262 /* remove any text still there from the command */
8263 msg_clr_eos();
8264 needclr = FALSE;
8265 }
8266 msg_putchar_attr(*p, echo_attr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008267 }
8268 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008269 {
8270#ifdef FEAT_MBYTE
8271 if (has_mbyte)
8272 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00008273 int i = (*mb_ptr2len)(p);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008274
8275 (void)msg_outtrans_len_attr(p, i, echo_attr);
8276 p += i - 1;
8277 }
8278 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00008279#endif
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008280 (void)msg_outtrans_len_attr(p, 1, echo_attr);
8281 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008282 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008283 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008284 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008285 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008286 arg = skipwhite(arg);
8287 }
8288 eap->nextcmd = check_nextcmd(arg);
8289
8290 if (eap->skip)
8291 --emsg_skip;
8292 else
8293 {
8294 /* remove text that may still be there from the command */
8295 if (needclr)
8296 msg_clr_eos();
8297 if (eap->cmdidx == CMD_echo)
8298 msg_end();
8299 }
8300}
8301
8302/*
8303 * ":echohl {name}".
8304 */
8305 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008306ex_echohl(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008307{
8308 int id;
8309
8310 id = syn_name2id(eap->arg);
8311 if (id == 0)
8312 echo_attr = 0;
8313 else
8314 echo_attr = syn_id2attr(id);
8315}
8316
8317/*
8318 * ":execute expr1 ..." execute the result of an expression.
8319 * ":echomsg expr1 ..." Print a message
8320 * ":echoerr expr1 ..." Print an error
8321 * Each gets spaces around each argument and a newline at the end for
8322 * echo commands
8323 */
8324 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008325ex_execute(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008326{
8327 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00008328 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008329 int ret = OK;
8330 char_u *p;
8331 garray_T ga;
8332 int len;
8333 int save_did_emsg;
8334
8335 ga_init2(&ga, 1, 80);
8336
8337 if (eap->skip)
8338 ++emsg_skip;
8339 while (*arg != NUL && *arg != '|' && *arg != '\n')
8340 {
8341 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008342 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008343 {
8344 /*
8345 * Report the invalid expression unless the expression evaluation
8346 * has been cancelled due to an aborting error, an interrupt, or an
8347 * exception.
8348 */
8349 if (!aborting())
8350 EMSG2(_(e_invexpr2), p);
8351 ret = FAIL;
8352 break;
8353 }
8354
8355 if (!eap->skip)
8356 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008357 p = get_tv_string(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008358 len = (int)STRLEN(p);
8359 if (ga_grow(&ga, len + 2) == FAIL)
8360 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008361 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008362 ret = FAIL;
8363 break;
8364 }
8365 if (ga.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008366 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
Bram Moolenaar071d4272004-06-13 20:20:40 +00008367 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008368 ga.ga_len += len;
8369 }
8370
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008371 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008372 arg = skipwhite(arg);
8373 }
8374
8375 if (ret != FAIL && ga.ga_data != NULL)
8376 {
8377 if (eap->cmdidx == CMD_echomsg)
Bram Moolenaar4770d092006-01-12 23:22:24 +00008378 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00008379 MSG_ATTR(ga.ga_data, echo_attr);
Bram Moolenaar4770d092006-01-12 23:22:24 +00008380 out_flush();
8381 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008382 else if (eap->cmdidx == CMD_echoerr)
8383 {
8384 /* We don't want to abort following commands, restore did_emsg. */
8385 save_did_emsg = did_emsg;
8386 EMSG((char_u *)ga.ga_data);
8387 if (!force_abort)
8388 did_emsg = save_did_emsg;
8389 }
8390 else if (eap->cmdidx == CMD_execute)
8391 do_cmdline((char_u *)ga.ga_data,
8392 eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE);
8393 }
8394
8395 ga_clear(&ga);
8396
8397 if (eap->skip)
8398 --emsg_skip;
8399
8400 eap->nextcmd = check_nextcmd(arg);
8401}
8402
8403/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008404 * Find window specified by "vp" in tabpage "tp".
8405 */
8406 win_T *
8407find_win_by_nr(
8408 typval_T *vp,
8409 tabpage_T *tp UNUSED) /* NULL for current tab page */
8410{
8411#ifdef FEAT_WINDOWS
8412 win_T *wp;
8413#endif
8414 int nr;
8415
8416 nr = (int)get_tv_number_chk(vp, NULL);
8417
8418#ifdef FEAT_WINDOWS
8419 if (nr < 0)
8420 return NULL;
8421 if (nr == 0)
8422 return curwin;
8423
Bram Moolenaar29323592016-07-24 22:04:11 +02008424 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
8425 {
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008426 if (nr >= LOWEST_WIN_ID)
8427 {
8428 if (wp->w_id == nr)
8429 return wp;
8430 }
8431 else if (--nr <= 0)
8432 break;
Bram Moolenaar29323592016-07-24 22:04:11 +02008433 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008434 if (nr >= LOWEST_WIN_ID)
8435 return NULL;
8436 return wp;
8437#else
8438 if (nr == 0 || nr == 1 || nr == curwin->w_id)
8439 return curwin;
8440 return NULL;
8441#endif
8442}
8443
8444/*
8445 * Find window specified by "wvp" in tabpage "tvp".
8446 */
8447 win_T *
8448find_tabwin(
8449 typval_T *wvp, /* VAR_UNKNOWN for current window */
8450 typval_T *tvp) /* VAR_UNKNOWN for current tab page */
8451{
8452 win_T *wp = NULL;
8453 tabpage_T *tp = NULL;
8454 long n;
8455
8456 if (wvp->v_type != VAR_UNKNOWN)
8457 {
8458 if (tvp->v_type != VAR_UNKNOWN)
8459 {
8460 n = (long)get_tv_number(tvp);
8461 if (n >= 0)
8462 tp = find_tabpage(n);
8463 }
8464 else
8465 tp = curtab;
8466
8467 if (tp != NULL)
8468 wp = find_win_by_nr(wvp, tp);
8469 }
8470 else
8471 wp = curwin;
8472
8473 return wp;
8474}
8475
8476/*
8477 * getwinvar() and gettabwinvar()
8478 */
8479 void
8480getwinvar(
8481 typval_T *argvars,
8482 typval_T *rettv,
8483 int off) /* 1 for gettabwinvar() */
8484{
8485 win_T *win;
8486 char_u *varname;
8487 dictitem_T *v;
8488 tabpage_T *tp = NULL;
8489 int done = FALSE;
8490#ifdef FEAT_WINDOWS
8491 win_T *oldcurwin;
8492 tabpage_T *oldtabpage;
8493 int need_switch_win;
8494#endif
8495
8496#ifdef FEAT_WINDOWS
8497 if (off == 1)
8498 tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL));
8499 else
8500 tp = curtab;
8501#endif
8502 win = find_win_by_nr(&argvars[off], tp);
8503 varname = get_tv_string_chk(&argvars[off + 1]);
8504 ++emsg_off;
8505
8506 rettv->v_type = VAR_STRING;
8507 rettv->vval.v_string = NULL;
8508
8509 if (win != NULL && varname != NULL)
8510 {
8511#ifdef FEAT_WINDOWS
8512 /* Set curwin to be our win, temporarily. Also set the tabpage,
8513 * otherwise the window is not valid. Only do this when needed,
8514 * autocommands get blocked. */
8515 need_switch_win = !(tp == curtab && win == curwin);
8516 if (!need_switch_win
8517 || switch_win(&oldcurwin, &oldtabpage, win, tp, TRUE) == OK)
8518#endif
8519 {
Bram Moolenaar30567352016-08-27 21:25:44 +02008520 if (*varname == '&')
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008521 {
Bram Moolenaar30567352016-08-27 21:25:44 +02008522 if (varname[1] == NUL)
8523 {
8524 /* get all window-local options in a dict */
8525 dict_T *opts = get_winbuf_options(FALSE);
8526
8527 if (opts != NULL)
8528 {
8529 rettv->v_type = VAR_DICT;
8530 rettv->vval.v_dict = opts;
8531 ++opts->dv_refcount;
8532 done = TRUE;
8533 }
8534 }
8535 else if (get_option_tv(&varname, rettv, 1) == OK)
8536 /* window-local-option */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008537 done = TRUE;
8538 }
8539 else
8540 {
8541 /* Look up the variable. */
8542 /* Let getwinvar({nr}, "") return the "w:" dictionary. */
8543 v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w',
8544 varname, FALSE);
8545 if (v != NULL)
8546 {
8547 copy_tv(&v->di_tv, rettv);
8548 done = TRUE;
8549 }
8550 }
8551 }
8552
8553#ifdef FEAT_WINDOWS
8554 if (need_switch_win)
8555 /* restore previous notion of curwin */
8556 restore_win(oldcurwin, oldtabpage, TRUE);
8557#endif
8558 }
8559
8560 if (!done && argvars[off + 2].v_type != VAR_UNKNOWN)
8561 /* use the default return value */
8562 copy_tv(&argvars[off + 2], rettv);
8563
8564 --emsg_off;
8565}
8566
8567/*
8568 * "setwinvar()" and "settabwinvar()" functions
8569 */
8570 void
8571setwinvar(typval_T *argvars, typval_T *rettv UNUSED, int off)
8572{
8573 win_T *win;
8574#ifdef FEAT_WINDOWS
8575 win_T *save_curwin;
8576 tabpage_T *save_curtab;
8577 int need_switch_win;
8578#endif
8579 char_u *varname, *winvarname;
8580 typval_T *varp;
8581 char_u nbuf[NUMBUFLEN];
8582 tabpage_T *tp = NULL;
8583
8584 if (check_restricted() || check_secure())
8585 return;
8586
8587#ifdef FEAT_WINDOWS
8588 if (off == 1)
8589 tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL));
8590 else
8591 tp = curtab;
8592#endif
8593 win = find_win_by_nr(&argvars[off], tp);
8594 varname = get_tv_string_chk(&argvars[off + 1]);
8595 varp = &argvars[off + 2];
8596
8597 if (win != NULL && varname != NULL && varp != NULL)
8598 {
8599#ifdef FEAT_WINDOWS
8600 need_switch_win = !(tp == curtab && win == curwin);
8601 if (!need_switch_win
8602 || switch_win(&save_curwin, &save_curtab, win, tp, TRUE) == OK)
8603#endif
8604 {
8605 if (*varname == '&')
8606 {
8607 long numval;
8608 char_u *strval;
8609 int error = FALSE;
8610
8611 ++varname;
8612 numval = (long)get_tv_number_chk(varp, &error);
8613 strval = get_tv_string_buf_chk(varp, nbuf);
8614 if (!error && strval != NULL)
8615 set_option_value(varname, numval, strval, OPT_LOCAL);
8616 }
8617 else
8618 {
8619 winvarname = alloc((unsigned)STRLEN(varname) + 3);
8620 if (winvarname != NULL)
8621 {
8622 STRCPY(winvarname, "w:");
8623 STRCPY(winvarname + 2, varname);
8624 set_var(winvarname, varp, TRUE);
8625 vim_free(winvarname);
8626 }
8627 }
8628 }
8629#ifdef FEAT_WINDOWS
8630 if (need_switch_win)
8631 restore_win(save_curwin, save_curtab, TRUE);
8632#endif
8633 }
8634}
8635
8636/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008637 * Skip over the name of an option: "&option", "&g:option" or "&l:option".
8638 * "arg" points to the "&" or '+' when called, to "option" when returning.
8639 * Returns NULL when no option name found. Otherwise pointer to the char
8640 * after the option name.
8641 */
8642 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01008643find_option_end(char_u **arg, int *opt_flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008644{
8645 char_u *p = *arg;
8646
8647 ++p;
8648 if (*p == 'g' && p[1] == ':')
8649 {
8650 *opt_flags = OPT_GLOBAL;
8651 p += 2;
8652 }
8653 else if (*p == 'l' && p[1] == ':')
8654 {
8655 *opt_flags = OPT_LOCAL;
8656 p += 2;
8657 }
8658 else
8659 *opt_flags = 0;
8660
8661 if (!ASCII_ISALPHA(*p))
8662 return NULL;
8663 *arg = p;
8664
8665 if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL)
8666 p += 4; /* termcap option */
8667 else
8668 while (ASCII_ISALPHA(*p))
8669 ++p;
8670 return p;
8671}
8672
8673/*
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008674 * Return the autoload script name for a function or variable name.
8675 * Returns NULL when out of memory.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008676 */
Bram Moolenaara1544c02013-05-30 12:35:52 +02008677 char_u *
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008678autoload_name(char_u *name)
Bram Moolenaara1544c02013-05-30 12:35:52 +02008679{
Bram Moolenaara1544c02013-05-30 12:35:52 +02008680 char_u *p;
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008681 char_u *scriptname;
Bram Moolenaara1544c02013-05-30 12:35:52 +02008682
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008683 /* Get the script file name: replace '#' with '/', append ".vim". */
8684 scriptname = alloc((unsigned)(STRLEN(name) + 14));
8685 if (scriptname == NULL)
Bram Moolenaar9bdfb002014-04-23 17:43:42 +02008686 return FALSE;
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008687 STRCPY(scriptname, "autoload/");
8688 STRCAT(scriptname, name);
8689 *vim_strrchr(scriptname, AUTOLOAD_CHAR) = NUL;
8690 STRCAT(scriptname, ".vim");
8691 while ((p = vim_strchr(scriptname, AUTOLOAD_CHAR)) != NULL)
8692 *p = '/';
8693 return scriptname;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008694}
8695
8696/*
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008697 * If "name" has a package name try autoloading the script for it.
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008698 * Return TRUE if a package was loaded.
8699 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008700 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01008701script_autoload(
8702 char_u *name,
8703 int reload) /* load script again when already loaded */
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008704{
8705 char_u *p;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00008706 char_u *scriptname, *tofree;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008707 int ret = FALSE;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00008708 int i;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008709
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00008710 /* If there is no '#' after name[0] there is no package name. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00008711 p = vim_strchr(name, AUTOLOAD_CHAR);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00008712 if (p == NULL || p == name)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008713 return FALSE;
8714
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00008715 tofree = scriptname = autoload_name(name);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008716
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00008717 /* Find the name in the list of previously loaded package names. Skip
8718 * "autoload/", it's always the same. */
8719 for (i = 0; i < ga_loaded.ga_len; ++i)
8720 if (STRCMP(((char_u **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0)
8721 break;
8722 if (!reload && i < ga_loaded.ga_len)
8723 ret = FALSE; /* was loaded already */
8724 else
8725 {
8726 /* Remember the name if it wasn't loaded already. */
8727 if (i == ga_loaded.ga_len && ga_grow(&ga_loaded, 1) == OK)
8728 {
8729 ((char_u **)ga_loaded.ga_data)[ga_loaded.ga_len++] = scriptname;
8730 tofree = NULL;
8731 }
8732
8733 /* Try loading the package from $VIMRUNTIME/autoload/<name>.vim */
Bram Moolenaar7f8989d2016-03-12 22:11:39 +01008734 if (source_runtime(scriptname, 0) == OK)
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00008735 ret = TRUE;
8736 }
8737
8738 vim_free(tofree);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008739 return ret;
8740}
8741
Bram Moolenaar071d4272004-06-13 20:20:40 +00008742#if defined(FEAT_VIMINFO) || defined(FEAT_SESSION)
8743typedef enum
8744{
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008745 VAR_FLAVOUR_DEFAULT, /* doesn't start with uppercase */
8746 VAR_FLAVOUR_SESSION, /* starts with uppercase, some lower */
8747 VAR_FLAVOUR_VIMINFO /* all uppercase */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008748} var_flavour_T;
8749
Bram Moolenaar48e697e2016-01-23 22:17:30 +01008750static var_flavour_T var_flavour(char_u *varname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008751
8752 static var_flavour_T
Bram Moolenaar7454a062016-01-30 15:14:10 +01008753var_flavour(char_u *varname)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008754{
8755 char_u *p = varname;
8756
8757 if (ASCII_ISUPPER(*p))
8758 {
8759 while (*(++p))
8760 if (ASCII_ISLOWER(*p))
8761 return VAR_FLAVOUR_SESSION;
8762 return VAR_FLAVOUR_VIMINFO;
8763 }
8764 else
8765 return VAR_FLAVOUR_DEFAULT;
8766}
8767#endif
8768
8769#if defined(FEAT_VIMINFO) || defined(PROTO)
8770/*
8771 * Restore global vars that start with a capital from the viminfo file
8772 */
8773 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01008774read_viminfo_varlist(vir_T *virp, int writing)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008775{
8776 char_u *tab;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008777 int type = VAR_NUMBER;
Bram Moolenaar33570922005-01-25 22:26:29 +00008778 typval_T tv;
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008779 void *save_funccal;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008780
8781 if (!writing && (find_viminfo_parameter('!') != NULL))
8782 {
8783 tab = vim_strchr(virp->vir_line + 1, '\t');
8784 if (tab != NULL)
8785 {
8786 *tab++ = '\0'; /* isolate the variable name */
Bram Moolenaar680eeca2010-10-20 17:44:42 +02008787 switch (*tab)
8788 {
8789 case 'S': type = VAR_STRING; break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008790#ifdef FEAT_FLOAT
Bram Moolenaar680eeca2010-10-20 17:44:42 +02008791 case 'F': type = VAR_FLOAT; break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008792#endif
Bram Moolenaar680eeca2010-10-20 17:44:42 +02008793 case 'D': type = VAR_DICT; break;
8794 case 'L': type = VAR_LIST; break;
Bram Moolenaara03f2332016-02-06 18:09:59 +01008795 case 'X': type = VAR_SPECIAL; break;
Bram Moolenaar680eeca2010-10-20 17:44:42 +02008796 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008797
8798 tab = vim_strchr(tab, '\t');
8799 if (tab != NULL)
8800 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008801 tv.v_type = type;
Bram Moolenaar680eeca2010-10-20 17:44:42 +02008802 if (type == VAR_STRING || type == VAR_DICT || type == VAR_LIST)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00008803 tv.vval.v_string = viminfo_readstring(virp,
Bram Moolenaar071d4272004-06-13 20:20:40 +00008804 (int)(tab - virp->vir_line + 1), TRUE);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008805#ifdef FEAT_FLOAT
8806 else if (type == VAR_FLOAT)
8807 (void)string2float(tab + 1, &tv.vval.v_float);
8808#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008809 else
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00008810 tv.vval.v_number = atol((char *)tab + 1);
Bram Moolenaar680eeca2010-10-20 17:44:42 +02008811 if (type == VAR_DICT || type == VAR_LIST)
8812 {
8813 typval_T *etv = eval_expr(tv.vval.v_string, NULL);
8814
8815 if (etv == NULL)
8816 /* Failed to parse back the dict or list, use it as a
8817 * string. */
8818 tv.v_type = VAR_STRING;
8819 else
8820 {
8821 vim_free(tv.vval.v_string);
8822 tv = *etv;
Bram Moolenaar507cc8a2012-03-23 15:37:02 +01008823 vim_free(etv);
Bram Moolenaar680eeca2010-10-20 17:44:42 +02008824 }
8825 }
8826
Bram Moolenaarb20e3342016-01-18 23:29:01 +01008827 /* when in a function use global variables */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008828 save_funccal = clear_current_funccal();
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00008829 set_var(virp->vir_line + 1, &tv, FALSE);
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008830 restore_current_funccal(save_funccal);
Bram Moolenaar680eeca2010-10-20 17:44:42 +02008831
8832 if (tv.v_type == VAR_STRING)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00008833 vim_free(tv.vval.v_string);
Bram Moolenaar680eeca2010-10-20 17:44:42 +02008834 else if (tv.v_type == VAR_DICT || tv.v_type == VAR_LIST)
8835 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008836 }
8837 }
8838 }
8839
8840 return viminfo_readline(virp);
8841}
8842
8843/*
8844 * Write global vars that start with a capital to the viminfo file
8845 */
8846 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008847write_viminfo_varlist(FILE *fp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008848{
Bram Moolenaar33570922005-01-25 22:26:29 +00008849 hashitem_T *hi;
8850 dictitem_T *this_var;
Bram Moolenaara7043832005-01-21 11:56:39 +00008851 int todo;
Bram Moolenaar2fc83fc2016-02-08 22:57:24 +01008852 char *s = "";
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008853 char_u *p;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008854 char_u *tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008855 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +00008856
8857 if (find_viminfo_parameter('!') == NULL)
8858 return;
8859
Bram Moolenaar9577c3e2010-05-14 12:16:25 +02008860 fputs(_("\n# global variables:\n"), fp);
Bram Moolenaara7043832005-01-21 11:56:39 +00008861
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008862 todo = (int)globvarht.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00008863 for (hi = globvarht.ht_array; todo > 0; ++hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008864 {
Bram Moolenaara7043832005-01-21 11:56:39 +00008865 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008866 {
Bram Moolenaara7043832005-01-21 11:56:39 +00008867 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00008868 this_var = HI2DI(hi);
8869 if (var_flavour(this_var->di_key) == VAR_FLAVOUR_VIMINFO)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008870 {
Bram Moolenaar33570922005-01-25 22:26:29 +00008871 switch (this_var->di_tv.v_type)
Bram Moolenaara7043832005-01-21 11:56:39 +00008872 {
8873 case VAR_STRING: s = "STR"; break;
8874 case VAR_NUMBER: s = "NUM"; break;
Bram Moolenaar680eeca2010-10-20 17:44:42 +02008875 case VAR_FLOAT: s = "FLO"; break;
Bram Moolenaar680eeca2010-10-20 17:44:42 +02008876 case VAR_DICT: s = "DIC"; break;
8877 case VAR_LIST: s = "LIS"; break;
Bram Moolenaara03f2332016-02-06 18:09:59 +01008878 case VAR_SPECIAL: s = "XPL"; break;
8879
8880 case VAR_UNKNOWN:
8881 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01008882 case VAR_PARTIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01008883 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01008884 case VAR_CHANNEL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01008885 continue;
Bram Moolenaara7043832005-01-21 11:56:39 +00008886 }
Bram Moolenaar33570922005-01-25 22:26:29 +00008887 fprintf(fp, "!%s\t%s\t", this_var->di_key, s);
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00008888 p = echo_string(&this_var->di_tv, &tofree, numbuf, 0);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008889 if (p != NULL)
8890 viminfo_writestring(fp, p);
Bram Moolenaara7043832005-01-21 11:56:39 +00008891 vim_free(tofree);
8892 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008893 }
8894 }
8895}
8896#endif
8897
8898#if defined(FEAT_SESSION) || defined(PROTO)
8899 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01008900store_session_globals(FILE *fd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008901{
Bram Moolenaar33570922005-01-25 22:26:29 +00008902 hashitem_T *hi;
8903 dictitem_T *this_var;
Bram Moolenaara7043832005-01-21 11:56:39 +00008904 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008905 char_u *p, *t;
8906
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008907 todo = (int)globvarht.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00008908 for (hi = globvarht.ht_array; todo > 0; ++hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008909 {
Bram Moolenaara7043832005-01-21 11:56:39 +00008910 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008911 {
Bram Moolenaara7043832005-01-21 11:56:39 +00008912 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00008913 this_var = HI2DI(hi);
8914 if ((this_var->di_tv.v_type == VAR_NUMBER
8915 || this_var->di_tv.v_type == VAR_STRING)
8916 && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00008917 {
Bram Moolenaara7043832005-01-21 11:56:39 +00008918 /* Escape special characters with a backslash. Turn a LF and
8919 * CR into \n and \r. */
Bram Moolenaar33570922005-01-25 22:26:29 +00008920 p = vim_strsave_escaped(get_tv_string(&this_var->di_tv),
Bram Moolenaara7043832005-01-21 11:56:39 +00008921 (char_u *)"\\\"\n\r");
8922 if (p == NULL) /* out of memory */
8923 break;
8924 for (t = p; *t != NUL; ++t)
8925 if (*t == '\n')
8926 *t = 'n';
8927 else if (*t == '\r')
8928 *t = 'r';
8929 if ((fprintf(fd, "let %s = %c%s%c",
Bram Moolenaar33570922005-01-25 22:26:29 +00008930 this_var->di_key,
8931 (this_var->di_tv.v_type == VAR_STRING) ? '"'
8932 : ' ',
8933 p,
8934 (this_var->di_tv.v_type == VAR_STRING) ? '"'
8935 : ' ') < 0)
Bram Moolenaara7043832005-01-21 11:56:39 +00008936 || put_eol(fd) == FAIL)
8937 {
8938 vim_free(p);
8939 return FAIL;
8940 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008941 vim_free(p);
8942 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008943#ifdef FEAT_FLOAT
8944 else if (this_var->di_tv.v_type == VAR_FLOAT
8945 && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION)
8946 {
8947 float_T f = this_var->di_tv.vval.v_float;
8948 int sign = ' ';
8949
8950 if (f < 0)
8951 {
8952 f = -f;
8953 sign = '-';
8954 }
Bram Moolenaar2b04b192012-01-26 11:45:30 +01008955 if ((fprintf(fd, "let %s = %c%f",
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008956 this_var->di_key, sign, f) < 0)
8957 || put_eol(fd) == FAIL)
8958 return FAIL;
8959 }
8960#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008961 }
8962 }
8963 return OK;
8964}
8965#endif
8966
Bram Moolenaar661b1822005-07-28 22:36:45 +00008967/*
8968 * Display script name where an item was last set.
8969 * Should only be invoked when 'verbose' is non-zero.
8970 */
8971 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008972last_set_msg(scid_T scriptID)
Bram Moolenaar661b1822005-07-28 22:36:45 +00008973{
Bram Moolenaarcafda4f2005-09-06 19:25:11 +00008974 char_u *p;
8975
Bram Moolenaar661b1822005-07-28 22:36:45 +00008976 if (scriptID != 0)
8977 {
Bram Moolenaarcafda4f2005-09-06 19:25:11 +00008978 p = home_replace_save(NULL, get_scriptname(scriptID));
8979 if (p != NULL)
8980 {
8981 verbose_enter();
8982 MSG_PUTS(_("\n\tLast set from "));
8983 MSG_PUTS(p);
8984 vim_free(p);
8985 verbose_leave();
8986 }
Bram Moolenaar661b1822005-07-28 22:36:45 +00008987 }
8988}
8989
Bram Moolenaar53744302015-07-17 17:38:22 +02008990/* reset v:option_new, v:option_old and v:option_type */
8991 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008992reset_v_option_vars(void)
Bram Moolenaar53744302015-07-17 17:38:22 +02008993{
8994 set_vim_var_string(VV_OPTION_NEW, NULL, -1);
8995 set_vim_var_string(VV_OPTION_OLD, NULL, -1);
8996 set_vim_var_string(VV_OPTION_TYPE, NULL, -1);
8997}
8998
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008999/*
9000 * Prepare "gap" for an assert error and add the sourcing position.
9001 */
9002 void
9003prepare_assert_error(garray_T *gap)
9004{
9005 char buf[NUMBUFLEN];
9006
9007 ga_init2(gap, 1, 100);
9008 if (sourcing_name != NULL)
9009 {
9010 ga_concat(gap, sourcing_name);
9011 if (sourcing_lnum > 0)
9012 ga_concat(gap, (char_u *)" ");
9013 }
9014 if (sourcing_lnum > 0)
9015 {
9016 sprintf(buf, "line %ld", (long)sourcing_lnum);
9017 ga_concat(gap, (char_u *)buf);
9018 }
9019 if (sourcing_name != NULL || sourcing_lnum > 0)
9020 ga_concat(gap, (char_u *)": ");
9021}
9022
9023/*
9024 * Add an assert error to v:errors.
9025 */
9026 void
9027assert_error(garray_T *gap)
9028{
9029 struct vimvar *vp = &vimvars[VV_ERRORS];
9030
9031 if (vp->vv_type != VAR_LIST || vimvars[VV_ERRORS].vv_list == NULL)
9032 /* Make sure v:errors is a list. */
9033 set_vim_var_list(VV_ERRORS, list_alloc());
9034 list_append_string(vimvars[VV_ERRORS].vv_list, gap->ga_data, gap->ga_len);
9035}
9036
9037 void
9038assert_equal_common(typval_T *argvars, assert_type_T atype)
9039{
9040 garray_T ga;
9041
9042 if (tv_equal(&argvars[0], &argvars[1], FALSE, FALSE)
9043 != (atype == ASSERT_EQUAL))
9044 {
9045 prepare_assert_error(&ga);
9046 fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1],
9047 atype);
9048 assert_error(&ga);
9049 ga_clear(&ga);
9050 }
9051}
9052
9053 void
9054assert_match_common(typval_T *argvars, assert_type_T atype)
9055{
9056 garray_T ga;
9057 char_u buf1[NUMBUFLEN];
9058 char_u buf2[NUMBUFLEN];
9059 char_u *pat = get_tv_string_buf_chk(&argvars[0], buf1);
9060 char_u *text = get_tv_string_buf_chk(&argvars[1], buf2);
9061
9062 if (pat == NULL || text == NULL)
9063 EMSG(_(e_invarg));
9064 else if (pattern_match(pat, text, FALSE) != (atype == ASSERT_MATCH))
9065 {
9066 prepare_assert_error(&ga);
9067 fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1],
9068 atype);
9069 assert_error(&ga);
9070 ga_clear(&ga);
9071 }
9072}
9073
Bram Moolenaar61c04492016-07-23 15:35:35 +02009074 void
9075assert_inrange(typval_T *argvars)
9076{
9077 garray_T ga;
9078 int error = FALSE;
9079 varnumber_T lower = get_tv_number_chk(&argvars[0], &error);
9080 varnumber_T upper = get_tv_number_chk(&argvars[1], &error);
9081 varnumber_T actual = get_tv_number_chk(&argvars[2], &error);
9082 char_u *tofree;
9083 char msg[200];
9084 char_u numbuf[NUMBUFLEN];
9085
9086 if (error)
9087 return;
9088 if (actual < lower || actual > upper)
9089 {
9090 prepare_assert_error(&ga);
9091 if (argvars[3].v_type != VAR_UNKNOWN)
9092 {
9093 ga_concat(&ga, tv2string(&argvars[3], &tofree, numbuf, 0));
9094 vim_free(tofree);
9095 }
9096 else
9097 {
9098 vim_snprintf(msg, 200, "Expected range %ld - %ld, but got %ld",
9099 (long)lower, (long)upper, (long)actual);
9100 ga_concat(&ga, (char_u *)msg);
9101 }
9102 assert_error(&ga);
9103 ga_clear(&ga);
9104 }
9105}
9106
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009107/*
9108 * Common for assert_true() and assert_false().
9109 */
9110 void
9111assert_bool(typval_T *argvars, int isTrue)
9112{
9113 int error = FALSE;
9114 garray_T ga;
9115
9116 if (argvars[0].v_type == VAR_SPECIAL
9117 && argvars[0].vval.v_number == (isTrue ? VVAL_TRUE : VVAL_FALSE))
9118 return;
9119 if (argvars[0].v_type != VAR_NUMBER
9120 || (get_tv_number_chk(&argvars[0], &error) == 0) == isTrue
9121 || error)
9122 {
9123 prepare_assert_error(&ga);
9124 fill_assert_error(&ga, &argvars[1],
9125 (char_u *)(isTrue ? "True" : "False"),
9126 NULL, &argvars[0], ASSERT_OTHER);
9127 assert_error(&ga);
9128 ga_clear(&ga);
9129 }
9130}
9131
9132 void
9133assert_exception(typval_T *argvars)
9134{
9135 garray_T ga;
9136 char_u *error = get_tv_string_chk(&argvars[0]);
9137
9138 if (vimvars[VV_EXCEPTION].vv_str == NULL)
9139 {
9140 prepare_assert_error(&ga);
9141 ga_concat(&ga, (char_u *)"v:exception is not set");
9142 assert_error(&ga);
9143 ga_clear(&ga);
9144 }
9145 else if (error != NULL
9146 && strstr((char *)vimvars[VV_EXCEPTION].vv_str, (char *)error) == NULL)
9147 {
9148 prepare_assert_error(&ga);
9149 fill_assert_error(&ga, &argvars[1], NULL, &argvars[0],
9150 &vimvars[VV_EXCEPTION].vv_tv, ASSERT_OTHER);
9151 assert_error(&ga);
9152 ga_clear(&ga);
9153 }
9154}
9155
9156 void
9157assert_fails(typval_T *argvars)
9158{
9159 char_u *cmd = get_tv_string_chk(&argvars[0]);
9160 garray_T ga;
9161
9162 called_emsg = FALSE;
9163 suppress_errthrow = TRUE;
9164 emsg_silent = TRUE;
9165 do_cmdline_cmd(cmd);
9166 if (!called_emsg)
9167 {
9168 prepare_assert_error(&ga);
9169 ga_concat(&ga, (char_u *)"command did not fail: ");
9170 ga_concat(&ga, cmd);
9171 assert_error(&ga);
9172 ga_clear(&ga);
9173 }
9174 else if (argvars[1].v_type != VAR_UNKNOWN)
9175 {
9176 char_u buf[NUMBUFLEN];
9177 char *error = (char *)get_tv_string_buf_chk(&argvars[1], buf);
9178
9179 if (error == NULL
9180 || strstr((char *)vimvars[VV_ERRMSG].vv_str, error) == NULL)
9181 {
9182 prepare_assert_error(&ga);
9183 fill_assert_error(&ga, &argvars[2], NULL, &argvars[1],
9184 &vimvars[VV_ERRMSG].vv_tv, ASSERT_OTHER);
9185 assert_error(&ga);
9186 ga_clear(&ga);
9187 }
9188 }
9189
9190 called_emsg = FALSE;
9191 suppress_errthrow = FALSE;
9192 emsg_silent = FALSE;
9193 emsg_on_display = FALSE;
9194 set_vim_var_string(VV_ERRMSG, NULL, 0);
9195}
9196
9197/*
9198 * Append "str" to "gap", escaping unprintable characters.
9199 * Changes NL to \n, CR to \r, etc.
9200 */
9201 static void
9202ga_concat_esc(garray_T *gap, char_u *str)
9203{
9204 char_u *p;
9205 char_u buf[NUMBUFLEN];
9206
9207 if (str == NULL)
9208 {
9209 ga_concat(gap, (char_u *)"NULL");
9210 return;
9211 }
9212
9213 for (p = str; *p != NUL; ++p)
9214 switch (*p)
9215 {
9216 case BS: ga_concat(gap, (char_u *)"\\b"); break;
9217 case ESC: ga_concat(gap, (char_u *)"\\e"); break;
9218 case FF: ga_concat(gap, (char_u *)"\\f"); break;
9219 case NL: ga_concat(gap, (char_u *)"\\n"); break;
9220 case TAB: ga_concat(gap, (char_u *)"\\t"); break;
9221 case CAR: ga_concat(gap, (char_u *)"\\r"); break;
9222 case '\\': ga_concat(gap, (char_u *)"\\\\"); break;
9223 default:
9224 if (*p < ' ')
9225 {
9226 vim_snprintf((char *)buf, NUMBUFLEN, "\\x%02x", *p);
9227 ga_concat(gap, buf);
9228 }
9229 else
9230 ga_append(gap, *p);
9231 break;
9232 }
9233}
9234
9235/*
9236 * Fill "gap" with information about an assert error.
9237 */
9238 void
9239fill_assert_error(
9240 garray_T *gap,
9241 typval_T *opt_msg_tv,
9242 char_u *exp_str,
9243 typval_T *exp_tv,
9244 typval_T *got_tv,
9245 assert_type_T atype)
9246{
9247 char_u numbuf[NUMBUFLEN];
9248 char_u *tofree;
9249
9250 if (opt_msg_tv->v_type != VAR_UNKNOWN)
9251 {
9252 ga_concat(gap, tv2string(opt_msg_tv, &tofree, numbuf, 0));
9253 vim_free(tofree);
9254 }
9255 else
9256 {
9257 if (atype == ASSERT_MATCH || atype == ASSERT_NOTMATCH)
9258 ga_concat(gap, (char_u *)"Pattern ");
Bram Moolenaar5869cf02017-01-14 20:06:14 +01009259 else if (atype == ASSERT_NOTEQUAL)
9260 ga_concat(gap, (char_u *)"Expected not equal to ");
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009261 else
9262 ga_concat(gap, (char_u *)"Expected ");
9263 if (exp_str == NULL)
9264 {
9265 ga_concat_esc(gap, tv2string(exp_tv, &tofree, numbuf, 0));
9266 vim_free(tofree);
9267 }
9268 else
9269 ga_concat_esc(gap, exp_str);
Bram Moolenaar5869cf02017-01-14 20:06:14 +01009270 if (atype != ASSERT_NOTEQUAL)
9271 {
9272 if (atype == ASSERT_MATCH)
9273 ga_concat(gap, (char_u *)" does not match ");
9274 else if (atype == ASSERT_NOTMATCH)
9275 ga_concat(gap, (char_u *)" does match ");
9276 else
9277 ga_concat(gap, (char_u *)" but got ");
9278 ga_concat_esc(gap, tv2string(got_tv, &tofree, numbuf, 0));
9279 vim_free(tofree);
9280 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009281 }
9282}
9283
Bram Moolenaar53744302015-07-17 17:38:22 +02009284
Bram Moolenaar071d4272004-06-13 20:20:40 +00009285#endif /* FEAT_EVAL */
9286
Bram Moolenaar071d4272004-06-13 20:20:40 +00009287
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009288#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009289
9290#ifdef WIN3264
9291/*
9292 * Functions for ":8" filename modifier: get 8.3 version of a filename.
9293 */
Bram Moolenaar48e697e2016-01-23 22:17:30 +01009294static int get_short_pathname(char_u **fnamep, char_u **bufp, int *fnamelen);
9295static int shortpath_for_invalid_fname(char_u **fname, char_u **bufp, int *fnamelen);
9296static int shortpath_for_partial(char_u **fnamep, char_u **bufp, int *fnamelen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009297
9298/*
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009299 * Get the short path (8.3) for the filename in "fnamep".
9300 * Only works for a valid file name.
9301 * When the path gets longer "fnamep" is changed and the allocated buffer
9302 * is put in "bufp".
9303 * *fnamelen is the length of "fnamep" and set to 0 for a nonexistent path.
9304 * Returns OK on success, FAIL on failure.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009305 */
9306 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01009307get_short_pathname(char_u **fnamep, char_u **bufp, int *fnamelen)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009308{
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009309 int l, len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009310 char_u *newbuf;
9311
9312 len = *fnamelen;
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +01009313 l = GetShortPathName((LPSTR)*fnamep, (LPSTR)*fnamep, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009314 if (l > len - 1)
9315 {
9316 /* If that doesn't work (not enough space), then save the string
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009317 * and try again with a new buffer big enough. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009318 newbuf = vim_strnsave(*fnamep, l);
9319 if (newbuf == NULL)
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009320 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009321
9322 vim_free(*bufp);
9323 *fnamep = *bufp = newbuf;
9324
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009325 /* Really should always succeed, as the buffer is big enough. */
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +01009326 l = GetShortPathName((LPSTR)*fnamep, (LPSTR)*fnamep, l+1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009327 }
9328
9329 *fnamelen = l;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009330 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009331}
9332
9333/*
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009334 * Get the short path (8.3) for the filename in "fname". The converted
9335 * path is returned in "bufp".
9336 *
9337 * Some of the directories specified in "fname" may not exist. This function
9338 * will shorten the existing directories at the beginning of the path and then
9339 * append the remaining non-existing path.
9340 *
9341 * fname - Pointer to the filename to shorten. On return, contains the
Bram Moolenaar2c704a72010-06-03 21:17:25 +02009342 * pointer to the shortened pathname
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009343 * bufp - Pointer to an allocated buffer for the filename.
9344 * fnamelen - Length of the filename pointed to by fname
9345 *
9346 * Returns OK on success (or nothing done) and FAIL on failure (out of memory).
Bram Moolenaar071d4272004-06-13 20:20:40 +00009347 */
9348 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01009349shortpath_for_invalid_fname(
9350 char_u **fname,
9351 char_u **bufp,
9352 int *fnamelen)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009353{
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009354 char_u *short_fname, *save_fname, *pbuf_unused;
9355 char_u *endp, *save_endp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009356 char_u ch;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009357 int old_len, len;
9358 int new_len, sfx_len;
9359 int retval = OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009360
9361 /* Make a copy */
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009362 old_len = *fnamelen;
9363 save_fname = vim_strnsave(*fname, old_len);
9364 pbuf_unused = NULL;
9365 short_fname = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009366
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009367 endp = save_fname + old_len - 1; /* Find the end of the copy */
9368 save_endp = endp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009369
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009370 /*
9371 * Try shortening the supplied path till it succeeds by removing one
9372 * directory at a time from the tail of the path.
9373 */
9374 len = 0;
9375 for (;;)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009376 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009377 /* go back one path-separator */
9378 while (endp > save_fname && !after_pathsep(save_fname, endp + 1))
9379 --endp;
9380 if (endp <= save_fname)
9381 break; /* processed the complete path */
9382
9383 /*
9384 * Replace the path separator with a NUL and try to shorten the
9385 * resulting path.
9386 */
9387 ch = *endp;
9388 *endp = 0;
9389 short_fname = save_fname;
Bram Moolenaarc236c162008-07-13 17:41:49 +00009390 len = (int)STRLEN(short_fname) + 1;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009391 if (get_short_pathname(&short_fname, &pbuf_unused, &len) == FAIL)
9392 {
9393 retval = FAIL;
9394 goto theend;
9395 }
9396 *endp = ch; /* preserve the string */
9397
9398 if (len > 0)
9399 break; /* successfully shortened the path */
9400
9401 /* failed to shorten the path. Skip the path separator */
9402 --endp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009403 }
9404
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009405 if (len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009406 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009407 /*
9408 * Succeeded in shortening the path. Now concatenate the shortened
9409 * path with the remaining path at the tail.
9410 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009411
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009412 /* Compute the length of the new path. */
9413 sfx_len = (int)(save_endp - endp) + 1;
9414 new_len = len + sfx_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009415
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009416 *fnamelen = new_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009417 vim_free(*bufp);
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009418 if (new_len > old_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009419 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009420 /* There is not enough space in the currently allocated string,
9421 * copy it to a buffer big enough. */
9422 *fname = *bufp = vim_strnsave(short_fname, new_len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009423 if (*fname == NULL)
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009424 {
9425 retval = FAIL;
9426 goto theend;
9427 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009428 }
9429 else
9430 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009431 /* Transfer short_fname to the main buffer (it's big enough),
9432 * unless get_short_pathname() did its work in-place. */
9433 *fname = *bufp = save_fname;
9434 if (short_fname != save_fname)
9435 vim_strncpy(save_fname, short_fname, len);
9436 save_fname = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009437 }
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009438
9439 /* concat the not-shortened part of the path */
9440 vim_strncpy(*fname + len, endp, sfx_len);
9441 (*fname)[new_len] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009442 }
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009443
9444theend:
9445 vim_free(pbuf_unused);
9446 vim_free(save_fname);
9447
9448 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009449}
9450
9451/*
9452 * Get a pathname for a partial path.
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009453 * Returns OK for success, FAIL for failure.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009454 */
9455 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01009456shortpath_for_partial(
9457 char_u **fnamep,
9458 char_u **bufp,
9459 int *fnamelen)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009460{
9461 int sepcount, len, tflen;
9462 char_u *p;
9463 char_u *pbuf, *tfname;
9464 int hasTilde;
9465
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009466 /* Count up the path separators from the RHS.. so we know which part
9467 * of the path to return. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009468 sepcount = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00009469 for (p = *fnamep; p < *fnamep + *fnamelen; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00009470 if (vim_ispathsep(*p))
9471 ++sepcount;
9472
9473 /* Need full path first (use expand_env() to remove a "~/") */
9474 hasTilde = (**fnamep == '~');
9475 if (hasTilde)
9476 pbuf = tfname = expand_env_save(*fnamep);
9477 else
9478 pbuf = tfname = FullName_save(*fnamep, FALSE);
9479
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00009480 len = tflen = (int)STRLEN(tfname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009481
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009482 if (get_short_pathname(&tfname, &pbuf, &len) == FAIL)
9483 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009484
9485 if (len == 0)
9486 {
9487 /* Don't have a valid filename, so shorten the rest of the
9488 * path if we can. This CAN give us invalid 8.3 filenames, but
9489 * there's not a lot of point in guessing what it might be.
9490 */
9491 len = tflen;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009492 if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == FAIL)
9493 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009494 }
9495
9496 /* Count the paths backward to find the beginning of the desired string. */
9497 for (p = tfname + len - 1; p >= tfname; --p)
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00009498 {
9499#ifdef FEAT_MBYTE
9500 if (has_mbyte)
9501 p -= mb_head_off(tfname, p);
9502#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009503 if (vim_ispathsep(*p))
9504 {
9505 if (sepcount == 0 || (hasTilde && sepcount == 1))
9506 break;
9507 else
9508 sepcount --;
9509 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00009510 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009511 if (hasTilde)
9512 {
9513 --p;
9514 if (p >= tfname)
9515 *p = '~';
9516 else
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009517 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009518 }
9519 else
9520 ++p;
9521
9522 /* Copy in the string - p indexes into tfname - allocated at pbuf */
9523 vim_free(*bufp);
9524 *fnamelen = (int)STRLEN(p);
9525 *bufp = pbuf;
9526 *fnamep = p;
9527
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009528 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009529}
9530#endif /* WIN3264 */
9531
9532/*
9533 * Adjust a filename, according to a string of modifiers.
9534 * *fnamep must be NUL terminated when called. When returning, the length is
9535 * determined by *fnamelen.
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009536 * Returns VALID_ flags or -1 for failure.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009537 * When there is an error, *fnamep is set to NULL.
9538 */
9539 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01009540modify_fname(
9541 char_u *src, /* string with modifiers */
9542 int *usedlen, /* characters after src that are used */
9543 char_u **fnamep, /* file name so far */
9544 char_u **bufp, /* buffer for allocated file name or NULL */
9545 int *fnamelen) /* length of fnamep */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009546{
9547 int valid = 0;
9548 char_u *tail;
9549 char_u *s, *p, *pbuf;
9550 char_u dirname[MAXPATHL];
9551 int c;
9552 int has_fullname = 0;
9553#ifdef WIN3264
Bram Moolenaardc935552011-08-17 15:23:23 +02009554 char_u *fname_start = *fnamep;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009555 int has_shortname = 0;
9556#endif
9557
9558repeat:
9559 /* ":p" - full path/file_name */
9560 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p')
9561 {
9562 has_fullname = 1;
9563
9564 valid |= VALID_PATH;
9565 *usedlen += 2;
9566
9567 /* Expand "~/path" for all systems and "~user/path" for Unix and VMS */
9568 if ((*fnamep)[0] == '~'
9569#if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME))
9570 && ((*fnamep)[1] == '/'
9571# ifdef BACKSLASH_IN_FILENAME
9572 || (*fnamep)[1] == '\\'
9573# endif
9574 || (*fnamep)[1] == NUL)
9575
9576#endif
9577 )
9578 {
9579 *fnamep = expand_env_save(*fnamep);
9580 vim_free(*bufp); /* free any allocated file name */
9581 *bufp = *fnamep;
9582 if (*fnamep == NULL)
9583 return -1;
9584 }
9585
9586 /* When "/." or "/.." is used: force expansion to get rid of it. */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00009587 for (p = *fnamep; *p != NUL; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00009588 {
9589 if (vim_ispathsep(*p)
9590 && p[1] == '.'
9591 && (p[2] == NUL
9592 || vim_ispathsep(p[2])
9593 || (p[2] == '.'
9594 && (p[3] == NUL || vim_ispathsep(p[3])))))
9595 break;
9596 }
9597
9598 /* FullName_save() is slow, don't use it when not needed. */
9599 if (*p != NUL || !vim_isAbsName(*fnamep))
9600 {
9601 *fnamep = FullName_save(*fnamep, *p != NUL);
9602 vim_free(*bufp); /* free any allocated file name */
9603 *bufp = *fnamep;
9604 if (*fnamep == NULL)
9605 return -1;
9606 }
9607
Bram Moolenaar9158f9e2012-06-20 14:02:27 +02009608#ifdef WIN3264
9609# if _WIN32_WINNT >= 0x0500
9610 if (vim_strchr(*fnamep, '~') != NULL)
9611 {
9612 /* Expand 8.3 filename to full path. Needed to make sure the same
9613 * file does not have two different names.
9614 * Note: problem does not occur if _WIN32_WINNT < 0x0500. */
9615 p = alloc(_MAX_PATH + 1);
9616 if (p != NULL)
9617 {
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +01009618 if (GetLongPathName((LPSTR)*fnamep, (LPSTR)p, _MAX_PATH))
Bram Moolenaar9158f9e2012-06-20 14:02:27 +02009619 {
9620 vim_free(*bufp);
9621 *bufp = *fnamep = p;
9622 }
9623 else
9624 vim_free(p);
9625 }
9626 }
9627# endif
9628#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009629 /* Append a path separator to a directory. */
9630 if (mch_isdir(*fnamep))
9631 {
9632 /* Make room for one or two extra characters. */
9633 *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2);
9634 vim_free(*bufp); /* free any allocated file name */
9635 *bufp = *fnamep;
9636 if (*fnamep == NULL)
9637 return -1;
9638 add_pathsep(*fnamep);
9639 }
9640 }
9641
9642 /* ":." - path relative to the current directory */
9643 /* ":~" - path relative to the home directory */
9644 /* ":8" - shortname path - postponed till after */
9645 while (src[*usedlen] == ':'
9646 && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8'))
9647 {
9648 *usedlen += 2;
9649 if (c == '8')
9650 {
9651#ifdef WIN3264
9652 has_shortname = 1; /* Postpone this. */
9653#endif
9654 continue;
9655 }
9656 pbuf = NULL;
9657 /* Need full path first (use expand_env() to remove a "~/") */
9658 if (!has_fullname)
9659 {
9660 if (c == '.' && **fnamep == '~')
9661 p = pbuf = expand_env_save(*fnamep);
9662 else
9663 p = pbuf = FullName_save(*fnamep, FALSE);
9664 }
9665 else
9666 p = *fnamep;
9667
9668 has_fullname = 0;
9669
9670 if (p != NULL)
9671 {
9672 if (c == '.')
9673 {
9674 mch_dirname(dirname, MAXPATHL);
9675 s = shorten_fname(p, dirname);
9676 if (s != NULL)
9677 {
9678 *fnamep = s;
9679 if (pbuf != NULL)
9680 {
9681 vim_free(*bufp); /* free any allocated file name */
9682 *bufp = pbuf;
9683 pbuf = NULL;
9684 }
9685 }
9686 }
9687 else
9688 {
9689 home_replace(NULL, p, dirname, MAXPATHL, TRUE);
9690 /* Only replace it when it starts with '~' */
9691 if (*dirname == '~')
9692 {
9693 s = vim_strsave(dirname);
9694 if (s != NULL)
9695 {
9696 *fnamep = s;
9697 vim_free(*bufp);
9698 *bufp = s;
9699 }
9700 }
9701 }
9702 vim_free(pbuf);
9703 }
9704 }
9705
9706 tail = gettail(*fnamep);
9707 *fnamelen = (int)STRLEN(*fnamep);
9708
9709 /* ":h" - head, remove "/file_name", can be repeated */
9710 /* Don't remove the first "/" or "c:\" */
9711 while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h')
9712 {
9713 valid |= VALID_HEAD;
9714 *usedlen += 2;
9715 s = get_past_head(*fnamep);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00009716 while (tail > s && after_pathsep(s, tail))
Bram Moolenaar5461cfe2007-09-25 18:40:14 +00009717 mb_ptr_back(*fnamep, tail);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009718 *fnamelen = (int)(tail - *fnamep);
9719#ifdef VMS
9720 if (*fnamelen > 0)
9721 *fnamelen += 1; /* the path separator is part of the path */
9722#endif
Bram Moolenaar5461cfe2007-09-25 18:40:14 +00009723 if (*fnamelen == 0)
9724 {
9725 /* Result is empty. Turn it into "." to make ":cd %:h" work. */
9726 p = vim_strsave((char_u *)".");
9727 if (p == NULL)
9728 return -1;
9729 vim_free(*bufp);
9730 *bufp = *fnamep = tail = p;
9731 *fnamelen = 1;
9732 }
9733 else
9734 {
9735 while (tail > s && !after_pathsep(s, tail))
9736 mb_ptr_back(*fnamep, tail);
9737 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009738 }
9739
9740 /* ":8" - shortname */
9741 if (src[*usedlen] == ':' && src[*usedlen + 1] == '8')
9742 {
9743 *usedlen += 2;
9744#ifdef WIN3264
9745 has_shortname = 1;
9746#endif
9747 }
9748
9749#ifdef WIN3264
Bram Moolenaardc935552011-08-17 15:23:23 +02009750 /*
9751 * Handle ":8" after we have done 'heads' and before we do 'tails'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009752 */
9753 if (has_shortname)
9754 {
Bram Moolenaardc935552011-08-17 15:23:23 +02009755 /* Copy the string if it is shortened by :h and when it wasn't copied
9756 * yet, because we are going to change it in place. Avoids changing
9757 * the buffer name for "%:8". */
9758 if (*fnamelen < (int)STRLEN(*fnamep) || *fnamep == fname_start)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009759 {
9760 p = vim_strnsave(*fnamep, *fnamelen);
Bram Moolenaardc935552011-08-17 15:23:23 +02009761 if (p == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009762 return -1;
9763 vim_free(*bufp);
9764 *bufp = *fnamep = p;
9765 }
9766
9767 /* Split into two implementations - makes it easier. First is where
Bram Moolenaardc935552011-08-17 15:23:23 +02009768 * there isn't a full name already, second is where there is. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009769 if (!has_fullname && !vim_isAbsName(*fnamep))
9770 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009771 if (shortpath_for_partial(fnamep, bufp, fnamelen) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009772 return -1;
9773 }
9774 else
9775 {
Bram Moolenaardc935552011-08-17 15:23:23 +02009776 int l = *fnamelen;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009777
Bram Moolenaardc935552011-08-17 15:23:23 +02009778 /* Simple case, already have the full-name.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009779 * Nearly always shorter, so try first time. */
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009780 if (get_short_pathname(fnamep, bufp, &l) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009781 return -1;
9782
9783 if (l == 0)
9784 {
Bram Moolenaardc935552011-08-17 15:23:23 +02009785 /* Couldn't find the filename, search the paths. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009786 l = *fnamelen;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009787 if (shortpath_for_invalid_fname(fnamep, bufp, &l) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009788 return -1;
9789 }
9790 *fnamelen = l;
9791 }
9792 }
9793#endif /* WIN3264 */
9794
9795 /* ":t" - tail, just the basename */
9796 if (src[*usedlen] == ':' && src[*usedlen + 1] == 't')
9797 {
9798 *usedlen += 2;
9799 *fnamelen -= (int)(tail - *fnamep);
9800 *fnamep = tail;
9801 }
9802
9803 /* ":e" - extension, can be repeated */
9804 /* ":r" - root, without extension, can be repeated */
9805 while (src[*usedlen] == ':'
9806 && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r'))
9807 {
9808 /* find a '.' in the tail:
9809 * - for second :e: before the current fname
9810 * - otherwise: The last '.'
9811 */
9812 if (src[*usedlen + 1] == 'e' && *fnamep > tail)
9813 s = *fnamep - 2;
9814 else
9815 s = *fnamep + *fnamelen - 1;
9816 for ( ; s > tail; --s)
9817 if (s[0] == '.')
9818 break;
9819 if (src[*usedlen + 1] == 'e') /* :e */
9820 {
9821 if (s > tail)
9822 {
9823 *fnamelen += (int)(*fnamep - (s + 1));
9824 *fnamep = s + 1;
9825#ifdef VMS
9826 /* cut version from the extension */
9827 s = *fnamep + *fnamelen - 1;
9828 for ( ; s > *fnamep; --s)
9829 if (s[0] == ';')
9830 break;
9831 if (s > *fnamep)
9832 *fnamelen = s - *fnamep;
9833#endif
9834 }
9835 else if (*fnamep <= tail)
9836 *fnamelen = 0;
9837 }
9838 else /* :r */
9839 {
9840 if (s > tail) /* remove one extension */
9841 *fnamelen = (int)(s - *fnamep);
9842 }
9843 *usedlen += 2;
9844 }
9845
9846 /* ":s?pat?foo?" - substitute */
9847 /* ":gs?pat?foo?" - global substitute */
9848 if (src[*usedlen] == ':'
9849 && (src[*usedlen + 1] == 's'
9850 || (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's')))
9851 {
9852 char_u *str;
9853 char_u *pat;
9854 char_u *sub;
9855 int sep;
9856 char_u *flags;
9857 int didit = FALSE;
9858
9859 flags = (char_u *)"";
9860 s = src + *usedlen + 2;
9861 if (src[*usedlen + 1] == 'g')
9862 {
9863 flags = (char_u *)"g";
9864 ++s;
9865 }
9866
9867 sep = *s++;
9868 if (sep)
9869 {
9870 /* find end of pattern */
9871 p = vim_strchr(s, sep);
9872 if (p != NULL)
9873 {
9874 pat = vim_strnsave(s, (int)(p - s));
9875 if (pat != NULL)
9876 {
9877 s = p + 1;
9878 /* find end of substitution */
9879 p = vim_strchr(s, sep);
9880 if (p != NULL)
9881 {
9882 sub = vim_strnsave(s, (int)(p - s));
9883 str = vim_strnsave(*fnamep, *fnamelen);
9884 if (sub != NULL && str != NULL)
9885 {
9886 *usedlen = (int)(p + 1 - src);
Bram Moolenaar72ab7292016-07-19 19:10:51 +02009887 s = do_string_sub(str, pat, sub, NULL, flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009888 if (s != NULL)
9889 {
9890 *fnamep = s;
9891 *fnamelen = (int)STRLEN(s);
9892 vim_free(*bufp);
9893 *bufp = s;
9894 didit = TRUE;
9895 }
9896 }
9897 vim_free(sub);
9898 vim_free(str);
9899 }
9900 vim_free(pat);
9901 }
9902 }
9903 /* after using ":s", repeat all the modifiers */
9904 if (didit)
9905 goto repeat;
9906 }
9907 }
9908
Bram Moolenaar26df0922014-02-23 23:39:13 +01009909 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'S')
9910 {
Bram Moolenaar5ca84ce2016-03-23 22:28:25 +01009911 /* vim_strsave_shellescape() needs a NUL terminated string. */
Bram Moolenaard4caf5c2016-03-24 19:14:35 +01009912 c = (*fnamep)[*fnamelen];
Bram Moolenaar52c6eaf2016-03-25 18:42:46 +01009913 if (c != NUL)
9914 (*fnamep)[*fnamelen] = NUL;
Bram Moolenaar26df0922014-02-23 23:39:13 +01009915 p = vim_strsave_shellescape(*fnamep, FALSE, FALSE);
Bram Moolenaar52c6eaf2016-03-25 18:42:46 +01009916 if (c != NUL)
9917 (*fnamep)[*fnamelen] = c;
Bram Moolenaar26df0922014-02-23 23:39:13 +01009918 if (p == NULL)
9919 return -1;
9920 vim_free(*bufp);
9921 *bufp = *fnamep = p;
9922 *fnamelen = (int)STRLEN(p);
9923 *usedlen += 2;
9924 }
9925
Bram Moolenaar071d4272004-06-13 20:20:40 +00009926 return valid;
9927}
9928
9929/*
9930 * Perform a substitution on "str" with pattern "pat" and substitute "sub".
Bram Moolenaar72ab7292016-07-19 19:10:51 +02009931 * When "sub" is NULL "expr" is used, must be a VAR_FUNC or VAR_PARTIAL.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009932 * "flags" can be "g" to do a global substitute.
9933 * Returns an allocated string, NULL for error.
9934 */
9935 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01009936do_string_sub(
9937 char_u *str,
9938 char_u *pat,
9939 char_u *sub,
Bram Moolenaar72ab7292016-07-19 19:10:51 +02009940 typval_T *expr,
Bram Moolenaar7454a062016-01-30 15:14:10 +01009941 char_u *flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009942{
9943 int sublen;
9944 regmatch_T regmatch;
9945 int i;
9946 int do_all;
9947 char_u *tail;
Bram Moolenaare90c8532014-11-05 16:03:44 +01009948 char_u *end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009949 garray_T ga;
9950 char_u *ret;
9951 char_u *save_cpo;
Bram Moolenaar8af26912014-01-23 20:09:34 +01009952 char_u *zero_width = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009953
9954 /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */
9955 save_cpo = p_cpo;
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +00009956 p_cpo = empty_option;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009957
9958 ga_init2(&ga, 1, 200);
9959
9960 do_all = (flags[0] == 'g');
9961
9962 regmatch.rm_ic = p_ic;
9963 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
9964 if (regmatch.regprog != NULL)
9965 {
9966 tail = str;
Bram Moolenaare90c8532014-11-05 16:03:44 +01009967 end = str + STRLEN(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009968 while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
9969 {
Bram Moolenaar8af26912014-01-23 20:09:34 +01009970 /* Skip empty match except for first match. */
9971 if (regmatch.startp[0] == regmatch.endp[0])
9972 {
9973 if (zero_width == regmatch.startp[0])
9974 {
9975 /* avoid getting stuck on a match with an empty string */
Bram Moolenaar8e7048c2014-06-12 18:39:22 +02009976 i = MB_PTR2LEN(tail);
9977 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail,
9978 (size_t)i);
9979 ga.ga_len += i;
9980 tail += i;
Bram Moolenaar8af26912014-01-23 20:09:34 +01009981 continue;
9982 }
9983 zero_width = regmatch.startp[0];
9984 }
9985
Bram Moolenaar071d4272004-06-13 20:20:40 +00009986 /*
9987 * Get some space for a temporary buffer to do the substitution
9988 * into. It will contain:
9989 * - The text up to where the match is.
9990 * - The substituted text.
9991 * - The text after the match.
9992 */
Bram Moolenaar72ab7292016-07-19 19:10:51 +02009993 sublen = vim_regsub(&regmatch, sub, expr, tail, FALSE, TRUE, FALSE);
Bram Moolenaare90c8532014-11-05 16:03:44 +01009994 if (ga_grow(&ga, (int)((end - tail) + sublen -
Bram Moolenaar071d4272004-06-13 20:20:40 +00009995 (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
9996 {
9997 ga_clear(&ga);
9998 break;
9999 }
10000
10001 /* copy the text up to where the match is */
10002 i = (int)(regmatch.startp[0] - tail);
10003 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
10004 /* add the substituted text */
Bram Moolenaar72ab7292016-07-19 19:10:51 +020010005 (void)vim_regsub(&regmatch, sub, expr, (char_u *)ga.ga_data
Bram Moolenaar071d4272004-06-13 20:20:40 +000010006 + ga.ga_len + i, TRUE, TRUE, FALSE);
10007 ga.ga_len += i + sublen - 1;
Bram Moolenaarceb84af2013-09-29 21:11:05 +020010008 tail = regmatch.endp[0];
10009 if (*tail == NUL)
10010 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010011 if (!do_all)
10012 break;
10013 }
10014
10015 if (ga.ga_data != NULL)
10016 STRCPY((char *)ga.ga_data + ga.ga_len, tail);
10017
Bram Moolenaar473de612013-06-08 18:19:48 +020010018 vim_regfree(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010019 }
10020
10021 ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data);
10022 ga_clear(&ga);
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +000010023 if (p_cpo == empty_option)
10024 p_cpo = save_cpo;
10025 else
Bram Moolenaar72ab7292016-07-19 19:10:51 +020010026 /* Darn, evaluating {sub} expression or {expr} changed the value. */
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +000010027 free_string_option(save_cpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010028
10029 return ret;
10030}
10031
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010032 static int
10033filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)
10034{
10035 typval_T rettv;
10036 typval_T argv[3];
10037 char_u buf[NUMBUFLEN];
10038 char_u *s;
10039 int retval = FAIL;
10040 int dummy;
10041
10042 copy_tv(tv, &vimvars[VV_VAL].vv_tv);
10043 argv[0] = vimvars[VV_KEY].vv_tv;
10044 argv[1] = vimvars[VV_VAL].vv_tv;
10045 if (expr->v_type == VAR_FUNC)
10046 {
10047 s = expr->vval.v_string;
Bram Moolenaardf48fb42016-07-22 21:50:18 +020010048 if (call_func(s, (int)STRLEN(s), &rettv, 2, argv, NULL,
10049 0L, 0L, &dummy, TRUE, NULL, NULL) == FAIL)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010050 goto theend;
10051 }
10052 else if (expr->v_type == VAR_PARTIAL)
10053 {
10054 partial_T *partial = expr->vval.v_partial;
10055
Bram Moolenaar437bafe2016-08-01 15:40:54 +020010056 s = partial_name(partial);
Bram Moolenaardf48fb42016-07-22 21:50:18 +020010057 if (call_func(s, (int)STRLEN(s), &rettv, 2, argv, NULL,
10058 0L, 0L, &dummy, TRUE, partial, NULL) == FAIL)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010059 goto theend;
10060 }
10061 else
10062 {
10063 s = get_tv_string_buf_chk(expr, buf);
10064 if (s == NULL)
10065 goto theend;
10066 s = skipwhite(s);
10067 if (eval1(&s, &rettv, TRUE) == FAIL)
10068 goto theend;
10069 if (*s != NUL) /* check for trailing chars after expr */
10070 {
10071 EMSG2(_(e_invexpr2), s);
10072 goto theend;
10073 }
10074 }
10075 if (map)
10076 {
10077 /* map(): replace the list item value */
10078 clear_tv(tv);
10079 rettv.v_lock = 0;
10080 *tv = rettv;
10081 }
10082 else
10083 {
10084 int error = FALSE;
10085
10086 /* filter(): when expr is zero remove the item */
10087 *remp = (get_tv_number_chk(&rettv, &error) == 0);
10088 clear_tv(&rettv);
10089 /* On type error, nothing has been removed; return FAIL to stop the
10090 * loop. The error message was given by get_tv_number_chk(). */
10091 if (error)
10092 goto theend;
10093 }
10094 retval = OK;
10095theend:
10096 clear_tv(&vimvars[VV_VAL].vv_tv);
10097 return retval;
10098}
10099
10100
10101/*
10102 * Implementation of map() and filter().
10103 */
10104 void
10105filter_map(typval_T *argvars, typval_T *rettv, int map)
10106{
10107 typval_T *expr;
10108 listitem_T *li, *nli;
10109 list_T *l = NULL;
10110 dictitem_T *di;
10111 hashtab_T *ht;
10112 hashitem_T *hi;
10113 dict_T *d = NULL;
10114 typval_T save_val;
10115 typval_T save_key;
10116 int rem;
10117 int todo;
10118 char_u *ermsg = (char_u *)(map ? "map()" : "filter()");
10119 char_u *arg_errmsg = (char_u *)(map ? N_("map() argument")
10120 : N_("filter() argument"));
10121 int save_did_emsg;
10122 int idx = 0;
10123
10124 if (argvars[0].v_type == VAR_LIST)
10125 {
10126 if ((l = argvars[0].vval.v_list) == NULL
10127 || (!map && tv_check_lock(l->lv_lock, arg_errmsg, TRUE)))
10128 return;
10129 }
10130 else if (argvars[0].v_type == VAR_DICT)
10131 {
10132 if ((d = argvars[0].vval.v_dict) == NULL
10133 || (!map && tv_check_lock(d->dv_lock, arg_errmsg, TRUE)))
10134 return;
10135 }
10136 else
10137 {
10138 EMSG2(_(e_listdictarg), ermsg);
10139 return;
10140 }
10141
10142 expr = &argvars[1];
10143 /* On type errors, the preceding call has already displayed an error
10144 * message. Avoid a misleading error message for an empty string that
10145 * was not passed as argument. */
10146 if (expr->v_type != VAR_UNKNOWN)
10147 {
10148 prepare_vimvar(VV_VAL, &save_val);
10149
10150 /* We reset "did_emsg" to be able to detect whether an error
10151 * occurred during evaluation of the expression. */
10152 save_did_emsg = did_emsg;
10153 did_emsg = FALSE;
10154
10155 prepare_vimvar(VV_KEY, &save_key);
10156 if (argvars[0].v_type == VAR_DICT)
10157 {
10158 vimvars[VV_KEY].vv_type = VAR_STRING;
10159
10160 ht = &d->dv_hashtab;
10161 hash_lock(ht);
10162 todo = (int)ht->ht_used;
10163 for (hi = ht->ht_array; todo > 0; ++hi)
10164 {
10165 if (!HASHITEM_EMPTY(hi))
10166 {
10167 int r;
10168
10169 --todo;
10170 di = HI2DI(hi);
10171 if (map &&
10172 (tv_check_lock(di->di_tv.v_lock, arg_errmsg, TRUE)
10173 || var_check_ro(di->di_flags, arg_errmsg, TRUE)))
10174 break;
10175 vimvars[VV_KEY].vv_str = vim_strsave(di->di_key);
10176 r = filter_map_one(&di->di_tv, expr, map, &rem);
10177 clear_tv(&vimvars[VV_KEY].vv_tv);
10178 if (r == FAIL || did_emsg)
10179 break;
10180 if (!map && rem)
10181 {
10182 if (var_check_fixed(di->di_flags, arg_errmsg, TRUE)
10183 || var_check_ro(di->di_flags, arg_errmsg, TRUE))
10184 break;
10185 dictitem_remove(d, di);
10186 }
10187 }
10188 }
10189 hash_unlock(ht);
10190 }
10191 else
10192 {
10193 vimvars[VV_KEY].vv_type = VAR_NUMBER;
10194
10195 for (li = l->lv_first; li != NULL; li = nli)
10196 {
10197 if (map && tv_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE))
10198 break;
10199 nli = li->li_next;
10200 vimvars[VV_KEY].vv_nr = idx;
10201 if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL
10202 || did_emsg)
10203 break;
10204 if (!map && rem)
10205 listitem_remove(l, li);
10206 ++idx;
10207 }
10208 }
10209
10210 restore_vimvar(VV_KEY, &save_key);
10211 restore_vimvar(VV_VAL, &save_val);
10212
10213 did_emsg |= save_did_emsg;
10214 }
10215
10216 copy_tv(&argvars[0], rettv);
10217}
10218
Bram Moolenaar071d4272004-06-13 20:20:40 +000010219#endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */