blob: 5c5fd2f10dec32aab21ff0aeb0dd8c3648238769 [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * eval.c: Expression evaluation.
12 */
Bram Moolenaarfefecb02016-02-27 21:27:20 +010013#define USING_FLOAT_STUFF
Bram Moolenaar071d4272004-06-13 20:20:40 +000014
15#include "vim.h"
16
Bram Moolenaar8c8de832008-06-24 22:58:06 +000017#if defined(FEAT_EVAL) || defined(PROTO)
18
Bram Moolenaar314f11d2010-08-09 22:07:08 +020019#ifdef VMS
20# include <float.h>
21#endif
22
Bram Moolenaar33570922005-01-25 22:26:29 +000023#define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */
Bram Moolenaar071d4272004-06-13 20:20:40 +000024
Bram Moolenaarc70646c2005-01-04 21:52:38 +000025static char *e_letunexp = N_("E18: Unexpected characters in :let");
Bram Moolenaarc70646c2005-01-04 21:52:38 +000026static char *e_undefvar = N_("E121: Undefined variable: %s");
27static char *e_missbrac = N_("E111: Missing ']'");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000028static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary");
29static char *e_letwrong = N_("E734: Wrong variable type for %s=");
Bram Moolenaar92124a32005-06-17 22:03:40 +000030static char *e_illvar = N_("E461: Illegal variable name: %s");
Bram Moolenaar9937a052019-06-15 15:45:06 +020031static char *e_cannot_mod = N_("E995: Cannot modify existing variable");
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020032#ifdef FEAT_FLOAT
Bram Moolenaar2a876e42013-06-12 22:08:58 +020033static char *e_float_as_string = N_("E806: using Float as a String");
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020034#endif
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +020035static char *e_nowhitespace = N_("E274: No white space allowed before parenthesis");
Bram Moolenaar8c8de832008-06-24 22:58:06 +000036
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +010037#define NAMESPACE_CHAR (char_u *)"abglstvw"
38
Bram Moolenaar230bb3f2013-04-24 14:07:45 +020039static dictitem_T globvars_var; /* variable used for g: */
Bram Moolenaar071d4272004-06-13 20:20:40 +000040
41/*
Bram Moolenaar532c7802005-01-27 14:44:31 +000042 * Old Vim variables such as "v:version" are also available without the "v:".
43 * Also in functions. We need a special hashtable for them.
44 */
Bram Moolenaar4debb442005-06-01 21:57:40 +000045static hashtab_T compat_hashtab;
Bram Moolenaar532c7802005-01-27 14:44:31 +000046
47/*
Bram Moolenaard9fba312005-06-26 22:34:35 +000048 * When recursively copying lists and dicts we need to remember which ones we
49 * have done to avoid endless recursiveness. This unique ID is used for that.
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +000050 * The last bit is used for previous_funccal, ignored when comparing.
Bram Moolenaard9fba312005-06-26 22:34:35 +000051 */
52static int current_copyID = 0;
Bram Moolenaar8502c702014-06-17 12:51:16 +020053
Bram Moolenaard9fba312005-06-26 22:34:35 +000054/*
Bram Moolenaar33570922005-01-25 22:26:29 +000055 * Array to hold the hashtab with variables local to each sourced script.
56 * Each item holds a variable (nameless) that points to the dict_T.
Bram Moolenaar071d4272004-06-13 20:20:40 +000057 */
Bram Moolenaar33570922005-01-25 22:26:29 +000058typedef struct
59{
60 dictitem_T sv_var;
61 dict_T sv_dict;
62} scriptvar_T;
63
Bram Moolenaar9577c3e2010-05-14 12:16:25 +020064static garray_T ga_scripts = {0, 0, sizeof(scriptvar_T *), 4, NULL};
65#define SCRIPT_SV(id) (((scriptvar_T **)ga_scripts.ga_data)[(id) - 1])
66#define SCRIPT_VARS(id) (SCRIPT_SV(id)->sv_dict.dv_hashtab)
Bram Moolenaar071d4272004-06-13 20:20:40 +000067
68static int echo_attr = 0; /* attributes used for ":echo" */
69
Bram Moolenaarc9b4b052006-04-30 18:54:39 +000070/* The names of packages that once were loaded are remembered. */
Bram Moolenaaraa35dd12006-04-29 22:03:41 +000071static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL};
72
Bram Moolenaar071d4272004-06-13 20:20:40 +000073/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000074 * Info used by a ":for" loop.
75 */
Bram Moolenaar33570922005-01-25 22:26:29 +000076typedef struct
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000077{
78 int fi_semicolon; /* TRUE if ending in '; var]' */
79 int fi_varcount; /* nr of variables in the list */
Bram Moolenaar33570922005-01-25 22:26:29 +000080 listwatch_T fi_lw; /* keep an eye on the item used. */
81 list_T *fi_list; /* list being used */
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +010082 int fi_bi; /* index of blob */
83 blob_T *fi_blob; /* blob being used */
Bram Moolenaar33570922005-01-25 22:26:29 +000084} forinfo_T;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000085
Bram Moolenaara7043832005-01-21 11:56:39 +000086
87/*
Bram Moolenaar33570922005-01-25 22:26:29 +000088 * Array to hold the value of v: variables.
89 * The value is in a dictitem, so that it can also be used in the v: scope.
90 * The reason to use this table anyway is for very quick access to the
91 * variables with the VV_ defines.
92 */
Bram Moolenaar33570922005-01-25 22:26:29 +000093
94/* values for vv_flags: */
95#define VV_COMPAT 1 /* compatible, also used without "v:" */
96#define VV_RO 2 /* read-only */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000097#define VV_RO_SBX 4 /* read-only in the sandbox */
Bram Moolenaar33570922005-01-25 22:26:29 +000098
Bram Moolenaarbee6c0c2016-03-25 15:40:50 +010099#define VV_NAME(s, t) s, {{t, 0, {0}}, 0, {0}}
Bram Moolenaar33570922005-01-25 22:26:29 +0000100
101static struct vimvar
102{
103 char *vv_name; /* name of variable, without v: */
Bram Moolenaarbee6c0c2016-03-25 15:40:50 +0100104 dictitem16_T vv_di; /* value and name for key (max 16 chars!) */
Bram Moolenaar33570922005-01-25 22:26:29 +0000105 char vv_flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */
106} vimvars[VV_LEN] =
107{
108 /*
109 * The order here must match the VV_ defines in vim.h!
110 * Initializing a union does not work, leave tv.vval empty to get zero's.
111 */
112 {VV_NAME("count", VAR_NUMBER), VV_COMPAT+VV_RO},
113 {VV_NAME("count1", VAR_NUMBER), VV_RO},
114 {VV_NAME("prevcount", VAR_NUMBER), VV_RO},
115 {VV_NAME("errmsg", VAR_STRING), VV_COMPAT},
116 {VV_NAME("warningmsg", VAR_STRING), 0},
117 {VV_NAME("statusmsg", VAR_STRING), 0},
118 {VV_NAME("shell_error", VAR_NUMBER), VV_COMPAT+VV_RO},
119 {VV_NAME("this_session", VAR_STRING), VV_COMPAT},
120 {VV_NAME("version", VAR_NUMBER), VV_COMPAT+VV_RO},
121 {VV_NAME("lnum", VAR_NUMBER), VV_RO_SBX},
122 {VV_NAME("termresponse", VAR_STRING), VV_RO},
123 {VV_NAME("fname", VAR_STRING), VV_RO},
124 {VV_NAME("lang", VAR_STRING), VV_RO},
125 {VV_NAME("lc_time", VAR_STRING), VV_RO},
126 {VV_NAME("ctype", VAR_STRING), VV_RO},
127 {VV_NAME("charconvert_from", VAR_STRING), VV_RO},
128 {VV_NAME("charconvert_to", VAR_STRING), VV_RO},
129 {VV_NAME("fname_in", VAR_STRING), VV_RO},
130 {VV_NAME("fname_out", VAR_STRING), VV_RO},
131 {VV_NAME("fname_new", VAR_STRING), VV_RO},
132 {VV_NAME("fname_diff", VAR_STRING), VV_RO},
133 {VV_NAME("cmdarg", VAR_STRING), VV_RO},
134 {VV_NAME("foldstart", VAR_NUMBER), VV_RO_SBX},
135 {VV_NAME("foldend", VAR_NUMBER), VV_RO_SBX},
136 {VV_NAME("folddashes", VAR_STRING), VV_RO_SBX},
137 {VV_NAME("foldlevel", VAR_NUMBER), VV_RO_SBX},
138 {VV_NAME("progname", VAR_STRING), VV_RO},
139 {VV_NAME("servername", VAR_STRING), VV_RO},
140 {VV_NAME("dying", VAR_NUMBER), VV_RO},
141 {VV_NAME("exception", VAR_STRING), VV_RO},
142 {VV_NAME("throwpoint", VAR_STRING), VV_RO},
143 {VV_NAME("register", VAR_STRING), VV_RO},
144 {VV_NAME("cmdbang", VAR_NUMBER), VV_RO},
145 {VV_NAME("insertmode", VAR_STRING), VV_RO},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000146 {VV_NAME("val", VAR_UNKNOWN), VV_RO},
147 {VV_NAME("key", VAR_UNKNOWN), VV_RO},
Bram Moolenaar05159a02005-02-26 23:04:13 +0000148 {VV_NAME("profiling", VAR_NUMBER), VV_RO},
Bram Moolenaar19a09a12005-03-04 23:39:37 +0000149 {VV_NAME("fcs_reason", VAR_STRING), VV_RO},
150 {VV_NAME("fcs_choice", VAR_STRING), 0},
Bram Moolenaare2ac10d2005-03-07 23:26:06 +0000151 {VV_NAME("beval_bufnr", VAR_NUMBER), VV_RO},
152 {VV_NAME("beval_winnr", VAR_NUMBER), VV_RO},
Bram Moolenaarc9721bd2016-06-04 17:41:03 +0200153 {VV_NAME("beval_winid", VAR_NUMBER), VV_RO},
Bram Moolenaare2ac10d2005-03-07 23:26:06 +0000154 {VV_NAME("beval_lnum", VAR_NUMBER), VV_RO},
155 {VV_NAME("beval_col", VAR_NUMBER), VV_RO},
156 {VV_NAME("beval_text", VAR_STRING), VV_RO},
Bram Moolenaar761b1132005-10-03 22:05:45 +0000157 {VV_NAME("scrollstart", VAR_STRING), 0},
Bram Moolenaard5bc83f2005-12-07 21:07:59 +0000158 {VV_NAME("swapname", VAR_STRING), VV_RO},
159 {VV_NAME("swapchoice", VAR_STRING), 0},
Bram Moolenaar63a121b2005-12-11 21:36:39 +0000160 {VV_NAME("swapcommand", VAR_STRING), VV_RO},
Bram Moolenaare659c952011-05-19 17:25:41 +0200161 {VV_NAME("char", VAR_STRING), 0},
Bram Moolenaar219b8702006-11-01 14:32:36 +0000162 {VV_NAME("mouse_win", VAR_NUMBER), 0},
Bram Moolenaar511972d2016-06-04 18:09:59 +0200163 {VV_NAME("mouse_winid", VAR_NUMBER), 0},
Bram Moolenaar219b8702006-11-01 14:32:36 +0000164 {VV_NAME("mouse_lnum", VAR_NUMBER), 0},
165 {VV_NAME("mouse_col", VAR_NUMBER), 0},
Bram Moolenaar8af1fbf2008-01-05 12:35:21 +0000166 {VV_NAME("operator", VAR_STRING), VV_RO},
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000167 {VV_NAME("searchforward", VAR_NUMBER), 0},
Bram Moolenaar8050efa2013-11-08 04:30:20 +0100168 {VV_NAME("hlsearch", VAR_NUMBER), 0},
Bram Moolenaard812df62008-11-09 12:46:09 +0000169 {VV_NAME("oldfiles", VAR_LIST), 0},
Bram Moolenaar727c8762010-10-20 19:17:48 +0200170 {VV_NAME("windowid", VAR_NUMBER), VV_RO},
Bram Moolenaara1706c92014-04-01 19:55:49 +0200171 {VV_NAME("progpath", VAR_STRING), VV_RO},
Bram Moolenaar42a45122015-07-10 17:56:23 +0200172 {VV_NAME("completed_item", VAR_DICT), VV_RO},
Bram Moolenaar53744302015-07-17 17:38:22 +0200173 {VV_NAME("option_new", VAR_STRING), VV_RO},
174 {VV_NAME("option_old", VAR_STRING), VV_RO},
Bram Moolenaard7c96872019-06-15 17:12:48 +0200175 {VV_NAME("option_oldlocal", VAR_STRING), VV_RO},
176 {VV_NAME("option_oldglobal", VAR_STRING), VV_RO},
177 {VV_NAME("option_command", VAR_STRING), VV_RO},
Bram Moolenaar53744302015-07-17 17:38:22 +0200178 {VV_NAME("option_type", VAR_STRING), VV_RO},
Bram Moolenaar43345542015-11-29 17:35:35 +0100179 {VV_NAME("errors", VAR_LIST), 0},
Bram Moolenaar520e1e42016-01-23 19:46:28 +0100180 {VV_NAME("false", VAR_SPECIAL), VV_RO},
181 {VV_NAME("true", VAR_SPECIAL), VV_RO},
182 {VV_NAME("null", VAR_SPECIAL), VV_RO},
183 {VV_NAME("none", VAR_SPECIAL), VV_RO},
Bram Moolenaar14735512016-03-26 21:00:08 +0100184 {VV_NAME("vim_did_enter", VAR_NUMBER), VV_RO},
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +0200185 {VV_NAME("testing", VAR_NUMBER), 0},
Bram Moolenaarf562e722016-07-19 17:25:25 +0200186 {VV_NAME("t_number", VAR_NUMBER), VV_RO},
187 {VV_NAME("t_string", VAR_NUMBER), VV_RO},
188 {VV_NAME("t_func", VAR_NUMBER), VV_RO},
189 {VV_NAME("t_list", VAR_NUMBER), VV_RO},
190 {VV_NAME("t_dict", VAR_NUMBER), VV_RO},
191 {VV_NAME("t_float", VAR_NUMBER), VV_RO},
192 {VV_NAME("t_bool", VAR_NUMBER), VV_RO},
193 {VV_NAME("t_none", VAR_NUMBER), VV_RO},
194 {VV_NAME("t_job", VAR_NUMBER), VV_RO},
195 {VV_NAME("t_channel", VAR_NUMBER), VV_RO},
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +0100196 {VV_NAME("t_blob", VAR_NUMBER), VV_RO},
Bram Moolenaar65e4c4f2017-10-14 23:24:25 +0200197 {VV_NAME("termrfgresp", VAR_STRING), VV_RO},
198 {VV_NAME("termrbgresp", VAR_STRING), VV_RO},
Bram Moolenaarf3af54e2017-08-30 14:53:06 +0200199 {VV_NAME("termu7resp", VAR_STRING), VV_RO},
Bram Moolenaar37df9a42019-06-14 14:39:51 +0200200 {VV_NAME("termstyleresp", VAR_STRING), VV_RO},
201 {VV_NAME("termblinkresp", VAR_STRING), VV_RO},
202 {VV_NAME("event", VAR_DICT), VV_RO},
203 {VV_NAME("versionlong", VAR_NUMBER), VV_RO},
Bram Moolenaar33570922005-01-25 22:26:29 +0000204};
205
206/* shorthand */
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000207#define vv_type vv_di.di_tv.v_type
208#define vv_nr vv_di.di_tv.vval.v_number
209#define vv_float vv_di.di_tv.vval.v_float
210#define vv_str vv_di.di_tv.vval.v_string
Bram Moolenaard812df62008-11-09 12:46:09 +0000211#define vv_list vv_di.di_tv.vval.v_list
Bram Moolenaar42a45122015-07-10 17:56:23 +0200212#define vv_dict vv_di.di_tv.vval.v_dict
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +0100213#define vv_blob vv_di.di_tv.vval.v_blob
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000214#define vv_tv vv_di.di_tv
Bram Moolenaar33570922005-01-25 22:26:29 +0000215
Bram Moolenaar230bb3f2013-04-24 14:07:45 +0200216static dictitem_T vimvars_var; /* variable used for v: */
Bram Moolenaar33570922005-01-25 22:26:29 +0000217#define vimvarht vimvardict.dv_hashtab
218
Bram Moolenaar9937a052019-06-15 15:45:06 +0200219static void ex_let_const(exarg_T *eap, int is_const);
220static int ex_let_vars(char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, int is_const, char_u *nextchars);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100221static char_u *skip_var_list(char_u *arg, int *var_count, int *semicolon);
222static char_u *skip_var_one(char_u *arg);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100223static void list_glob_vars(int *first);
224static void list_buf_vars(int *first);
225static void list_win_vars(int *first);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100226static void list_tab_vars(int *first);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100227static void list_vim_vars(int *first);
228static void list_script_vars(int *first);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100229static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first);
Bram Moolenaar9937a052019-06-15 15:45:06 +0200230static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, int is_const, char_u *endchars, char_u *op);
231static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, int is_const, char_u *op);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100232static int tv_op(typval_T *tv1, typval_T *tv2, char_u *op);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100233static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep);
234static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit);
235static int do_lock_var(lval_T *lp, char_u *name_end, int deep, int lock);
236static void item_lock(typval_T *tv, int deep, int lock);
Bram Moolenaara40058a2005-07-11 22:42:07 +0000237
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100238static int eval2(char_u **arg, typval_T *rettv, int evaluate);
239static int eval3(char_u **arg, typval_T *rettv, int evaluate);
240static int eval4(char_u **arg, typval_T *rettv, int evaluate);
241static int eval5(char_u **arg, typval_T *rettv, int evaluate);
242static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string);
243static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string);
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +0200244static int eval7_leader(typval_T *rettv, char_u *start_leader, char_u **end_leaderp);
Bram Moolenaara40058a2005-07-11 22:42:07 +0000245
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100246static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate);
247static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100248static int free_unref_items(int copyID);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100249static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100250static int get_env_len(char_u **arg);
Bram Moolenaar5843f5f2019-08-20 20:13:45 +0200251static int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose);
252static char_u *make_expanded_name(char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end);
253static int get_var_tv(char_u *name, int len, typval_T *rettv, dictitem_T **dip, int verbose, int no_autoload);
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +0200254static void check_vars(char_u *name, int len);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100255static typval_T *alloc_string_tv(char_u *string);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100256static void delete_var(hashtab_T *ht, hashitem_T *hi);
Bram Moolenaar32526b32019-01-19 17:43:09 +0100257static void list_one_var(dictitem_T *v, char *prefix, int *first);
258static void list_one_var_a(char *prefix, char_u *name, int type, char_u *string, int *first);
Bram Moolenaar9937a052019-06-15 15:45:06 +0200259static void set_var_const(char_u *name, typval_T *tv, int copy, int is_const);
Bram Moolenaar05c00c02019-02-11 22:00:11 +0100260static int tv_check_lock(typval_T *tv, char_u *name, int use_gettext);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100261static char_u *find_option_end(char_u **arg, int *opt_flags);
Bram Moolenaar2c704a72010-06-03 21:17:25 +0200262
Bram Moolenaar73dad1e2016-07-17 22:13:49 +0200263/* for VIM_VERSION_ defines */
264#include "version.h"
265
Bram Moolenaare21c1582019-03-02 11:57:09 +0100266/*
267 * Return "n1" divided by "n2", taking care of dividing by zero.
268 */
269 static varnumber_T
270num_divide(varnumber_T n1, varnumber_T n2)
271{
272 varnumber_T result;
273
274 if (n2 == 0) // give an error message?
275 {
276 if (n1 == 0)
277 result = VARNUM_MIN; // similar to NaN
278 else if (n1 < 0)
279 result = -VARNUM_MAX;
280 else
281 result = VARNUM_MAX;
282 }
283 else
284 result = n1 / n2;
285
286 return result;
287}
288
289/*
290 * Return "n1" modulus "n2", taking care of dividing by zero.
291 */
292 static varnumber_T
293num_modulus(varnumber_T n1, varnumber_T n2)
294{
295 // Give an error when n2 is 0?
296 return (n2 == 0) ? 0 : (n1 % n2);
297}
298
Bram Moolenaara1fa8922017-01-12 20:06:33 +0100299
300#if defined(EBCDIC) || defined(PROTO)
301/*
302 * Compare struct fst by function name.
303 */
304 static int
305compare_func_name(const void *s1, const void *s2)
306{
307 struct fst *p1 = (struct fst *)s1;
308 struct fst *p2 = (struct fst *)s2;
309
310 return STRCMP(p1->f_name, p2->f_name);
311}
312
313/*
314 * Sort the function table by function name.
Bram Moolenaarb5443cc2019-01-15 20:19:40 +0100315 * The sorting of the table above is ASCII dependent.
Bram Moolenaara1fa8922017-01-12 20:06:33 +0100316 * On machines using EBCDIC we have to sort it.
317 */
318 static void
319sortFunctions(void)
320{
321 int funcCnt = (int)(sizeof(functions) / sizeof(struct fst)) - 1;
322
323 qsort(functions, (size_t)funcCnt, sizeof(struct fst), compare_func_name);
324}
325#endif
326
327
Bram Moolenaar33570922005-01-25 22:26:29 +0000328/*
329 * Initialize the global and v: variables.
Bram Moolenaara7043832005-01-21 11:56:39 +0000330 */
331 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100332eval_init(void)
Bram Moolenaara7043832005-01-21 11:56:39 +0000333{
Bram Moolenaar33570922005-01-25 22:26:29 +0000334 int i;
335 struct vimvar *p;
336
Bram Moolenaarbdb62052012-07-16 17:31:53 +0200337 init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE);
338 init_var_dict(&vimvardict, &vimvars_var, VAR_SCOPE);
Bram Moolenaar32f649e2011-04-11 13:46:13 +0200339 vimvardict.dv_lock = VAR_FIXED;
Bram Moolenaar532c7802005-01-27 14:44:31 +0000340 hash_init(&compat_hashtab);
Bram Moolenaara9b579f2016-07-17 18:29:19 +0200341 func_init();
Bram Moolenaar33570922005-01-25 22:26:29 +0000342
343 for (i = 0; i < VV_LEN; ++i)
344 {
345 p = &vimvars[i];
Bram Moolenaard7c96872019-06-15 17:12:48 +0200346 if (STRLEN(p->vv_name) > DICTITEM16_KEY_LEN)
Bram Moolenaaref9d9b92016-03-28 22:44:50 +0200347 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100348 iemsg("INTERNAL: name too long, increase size of dictitem16_T");
Bram Moolenaaref9d9b92016-03-28 22:44:50 +0200349 getout(1);
350 }
Bram Moolenaar33570922005-01-25 22:26:29 +0000351 STRCPY(p->vv_di.di_key, p->vv_name);
352 if (p->vv_flags & VV_RO)
353 p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
354 else if (p->vv_flags & VV_RO_SBX)
355 p->vv_di.di_flags = DI_FLAGS_RO_SBX | DI_FLAGS_FIX;
356 else
357 p->vv_di.di_flags = DI_FLAGS_FIX;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000358
359 /* add to v: scope dict, unless the value is not always available */
360 if (p->vv_type != VAR_UNKNOWN)
361 hash_add(&vimvarht, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000362 if (p->vv_flags & VV_COMPAT)
Bram Moolenaar532c7802005-01-27 14:44:31 +0000363 /* add to compat scope dict */
364 hash_add(&compat_hashtab, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000365 }
Bram Moolenaara542c682016-01-31 16:28:04 +0100366 vimvars[VV_VERSION].vv_nr = VIM_VERSION_100;
Bram Moolenaar37df9a42019-06-14 14:39:51 +0200367 vimvars[VV_VERSIONLONG].vv_nr = VIM_VERSION_100 * 10000 + highest_patch();
Bram Moolenaara542c682016-01-31 16:28:04 +0100368
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000369 set_vim_var_nr(VV_SEARCHFORWARD, 1L);
Bram Moolenaar8050efa2013-11-08 04:30:20 +0100370 set_vim_var_nr(VV_HLSEARCH, 1L);
Bram Moolenaar7e1652c2017-12-16 18:27:02 +0100371 set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED));
Bram Moolenaar4649ded2015-12-03 14:55:55 +0100372 set_vim_var_list(VV_ERRORS, list_alloc());
Bram Moolenaar7e1652c2017-12-16 18:27:02 +0100373 set_vim_var_dict(VV_EVENT, dict_alloc_lock(VAR_FIXED));
Bram Moolenaar520e1e42016-01-23 19:46:28 +0100374
375 set_vim_var_nr(VV_FALSE, VVAL_FALSE);
376 set_vim_var_nr(VV_TRUE, VVAL_TRUE);
377 set_vim_var_nr(VV_NONE, VVAL_NONE);
378 set_vim_var_nr(VV_NULL, VVAL_NULL);
379
Bram Moolenaarf562e722016-07-19 17:25:25 +0200380 set_vim_var_nr(VV_TYPE_NUMBER, VAR_TYPE_NUMBER);
381 set_vim_var_nr(VV_TYPE_STRING, VAR_TYPE_STRING);
382 set_vim_var_nr(VV_TYPE_FUNC, VAR_TYPE_FUNC);
383 set_vim_var_nr(VV_TYPE_LIST, VAR_TYPE_LIST);
384 set_vim_var_nr(VV_TYPE_DICT, VAR_TYPE_DICT);
385 set_vim_var_nr(VV_TYPE_FLOAT, VAR_TYPE_FLOAT);
386 set_vim_var_nr(VV_TYPE_BOOL, VAR_TYPE_BOOL);
387 set_vim_var_nr(VV_TYPE_NONE, VAR_TYPE_NONE);
388 set_vim_var_nr(VV_TYPE_JOB, VAR_TYPE_JOB);
389 set_vim_var_nr(VV_TYPE_CHANNEL, VAR_TYPE_CHANNEL);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +0100390 set_vim_var_nr(VV_TYPE_BLOB, VAR_TYPE_BLOB);
Bram Moolenaarf562e722016-07-19 17:25:25 +0200391
Bram Moolenaarb429cde2012-04-25 18:24:29 +0200392 set_reg_var(0); /* default for v:register is not 0 but '"' */
Bram Moolenaar2c704a72010-06-03 21:17:25 +0200393
394#ifdef EBCDIC
395 /*
Bram Moolenaar195ea0f2011-11-30 14:57:31 +0100396 * Sort the function table, to enable binary search.
Bram Moolenaar2c704a72010-06-03 21:17:25 +0200397 */
398 sortFunctions();
399#endif
Bram Moolenaara7043832005-01-21 11:56:39 +0000400}
401
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000402#if defined(EXITFREE) || defined(PROTO)
403 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100404eval_clear(void)
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000405{
406 int i;
407 struct vimvar *p;
408
409 for (i = 0; i < VV_LEN; ++i)
410 {
411 p = &vimvars[i];
412 if (p->vv_di.di_tv.v_type == VAR_STRING)
Bram Moolenaard23a8232018-02-10 18:45:26 +0100413 VIM_CLEAR(p->vv_str);
Bram Moolenaard812df62008-11-09 12:46:09 +0000414 else if (p->vv_di.di_tv.v_type == VAR_LIST)
415 {
416 list_unref(p->vv_list);
417 p->vv_list = NULL;
Bram Moolenaard9fba312005-06-26 22:34:35 +0000418 }
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000419 }
420 hash_clear(&vimvarht);
Bram Moolenaar0f71c6d2008-11-12 14:29:28 +0000421 hash_init(&vimvarht); /* garbage_collect() will access it */
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000422 hash_clear(&compat_hashtab);
423
Bram Moolenaard9fba312005-06-26 22:34:35 +0000424 free_scriptnames();
Bram Moolenaar9b486ca2011-05-19 18:26:40 +0200425 free_locales();
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000426
427 /* global variables */
428 vars_clear(&globvarht);
Bram Moolenaard9fba312005-06-26 22:34:35 +0000429
Bram Moolenaaraa35dd12006-04-29 22:03:41 +0000430 /* autoloaded script names */
431 ga_clear_strings(&ga_loaded);
432
Bram Moolenaarcca74132013-09-25 21:00:28 +0200433 /* Script-local variables. First clear all the variables and in a second
434 * loop free the scriptvar_T, because a variable in one script might hold
435 * a reference to the whole scope of another script. */
Bram Moolenaar9577c3e2010-05-14 12:16:25 +0200436 for (i = 1; i <= ga_scripts.ga_len; ++i)
Bram Moolenaar9577c3e2010-05-14 12:16:25 +0200437 vars_clear(&SCRIPT_VARS(i));
Bram Moolenaarcca74132013-09-25 21:00:28 +0200438 for (i = 1; i <= ga_scripts.ga_len; ++i)
Bram Moolenaar9577c3e2010-05-14 12:16:25 +0200439 vim_free(SCRIPT_SV(i));
Bram Moolenaar9577c3e2010-05-14 12:16:25 +0200440 ga_clear(&ga_scripts);
441
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200442 // unreferenced lists and dicts
443 (void)garbage_collect(FALSE);
Bram Moolenaarc07f67a2019-06-06 19:03:17 +0200444
445 // functions not garbage collected
446 free_all_functions();
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000447}
448#endif
449
Bram Moolenaar071d4272004-06-13 20:20:40 +0000450
451/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000452 * Set an internal variable to a string value. Creates the variable if it does
453 * not already exist.
454 */
455 void
Bram Moolenaarb7604cc2016-01-15 21:23:22 +0100456set_internal_string_var(char_u *name, char_u *value)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000457{
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000458 char_u *val;
Bram Moolenaar33570922005-01-25 22:26:29 +0000459 typval_T *tvp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000460
461 val = vim_strsave(value);
462 if (val != NULL)
463 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000464 tvp = alloc_string_tv(val);
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000465 if (tvp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000466 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000467 set_var(name, tvp, FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000468 free_tv(tvp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000469 }
470 }
471}
472
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000473static lval_T *redir_lval = NULL;
Bram Moolenaar1e5e1232016-07-07 17:33:02 +0200474#define EVALCMD_BUSY (redir_lval == (lval_T *)&redir_lval)
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000475static garray_T redir_ga; /* only valid when redir_lval is not NULL */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000476static char_u *redir_endp = NULL;
477static char_u *redir_varname = NULL;
478
479/*
480 * Start recording command output to a variable
Bram Moolenaarb7604cc2016-01-15 21:23:22 +0100481 * When "append" is TRUE append to an existing variable.
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000482 * Returns OK if successfully completed the setup. FAIL otherwise.
483 */
484 int
Bram Moolenaarb7604cc2016-01-15 21:23:22 +0100485var_redir_start(char_u *name, int append)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000486{
487 int save_emsg;
488 int err;
489 typval_T tv;
490
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000491 /* Catch a bad name early. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000492 if (!eval_isnamec1(*name))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000493 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100494 emsg(_(e_invarg));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000495 return FAIL;
496 }
497
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000498 /* Make a copy of the name, it is used in redir_lval until redir ends. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000499 redir_varname = vim_strsave(name);
500 if (redir_varname == NULL)
501 return FAIL;
502
Bram Moolenaarc799fe22019-05-28 23:08:19 +0200503 redir_lval = ALLOC_CLEAR_ONE(lval_T);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000504 if (redir_lval == NULL)
505 {
506 var_redir_stop();
507 return FAIL;
508 }
509
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000510 /* The output is stored in growarray "redir_ga" until redirection ends. */
511 ga_init2(&redir_ga, (int)sizeof(char), 500);
512
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000513 /* Parse the variable name (can be a dict or list entry). */
Bram Moolenaar6d977d62014-01-14 15:24:39 +0100514 redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, 0,
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000515 FNE_CHECK_START);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000516 if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != NUL)
517 {
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +0200518 clear_lval(redir_lval);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000519 if (redir_endp != NULL && *redir_endp != NUL)
520 /* Trailing characters are present after the variable name */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100521 emsg(_(e_trailing));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000522 else
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100523 emsg(_(e_invarg));
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000524 redir_endp = NULL; /* don't store a value, only cleanup */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000525 var_redir_stop();
526 return FAIL;
527 }
528
529 /* check if we can write to the variable: set it to or append an empty
530 * string */
531 save_emsg = did_emsg;
532 did_emsg = FALSE;
533 tv.v_type = VAR_STRING;
534 tv.vval.v_string = (char_u *)"";
535 if (append)
Bram Moolenaar9937a052019-06-15 15:45:06 +0200536 set_var_lval(redir_lval, redir_endp, &tv, TRUE, FALSE, (char_u *)".");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000537 else
Bram Moolenaar9937a052019-06-15 15:45:06 +0200538 set_var_lval(redir_lval, redir_endp, &tv, TRUE, FALSE, (char_u *)"=");
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +0200539 clear_lval(redir_lval);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000540 err = did_emsg;
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000541 did_emsg |= save_emsg;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000542 if (err)
543 {
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000544 redir_endp = NULL; /* don't store a value, only cleanup */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000545 var_redir_stop();
546 return FAIL;
547 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000548
549 return OK;
550}
551
552/*
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000553 * Append "value[value_len]" to the variable set by var_redir_start().
554 * The actual appending is postponed until redirection ends, because the value
555 * appended may in fact be the string we write to, changing it may cause freed
556 * memory to be used:
557 * :redir => foo
558 * :let foo
559 * :redir END
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000560 */
561 void
Bram Moolenaarb7604cc2016-01-15 21:23:22 +0100562var_redir_str(char_u *value, int value_len)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000563{
Bram Moolenaar5fdec472007-07-24 08:45:13 +0000564 int len;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000565
566 if (redir_lval == NULL)
567 return;
568
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000569 if (value_len == -1)
Bram Moolenaar5fdec472007-07-24 08:45:13 +0000570 len = (int)STRLEN(value); /* Append the entire string */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000571 else
Bram Moolenaar5fdec472007-07-24 08:45:13 +0000572 len = value_len; /* Append only "value_len" characters */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000573
Bram Moolenaar5fdec472007-07-24 08:45:13 +0000574 if (ga_grow(&redir_ga, len) == OK)
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000575 {
576 mch_memmove((char *)redir_ga.ga_data + redir_ga.ga_len, value, len);
Bram Moolenaar5fdec472007-07-24 08:45:13 +0000577 redir_ga.ga_len += len;
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000578 }
579 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000580 var_redir_stop();
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000581}
582
583/*
584 * Stop redirecting command output to a variable.
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000585 * Frees the allocated memory.
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000586 */
587 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100588var_redir_stop(void)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000589{
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000590 typval_T tv;
591
Bram Moolenaar1e5e1232016-07-07 17:33:02 +0200592 if (EVALCMD_BUSY)
593 {
594 redir_lval = NULL;
595 return;
596 }
597
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000598 if (redir_lval != NULL)
599 {
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000600 /* If there was no error: assign the text to the variable. */
601 if (redir_endp != NULL)
602 {
603 ga_append(&redir_ga, NUL); /* Append the trailing NUL. */
604 tv.v_type = VAR_STRING;
605 tv.vval.v_string = redir_ga.ga_data;
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +0200606 /* Call get_lval() again, if it's inside a Dict or List it may
607 * have changed. */
608 redir_endp = get_lval(redir_varname, NULL, redir_lval,
Bram Moolenaar6d977d62014-01-14 15:24:39 +0100609 FALSE, FALSE, 0, FNE_CHECK_START);
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +0200610 if (redir_endp != NULL && redir_lval->ll_name != NULL)
Bram Moolenaar9937a052019-06-15 15:45:06 +0200611 set_var_lval(redir_lval, redir_endp, &tv, FALSE, FALSE,
612 (char_u *)".");
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +0200613 clear_lval(redir_lval);
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000614 }
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000615
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +0000616 /* free the collected output */
Bram Moolenaard23a8232018-02-10 18:45:26 +0100617 VIM_CLEAR(redir_ga.ga_data);
Bram Moolenaar863b53b2007-01-14 14:28:34 +0000618
Bram Moolenaard23a8232018-02-10 18:45:26 +0100619 VIM_CLEAR(redir_lval);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000620 }
Bram Moolenaard23a8232018-02-10 18:45:26 +0100621 VIM_CLEAR(redir_varname);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000622}
623
Bram Moolenaar071d4272004-06-13 20:20:40 +0000624 int
Bram Moolenaarb7604cc2016-01-15 21:23:22 +0100625eval_charconvert(
626 char_u *enc_from,
627 char_u *enc_to,
628 char_u *fname_from,
629 char_u *fname_to)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000630{
631 int err = FALSE;
632
633 set_vim_var_string(VV_CC_FROM, enc_from, -1);
634 set_vim_var_string(VV_CC_TO, enc_to, -1);
635 set_vim_var_string(VV_FNAME_IN, fname_from, -1);
636 set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
637 if (eval_to_bool(p_ccv, &err, NULL, FALSE))
638 err = TRUE;
639 set_vim_var_string(VV_CC_FROM, NULL, -1);
640 set_vim_var_string(VV_CC_TO, NULL, -1);
641 set_vim_var_string(VV_FNAME_IN, NULL, -1);
642 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
643
644 if (err)
645 return FAIL;
646 return OK;
647}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000648
649# if defined(FEAT_POSTSCRIPT) || defined(PROTO)
650 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100651eval_printexpr(char_u *fname, char_u *args)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000652{
653 int err = FALSE;
654
655 set_vim_var_string(VV_FNAME_IN, fname, -1);
656 set_vim_var_string(VV_CMDARG, args, -1);
657 if (eval_to_bool(p_pexpr, &err, NULL, FALSE))
658 err = TRUE;
659 set_vim_var_string(VV_FNAME_IN, NULL, -1);
660 set_vim_var_string(VV_CMDARG, NULL, -1);
661
662 if (err)
663 {
664 mch_remove(fname);
665 return FAIL;
666 }
667 return OK;
668}
669# endif
670
671# if defined(FEAT_DIFF) || defined(PROTO)
672 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100673eval_diff(
674 char_u *origfile,
675 char_u *newfile,
676 char_u *outfile)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000677{
678 int err = FALSE;
679
680 set_vim_var_string(VV_FNAME_IN, origfile, -1);
681 set_vim_var_string(VV_FNAME_NEW, newfile, -1);
682 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
683 (void)eval_to_bool(p_dex, &err, NULL, FALSE);
684 set_vim_var_string(VV_FNAME_IN, NULL, -1);
685 set_vim_var_string(VV_FNAME_NEW, NULL, -1);
686 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
687}
688
689 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100690eval_patch(
691 char_u *origfile,
692 char_u *difffile,
693 char_u *outfile)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000694{
695 int err;
696
697 set_vim_var_string(VV_FNAME_IN, origfile, -1);
698 set_vim_var_string(VV_FNAME_DIFF, difffile, -1);
699 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
700 (void)eval_to_bool(p_pex, &err, NULL, FALSE);
701 set_vim_var_string(VV_FNAME_IN, NULL, -1);
702 set_vim_var_string(VV_FNAME_DIFF, NULL, -1);
703 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
704}
705# endif
706
707/*
708 * Top level evaluation function, returning a boolean.
709 * Sets "error" to TRUE if there was an error.
710 * Return TRUE or FALSE.
711 */
712 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100713eval_to_bool(
714 char_u *arg,
715 int *error,
716 char_u **nextcmd,
717 int skip) /* only parse, don't execute */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000718{
Bram Moolenaar33570922005-01-25 22:26:29 +0000719 typval_T tv;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +0200720 varnumber_T retval = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000721
722 if (skip)
723 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000724 if (eval0(arg, &tv, nextcmd, !skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000725 *error = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000726 else
727 {
728 *error = FALSE;
729 if (!skip)
730 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +0100731 retval = (tv_get_number_chk(&tv, error) != 0);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000732 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000733 }
734 }
735 if (skip)
736 --emsg_skip;
737
Bram Moolenaar22fcfad2016-07-01 18:17:26 +0200738 return (int)retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000739}
740
Bram Moolenaarce9d50d2019-01-14 22:22:29 +0100741/*
742 * Call eval1() and give an error message if not done at a lower level.
743 */
744 static int
745eval1_emsg(char_u **arg, typval_T *rettv, int evaluate)
746{
Bram Moolenaar6acc79f2019-01-14 22:53:31 +0100747 char_u *start = *arg;
Bram Moolenaarce9d50d2019-01-14 22:22:29 +0100748 int ret;
749 int did_emsg_before = did_emsg;
750 int called_emsg_before = called_emsg;
751
752 ret = eval1(arg, rettv, evaluate);
753 if (ret == FAIL)
754 {
755 // Report the invalid expression unless the expression evaluation has
756 // been cancelled due to an aborting error, an interrupt, or an
757 // exception, or we already gave a more specific error.
758 // Also check called_emsg for when using assert_fails().
759 if (!aborting() && did_emsg == did_emsg_before
760 && called_emsg == called_emsg_before)
Bram Moolenaar6acc79f2019-01-14 22:53:31 +0100761 semsg(_(e_invexpr2), start);
Bram Moolenaarce9d50d2019-01-14 22:22:29 +0100762 }
763 return ret;
764}
765
Bram Moolenaar543c9b12019-04-05 22:50:40 +0200766 int
Bram Moolenaar48570482017-10-30 21:48:41 +0100767eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv)
768{
769 char_u *s;
Bram Moolenaar48570482017-10-30 21:48:41 +0100770 char_u buf[NUMBUFLEN];
Bram Moolenaarc6538bc2019-08-03 18:17:11 +0200771 funcexe_T funcexe;
Bram Moolenaar48570482017-10-30 21:48:41 +0100772
773 if (expr->v_type == VAR_FUNC)
774 {
775 s = expr->vval.v_string;
776 if (s == NULL || *s == NUL)
777 return FAIL;
Bram Moolenaarc6538bc2019-08-03 18:17:11 +0200778 vim_memset(&funcexe, 0, sizeof(funcexe));
779 funcexe.evaluate = TRUE;
780 if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL)
Bram Moolenaar48570482017-10-30 21:48:41 +0100781 return FAIL;
782 }
783 else if (expr->v_type == VAR_PARTIAL)
784 {
785 partial_T *partial = expr->vval.v_partial;
786
787 s = partial_name(partial);
788 if (s == NULL || *s == NUL)
789 return FAIL;
Bram Moolenaarc6538bc2019-08-03 18:17:11 +0200790 vim_memset(&funcexe, 0, sizeof(funcexe));
791 funcexe.evaluate = TRUE;
792 funcexe.partial = partial;
793 if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL)
Bram Moolenaar48570482017-10-30 21:48:41 +0100794 return FAIL;
795 }
796 else
797 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +0100798 s = tv_get_string_buf_chk(expr, buf);
Bram Moolenaar48570482017-10-30 21:48:41 +0100799 if (s == NULL)
800 return FAIL;
801 s = skipwhite(s);
Bram Moolenaarce9d50d2019-01-14 22:22:29 +0100802 if (eval1_emsg(&s, rettv, TRUE) == FAIL)
Bram Moolenaar48570482017-10-30 21:48:41 +0100803 return FAIL;
804 if (*s != NUL) /* check for trailing chars after expr */
805 {
Bram Moolenaara43ebe92018-07-14 17:25:01 +0200806 clear_tv(rettv);
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100807 semsg(_(e_invexpr2), s);
Bram Moolenaar48570482017-10-30 21:48:41 +0100808 return FAIL;
809 }
810 }
811 return OK;
812}
813
814/*
815 * Like eval_to_bool() but using a typval_T instead of a string.
816 * Works for string, funcref and partial.
817 */
818 int
819eval_expr_to_bool(typval_T *expr, int *error)
820{
821 typval_T rettv;
822 int res;
823
824 if (eval_expr_typval(expr, NULL, 0, &rettv) == FAIL)
825 {
826 *error = TRUE;
827 return FALSE;
828 }
Bram Moolenaard155d7a2018-12-21 16:04:21 +0100829 res = (tv_get_number_chk(&rettv, error) != 0);
Bram Moolenaar48570482017-10-30 21:48:41 +0100830 clear_tv(&rettv);
831 return res;
832}
833
Bram Moolenaar071d4272004-06-13 20:20:40 +0000834/*
835 * Top level evaluation function, returning a string. If "skip" is TRUE,
836 * only parsing to "nextcmd" is done, without reporting errors. Return
837 * pointer to allocated memory, or NULL for failure or when "skip" is TRUE.
838 */
839 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100840eval_to_string_skip(
841 char_u *arg,
842 char_u **nextcmd,
843 int skip) /* only parse, don't execute */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000844{
Bram Moolenaar33570922005-01-25 22:26:29 +0000845 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000846 char_u *retval;
847
848 if (skip)
849 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000850 if (eval0(arg, &tv, nextcmd, !skip) == FAIL || skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000851 retval = NULL;
852 else
853 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +0100854 retval = vim_strsave(tv_get_string(&tv));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000855 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000856 }
857 if (skip)
858 --emsg_skip;
859
860 return retval;
861}
862
863/*
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000864 * Skip over an expression at "*pp".
865 * Return FAIL for an error, OK otherwise.
866 */
867 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100868skip_expr(char_u **pp)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000869{
Bram Moolenaar33570922005-01-25 22:26:29 +0000870 typval_T rettv;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000871
872 *pp = skipwhite(*pp);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000873 return eval1(pp, &rettv, FALSE);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000874}
875
876/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000877 * Top level evaluation function, returning a string.
Bram Moolenaara85fb752008-09-07 11:55:43 +0000878 * When "convert" is TRUE convert a List into a sequence of lines and convert
879 * a Float to a String.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000880 * Return pointer to allocated memory, or NULL for failure.
881 */
882 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100883eval_to_string(
884 char_u *arg,
885 char_u **nextcmd,
886 int convert)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000887{
Bram Moolenaar33570922005-01-25 22:26:29 +0000888 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000889 char_u *retval;
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000890 garray_T ga;
Bram Moolenaar798b30b2009-04-22 10:56:16 +0000891#ifdef FEAT_FLOAT
Bram Moolenaara85fb752008-09-07 11:55:43 +0000892 char_u numbuf[NUMBUFLEN];
Bram Moolenaar798b30b2009-04-22 10:56:16 +0000893#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000894
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000895 if (eval0(arg, &tv, nextcmd, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000896 retval = NULL;
897 else
898 {
Bram Moolenaara85fb752008-09-07 11:55:43 +0000899 if (convert && tv.v_type == VAR_LIST)
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000900 {
901 ga_init2(&ga, (int)sizeof(char), 80);
Bram Moolenaar9bf749b2008-07-27 13:57:29 +0000902 if (tv.vval.v_list != NULL)
Bram Moolenaar213b10a2011-08-10 12:38:08 +0200903 {
Bram Moolenaar18dfb442016-05-31 22:31:23 +0200904 list_join(&ga, tv.vval.v_list, (char_u *)"\n", TRUE, FALSE, 0);
Bram Moolenaar213b10a2011-08-10 12:38:08 +0200905 if (tv.vval.v_list->lv_len > 0)
906 ga_append(&ga, NL);
907 }
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000908 ga_append(&ga, NUL);
909 retval = (char_u *)ga.ga_data;
910 }
Bram Moolenaara85fb752008-09-07 11:55:43 +0000911#ifdef FEAT_FLOAT
912 else if (convert && tv.v_type == VAR_FLOAT)
913 {
914 vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv.vval.v_float);
915 retval = vim_strsave(numbuf);
916 }
917#endif
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000918 else
Bram Moolenaard155d7a2018-12-21 16:04:21 +0100919 retval = vim_strsave(tv_get_string(&tv));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000920 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000921 }
922
923 return retval;
924}
925
926/*
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000927 * Call eval_to_string() without using current local variables and using
928 * textlock. When "use_sandbox" is TRUE use the sandbox.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000929 */
930 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100931eval_to_string_safe(
932 char_u *arg,
933 char_u **nextcmd,
934 int use_sandbox)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000935{
936 char_u *retval;
Bram Moolenaar27e80c82018-10-14 21:41:01 +0200937 funccal_entry_T funccal_entry;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000938
Bram Moolenaar27e80c82018-10-14 21:41:01 +0200939 save_funccal(&funccal_entry);
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000940 if (use_sandbox)
941 ++sandbox;
942 ++textlock;
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000943 retval = eval_to_string(arg, nextcmd, FALSE);
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000944 if (use_sandbox)
945 --sandbox;
946 --textlock;
Bram Moolenaar27e80c82018-10-14 21:41:01 +0200947 restore_funccal();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000948 return retval;
949}
950
Bram Moolenaar071d4272004-06-13 20:20:40 +0000951/*
952 * Top level evaluation function, returning a number.
953 * Evaluates "expr" silently.
954 * Returns -1 for an error.
955 */
Bram Moolenaar22fcfad2016-07-01 18:17:26 +0200956 varnumber_T
Bram Moolenaar7454a062016-01-30 15:14:10 +0100957eval_to_number(char_u *expr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000958{
Bram Moolenaar33570922005-01-25 22:26:29 +0000959 typval_T rettv;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +0200960 varnumber_T retval;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +0000961 char_u *p = skipwhite(expr);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000962
963 ++emsg_off;
964
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000965 if (eval1(&p, &rettv, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000966 retval = -1;
967 else
968 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +0100969 retval = tv_get_number_chk(&rettv, NULL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000970 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000971 }
972 --emsg_off;
973
974 return retval;
975}
976
Bram Moolenaara40058a2005-07-11 22:42:07 +0000977/*
978 * Prepare v: variable "idx" to be used.
979 * Save the current typeval in "save_tv".
980 * When not used yet add the variable to the v: hashtable.
981 */
Bram Moolenaar543c9b12019-04-05 22:50:40 +0200982 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100983prepare_vimvar(int idx, typval_T *save_tv)
Bram Moolenaara40058a2005-07-11 22:42:07 +0000984{
985 *save_tv = vimvars[idx].vv_tv;
986 if (vimvars[idx].vv_type == VAR_UNKNOWN)
987 hash_add(&vimvarht, vimvars[idx].vv_di.di_key);
988}
989
990/*
991 * Restore v: variable "idx" to typeval "save_tv".
992 * When no longer defined, remove the variable from the v: hashtable.
993 */
Bram Moolenaar543c9b12019-04-05 22:50:40 +0200994 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100995restore_vimvar(int idx, typval_T *save_tv)
Bram Moolenaara40058a2005-07-11 22:42:07 +0000996{
997 hashitem_T *hi;
998
Bram Moolenaara40058a2005-07-11 22:42:07 +0000999 vimvars[idx].vv_tv = *save_tv;
1000 if (vimvars[idx].vv_type == VAR_UNKNOWN)
1001 {
1002 hi = hash_find(&vimvarht, vimvars[idx].vv_di.di_key);
1003 if (HASHITEM_EMPTY(hi))
Bram Moolenaar95f09602016-11-10 20:01:45 +01001004 internal_error("restore_vimvar()");
Bram Moolenaara40058a2005-07-11 22:42:07 +00001005 else
1006 hash_remove(&vimvarht, hi);
1007 }
1008}
1009
Bram Moolenaar3c56a962006-03-12 22:19:04 +00001010#if defined(FEAT_SPELL) || defined(PROTO)
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001011/*
1012 * Evaluate an expression to a list with suggestions.
1013 * For the "expr:" part of 'spellsuggest'.
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00001014 * Returns NULL when there is an error.
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001015 */
1016 list_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001017eval_spell_expr(char_u *badword, char_u *expr)
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001018{
1019 typval_T save_val;
1020 typval_T rettv;
1021 list_T *list = NULL;
1022 char_u *p = skipwhite(expr);
1023
1024 /* Set "v:val" to the bad word. */
1025 prepare_vimvar(VV_VAL, &save_val);
1026 vimvars[VV_VAL].vv_type = VAR_STRING;
1027 vimvars[VV_VAL].vv_str = badword;
1028 if (p_verbose == 0)
1029 ++emsg_off;
1030
1031 if (eval1(&p, &rettv, TRUE) == OK)
1032 {
1033 if (rettv.v_type != VAR_LIST)
1034 clear_tv(&rettv);
1035 else
1036 list = rettv.vval.v_list;
1037 }
1038
1039 if (p_verbose == 0)
1040 --emsg_off;
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001041 restore_vimvar(VV_VAL, &save_val);
1042
1043 return list;
1044}
1045
1046/*
1047 * "list" is supposed to contain two items: a word and a number. Return the
1048 * word in "pp" and the number as the return value.
1049 * Return -1 if anything isn't right.
1050 * Used to get the good word and score from the eval_spell_expr() result.
1051 */
1052 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001053get_spellword(list_T *list, char_u **pp)
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001054{
1055 listitem_T *li;
1056
1057 li = list->lv_first;
1058 if (li == NULL)
1059 return -1;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01001060 *pp = tv_get_string(&li->li_tv);
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001061
1062 li = li->li_next;
1063 if (li == NULL)
1064 return -1;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01001065 return (int)tv_get_number(&li->li_tv);
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001066}
1067#endif
1068
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001069/*
Bram Moolenaar4770d092006-01-12 23:22:24 +00001070 * Top level evaluation function.
1071 * Returns an allocated typval_T with the result.
1072 * Returns NULL when there is an error.
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001073 */
1074 typval_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001075eval_expr(char_u *arg, char_u **nextcmd)
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001076{
1077 typval_T *tv;
1078
Bram Moolenaarc799fe22019-05-28 23:08:19 +02001079 tv = ALLOC_ONE(typval_T);
Bram Moolenaar4770d092006-01-12 23:22:24 +00001080 if (tv != NULL && eval0(arg, tv, nextcmd, TRUE) == FAIL)
Bram Moolenaard23a8232018-02-10 18:45:26 +01001081 VIM_CLEAR(tv);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001082
1083 return tv;
1084}
1085
1086
Bram Moolenaar071d4272004-06-13 20:20:40 +00001087/*
Bram Moolenaarb544f3c2017-02-23 19:03:28 +01001088 * Call some Vim script function and return the result in "*rettv".
Bram Moolenaarffa96842018-06-12 22:05:14 +02001089 * Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc]
1090 * should have type VAR_UNKNOWN.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001091 * Returns OK or FAIL.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001092 */
Bram Moolenaar82139082011-09-14 16:52:09 +02001093 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001094call_vim_function(
1095 char_u *func,
1096 int argc,
Bram Moolenaarffa96842018-06-12 22:05:14 +02001097 typval_T *argv,
Bram Moolenaarded27a12018-08-01 19:06:03 +02001098 typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001099{
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001100 int ret;
Bram Moolenaarc6538bc2019-08-03 18:17:11 +02001101 funcexe_T funcexe;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001102
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001103 rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */
Bram Moolenaarc6538bc2019-08-03 18:17:11 +02001104 vim_memset(&funcexe, 0, sizeof(funcexe));
1105 funcexe.firstline = curwin->w_cursor.lnum;
1106 funcexe.lastline = curwin->w_cursor.lnum;
1107 funcexe.evaluate = TRUE;
1108 ret = call_func(func, -1, rettv, argc, argv, &funcexe);
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001109 if (ret == FAIL)
1110 clear_tv(rettv);
1111
1112 return ret;
1113}
1114
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001115/*
Bram Moolenaarb544f3c2017-02-23 19:03:28 +01001116 * Call Vim script function "func" and return the result as a number.
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001117 * Returns -1 when calling the function fails.
Bram Moolenaarffa96842018-06-12 22:05:14 +02001118 * Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc] should
1119 * have type VAR_UNKNOWN.
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001120 */
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001121 varnumber_T
Bram Moolenaar7454a062016-01-30 15:14:10 +01001122call_func_retnr(
1123 char_u *func,
1124 int argc,
Bram Moolenaarded27a12018-08-01 19:06:03 +02001125 typval_T *argv)
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001126{
1127 typval_T rettv;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001128 varnumber_T retval;
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001129
Bram Moolenaarded27a12018-08-01 19:06:03 +02001130 if (call_vim_function(func, argc, argv, &rettv) == FAIL)
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001131 return -1;
1132
Bram Moolenaard155d7a2018-12-21 16:04:21 +01001133 retval = tv_get_number_chk(&rettv, NULL);
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001134 clear_tv(&rettv);
1135 return retval;
1136}
1137
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001138/*
Bram Moolenaarb544f3c2017-02-23 19:03:28 +01001139 * Call Vim script function "func" and return the result as a string.
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001140 * Returns NULL when calling the function fails.
Bram Moolenaarffa96842018-06-12 22:05:14 +02001141 * Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc] should
1142 * have type VAR_UNKNOWN.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001143 */
1144 void *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001145call_func_retstr(
1146 char_u *func,
1147 int argc,
Bram Moolenaarded27a12018-08-01 19:06:03 +02001148 typval_T *argv)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001149{
1150 typval_T rettv;
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001151 char_u *retval;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001152
Bram Moolenaarded27a12018-08-01 19:06:03 +02001153 if (call_vim_function(func, argc, argv, &rettv) == FAIL)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001154 return NULL;
1155
Bram Moolenaard155d7a2018-12-21 16:04:21 +01001156 retval = vim_strsave(tv_get_string(&rettv));
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001157 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001158 return retval;
1159}
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001160
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001161/*
Bram Moolenaarb544f3c2017-02-23 19:03:28 +01001162 * Call Vim script function "func" and return the result as a List.
Bram Moolenaarffa96842018-06-12 22:05:14 +02001163 * Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc] should
1164 * have type VAR_UNKNOWN.
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00001165 * Returns NULL when there is something wrong.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001166 */
1167 void *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001168call_func_retlist(
1169 char_u *func,
1170 int argc,
Bram Moolenaarded27a12018-08-01 19:06:03 +02001171 typval_T *argv)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001172{
1173 typval_T rettv;
1174
Bram Moolenaarded27a12018-08-01 19:06:03 +02001175 if (call_vim_function(func, argc, argv, &rettv) == FAIL)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001176 return NULL;
1177
1178 if (rettv.v_type != VAR_LIST)
1179 {
1180 clear_tv(&rettv);
1181 return NULL;
1182 }
1183
1184 return rettv.vval.v_list;
1185}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001186
Bram Moolenaar05159a02005-02-26 23:04:13 +00001187
Bram Moolenaar071d4272004-06-13 20:20:40 +00001188#ifdef FEAT_FOLDING
1189/*
1190 * Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding
1191 * it in "*cp". Doesn't give error messages.
1192 */
1193 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001194eval_foldexpr(char_u *arg, int *cp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001195{
Bram Moolenaar33570922005-01-25 22:26:29 +00001196 typval_T tv;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001197 varnumber_T retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001198 char_u *s;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00001199 int use_sandbox = was_set_insecurely((char_u *)"foldexpr",
1200 OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001201
1202 ++emsg_off;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001203 if (use_sandbox)
1204 ++sandbox;
1205 ++textlock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001206 *cp = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001207 if (eval0(arg, &tv, NULL, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001208 retval = 0;
1209 else
1210 {
1211 /* If the result is a number, just return the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001212 if (tv.v_type == VAR_NUMBER)
1213 retval = tv.vval.v_number;
Bram Moolenaar758711c2005-02-02 23:11:38 +00001214 else if (tv.v_type != VAR_STRING || tv.vval.v_string == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001215 retval = 0;
1216 else
1217 {
1218 /* If the result is a string, check if there is a non-digit before
1219 * the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001220 s = tv.vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001221 if (!VIM_ISDIGIT(*s) && *s != '-')
1222 *cp = *s++;
1223 retval = atol((char *)s);
1224 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001225 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001226 }
1227 --emsg_off;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001228 if (use_sandbox)
1229 --sandbox;
1230 --textlock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001231
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001232 return (int)retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001233}
1234#endif
1235
Bram Moolenaar071d4272004-06-13 20:20:40 +00001236/*
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001237 * Get a list of lines from a HERE document. The here document is a list of
1238 * lines surrounded by a marker.
1239 * cmd << {marker}
1240 * {line1}
1241 * {line2}
1242 * ....
1243 * {marker}
1244 *
1245 * The {marker} is a string. If the optional 'trim' word is supplied before the
1246 * marker, then the leading indentation before the lines (matching the
1247 * indentation in the 'cmd' line) is stripped.
1248 * Returns a List with {lines} or NULL.
1249 */
1250 static list_T *
1251heredoc_get(exarg_T *eap, char_u *cmd)
1252{
1253 char_u *theline;
1254 char_u *marker;
1255 list_T *l;
1256 char_u *p;
Bram Moolenaare7eb9272019-06-24 00:58:07 +02001257 int marker_indent_len = 0;
1258 int text_indent_len = 0;
1259 char_u *text_indent = NULL;
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001260
1261 if (eap->getline == NULL)
1262 {
1263 emsg(_("E991: cannot use =<< here"));
1264 return NULL;
1265 }
1266
1267 // Check for the optional 'trim' word before the marker
1268 cmd = skipwhite(cmd);
1269 if (STRNCMP(cmd, "trim", 4) == 0 && (cmd[4] == NUL || VIM_ISWHITE(cmd[4])))
1270 {
1271 cmd = skipwhite(cmd + 4);
1272
Bram Moolenaare7eb9272019-06-24 00:58:07 +02001273 // Trim the indentation from all the lines in the here document.
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001274 // The amount of indentation trimmed is the same as the indentation of
Bram Moolenaare7eb9272019-06-24 00:58:07 +02001275 // the first line after the :let command line. To find the end marker
1276 // the indent of the :let command line is trimmed.
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001277 p = *eap->cmdlinep;
1278 while (VIM_ISWHITE(*p))
1279 {
1280 p++;
Bram Moolenaare7eb9272019-06-24 00:58:07 +02001281 marker_indent_len++;
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001282 }
Bram Moolenaare7eb9272019-06-24 00:58:07 +02001283 text_indent_len = -1;
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001284 }
1285
Bram Moolenaar24582002019-07-21 14:14:26 +02001286 // The marker is the next word.
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001287 if (*cmd != NUL && *cmd != '"')
1288 {
1289 marker = skipwhite(cmd);
1290 p = skiptowhite(marker);
1291 if (*skipwhite(p) != NUL && *skipwhite(p) != '"')
1292 {
1293 emsg(_(e_trailing));
1294 return NULL;
1295 }
1296 *p = NUL;
Bram Moolenaar24582002019-07-21 14:14:26 +02001297 if (vim_islower(*marker))
1298 {
1299 emsg(_("E221: Marker cannot start with lower case letter"));
1300 return NULL;
1301 }
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001302 }
1303 else
Bram Moolenaar24582002019-07-21 14:14:26 +02001304 {
1305 emsg(_("E172: Missing marker"));
1306 return NULL;
1307 }
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001308
1309 l = list_alloc();
1310 if (l == NULL)
1311 return NULL;
1312
1313 for (;;)
1314 {
Bram Moolenaare7eb9272019-06-24 00:58:07 +02001315 int mi = 0;
1316 int ti = 0;
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001317
Bram Moolenaare96a2492019-06-25 04:12:16 +02001318 theline = eap->getline(NUL, eap->cookie, 0, FALSE);
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001319 if (theline == NULL)
1320 {
1321 semsg(_("E990: Missing end marker '%s'"), marker);
1322 break;
1323 }
Bram Moolenaare7eb9272019-06-24 00:58:07 +02001324
1325 // with "trim": skip the indent matching the :let line to find the
1326 // marker
1327 if (marker_indent_len > 0
1328 && STRNCMP(theline, *eap->cmdlinep, marker_indent_len) == 0)
1329 mi = marker_indent_len;
1330 if (STRCMP(marker, theline + mi) == 0)
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001331 {
1332 vim_free(theline);
1333 break;
1334 }
1335
Bram Moolenaare7eb9272019-06-24 00:58:07 +02001336 if (text_indent_len == -1 && *theline != NUL)
1337 {
1338 // set the text indent from the first line.
1339 p = theline;
1340 text_indent_len = 0;
1341 while (VIM_ISWHITE(*p))
1342 {
1343 p++;
1344 text_indent_len++;
1345 }
1346 text_indent = vim_strnsave(theline, text_indent_len);
1347 }
1348 // with "trim": skip the indent matching the first line
1349 if (text_indent != NULL)
1350 for (ti = 0; ti < text_indent_len; ++ti)
1351 if (theline[ti] != text_indent[ti])
1352 break;
1353
1354 if (list_append_string(l, theline + ti, -1) == FAIL)
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001355 break;
1356 vim_free(theline);
1357 }
Bram Moolenaare7eb9272019-06-24 00:58:07 +02001358 vim_free(text_indent);
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001359
1360 return l;
1361}
1362
1363/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001364 * ":let" list all variable values
1365 * ":let var1 var2" list variable values
1366 * ":let var = expr" assignment command.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001367 * ":let var += expr" assignment command.
1368 * ":let var -= expr" assignment command.
Bram Moolenaarff697e62019-02-12 22:28:33 +01001369 * ":let var *= expr" assignment command.
1370 * ":let var /= expr" assignment command.
1371 * ":let var %= expr" assignment command.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001372 * ":let var .= expr" assignment command.
Bram Moolenaar0f248b02019-04-04 15:36:05 +02001373 * ":let var ..= expr" assignment command.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001374 * ":let [var1, var2] = expr" unpack list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001375 */
1376 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001377ex_let(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001378{
Bram Moolenaar9937a052019-06-15 15:45:06 +02001379 ex_let_const(eap, FALSE);
1380}
1381
1382/*
1383 * ":const" list all variable values
1384 * ":const var1 var2" list variable values
1385 * ":const var = expr" assignment command.
1386 * ":const [var1, var2] = expr" unpack list.
1387 */
1388 void
1389ex_const(exarg_T *eap)
1390{
1391 ex_let_const(eap, TRUE);
1392}
1393
1394 static void
1395ex_let_const(exarg_T *eap, int is_const)
1396{
Bram Moolenaar071d4272004-06-13 20:20:40 +00001397 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001398 char_u *expr = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00001399 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001400 int i;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001401 int var_count = 0;
1402 int semicolon = 0;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001403 char_u op[2];
Bram Moolenaardb552d602006-03-23 22:59:57 +00001404 char_u *argend;
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001405 int first = TRUE;
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02001406 int concat;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001407
Bram Moolenaardb552d602006-03-23 22:59:57 +00001408 argend = skip_var_list(arg, &var_count, &semicolon);
1409 if (argend == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001410 return;
Bram Moolenaarff697e62019-02-12 22:28:33 +01001411 if (argend > arg && argend[-1] == '.') // for var.='str'
Bram Moolenaar76b92b22006-03-24 22:46:53 +00001412 --argend;
Bram Moolenaara3920382014-03-30 16:49:09 +02001413 expr = skipwhite(argend);
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02001414 concat = expr[0] == '.'
1415 && ((expr[1] == '=' && current_sctx.sc_version < 2)
1416 || (expr[1] == '.' && expr[2] == '='));
1417 if (*expr != '=' && !((vim_strchr((char_u *)"+-*/%", *expr) != NULL
1418 && expr[1] == '=') || concat))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001419 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001420 /*
1421 * ":let" without "=": list variables
1422 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001423 if (*arg == '[')
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001424 emsg(_(e_invarg));
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02001425 else if (expr[0] == '.')
1426 emsg(_("E985: .= is not supported with script version 2"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001427 else if (!ends_excmd(*arg))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001428 /* ":let var1 var2" */
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001429 arg = list_arg_vars(eap, arg, &first);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001430 else if (!eap->skip)
Bram Moolenaara7043832005-01-21 11:56:39 +00001431 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001432 /* ":let" */
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001433 list_glob_vars(&first);
1434 list_buf_vars(&first);
1435 list_win_vars(&first);
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001436 list_tab_vars(&first);
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001437 list_script_vars(&first);
1438 list_func_vars(&first);
1439 list_vim_vars(&first);
Bram Moolenaara7043832005-01-21 11:56:39 +00001440 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001441 eap->nextcmd = check_nextcmd(arg);
1442 }
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001443 else if (expr[0] == '=' && expr[1] == '<' && expr[2] == '<')
1444 {
1445 list_T *l;
1446
1447 // HERE document
1448 l = heredoc_get(eap, expr + 3);
1449 if (l != NULL)
1450 {
1451 rettv_list_set(&rettv, l);
1452 op[0] = '=';
1453 op[1] = NUL;
1454 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
Bram Moolenaar9937a052019-06-15 15:45:06 +02001455 is_const, op);
Bram Moolenaarf5842c52019-05-19 18:41:26 +02001456 clear_tv(&rettv);
1457 }
1458 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001459 else
1460 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001461 op[0] = '=';
1462 op[1] = NUL;
Bram Moolenaara3920382014-03-30 16:49:09 +02001463 if (*expr != '=')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001464 {
Bram Moolenaarff697e62019-02-12 22:28:33 +01001465 if (vim_strchr((char_u *)"+-*/%.", *expr) != NULL)
Bram Moolenaar0f248b02019-04-04 15:36:05 +02001466 {
Bram Moolenaarff697e62019-02-12 22:28:33 +01001467 op[0] = *expr; // +=, -=, *=, /=, %= or .=
Bram Moolenaar0f248b02019-04-04 15:36:05 +02001468 if (expr[0] == '.' && expr[1] == '.') // ..=
1469 ++expr;
1470 }
Bram Moolenaara3920382014-03-30 16:49:09 +02001471 expr = skipwhite(expr + 2);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001472 }
Bram Moolenaara3920382014-03-30 16:49:09 +02001473 else
1474 expr = skipwhite(expr + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001475
Bram Moolenaar071d4272004-06-13 20:20:40 +00001476 if (eap->skip)
1477 ++emsg_skip;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001478 i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001479 if (eap->skip)
1480 {
1481 if (i != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001482 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001483 --emsg_skip;
1484 }
1485 else if (i != FAIL)
1486 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001487 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
Bram Moolenaar9937a052019-06-15 15:45:06 +02001488 is_const, op);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001489 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001490 }
1491 }
1492}
1493
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001494/*
1495 * Assign the typevalue "tv" to the variable or variables at "arg_start".
1496 * Handles both "var" with any type and "[var, var; var]" with a list type.
Bram Moolenaar61343f02019-07-20 21:11:13 +02001497 * When "op" is not NULL it points to a string with characters that
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001498 * must appear after the variable(s). Use "+", "-" or "." for add, subtract
1499 * or concatenate.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001500 * Returns OK or FAIL;
1501 */
1502 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001503ex_let_vars(
1504 char_u *arg_start,
1505 typval_T *tv,
Bram Moolenaar9937a052019-06-15 15:45:06 +02001506 int copy, // copy values from "tv", don't move
1507 int semicolon, // from skip_var_list()
1508 int var_count, // from skip_var_list()
1509 int is_const, // lock variables for const
Bram Moolenaar61343f02019-07-20 21:11:13 +02001510 char_u *op)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001511{
1512 char_u *arg = arg_start;
Bram Moolenaar33570922005-01-25 22:26:29 +00001513 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001514 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00001515 listitem_T *item;
1516 typval_T ltv;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001517
1518 if (*arg != '[')
1519 {
1520 /*
1521 * ":let var = expr" or ":for var in list"
1522 */
Bram Moolenaar61343f02019-07-20 21:11:13 +02001523 if (ex_let_one(arg, tv, copy, is_const, op, op) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001524 return FAIL;
1525 return OK;
1526 }
1527
1528 /*
1529 * ":let [v1, v2] = list" or ":for [v1, v2] in listlist"
1530 */
Bram Moolenaar758711c2005-02-02 23:11:38 +00001531 if (tv->v_type != VAR_LIST || (l = tv->vval.v_list) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001532 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001533 emsg(_(e_listreq));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001534 return FAIL;
1535 }
1536
1537 i = list_len(l);
1538 if (semicolon == 0 && var_count < i)
1539 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001540 emsg(_("E687: Less targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001541 return FAIL;
1542 }
1543 if (var_count - semicolon > i)
1544 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001545 emsg(_("E688: More targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001546 return FAIL;
1547 }
1548
1549 item = l->lv_first;
1550 while (*arg != ']')
1551 {
1552 arg = skipwhite(arg + 1);
Bram Moolenaar9937a052019-06-15 15:45:06 +02001553 arg = ex_let_one(arg, &item->li_tv, TRUE, is_const,
Bram Moolenaar61343f02019-07-20 21:11:13 +02001554 (char_u *)",;]", op);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001555 item = item->li_next;
1556 if (arg == NULL)
1557 return FAIL;
1558
1559 arg = skipwhite(arg);
1560 if (*arg == ';')
1561 {
1562 /* Put the rest of the list (may be empty) in the var after ';'.
1563 * Create a new list for this. */
1564 l = list_alloc();
1565 if (l == NULL)
1566 return FAIL;
1567 while (item != NULL)
1568 {
1569 list_append_tv(l, &item->li_tv);
1570 item = item->li_next;
1571 }
1572
1573 ltv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001574 ltv.v_lock = 0;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001575 ltv.vval.v_list = l;
1576 l->lv_refcount = 1;
1577
Bram Moolenaar9937a052019-06-15 15:45:06 +02001578 arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE, is_const,
Bram Moolenaar61343f02019-07-20 21:11:13 +02001579 (char_u *)"]", op);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001580 clear_tv(&ltv);
1581 if (arg == NULL)
1582 return FAIL;
1583 break;
1584 }
1585 else if (*arg != ',' && *arg != ']')
1586 {
Bram Moolenaar95f09602016-11-10 20:01:45 +01001587 internal_error("ex_let_vars()");
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001588 return FAIL;
1589 }
1590 }
1591
1592 return OK;
1593}
1594
1595/*
1596 * Skip over assignable variable "var" or list of variables "[var, var]".
1597 * Used for ":let varvar = expr" and ":for varvar in expr".
1598 * For "[var, var]" increment "*var_count" for each variable.
1599 * for "[var, var; var]" set "semicolon".
1600 * Return NULL for an error.
1601 */
1602 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001603skip_var_list(
1604 char_u *arg,
1605 int *var_count,
1606 int *semicolon)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001607{
1608 char_u *p, *s;
1609
1610 if (*arg == '[')
1611 {
1612 /* "[var, var]": find the matching ']'. */
1613 p = arg;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001614 for (;;)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001615 {
1616 p = skipwhite(p + 1); /* skip whites after '[', ';' or ',' */
1617 s = skip_var_one(p);
1618 if (s == p)
1619 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001620 semsg(_(e_invarg2), p);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001621 return NULL;
1622 }
1623 ++*var_count;
1624
1625 p = skipwhite(s);
1626 if (*p == ']')
1627 break;
1628 else if (*p == ';')
1629 {
1630 if (*semicolon == 1)
1631 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001632 emsg(_("Double ; in list of variables"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001633 return NULL;
1634 }
1635 *semicolon = 1;
1636 }
1637 else if (*p != ',')
1638 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001639 semsg(_(e_invarg2), p);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001640 return NULL;
1641 }
1642 }
1643 return p + 1;
1644 }
1645 else
1646 return skip_var_one(arg);
1647}
1648
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001649/*
Bram Moolenaarbae0c162007-05-10 19:30:25 +00001650 * Skip one (assignable) variable name, including @r, $VAR, &option, d.key,
Bram Moolenaar92124a32005-06-17 22:03:40 +00001651 * l[idx].
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001652 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001653 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001654skip_var_one(char_u *arg)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001655{
Bram Moolenaar92124a32005-06-17 22:03:40 +00001656 if (*arg == '@' && arg[1] != NUL)
1657 return arg + 2;
1658 return find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg,
1659 NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001660}
1661
Bram Moolenaara7043832005-01-21 11:56:39 +00001662/*
Bram Moolenaar33570922005-01-25 22:26:29 +00001663 * List variables for hashtab "ht" with prefix "prefix".
1664 * If "empty" is TRUE also list NULL strings as empty strings.
Bram Moolenaara7043832005-01-21 11:56:39 +00001665 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02001666 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001667list_hashtable_vars(
1668 hashtab_T *ht,
Bram Moolenaar32526b32019-01-19 17:43:09 +01001669 char *prefix,
Bram Moolenaar7454a062016-01-30 15:14:10 +01001670 int empty,
1671 int *first)
Bram Moolenaara7043832005-01-21 11:56:39 +00001672{
Bram Moolenaar33570922005-01-25 22:26:29 +00001673 hashitem_T *hi;
1674 dictitem_T *di;
Bram Moolenaara7043832005-01-21 11:56:39 +00001675 int todo;
Bram Moolenaarf86db782018-10-25 13:31:37 +02001676 char_u buf[IOSIZE];
Bram Moolenaara7043832005-01-21 11:56:39 +00001677
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001678 todo = (int)ht->ht_used;
Bram Moolenaara7043832005-01-21 11:56:39 +00001679 for (hi = ht->ht_array; todo > 0 && !got_int; ++hi)
1680 {
1681 if (!HASHITEM_EMPTY(hi))
1682 {
1683 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00001684 di = HI2DI(hi);
Bram Moolenaarf86db782018-10-25 13:31:37 +02001685
1686 // apply :filter /pat/ to variable name
Bram Moolenaar32526b32019-01-19 17:43:09 +01001687 vim_strncpy((char_u *)buf, (char_u *)prefix, IOSIZE - 1);
1688 vim_strcat((char_u *)buf, di->di_key, IOSIZE);
Bram Moolenaarf86db782018-10-25 13:31:37 +02001689 if (message_filtered(buf))
1690 continue;
1691
Bram Moolenaar33570922005-01-25 22:26:29 +00001692 if (empty || di->di_tv.v_type != VAR_STRING
1693 || di->di_tv.vval.v_string != NULL)
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001694 list_one_var(di, prefix, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00001695 }
1696 }
1697}
1698
1699/*
1700 * List global variables.
1701 */
1702 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001703list_glob_vars(int *first)
Bram Moolenaara7043832005-01-21 11:56:39 +00001704{
Bram Moolenaar32526b32019-01-19 17:43:09 +01001705 list_hashtable_vars(&globvarht, "", TRUE, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00001706}
1707
1708/*
1709 * List buffer variables.
1710 */
1711 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001712list_buf_vars(int *first)
Bram Moolenaara7043832005-01-21 11:56:39 +00001713{
Bram Moolenaar32526b32019-01-19 17:43:09 +01001714 list_hashtable_vars(&curbuf->b_vars->dv_hashtab, "b:", TRUE, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00001715}
1716
1717/*
1718 * List window variables.
1719 */
1720 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001721list_win_vars(int *first)
Bram Moolenaara7043832005-01-21 11:56:39 +00001722{
Bram Moolenaar32526b32019-01-19 17:43:09 +01001723 list_hashtable_vars(&curwin->w_vars->dv_hashtab, "w:", TRUE, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00001724}
1725
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001726/*
1727 * List tab page variables.
1728 */
1729 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001730list_tab_vars(int *first)
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001731{
Bram Moolenaar32526b32019-01-19 17:43:09 +01001732 list_hashtable_vars(&curtab->tp_vars->dv_hashtab, "t:", TRUE, first);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001733}
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001734
Bram Moolenaara7043832005-01-21 11:56:39 +00001735/*
1736 * List Vim variables.
1737 */
1738 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001739list_vim_vars(int *first)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001740{
Bram Moolenaar32526b32019-01-19 17:43:09 +01001741 list_hashtable_vars(&vimvarht, "v:", FALSE, first);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001742}
1743
1744/*
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00001745 * List script-local variables, if there is a script.
1746 */
1747 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001748list_script_vars(int *first)
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00001749{
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02001750 if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= ga_scripts.ga_len)
1751 list_hashtable_vars(&SCRIPT_VARS(current_sctx.sc_sid),
Bram Moolenaar32526b32019-01-19 17:43:09 +01001752 "s:", FALSE, first);
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00001753}
1754
1755/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001756 * List variables in "arg".
1757 */
1758 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001759list_arg_vars(exarg_T *eap, char_u *arg, int *first)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001760{
1761 int error = FALSE;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001762 int len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001763 char_u *name;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001764 char_u *name_start;
1765 char_u *arg_subsc;
1766 char_u *tofree;
1767 typval_T tv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001768
1769 while (!ends_excmd(*arg) && !got_int)
1770 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001771 if (error || eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001772 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001773 arg = find_name_end(arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
Bram Moolenaar1c465442017-03-12 20:10:05 +01001774 if (!VIM_ISWHITE(*arg) && !ends_excmd(*arg))
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001775 {
1776 emsg_severe = TRUE;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001777 emsg(_(e_trailing));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001778 break;
1779 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001780 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001781 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001782 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001783 /* get_name_len() takes care of expanding curly braces */
1784 name_start = name = arg;
1785 len = get_name_len(&arg, &tofree, TRUE, TRUE);
1786 if (len <= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001787 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001788 /* This is mainly to keep test 49 working: when expanding
1789 * curly braces fails overrule the exception error message. */
1790 if (len < 0 && !aborting())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001791 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001792 emsg_severe = TRUE;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001793 semsg(_(e_invarg2), arg);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001794 break;
1795 }
1796 error = TRUE;
1797 }
1798 else
1799 {
1800 if (tofree != NULL)
1801 name = tofree;
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02001802 if (get_var_tv(name, len, &tv, NULL, TRUE, FALSE) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001803 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001804 else
1805 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001806 /* handle d.key, l[idx], f(expr) */
1807 arg_subsc = arg;
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02001808 if (handle_subscript(&arg, &tv, TRUE, TRUE,
1809 name, &name) == FAIL)
Bram Moolenaara7043832005-01-21 11:56:39 +00001810 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001811 else
Bram Moolenaara7043832005-01-21 11:56:39 +00001812 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001813 if (arg == arg_subsc && len == 2 && name[1] == ':')
Bram Moolenaara7043832005-01-21 11:56:39 +00001814 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001815 switch (*name)
Bram Moolenaara7043832005-01-21 11:56:39 +00001816 {
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001817 case 'g': list_glob_vars(first); break;
1818 case 'b': list_buf_vars(first); break;
1819 case 'w': list_win_vars(first); break;
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001820 case 't': list_tab_vars(first); break;
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001821 case 'v': list_vim_vars(first); break;
1822 case 's': list_script_vars(first); break;
1823 case 'l': list_func_vars(first); break;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001824 default:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001825 semsg(_("E738: Can't list variables for %s"), name);
Bram Moolenaara7043832005-01-21 11:56:39 +00001826 }
Bram Moolenaara7043832005-01-21 11:56:39 +00001827 }
1828 else
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001829 {
1830 char_u numbuf[NUMBUFLEN];
1831 char_u *tf;
1832 int c;
1833 char_u *s;
1834
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001835 s = echo_string(&tv, &tf, numbuf, 0);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001836 c = *arg;
1837 *arg = NUL;
Bram Moolenaar32526b32019-01-19 17:43:09 +01001838 list_one_var_a("",
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001839 arg == arg_subsc ? name : name_start,
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001840 tv.v_type,
1841 s == NULL ? (char_u *)"" : s,
1842 first);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001843 *arg = c;
1844 vim_free(tf);
1845 }
1846 clear_tv(&tv);
Bram Moolenaara7043832005-01-21 11:56:39 +00001847 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001848 }
1849 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001850
1851 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001852 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001853
1854 arg = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001855 }
1856
1857 return arg;
1858}
1859
1860/*
1861 * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value.
1862 * Returns a pointer to the char just after the var name.
1863 * Returns NULL if there is an error.
1864 */
1865 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001866ex_let_one(
Bram Moolenaar9937a052019-06-15 15:45:06 +02001867 char_u *arg, // points to variable name
1868 typval_T *tv, // value to assign to variable
1869 int copy, // copy value from "tv"
1870 int is_const, // lock variable for const
1871 char_u *endchars, // valid chars after variable name or NULL
1872 char_u *op) // "+", "-", "." or NULL
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001873{
1874 int c1;
1875 char_u *name;
1876 char_u *p;
1877 char_u *arg_end = NULL;
1878 int len;
1879 int opt_flags;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001880 char_u *tofree = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001881
1882 /*
1883 * ":let $VAR = expr": Set environment variable.
1884 */
1885 if (*arg == '$')
1886 {
Bram Moolenaar9937a052019-06-15 15:45:06 +02001887 if (is_const)
1888 {
1889 emsg(_("E996: Cannot lock an environment variable"));
1890 return NULL;
1891 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001892 /* Find the end of the name. */
1893 ++arg;
1894 name = arg;
1895 len = get_env_len(&arg);
1896 if (len == 0)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001897 semsg(_(e_invarg2), name - 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001898 else
1899 {
Bram Moolenaarff697e62019-02-12 22:28:33 +01001900 if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001901 semsg(_(e_letwrong), op);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001902 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001903 && vim_strchr(endchars, *skipwhite(arg)) == NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001904 emsg(_(e_letunexp));
Bram Moolenaard4ddfaf2010-12-02 14:48:14 +01001905 else if (!check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001906 {
1907 c1 = name[len];
1908 name[len] = NUL;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01001909 p = tv_get_string_chk(tv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001910 if (p != NULL && op != NULL && *op == '.')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001911 {
1912 int mustfree = FALSE;
1913 char_u *s = vim_getenv(name, &mustfree);
1914
1915 if (s != NULL)
1916 {
1917 p = tofree = concat_str(s, p);
1918 if (mustfree)
1919 vim_free(s);
1920 }
1921 }
1922 if (p != NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001923 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001924 vim_setenv(name, p);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001925 if (STRICMP(name, "HOME") == 0)
1926 init_homedir();
1927 else if (didset_vim && STRICMP(name, "VIM") == 0)
1928 didset_vim = FALSE;
1929 else if (didset_vimruntime
1930 && STRICMP(name, "VIMRUNTIME") == 0)
1931 didset_vimruntime = FALSE;
1932 arg_end = arg;
1933 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001934 name[len] = c1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001935 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001936 }
1937 }
1938 }
1939
1940 /*
1941 * ":let &option = expr": Set option value.
1942 * ":let &l:option = expr": Set local option value.
1943 * ":let &g:option = expr": Set global option value.
1944 */
1945 else if (*arg == '&')
1946 {
Bram Moolenaar9937a052019-06-15 15:45:06 +02001947 if (is_const)
1948 {
1949 emsg(_("E996: Cannot lock an option"));
1950 return NULL;
1951 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001952 /* Find the end of the name. */
1953 p = find_option_end(&arg, &opt_flags);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001954 if (p == NULL || (endchars != NULL
1955 && vim_strchr(endchars, *skipwhite(p)) == NULL))
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001956 emsg(_(e_letunexp));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001957 else
1958 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001959 long n;
1960 int opt_type;
1961 long numval;
1962 char_u *stringval = NULL;
1963 char_u *s;
1964
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001965 c1 = *p;
1966 *p = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001967
Bram Moolenaard155d7a2018-12-21 16:04:21 +01001968 n = (long)tv_get_number(tv);
1969 s = tv_get_string_chk(tv); /* != NULL if number or string */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001970 if (s != NULL && op != NULL && *op != '=')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001971 {
1972 opt_type = get_option_value(arg, &numval,
1973 &stringval, opt_flags);
1974 if ((opt_type == 1 && *op == '.')
1975 || (opt_type == 0 && *op != '.'))
Bram Moolenaar2a6a6c32017-10-02 19:29:48 +02001976 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001977 semsg(_(e_letwrong), op);
Bram Moolenaarff697e62019-02-12 22:28:33 +01001978 s = NULL; // don't set the value
Bram Moolenaar2a6a6c32017-10-02 19:29:48 +02001979 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001980 else
1981 {
Bram Moolenaarff697e62019-02-12 22:28:33 +01001982 if (opt_type == 1) // number
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001983 {
Bram Moolenaarff697e62019-02-12 22:28:33 +01001984 switch (*op)
1985 {
1986 case '+': n = numval + n; break;
1987 case '-': n = numval - n; break;
1988 case '*': n = numval * n; break;
Bram Moolenaare21c1582019-03-02 11:57:09 +01001989 case '/': n = (long)num_divide(numval, n); break;
1990 case '%': n = (long)num_modulus(numval, n); break;
Bram Moolenaarff697e62019-02-12 22:28:33 +01001991 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001992 }
Bram Moolenaarff697e62019-02-12 22:28:33 +01001993 else if (opt_type == 0 && stringval != NULL) // string
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001994 {
1995 s = concat_str(stringval, s);
1996 vim_free(stringval);
1997 stringval = s;
1998 }
1999 }
2000 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002001 if (s != NULL)
2002 {
2003 set_option_value(arg, n, s, opt_flags);
2004 arg_end = p;
2005 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002006 *p = c1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002007 vim_free(stringval);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002008 }
2009 }
2010
2011 /*
2012 * ":let @r = expr": Set register contents.
2013 */
2014 else if (*arg == '@')
2015 {
Bram Moolenaar9937a052019-06-15 15:45:06 +02002016 if (is_const)
2017 {
2018 emsg(_("E996: Cannot lock a register"));
2019 return NULL;
2020 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002021 ++arg;
Bram Moolenaarff697e62019-02-12 22:28:33 +01002022 if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002023 semsg(_(e_letwrong), op);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002024 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002025 && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002026 emsg(_(e_letunexp));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002027 else
2028 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00002029 char_u *ptofree = NULL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002030 char_u *s;
2031
Bram Moolenaard155d7a2018-12-21 16:04:21 +01002032 p = tv_get_string_chk(tv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002033 if (p != NULL && op != NULL && *op == '.')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002034 {
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +02002035 s = get_reg_contents(*arg == '@' ? '"' : *arg, GREG_EXPR_SRC);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002036 if (s != NULL)
2037 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00002038 p = ptofree = concat_str(s, p);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002039 vim_free(s);
2040 }
2041 }
2042 if (p != NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002043 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002044 write_reg_contents(*arg == '@' ? '"' : *arg, p, -1, FALSE);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002045 arg_end = arg + 1;
2046 }
Bram Moolenaar89d40322006-08-29 15:30:07 +00002047 vim_free(ptofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002048 }
2049 }
2050
2051 /*
2052 * ":let var = expr": Set internal variable.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002053 * ":let {expr} = expr": Idem, name made with curly braces
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002054 */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002055 else if (eval_isnamec1(*arg) || *arg == '{')
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002056 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002057 lval_T lv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002058
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002059 p = get_lval(arg, tv, &lv, FALSE, FALSE, 0, FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002060 if (p != NULL && lv.ll_name != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002061 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002062 if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002063 emsg(_(e_letunexp));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002064 else
2065 {
Bram Moolenaar9937a052019-06-15 15:45:06 +02002066 set_var_lval(&lv, p, tv, copy, is_const, op);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002067 arg_end = p;
2068 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002069 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002070 clear_lval(&lv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002071 }
2072
2073 else
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002074 semsg(_(e_invarg2), arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002075
2076 return arg_end;
2077}
2078
2079/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002080 * Get an lval: variable, Dict item or List item that can be assigned a value
2081 * to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]",
2082 * "name.key", "name.key[expr]" etc.
2083 * Indexing only works if "name" is an existing List or Dictionary.
2084 * "name" points to the start of the name.
2085 * If "rettv" is not NULL it points to the value to be assigned.
2086 * "unlet" is TRUE for ":unlet": slightly different behavior when something is
2087 * wrong; must end in space or cmd separator.
2088 *
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002089 * flags:
2090 * GLV_QUIET: do not give error messages
Bram Moolenaar3a257732017-02-21 20:47:13 +01002091 * GLV_READ_ONLY: will not change the variable
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002092 * GLV_NO_AUTOLOAD: do not use script autoloading
2093 *
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002094 * Returns a pointer to just after the name, including indexes.
Bram Moolenaara7043832005-01-21 11:56:39 +00002095 * When an evaluation error occurs "lp->ll_name" is NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002096 * Returns NULL for a parsing error. Still need to free items in "lp"!
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002097 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02002098 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01002099get_lval(
2100 char_u *name,
2101 typval_T *rettv,
2102 lval_T *lp,
2103 int unlet,
2104 int skip,
2105 int flags, /* GLV_ values */
2106 int fne_flags) /* flags for find_name_end() */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002107{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002108 char_u *p;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002109 char_u *expr_start, *expr_end;
2110 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00002111 dictitem_T *v;
2112 typval_T var1;
2113 typval_T var2;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002114 int empty1 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00002115 listitem_T *ni;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002116 char_u *key = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002117 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +00002118 hashtab_T *ht;
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002119 int quiet = flags & GLV_QUIET;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002120
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002121 /* Clear everything in "lp". */
Bram Moolenaar33570922005-01-25 22:26:29 +00002122 vim_memset(lp, 0, sizeof(lval_T));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002123
2124 if (skip)
2125 {
2126 /* When skipping just find the end of the name. */
2127 lp->ll_name = name;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002128 return find_name_end(name, NULL, NULL, FNE_INCL_BR | fne_flags);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002129 }
2130
2131 /* Find the end of the name. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002132 p = find_name_end(name, &expr_start, &expr_end, fne_flags);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002133 if (expr_start != NULL)
2134 {
2135 /* Don't expand the name when we already know there is an error. */
Bram Moolenaar1c465442017-03-12 20:10:05 +01002136 if (unlet && !VIM_ISWHITE(*p) && !ends_excmd(*p)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002137 && *p != '[' && *p != '.')
2138 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002139 emsg(_(e_trailing));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002140 return NULL;
2141 }
2142
2143 lp->ll_exp_name = make_expanded_name(name, expr_start, expr_end, p);
2144 if (lp->ll_exp_name == NULL)
2145 {
2146 /* Report an invalid expression in braces, unless the
2147 * expression evaluation has been cancelled due to an
2148 * aborting error, an interrupt, or an exception. */
2149 if (!aborting() && !quiet)
2150 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002151 emsg_severe = TRUE;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002152 semsg(_(e_invarg2), name);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002153 return NULL;
2154 }
2155 }
2156 lp->ll_name = lp->ll_exp_name;
2157 }
2158 else
2159 lp->ll_name = name;
2160
2161 /* Without [idx] or .key we are done. */
2162 if ((*p != '[' && *p != '.') || lp->ll_name == NULL)
2163 return p;
2164
2165 cc = *p;
2166 *p = NUL;
Bram Moolenaar6e65d592017-12-07 22:11:27 +01002167 /* Only pass &ht when we would write to the variable, it prevents autoload
2168 * as well. */
2169 v = find_var(lp->ll_name, (flags & GLV_READ_ONLY) ? NULL : &ht,
2170 flags & GLV_NO_AUTOLOAD);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002171 if (v == NULL && !quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002172 semsg(_(e_undefvar), lp->ll_name);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002173 *p = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002174 if (v == NULL)
2175 return NULL;
2176
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002177 /*
2178 * Loop until no more [idx] or .key is following.
2179 */
Bram Moolenaar33570922005-01-25 22:26:29 +00002180 lp->ll_tv = &v->di_tv;
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002181 var1.v_type = VAR_UNKNOWN;
2182 var2.v_type = VAR_UNKNOWN;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002183 while (*p == '[' || (*p == '.' && lp->ll_tv->v_type == VAR_DICT))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002184 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002185 if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL)
2186 && !(lp->ll_tv->v_type == VAR_DICT
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002187 && lp->ll_tv->vval.v_dict != NULL)
2188 && !(lp->ll_tv->v_type == VAR_BLOB
2189 && lp->ll_tv->vval.v_blob != NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002190 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002191 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002192 emsg(_("E689: Can only index a List, Dictionary or Blob"));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002193 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002194 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002195 if (lp->ll_range)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002196 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002197 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002198 emsg(_("E708: [:] must come last"));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002199 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002200 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002201
Bram Moolenaar8c711452005-01-14 21:53:12 +00002202 len = -1;
2203 if (*p == '.')
2204 {
2205 key = p + 1;
2206 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
2207 ;
2208 if (len == 0)
2209 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002210 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002211 emsg(_(e_emptykey));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002212 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002213 }
2214 p = key + len;
2215 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002216 else
2217 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002218 /* Get the index [expr] or the first index [expr: ]. */
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002219 p = skipwhite(p + 1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002220 if (*p == ':')
2221 empty1 = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002222 else
2223 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002224 empty1 = FALSE;
2225 if (eval1(&p, &var1, TRUE) == FAIL) /* recursive! */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002226 return NULL;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01002227 if (tv_get_string_chk(&var1) == NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002228 {
2229 /* not a number or string */
2230 clear_tv(&var1);
2231 return NULL;
2232 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002233 }
2234
2235 /* Optionally get the second index [ :expr]. */
2236 if (*p == ':')
2237 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002238 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002239 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002240 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002241 emsg(_(e_dictrange));
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002242 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002243 return NULL;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002244 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002245 if (rettv != NULL
2246 && !(rettv->v_type == VAR_LIST
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002247 && rettv->vval.v_list != NULL)
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002248 && !(rettv->v_type == VAR_BLOB
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002249 && rettv->vval.v_blob != NULL))
Bram Moolenaar8c711452005-01-14 21:53:12 +00002250 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002251 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002252 emsg(_("E709: [:] requires a List or Blob value"));
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002253 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002254 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002255 }
2256 p = skipwhite(p + 1);
2257 if (*p == ']')
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002258 lp->ll_empty2 = TRUE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002259 else
2260 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002261 lp->ll_empty2 = FALSE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002262 if (eval1(&p, &var2, TRUE) == FAIL) /* recursive! */
2263 {
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002264 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002265 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002266 }
Bram Moolenaard155d7a2018-12-21 16:04:21 +01002267 if (tv_get_string_chk(&var2) == NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002268 {
2269 /* not a number or string */
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002270 clear_tv(&var1);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002271 clear_tv(&var2);
2272 return NULL;
2273 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002274 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002275 lp->ll_range = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002276 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002277 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002278 lp->ll_range = FALSE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002279
Bram Moolenaar8c711452005-01-14 21:53:12 +00002280 if (*p != ']')
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002281 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002282 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002283 emsg(_(e_missbrac));
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002284 clear_tv(&var1);
2285 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002286 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002287 }
2288
2289 /* Skip to past ']'. */
2290 ++p;
2291 }
2292
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002293 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002294 {
2295 if (len == -1)
2296 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002297 /* "[key]": get key from "var1" */
Bram Moolenaard155d7a2018-12-21 16:04:21 +01002298 key = tv_get_string_chk(&var1); /* is number or string */
Bram Moolenaar0921ecf2016-04-03 22:44:36 +02002299 if (key == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002300 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002301 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002302 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002303 }
2304 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002305 lp->ll_list = NULL;
2306 lp->ll_dict = lp->ll_tv->vval.v_dict;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002307 lp->ll_di = dict_find(lp->ll_dict, key, len);
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002308
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002309 /* When assigning to a scope dictionary check that a function and
2310 * variable name is valid (only variable name unless it is l: or
2311 * g: dictionary). Disallow overwriting a builtin function. */
2312 if (rettv != NULL && lp->ll_dict->dv_scope != 0)
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002313 {
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002314 int prevval;
2315 int wrong;
2316
2317 if (len != -1)
2318 {
2319 prevval = key[len];
2320 key[len] = NUL;
2321 }
Bram Moolenaar4380d1e2013-06-09 20:51:00 +02002322 else
2323 prevval = 0; /* avoid compiler warning */
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002324 wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE
2325 && rettv->v_type == VAR_FUNC
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002326 && var_check_func_name(key, lp->ll_di == NULL))
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002327 || !valid_varname(key);
2328 if (len != -1)
2329 key[len] = prevval;
2330 if (wrong)
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002331 return NULL;
2332 }
2333
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002334 if (lp->ll_di == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002335 {
Bram Moolenaar31b81602019-02-10 22:14:27 +01002336 // Can't add "v:" or "a:" variable.
2337 if (lp->ll_dict == &vimvardict
2338 || &lp->ll_dict->dv_hashtab == get_funccal_args_ht())
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002339 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002340 semsg(_(e_illvar), name);
Bram Moolenaarab89d7a2019-03-17 14:43:31 +01002341 clear_tv(&var1);
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002342 return NULL;
2343 }
2344
Bram Moolenaar31b81602019-02-10 22:14:27 +01002345 // Key does not exist in dict: may need to add it.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002346 if (*p == '[' || *p == '.' || unlet)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002347 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002348 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002349 semsg(_(e_dictkey), key);
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002350 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002351 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002352 }
2353 if (len == -1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002354 lp->ll_newkey = vim_strsave(key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002355 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002356 lp->ll_newkey = vim_strnsave(key, len);
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002357 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002358 if (lp->ll_newkey == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002359 p = NULL;
2360 break;
2361 }
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002362 /* existing variable, need to check if it can be changed */
Bram Moolenaar3a257732017-02-21 20:47:13 +01002363 else if ((flags & GLV_READ_ONLY) == 0
2364 && var_check_ro(lp->ll_di->di_flags, name, FALSE))
Bram Moolenaar49439c42017-02-20 23:07:05 +01002365 {
2366 clear_tv(&var1);
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002367 return NULL;
Bram Moolenaar49439c42017-02-20 23:07:05 +01002368 }
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002369
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002370 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002371 lp->ll_tv = &lp->ll_di->di_tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002372 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002373 else if (lp->ll_tv->v_type == VAR_BLOB)
2374 {
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002375 long bloblen = blob_len(lp->ll_tv->vval.v_blob);
2376
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002377 /*
2378 * Get the number and item for the only or first index of the List.
2379 */
2380 if (empty1)
2381 lp->ll_n1 = 0;
2382 else
2383 // is number or string
2384 lp->ll_n1 = (long)tv_get_number(&var1);
2385 clear_tv(&var1);
2386
2387 if (lp->ll_n1 < 0
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002388 || lp->ll_n1 > bloblen
2389 || (lp->ll_range && lp->ll_n1 == bloblen))
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002390 {
2391 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002392 semsg(_(e_blobidx), lp->ll_n1);
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002393 clear_tv(&var2);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002394 return NULL;
2395 }
2396 if (lp->ll_range && !lp->ll_empty2)
2397 {
2398 lp->ll_n2 = (long)tv_get_number(&var2);
2399 clear_tv(&var2);
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002400 if (lp->ll_n2 < 0
2401 || lp->ll_n2 >= bloblen
2402 || lp->ll_n2 < lp->ll_n1)
2403 {
2404 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002405 semsg(_(e_blobidx), lp->ll_n2);
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002406 return NULL;
2407 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002408 }
2409 lp->ll_blob = lp->ll_tv->vval.v_blob;
2410 lp->ll_tv = NULL;
Bram Moolenaar61be3762019-03-19 23:04:17 +01002411 break;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002412 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002413 else
2414 {
2415 /*
2416 * Get the number and item for the only or first index of the List.
2417 */
2418 if (empty1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002419 lp->ll_n1 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002420 else
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002421 /* is number or string */
Bram Moolenaard155d7a2018-12-21 16:04:21 +01002422 lp->ll_n1 = (long)tv_get_number(&var1);
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002423 clear_tv(&var1);
2424
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002425 lp->ll_dict = NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002426 lp->ll_list = lp->ll_tv->vval.v_list;
2427 lp->ll_li = list_find(lp->ll_list, lp->ll_n1);
2428 if (lp->ll_li == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002429 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00002430 if (lp->ll_n1 < 0)
2431 {
2432 lp->ll_n1 = 0;
2433 lp->ll_li = list_find(lp->ll_list, lp->ll_n1);
2434 }
2435 }
2436 if (lp->ll_li == NULL)
2437 {
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002438 clear_tv(&var2);
Bram Moolenaare9623882011-04-21 14:27:28 +02002439 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002440 semsg(_(e_listidx), lp->ll_n1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002441 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002442 }
2443
2444 /*
2445 * May need to find the item or absolute index for the second
2446 * index of a range.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002447 * When no index given: "lp->ll_empty2" is TRUE.
2448 * Otherwise "lp->ll_n2" is set to the second index.
Bram Moolenaar8c711452005-01-14 21:53:12 +00002449 */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002450 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002451 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01002452 lp->ll_n2 = (long)tv_get_number(&var2);
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02002453 /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002454 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002455 if (lp->ll_n2 < 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002456 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002457 ni = list_find(lp->ll_list, lp->ll_n2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002458 if (ni == NULL)
Bram Moolenaare9623882011-04-21 14:27:28 +02002459 {
2460 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002461 semsg(_(e_listidx), lp->ll_n2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002462 return NULL;
Bram Moolenaare9623882011-04-21 14:27:28 +02002463 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002464 lp->ll_n2 = list_idx_of_item(lp->ll_list, ni);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002465 }
2466
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002467 /* Check that lp->ll_n2 isn't before lp->ll_n1. */
2468 if (lp->ll_n1 < 0)
2469 lp->ll_n1 = list_idx_of_item(lp->ll_list, lp->ll_li);
2470 if (lp->ll_n2 < lp->ll_n1)
Bram Moolenaare9623882011-04-21 14:27:28 +02002471 {
2472 if (!quiet)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002473 semsg(_(e_listidx), lp->ll_n2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002474 return NULL;
Bram Moolenaare9623882011-04-21 14:27:28 +02002475 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002476 }
2477
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002478 lp->ll_tv = &lp->ll_li->li_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002479 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002480 }
2481
Bram Moolenaarf06e5a52017-02-23 14:25:17 +01002482 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002483 return p;
2484}
2485
2486/*
Bram Moolenaar33570922005-01-25 22:26:29 +00002487 * Clear lval "lp" that was filled by get_lval().
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002488 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02002489 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002490clear_lval(lval_T *lp)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002491{
2492 vim_free(lp->ll_exp_name);
2493 vim_free(lp->ll_newkey);
2494}
2495
2496/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002497 * Set a variable that was parsed by get_lval() to "rettv".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002498 * "endp" points to just after the parsed name.
Bram Moolenaarff697e62019-02-12 22:28:33 +01002499 * "op" is NULL, "+" for "+=", "-" for "-=", "*" for "*=", "/" for "/=",
2500 * "%" for "%=", "." for ".=" or "=" for "=".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002501 */
2502 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002503set_var_lval(
2504 lval_T *lp,
2505 char_u *endp,
2506 typval_T *rettv,
2507 int copy,
Bram Moolenaar9937a052019-06-15 15:45:06 +02002508 int is_const, // Disallow to modify existing variable for :const
Bram Moolenaar7454a062016-01-30 15:14:10 +01002509 char_u *op)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002510{
2511 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00002512 listitem_T *ri;
2513 dictitem_T *di;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002514
2515 if (lp->ll_tv == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002516 {
Bram Moolenaar79518e22017-02-17 16:31:35 +01002517 cc = *endp;
2518 *endp = NUL;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002519 if (lp->ll_blob != NULL)
2520 {
2521 int error = FALSE, val;
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002522
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002523 if (op != NULL && *op != '=')
2524 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002525 semsg(_(e_letwrong), op);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002526 return;
2527 }
2528
2529 if (lp->ll_range && rettv->v_type == VAR_BLOB)
2530 {
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002531 int il, ir;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002532
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002533 if (lp->ll_empty2)
2534 lp->ll_n2 = blob_len(lp->ll_blob) - 1;
2535
2536 if (lp->ll_n2 - lp->ll_n1 + 1 != blob_len(rettv->vval.v_blob))
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002537 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002538 emsg(_("E972: Blob value does not have the right number of bytes"));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002539 return;
2540 }
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002541 if (lp->ll_empty2)
2542 lp->ll_n2 = blob_len(lp->ll_blob);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002543
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002544 ir = 0;
2545 for (il = lp->ll_n1; il <= lp->ll_n2; il++)
2546 blob_set(lp->ll_blob, il,
2547 blob_get(rettv->vval.v_blob, ir++));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002548 }
2549 else
2550 {
2551 val = (int)tv_get_number_chk(rettv, &error);
2552 if (!error)
2553 {
2554 garray_T *gap = &lp->ll_blob->bv_ga;
2555
2556 // Allow for appending a byte. Setting a byte beyond
2557 // the end is an error otherwise.
2558 if (lp->ll_n1 < gap->ga_len
2559 || (lp->ll_n1 == gap->ga_len
2560 && ga_grow(&lp->ll_blob->bv_ga, 1) == OK))
2561 {
2562 blob_set(lp->ll_blob, lp->ll_n1, val);
2563 if (lp->ll_n1 == gap->ga_len)
2564 ++gap->ga_len;
2565 }
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002566 // error for invalid range was already given in get_lval()
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002567 }
2568 }
2569 }
2570 else if (op != NULL && *op != '=')
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002571 {
Bram Moolenaar79518e22017-02-17 16:31:35 +01002572 typval_T tv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002573
Bram Moolenaar9937a052019-06-15 15:45:06 +02002574 if (is_const)
2575 {
2576 emsg(_(e_cannot_mod));
2577 *endp = cc;
2578 return;
2579 }
2580
Bram Moolenaarff697e62019-02-12 22:28:33 +01002581 // handle +=, -=, *=, /=, %= and .=
Bram Moolenaar79518e22017-02-17 16:31:35 +01002582 di = NULL;
2583 if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
2584 &tv, &di, TRUE, FALSE) == OK)
2585 {
2586 if ((di == NULL
Bram Moolenaar05c00c02019-02-11 22:00:11 +01002587 || (!var_check_ro(di->di_flags, lp->ll_name, FALSE)
2588 && !tv_check_lock(&di->di_tv, lp->ll_name, FALSE)))
Bram Moolenaar79518e22017-02-17 16:31:35 +01002589 && tv_op(&tv, rettv, op) == OK)
2590 set_var(lp->ll_name, &tv, FALSE);
2591 clear_tv(&tv);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002592 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002593 }
Bram Moolenaar79518e22017-02-17 16:31:35 +01002594 else
Bram Moolenaar9937a052019-06-15 15:45:06 +02002595 set_var_const(lp->ll_name, rettv, copy, is_const);
Bram Moolenaar79518e22017-02-17 16:31:35 +01002596 *endp = cc;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002597 }
Bram Moolenaar05c00c02019-02-11 22:00:11 +01002598 else if (var_check_lock(lp->ll_newkey == NULL
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002599 ? lp->ll_tv->v_lock
Bram Moolenaar77354e72015-04-21 16:49:05 +02002600 : lp->ll_tv->vval.v_dict->dv_lock, lp->ll_name, FALSE))
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002601 ;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002602 else if (lp->ll_range)
2603 {
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02002604 listitem_T *ll_li = lp->ll_li;
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002605 int ll_n1 = lp->ll_n1;
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02002606
Bram Moolenaar9937a052019-06-15 15:45:06 +02002607 if (is_const)
2608 {
2609 emsg(_("E996: Cannot lock a range"));
2610 return;
2611 }
2612
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02002613 /*
2614 * Check whether any of the list items is locked
2615 */
Bram Moolenaarb2a851f2014-12-07 00:18:33 +01002616 for (ri = rettv->vval.v_list->lv_first; ri != NULL && ll_li != NULL; )
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02002617 {
Bram Moolenaar05c00c02019-02-11 22:00:11 +01002618 if (var_check_lock(ll_li->li_tv.v_lock, lp->ll_name, FALSE))
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02002619 return;
2620 ri = ri->li_next;
2621 if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == ll_n1))
2622 break;
2623 ll_li = ll_li->li_next;
2624 ++ll_n1;
2625 }
2626
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002627 /*
2628 * Assign the List values to the list items.
2629 */
2630 for (ri = rettv->vval.v_list->lv_first; ri != NULL; )
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002631 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002632 if (op != NULL && *op != '=')
2633 tv_op(&lp->ll_li->li_tv, &ri->li_tv, op);
2634 else
2635 {
2636 clear_tv(&lp->ll_li->li_tv);
2637 copy_tv(&ri->li_tv, &lp->ll_li->li_tv);
2638 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002639 ri = ri->li_next;
2640 if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == lp->ll_n1))
2641 break;
2642 if (lp->ll_li->li_next == NULL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002643 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002644 /* Need to add an empty item. */
Bram Moolenaar4463f292005-09-25 22:20:24 +00002645 if (list_append_number(lp->ll_list, 0) == FAIL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002646 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002647 ri = NULL;
2648 break;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002649 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002650 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002651 lp->ll_li = lp->ll_li->li_next;
2652 ++lp->ll_n1;
2653 }
2654 if (ri != NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002655 emsg(_("E710: List value has more items than target"));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002656 else if (lp->ll_empty2
2657 ? (lp->ll_li != NULL && lp->ll_li->li_next != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002658 : lp->ll_n1 != lp->ll_n2)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002659 emsg(_("E711: List value has not enough items"));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002660 }
2661 else
2662 {
2663 /*
2664 * Assign to a List or Dictionary item.
2665 */
Bram Moolenaar9937a052019-06-15 15:45:06 +02002666 if (is_const)
2667 {
2668 emsg(_("E996: Cannot lock a list or dict"));
2669 return;
2670 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002671 if (lp->ll_newkey != NULL)
2672 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002673 if (op != NULL && *op != '=')
2674 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002675 semsg(_(e_letwrong), op);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002676 return;
2677 }
2678
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002679 /* Need to add an item to the Dictionary. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002680 di = dictitem_alloc(lp->ll_newkey);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002681 if (di == NULL)
2682 return;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002683 if (dict_add(lp->ll_tv->vval.v_dict, di) == FAIL)
2684 {
2685 vim_free(di);
2686 return;
2687 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002688 lp->ll_tv = &di->di_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002689 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002690 else if (op != NULL && *op != '=')
2691 {
2692 tv_op(lp->ll_tv, rettv, op);
2693 return;
2694 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002695 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002696 clear_tv(lp->ll_tv);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002697
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002698 /*
2699 * Assign the value to the variable or list item.
2700 */
2701 if (copy)
2702 copy_tv(rettv, lp->ll_tv);
2703 else
2704 {
2705 *lp->ll_tv = *rettv;
Bram Moolenaar758711c2005-02-02 23:11:38 +00002706 lp->ll_tv->v_lock = 0;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002707 init_tv(rettv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002708 }
2709 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002710}
2711
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002712/*
Bram Moolenaarff697e62019-02-12 22:28:33 +01002713 * Handle "tv1 += tv2", "tv1 -= tv2", "tv1 *= tv2", "tv1 /= tv2", "tv1 %= tv2"
2714 * and "tv1 .= tv2"
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002715 * Returns OK or FAIL.
2716 */
2717 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01002718tv_op(typval_T *tv1, typval_T *tv2, char_u *op)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002719{
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02002720 varnumber_T n;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002721 char_u numbuf[NUMBUFLEN];
2722 char_u *s;
2723
Bram Moolenaar520e1e42016-01-23 19:46:28 +01002724 /* Can't do anything with a Funcref, Dict, v:true on the right. */
2725 if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT
2726 && tv2->v_type != VAR_SPECIAL)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002727 {
2728 switch (tv1->v_type)
2729 {
Bram Moolenaar835dc632016-02-07 14:27:38 +01002730 case VAR_UNKNOWN:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002731 case VAR_DICT:
2732 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01002733 case VAR_PARTIAL:
Bram Moolenaar520e1e42016-01-23 19:46:28 +01002734 case VAR_SPECIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01002735 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01002736 case VAR_CHANNEL:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002737 break;
2738
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002739 case VAR_BLOB:
2740 if (*op != '+' || tv2->v_type != VAR_BLOB)
2741 break;
2742 // BLOB += BLOB
2743 if (tv1->vval.v_blob != NULL && tv2->vval.v_blob != NULL)
2744 {
2745 blob_T *b1 = tv1->vval.v_blob;
2746 blob_T *b2 = tv2->vval.v_blob;
2747 int i, len = blob_len(b2);
2748 for (i = 0; i < len; i++)
2749 ga_append(&b1->bv_ga, blob_get(b2, i));
2750 }
2751 return OK;
2752
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002753 case VAR_LIST:
2754 if (*op != '+' || tv2->v_type != VAR_LIST)
2755 break;
Bram Moolenaarff697e62019-02-12 22:28:33 +01002756 // List += List
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002757 if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL)
2758 list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL);
2759 return OK;
2760
2761 case VAR_NUMBER:
2762 case VAR_STRING:
2763 if (tv2->v_type == VAR_LIST)
2764 break;
Bram Moolenaarff697e62019-02-12 22:28:33 +01002765 if (vim_strchr((char_u *)"+-*/%", *op) != NULL)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002766 {
Bram Moolenaarff697e62019-02-12 22:28:33 +01002767 // nr += nr , nr -= nr , nr *=nr , nr /= nr , nr %= nr
Bram Moolenaard155d7a2018-12-21 16:04:21 +01002768 n = tv_get_number(tv1);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002769#ifdef FEAT_FLOAT
2770 if (tv2->v_type == VAR_FLOAT)
2771 {
2772 float_T f = n;
2773
Bram Moolenaarff697e62019-02-12 22:28:33 +01002774 if (*op == '%')
2775 break;
2776 switch (*op)
2777 {
2778 case '+': f += tv2->vval.v_float; break;
2779 case '-': f -= tv2->vval.v_float; break;
2780 case '*': f *= tv2->vval.v_float; break;
2781 case '/': f /= tv2->vval.v_float; break;
2782 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002783 clear_tv(tv1);
2784 tv1->v_type = VAR_FLOAT;
2785 tv1->vval.v_float = f;
2786 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002787 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002788#endif
2789 {
Bram Moolenaarff697e62019-02-12 22:28:33 +01002790 switch (*op)
2791 {
2792 case '+': n += tv_get_number(tv2); break;
2793 case '-': n -= tv_get_number(tv2); break;
2794 case '*': n *= tv_get_number(tv2); break;
Bram Moolenaare21c1582019-03-02 11:57:09 +01002795 case '/': n = num_divide(n, tv_get_number(tv2)); break;
2796 case '%': n = num_modulus(n, tv_get_number(tv2)); break;
Bram Moolenaarff697e62019-02-12 22:28:33 +01002797 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002798 clear_tv(tv1);
2799 tv1->v_type = VAR_NUMBER;
2800 tv1->vval.v_number = n;
2801 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002802 }
2803 else
2804 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002805 if (tv2->v_type == VAR_FLOAT)
2806 break;
2807
Bram Moolenaarff697e62019-02-12 22:28:33 +01002808 // str .= str
Bram Moolenaard155d7a2018-12-21 16:04:21 +01002809 s = tv_get_string(tv1);
2810 s = concat_str(s, tv_get_string_buf(tv2, numbuf));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002811 clear_tv(tv1);
2812 tv1->v_type = VAR_STRING;
2813 tv1->vval.v_string = s;
2814 }
2815 return OK;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002816
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002817 case VAR_FLOAT:
Bram Moolenaar5fac4672016-03-02 22:16:32 +01002818#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002819 {
2820 float_T f;
2821
Bram Moolenaarff697e62019-02-12 22:28:33 +01002822 if (*op == '%' || *op == '.'
2823 || (tv2->v_type != VAR_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002824 && tv2->v_type != VAR_NUMBER
2825 && tv2->v_type != VAR_STRING))
2826 break;
2827 if (tv2->v_type == VAR_FLOAT)
2828 f = tv2->vval.v_float;
2829 else
Bram Moolenaard155d7a2018-12-21 16:04:21 +01002830 f = tv_get_number(tv2);
Bram Moolenaarff697e62019-02-12 22:28:33 +01002831 switch (*op)
2832 {
2833 case '+': tv1->vval.v_float += f; break;
2834 case '-': tv1->vval.v_float -= f; break;
2835 case '*': tv1->vval.v_float *= f; break;
2836 case '/': tv1->vval.v_float /= f; break;
2837 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002838 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00002839#endif
Bram Moolenaar5fac4672016-03-02 22:16:32 +01002840 return OK;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002841 }
2842 }
2843
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002844 semsg(_(e_letwrong), op);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002845 return FAIL;
2846}
2847
2848/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002849 * Evaluate the expression used in a ":for var in expr" command.
2850 * "arg" points to "var".
2851 * Set "*errp" to TRUE for an error, FALSE otherwise;
2852 * Return a pointer that holds the info. Null when there is an error.
2853 */
2854 void *
Bram Moolenaar7454a062016-01-30 15:14:10 +01002855eval_for_line(
2856 char_u *arg,
2857 int *errp,
2858 char_u **nextcmdp,
2859 int skip)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002860{
Bram Moolenaar33570922005-01-25 22:26:29 +00002861 forinfo_T *fi;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002862 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +00002863 typval_T tv;
2864 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002865
2866 *errp = TRUE; /* default: there is an error */
2867
Bram Moolenaarc799fe22019-05-28 23:08:19 +02002868 fi = ALLOC_CLEAR_ONE(forinfo_T);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002869 if (fi == NULL)
2870 return NULL;
2871
2872 expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
2873 if (expr == NULL)
2874 return fi;
2875
2876 expr = skipwhite(expr);
Bram Moolenaar1c465442017-03-12 20:10:05 +01002877 if (expr[0] != 'i' || expr[1] != 'n' || !VIM_ISWHITE(expr[2]))
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002878 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002879 emsg(_("E690: Missing \"in\" after :for"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002880 return fi;
2881 }
2882
2883 if (skip)
2884 ++emsg_skip;
2885 if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK)
2886 {
2887 *errp = FALSE;
2888 if (!skip)
2889 {
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002890 if (tv.v_type == VAR_LIST)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002891 {
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002892 l = tv.vval.v_list;
2893 if (l == NULL)
2894 {
2895 // a null list is like an empty list: do nothing
2896 clear_tv(&tv);
2897 }
2898 else
2899 {
2900 // No need to increment the refcount, it's already set for
2901 // the list being used in "tv".
2902 fi->fi_list = l;
2903 list_add_watch(l, &fi->fi_lw);
2904 fi->fi_lw.lw_item = l->lv_first;
2905 }
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002906 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002907 else if (tv.v_type == VAR_BLOB)
Bram Moolenaard8585ed2016-05-01 23:05:53 +02002908 {
Bram Moolenaardd29ea12019-01-23 21:56:21 +01002909 fi->fi_bi = 0;
2910 if (tv.vval.v_blob != NULL)
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002911 {
Bram Moolenaardd29ea12019-01-23 21:56:21 +01002912 typval_T btv;
2913
2914 // Make a copy, so that the iteration still works when the
2915 // blob is changed.
2916 blob_copy(&tv, &btv);
2917 fi->fi_blob = btv.vval.v_blob;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002918 }
Bram Moolenaardd29ea12019-01-23 21:56:21 +01002919 clear_tv(&tv);
Bram Moolenaard8585ed2016-05-01 23:05:53 +02002920 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002921 else
2922 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002923 emsg(_(e_listreq));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002924 clear_tv(&tv);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002925 }
2926 }
2927 }
2928 if (skip)
2929 --emsg_skip;
2930
2931 return fi;
2932}
2933
2934/*
2935 * Use the first item in a ":for" list. Advance to the next.
2936 * Assign the values to the variable (list). "arg" points to the first one.
2937 * Return TRUE when a valid item was found, FALSE when at end of list or
2938 * something wrong.
2939 */
2940 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01002941next_for_item(void *fi_void, char_u *arg)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002942{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002943 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002944 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00002945 listitem_T *item;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002946
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002947 if (fi->fi_blob != NULL)
2948 {
2949 typval_T tv;
2950
2951 if (fi->fi_bi >= blob_len(fi->fi_blob))
2952 return FALSE;
2953 tv.v_type = VAR_NUMBER;
2954 tv.v_lock = VAR_FIXED;
2955 tv.vval.v_number = blob_get(fi->fi_blob, fi->fi_bi);
2956 ++fi->fi_bi;
Bram Moolenaar9937a052019-06-15 15:45:06 +02002957 return ex_let_vars(arg, &tv, TRUE, fi->fi_semicolon,
2958 fi->fi_varcount, FALSE, NULL) == OK;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002959 }
2960
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002961 item = fi->fi_lw.lw_item;
2962 if (item == NULL)
2963 result = FALSE;
2964 else
2965 {
2966 fi->fi_lw.lw_item = item->li_next;
Bram Moolenaar9937a052019-06-15 15:45:06 +02002967 result = (ex_let_vars(arg, &item->li_tv, TRUE, fi->fi_semicolon,
2968 fi->fi_varcount, FALSE, NULL) == OK);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002969 }
2970 return result;
2971}
2972
2973/*
2974 * Free the structure used to store info used by ":for".
2975 */
2976 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002977free_for_info(void *fi_void)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002978{
Bram Moolenaar33570922005-01-25 22:26:29 +00002979 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002980
Bram Moolenaarab7013c2005-01-09 21:23:56 +00002981 if (fi != NULL && fi->fi_list != NULL)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002982 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002983 list_rem_watch(fi->fi_list, &fi->fi_lw);
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002984 list_unref(fi->fi_list);
2985 }
Bram Moolenaarecc8bc42019-01-13 16:07:21 +01002986 if (fi != NULL && fi->fi_blob != NULL)
2987 blob_unref(fi->fi_blob);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002988 vim_free(fi);
2989}
2990
Bram Moolenaar071d4272004-06-13 20:20:40 +00002991 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002992set_context_for_expression(
2993 expand_T *xp,
2994 char_u *arg,
2995 cmdidx_T cmdidx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002996{
2997 int got_eq = FALSE;
2998 int c;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002999 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003000
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003001 if (cmdidx == CMD_let)
3002 {
3003 xp->xp_context = EXPAND_USER_VARS;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00003004 if (vim_strpbrk(arg, (char_u *)"\"'+-*/%.=!?~|&$([<>,#") == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003005 {
3006 /* ":let var1 var2 ...": find last space. */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00003007 for (p = arg + STRLEN(arg); p >= arg; )
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003008 {
3009 xp->xp_pattern = p;
Bram Moolenaar91acfff2017-03-12 19:22:36 +01003010 MB_PTR_BACK(arg, p);
Bram Moolenaar1c465442017-03-12 20:10:05 +01003011 if (VIM_ISWHITE(*p))
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003012 break;
3013 }
3014 return;
3015 }
3016 }
3017 else
3018 xp->xp_context = cmdidx == CMD_call ? EXPAND_FUNCTIONS
3019 : EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003020 while ((xp->xp_pattern = vim_strpbrk(arg,
3021 (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL)
3022 {
3023 c = *xp->xp_pattern;
3024 if (c == '&')
3025 {
3026 c = xp->xp_pattern[1];
3027 if (c == '&')
3028 {
3029 ++xp->xp_pattern;
3030 xp->xp_context = cmdidx != CMD_let || got_eq
3031 ? EXPAND_EXPRESSION : EXPAND_NOTHING;
3032 }
3033 else if (c != ' ')
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00003034 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00003035 xp->xp_context = EXPAND_SETTINGS;
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00003036 if ((c == 'l' || c == 'g') && xp->xp_pattern[2] == ':')
3037 xp->xp_pattern += 2;
3038
3039 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003040 }
3041 else if (c == '$')
3042 {
3043 /* environment variable */
3044 xp->xp_context = EXPAND_ENV_VARS;
3045 }
3046 else if (c == '=')
3047 {
3048 got_eq = TRUE;
3049 xp->xp_context = EXPAND_EXPRESSION;
3050 }
Bram Moolenaara32095f2016-03-28 19:27:13 +02003051 else if (c == '#'
3052 && xp->xp_context == EXPAND_EXPRESSION)
3053 {
3054 /* Autoload function/variable contains '#'. */
3055 break;
3056 }
Bram Moolenaar8a349ff2014-11-12 20:09:06 +01003057 else if ((c == '<' || c == '#')
Bram Moolenaar071d4272004-06-13 20:20:40 +00003058 && xp->xp_context == EXPAND_FUNCTIONS
3059 && vim_strchr(xp->xp_pattern, '(') == NULL)
3060 {
Bram Moolenaar8a349ff2014-11-12 20:09:06 +01003061 /* Function name can start with "<SNR>" and contain '#'. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003062 break;
3063 }
3064 else if (cmdidx != CMD_let || got_eq)
3065 {
3066 if (c == '"') /* string */
3067 {
3068 while ((c = *++xp->xp_pattern) != NUL && c != '"')
3069 if (c == '\\' && xp->xp_pattern[1] != NUL)
3070 ++xp->xp_pattern;
3071 xp->xp_context = EXPAND_NOTHING;
3072 }
3073 else if (c == '\'') /* literal string */
3074 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00003075 /* Trick: '' is like stopping and starting a literal string. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003076 while ((c = *++xp->xp_pattern) != NUL && c != '\'')
3077 /* skip */ ;
3078 xp->xp_context = EXPAND_NOTHING;
3079 }
3080 else if (c == '|')
3081 {
3082 if (xp->xp_pattern[1] == '|')
3083 {
3084 ++xp->xp_pattern;
3085 xp->xp_context = EXPAND_EXPRESSION;
3086 }
3087 else
3088 xp->xp_context = EXPAND_COMMANDS;
3089 }
3090 else
3091 xp->xp_context = EXPAND_EXPRESSION;
3092 }
3093 else
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003094 /* Doesn't look like something valid, expand as an expression
3095 * anyway. */
3096 xp->xp_context = EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003097 arg = xp->xp_pattern;
3098 if (*arg != NUL)
3099 while ((c = *++arg) != NUL && (c == ' ' || c == '\t'))
3100 /* skip */ ;
3101 }
3102 xp->xp_pattern = arg;
3103}
3104
Bram Moolenaar071d4272004-06-13 20:20:40 +00003105/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003106 * ":unlet[!] var1 ... " command.
3107 */
3108 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003109ex_unlet(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003110{
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003111 ex_unletlock(eap, eap->arg, 0);
3112}
3113
3114/*
3115 * ":lockvar" and ":unlockvar" commands
3116 */
3117 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003118ex_lockvar(exarg_T *eap)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003119{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003120 char_u *arg = eap->arg;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003121 int deep = 2;
3122
3123 if (eap->forceit)
3124 deep = -1;
3125 else if (vim_isdigit(*arg))
3126 {
3127 deep = getdigits(&arg);
3128 arg = skipwhite(arg);
3129 }
3130
3131 ex_unletlock(eap, arg, deep);
3132}
3133
3134/*
3135 * ":unlet", ":lockvar" and ":unlockvar" are quite similar.
3136 */
3137 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003138ex_unletlock(
3139 exarg_T *eap,
3140 char_u *argstart,
3141 int deep)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003142{
3143 char_u *arg = argstart;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003144 char_u *name_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003145 int error = FALSE;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003146 lval_T lv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003147
3148 do
3149 {
Bram Moolenaar137374f2018-05-13 15:59:50 +02003150 if (*arg == '$')
3151 {
3152 char_u *name = ++arg;
3153
3154 if (get_env_len(&arg) == 0)
3155 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003156 semsg(_(e_invarg2), name - 1);
Bram Moolenaar137374f2018-05-13 15:59:50 +02003157 return;
3158 }
3159 vim_unsetenv(name);
3160 arg = skipwhite(arg);
3161 continue;
3162 }
3163
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003164 /* Parse the name and find the end. */
Bram Moolenaar6d977d62014-01-14 15:24:39 +01003165 name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error, 0,
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00003166 FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003167 if (lv.ll_name == NULL)
3168 error = TRUE; /* error but continue parsing */
Bram Moolenaar1c465442017-03-12 20:10:05 +01003169 if (name_end == NULL || (!VIM_ISWHITE(*name_end)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003170 && !ends_excmd(*name_end)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003171 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003172 if (name_end != NULL)
3173 {
3174 emsg_severe = TRUE;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003175 emsg(_(e_trailing));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003176 }
3177 if (!(eap->skip || error))
3178 clear_lval(&lv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003179 break;
3180 }
3181
3182 if (!error && !eap->skip)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003183 {
3184 if (eap->cmdidx == CMD_unlet)
3185 {
3186 if (do_unlet_var(&lv, name_end, eap->forceit) == FAIL)
3187 error = TRUE;
3188 }
3189 else
3190 {
3191 if (do_lock_var(&lv, name_end, deep,
3192 eap->cmdidx == CMD_lockvar) == FAIL)
3193 error = TRUE;
3194 }
3195 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003196
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003197 if (!eap->skip)
3198 clear_lval(&lv);
3199
Bram Moolenaar071d4272004-06-13 20:20:40 +00003200 arg = skipwhite(name_end);
3201 } while (!ends_excmd(*arg));
3202
3203 eap->nextcmd = check_nextcmd(arg);
3204}
3205
Bram Moolenaar8c711452005-01-14 21:53:12 +00003206 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003207do_unlet_var(
3208 lval_T *lp,
3209 char_u *name_end,
3210 int forceit)
Bram Moolenaar8c711452005-01-14 21:53:12 +00003211{
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003212 int ret = OK;
3213 int cc;
3214
3215 if (lp->ll_tv == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00003216 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003217 cc = *name_end;
3218 *name_end = NUL;
3219
3220 /* Normal name or expanded name. */
Bram Moolenaar79518e22017-02-17 16:31:35 +01003221 if (do_unlet(lp->ll_name, forceit) == FAIL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003222 ret = FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003223 *name_end = cc;
Bram Moolenaar8c711452005-01-14 21:53:12 +00003224 }
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02003225 else if ((lp->ll_list != NULL
Bram Moolenaar05c00c02019-02-11 22:00:11 +01003226 && var_check_lock(lp->ll_list->lv_lock, lp->ll_name, FALSE))
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02003227 || (lp->ll_dict != NULL
Bram Moolenaar05c00c02019-02-11 22:00:11 +01003228 && var_check_lock(lp->ll_dict->dv_lock, lp->ll_name, FALSE)))
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003229 return FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003230 else if (lp->ll_range)
3231 {
Bram Moolenaar33570922005-01-25 22:26:29 +00003232 listitem_T *li;
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02003233 listitem_T *ll_li = lp->ll_li;
Bram Moolenaarc9703302016-01-17 21:49:33 +01003234 int ll_n1 = lp->ll_n1;
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02003235
3236 while (ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= ll_n1))
3237 {
3238 li = ll_li->li_next;
Bram Moolenaar05c00c02019-02-11 22:00:11 +01003239 if (var_check_lock(ll_li->li_tv.v_lock, lp->ll_name, FALSE))
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02003240 return FAIL;
3241 ll_li = li;
3242 ++ll_n1;
3243 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003244
3245 /* Delete a range of List items. */
3246 while (lp->ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
3247 {
3248 li = lp->ll_li->li_next;
3249 listitem_remove(lp->ll_list, lp->ll_li);
3250 lp->ll_li = li;
3251 ++lp->ll_n1;
3252 }
3253 }
3254 else
3255 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003256 if (lp->ll_list != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003257 /* unlet a List item. */
3258 listitem_remove(lp->ll_list, lp->ll_li);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003259 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003260 /* unlet a Dictionary item. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003261 dictitem_remove(lp->ll_dict, lp->ll_di);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003262 }
3263
3264 return ret;
Bram Moolenaar8c711452005-01-14 21:53:12 +00003265}
3266
Bram Moolenaar071d4272004-06-13 20:20:40 +00003267/*
3268 * "unlet" a variable. Return OK if it existed, FAIL if not.
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003269 * When "forceit" is TRUE don't complain if the variable doesn't exist.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003270 */
3271 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003272do_unlet(char_u *name, int forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003273{
Bram Moolenaar33570922005-01-25 22:26:29 +00003274 hashtab_T *ht;
3275 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003276 char_u *varname;
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02003277 dict_T *d;
Bram Moolenaarafbdeb82008-01-05 21:16:31 +00003278 dictitem_T *di;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003279
Bram Moolenaar33570922005-01-25 22:26:29 +00003280 ht = find_var_ht(name, &varname);
3281 if (ht != NULL && *varname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003282 {
Bram Moolenaara9b579f2016-07-17 18:29:19 +02003283 d = get_current_funccal_dict(ht);
Bram Moolenaar71bcfdf2016-01-09 18:20:46 +01003284 if (d == NULL)
3285 {
Bram Moolenaara9b579f2016-07-17 18:29:19 +02003286 if (ht == &globvarht)
3287 d = &globvardict;
3288 else if (ht == &compat_hashtab)
3289 d = &vimvardict;
3290 else
3291 {
3292 di = find_var_in_ht(ht, *name, (char_u *)"", FALSE);
3293 d = di == NULL ? NULL : di->di_tv.vval.v_dict;
3294 }
3295 if (d == NULL)
3296 {
Bram Moolenaar95f09602016-11-10 20:01:45 +01003297 internal_error("do_unlet()");
Bram Moolenaara9b579f2016-07-17 18:29:19 +02003298 return FAIL;
3299 }
Bram Moolenaar71bcfdf2016-01-09 18:20:46 +01003300 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003301 hi = hash_find(ht, varname);
Bram Moolenaar10ce39a2016-07-29 22:37:06 +02003302 if (HASHITEM_EMPTY(hi))
Bram Moolenaarba96e9a2016-08-01 17:10:20 +02003303 hi = find_hi_in_scoped_ht(name, &ht);
Bram Moolenaar10ce39a2016-07-29 22:37:06 +02003304 if (hi != NULL && !HASHITEM_EMPTY(hi))
Bram Moolenaara7043832005-01-21 11:56:39 +00003305 {
Bram Moolenaarafbdeb82008-01-05 21:16:31 +00003306 di = HI2DI(hi);
Bram Moolenaar77354e72015-04-21 16:49:05 +02003307 if (var_check_fixed(di->di_flags, name, FALSE)
Bram Moolenaar71bcfdf2016-01-09 18:20:46 +01003308 || var_check_ro(di->di_flags, name, FALSE)
Bram Moolenaar05c00c02019-02-11 22:00:11 +01003309 || var_check_lock(d->dv_lock, name, FALSE))
Bram Moolenaaraf8af8b2016-01-04 22:05:24 +01003310 return FAIL;
3311
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003312 delete_var(ht, hi);
3313 return OK;
Bram Moolenaara7043832005-01-21 11:56:39 +00003314 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003315 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003316 if (forceit)
3317 return OK;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003318 semsg(_("E108: No such variable: \"%s\""), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003319 return FAIL;
3320}
3321
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003322/*
3323 * Lock or unlock variable indicated by "lp".
3324 * "deep" is the levels to go (-1 for unlimited);
3325 * "lock" is TRUE for ":lockvar", FALSE for ":unlockvar".
3326 */
3327 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003328do_lock_var(
3329 lval_T *lp,
3330 char_u *name_end,
3331 int deep,
3332 int lock)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003333{
3334 int ret = OK;
3335 int cc;
3336 dictitem_T *di;
3337
3338 if (deep == 0) /* nothing to do */
3339 return OK;
3340
3341 if (lp->ll_tv == NULL)
3342 {
3343 cc = *name_end;
3344 *name_end = NUL;
3345
3346 /* Normal name or expanded name. */
Bram Moolenaar79518e22017-02-17 16:31:35 +01003347 di = find_var(lp->ll_name, NULL, TRUE);
3348 if (di == NULL)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003349 ret = FAIL;
Bram Moolenaare7877fe2017-02-20 22:35:33 +01003350 else if ((di->di_flags & DI_FLAGS_FIX)
3351 && di->di_tv.v_type != VAR_DICT
3352 && di->di_tv.v_type != VAR_LIST)
3353 /* For historic reasons this error is not given for a list or dict.
3354 * E.g., the b: dict could be locked/unlocked. */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003355 semsg(_("E940: Cannot lock or unlock variable %s"), lp->ll_name);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003356 else
3357 {
Bram Moolenaar79518e22017-02-17 16:31:35 +01003358 if (lock)
3359 di->di_flags |= DI_FLAGS_LOCK;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003360 else
Bram Moolenaar79518e22017-02-17 16:31:35 +01003361 di->di_flags &= ~DI_FLAGS_LOCK;
3362 item_lock(&di->di_tv, deep, lock);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003363 }
3364 *name_end = cc;
3365 }
3366 else if (lp->ll_range)
3367 {
3368 listitem_T *li = lp->ll_li;
3369
3370 /* (un)lock a range of List items. */
3371 while (li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
3372 {
3373 item_lock(&li->li_tv, deep, lock);
3374 li = li->li_next;
3375 ++lp->ll_n1;
3376 }
3377 }
3378 else if (lp->ll_list != NULL)
3379 /* (un)lock a List item. */
3380 item_lock(&lp->ll_li->li_tv, deep, lock);
3381 else
Bram Moolenaar641e48c2015-06-25 16:09:26 +02003382 /* (un)lock a Dictionary item. */
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003383 item_lock(&lp->ll_di->di_tv, deep, lock);
3384
3385 return ret;
3386}
3387
3388/*
3389 * Lock or unlock an item. "deep" is nr of levels to go.
3390 */
3391 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003392item_lock(typval_T *tv, int deep, int lock)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003393{
3394 static int recurse = 0;
3395 list_T *l;
3396 listitem_T *li;
3397 dict_T *d;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01003398 blob_T *b;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003399 hashitem_T *hi;
3400 int todo;
3401
3402 if (recurse >= DICT_MAXNEST)
3403 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003404 emsg(_("E743: variable nested too deep for (un)lock"));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003405 return;
3406 }
3407 if (deep == 0)
3408 return;
3409 ++recurse;
3410
3411 /* lock/unlock the item itself */
3412 if (lock)
3413 tv->v_lock |= VAR_LOCKED;
3414 else
3415 tv->v_lock &= ~VAR_LOCKED;
3416
3417 switch (tv->v_type)
3418 {
Bram Moolenaara03f2332016-02-06 18:09:59 +01003419 case VAR_UNKNOWN:
3420 case VAR_NUMBER:
3421 case VAR_STRING:
3422 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01003423 case VAR_PARTIAL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01003424 case VAR_FLOAT:
3425 case VAR_SPECIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01003426 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01003427 case VAR_CHANNEL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01003428 break;
3429
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01003430 case VAR_BLOB:
3431 if ((b = tv->vval.v_blob) != NULL)
3432 {
3433 if (lock)
3434 b->bv_lock |= VAR_LOCKED;
3435 else
3436 b->bv_lock &= ~VAR_LOCKED;
3437 }
3438 break;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003439 case VAR_LIST:
3440 if ((l = tv->vval.v_list) != NULL)
3441 {
3442 if (lock)
3443 l->lv_lock |= VAR_LOCKED;
3444 else
3445 l->lv_lock &= ~VAR_LOCKED;
3446 if (deep < 0 || deep > 1)
3447 /* recursive: lock/unlock the items the List contains */
3448 for (li = l->lv_first; li != NULL; li = li->li_next)
3449 item_lock(&li->li_tv, deep - 1, lock);
3450 }
3451 break;
3452 case VAR_DICT:
3453 if ((d = tv->vval.v_dict) != NULL)
3454 {
3455 if (lock)
3456 d->dv_lock |= VAR_LOCKED;
3457 else
3458 d->dv_lock &= ~VAR_LOCKED;
3459 if (deep < 0 || deep > 1)
3460 {
3461 /* recursive: lock/unlock the items the List contains */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003462 todo = (int)d->dv_hashtab.ht_used;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003463 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
3464 {
3465 if (!HASHITEM_EMPTY(hi))
3466 {
3467 --todo;
3468 item_lock(&HI2DI(hi)->di_tv, deep - 1, lock);
3469 }
3470 }
3471 }
3472 }
3473 }
3474 --recurse;
3475}
3476
Bram Moolenaar071d4272004-06-13 20:20:40 +00003477#if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO)
3478/*
3479 * Delete all "menutrans_" variables.
3480 */
3481 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003482del_menutrans_vars(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003483{
Bram Moolenaar33570922005-01-25 22:26:29 +00003484 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003485 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003486
Bram Moolenaar33570922005-01-25 22:26:29 +00003487 hash_lock(&globvarht);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003488 todo = (int)globvarht.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00003489 for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaara7043832005-01-21 11:56:39 +00003490 {
3491 if (!HASHITEM_EMPTY(hi))
3492 {
3493 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00003494 if (STRNCMP(HI2DI(hi)->di_key, "menutrans_", 10) == 0)
3495 delete_var(&globvarht, hi);
Bram Moolenaara7043832005-01-21 11:56:39 +00003496 }
3497 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003498 hash_unlock(&globvarht);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003499}
3500#endif
3501
Bram Moolenaar071d4272004-06-13 20:20:40 +00003502/*
3503 * Local string buffer for the next two functions to store a variable name
3504 * with its prefix. Allocated in cat_prefix_varname(), freed later in
3505 * get_user_var_name().
3506 */
3507
Bram Moolenaar071d4272004-06-13 20:20:40 +00003508static char_u *varnamebuf = NULL;
3509static int varnamebuflen = 0;
3510
3511/*
3512 * Function to concatenate a prefix and a variable name.
3513 */
3514 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01003515cat_prefix_varname(int prefix, char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003516{
3517 int len;
3518
3519 len = (int)STRLEN(name) + 3;
3520 if (len > varnamebuflen)
3521 {
3522 vim_free(varnamebuf);
3523 len += 10; /* some additional space */
3524 varnamebuf = alloc(len);
3525 if (varnamebuf == NULL)
3526 {
3527 varnamebuflen = 0;
3528 return NULL;
3529 }
3530 varnamebuflen = len;
3531 }
3532 *varnamebuf = prefix;
3533 varnamebuf[1] = ':';
3534 STRCPY(varnamebuf + 2, name);
3535 return varnamebuf;
3536}
3537
3538/*
3539 * Function given to ExpandGeneric() to obtain the list of user defined
3540 * (global/buffer/window/built-in) variable names.
3541 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003542 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01003543get_user_var_name(expand_T *xp, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003544{
Bram Moolenaar532c7802005-01-27 14:44:31 +00003545 static long_u gdone;
3546 static long_u bdone;
3547 static long_u wdone;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003548 static long_u tdone;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003549 static int vidx;
3550 static hashitem_T *hi;
3551 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003552
3553 if (idx == 0)
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003554 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003555 gdone = bdone = wdone = vidx = 0;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003556 tdone = 0;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003557 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003558
3559 /* Global variables */
3560 if (gdone < globvarht.ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003561 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003562 if (gdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003563 hi = globvarht.ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003564 else
3565 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003566 while (HASHITEM_EMPTY(hi))
3567 ++hi;
3568 if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
3569 return cat_prefix_varname('g', hi->hi_key);
3570 return hi->hi_key;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003571 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003572
3573 /* b: variables */
Bram Moolenaar429fa852013-04-15 12:27:36 +02003574 ht = &curbuf->b_vars->dv_hashtab;
Bram Moolenaar33570922005-01-25 22:26:29 +00003575 if (bdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003576 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003577 if (bdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003578 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003579 else
3580 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003581 while (HASHITEM_EMPTY(hi))
3582 ++hi;
3583 return cat_prefix_varname('b', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003584 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003585
3586 /* w: variables */
Bram Moolenaar429fa852013-04-15 12:27:36 +02003587 ht = &curwin->w_vars->dv_hashtab;
Bram Moolenaar33570922005-01-25 22:26:29 +00003588 if (wdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003589 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00003590 if (wdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003591 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003592 else
3593 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003594 while (HASHITEM_EMPTY(hi))
3595 ++hi;
3596 return cat_prefix_varname('w', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003597 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003598
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003599 /* t: variables */
Bram Moolenaar429fa852013-04-15 12:27:36 +02003600 ht = &curtab->tp_vars->dv_hashtab;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003601 if (tdone < ht->ht_used)
3602 {
3603 if (tdone++ == 0)
3604 hi = ht->ht_array;
3605 else
3606 ++hi;
3607 while (HASHITEM_EMPTY(hi))
3608 ++hi;
3609 return cat_prefix_varname('t', hi->hi_key);
3610 }
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003611
Bram Moolenaar33570922005-01-25 22:26:29 +00003612 /* v: variables */
3613 if (vidx < VV_LEN)
3614 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].vv_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003615
Bram Moolenaard23a8232018-02-10 18:45:26 +01003616 VIM_CLEAR(varnamebuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003617 varnamebuflen = 0;
3618 return NULL;
3619}
3620
Bram Moolenaar071d4272004-06-13 20:20:40 +00003621/*
Bram Moolenaarea6553b2016-03-27 15:13:38 +02003622 * Return TRUE if "pat" matches "text".
3623 * Does not use 'cpo' and always uses 'magic'.
3624 */
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02003625 int
Bram Moolenaarea6553b2016-03-27 15:13:38 +02003626pattern_match(char_u *pat, char_u *text, int ic)
3627{
3628 int matches = FALSE;
3629 char_u *save_cpo;
3630 regmatch_T regmatch;
3631
3632 /* avoid 'l' flag in 'cpoptions' */
3633 save_cpo = p_cpo;
3634 p_cpo = (char_u *)"";
3635 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
3636 if (regmatch.regprog != NULL)
3637 {
3638 regmatch.rm_ic = ic;
3639 matches = vim_regexec_nl(&regmatch, text, (colnr_T)0);
3640 vim_regfree(regmatch.regprog);
3641 }
3642 p_cpo = save_cpo;
3643 return matches;
3644}
3645
3646/*
Bram Moolenaar761fdf02019-08-05 23:10:16 +02003647 * Handle a name followed by "(". Both for just "name(arg)" and for
3648 * "expr->name(arg)".
3649 * Returns OK or FAIL.
3650 */
3651 static int
3652eval_func(
3653 char_u **arg, // points to "(", will be advanced
3654 char_u *name,
3655 int name_len,
3656 typval_T *rettv,
3657 int evaluate,
3658 typval_T *basetv) // "expr" for "expr->name(arg)"
3659{
3660 char_u *s = name;
3661 int len = name_len;
3662 partial_T *partial;
3663 int ret = OK;
3664
3665 if (!evaluate)
3666 check_vars(s, len);
3667
3668 /* If "s" is the name of a variable of type VAR_FUNC
3669 * use its contents. */
3670 s = deref_func_name(s, &len, &partial, !evaluate);
3671
3672 /* Need to make a copy, in case evaluating the arguments makes
3673 * the name invalid. */
3674 s = vim_strsave(s);
3675 if (s == NULL)
3676 ret = FAIL;
3677 else
3678 {
3679 funcexe_T funcexe;
3680
3681 // Invoke the function.
3682 vim_memset(&funcexe, 0, sizeof(funcexe));
3683 funcexe.firstline = curwin->w_cursor.lnum;
3684 funcexe.lastline = curwin->w_cursor.lnum;
Bram Moolenaar761fdf02019-08-05 23:10:16 +02003685 funcexe.evaluate = evaluate;
3686 funcexe.partial = partial;
3687 funcexe.basetv = basetv;
3688 ret = get_func_tv(s, len, rettv, arg, &funcexe);
3689 }
3690 vim_free(s);
3691
3692 /* If evaluate is FALSE rettv->v_type was not set in
3693 * get_func_tv, but it's needed in handle_subscript() to parse
3694 * what follows. So set it here. */
3695 if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(')
3696 {
3697 rettv->vval.v_string = NULL;
3698 rettv->v_type = VAR_FUNC;
3699 }
3700
3701 /* Stop the expression evaluation when immediately
3702 * aborting on error, or when an interrupt occurred or
3703 * an exception was thrown but not caught. */
3704 if (evaluate && aborting())
3705 {
3706 if (ret == OK)
3707 clear_tv(rettv);
3708 ret = FAIL;
3709 }
3710 return ret;
3711}
3712
3713/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003714 * The "evaluate" argument: When FALSE, the argument is only parsed but not
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003715 * executed. The function may return OK, but the rettv will be of type
Bram Moolenaar071d4272004-06-13 20:20:40 +00003716 * VAR_UNKNOWN. The function still returns FAIL for a syntax error.
3717 */
3718
3719/*
3720 * Handle zero level expression.
3721 * This calls eval1() and handles error message and nextcmd.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003722 * Put the result in "rettv" when returning OK and "evaluate" is TRUE.
Bram Moolenaar4463f292005-09-25 22:20:24 +00003723 * Note: "rettv.v_lock" is not set.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003724 * Return OK or FAIL.
3725 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02003726 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003727eval0(
3728 char_u *arg,
3729 typval_T *rettv,
3730 char_u **nextcmd,
3731 int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003732{
3733 int ret;
3734 char_u *p;
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01003735 int did_emsg_before = did_emsg;
3736 int called_emsg_before = called_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003737
3738 p = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003739 ret = eval1(&p, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003740 if (ret == FAIL || !ends_excmd(*p))
3741 {
3742 if (ret != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003743 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003744 /*
3745 * Report the invalid expression unless the expression evaluation has
3746 * been cancelled due to an aborting error, an interrupt, or an
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01003747 * exception, or we already gave a more specific error.
3748 * Also check called_emsg for when using assert_fails().
Bram Moolenaar071d4272004-06-13 20:20:40 +00003749 */
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01003750 if (!aborting() && did_emsg == did_emsg_before
3751 && called_emsg == called_emsg_before)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003752 semsg(_(e_invexpr2), arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003753 ret = FAIL;
3754 }
3755 if (nextcmd != NULL)
3756 *nextcmd = check_nextcmd(p);
3757
3758 return ret;
3759}
3760
3761/*
3762 * Handle top level expression:
Bram Moolenaarb67cc162009-02-04 15:27:06 +00003763 * expr2 ? expr1 : expr1
Bram Moolenaar071d4272004-06-13 20:20:40 +00003764 *
3765 * "arg" must point to the first non-white of the expression.
3766 * "arg" is advanced to the next non-white after the recognized expression.
3767 *
Bram Moolenaar4463f292005-09-25 22:20:24 +00003768 * Note: "rettv.v_lock" is not set.
3769 *
Bram Moolenaar071d4272004-06-13 20:20:40 +00003770 * Return OK or FAIL.
3771 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02003772 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003773eval1(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003774{
3775 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00003776 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003777
3778 /*
3779 * Get the first variable.
3780 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003781 if (eval2(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003782 return FAIL;
3783
3784 if ((*arg)[0] == '?')
3785 {
3786 result = FALSE;
3787 if (evaluate)
3788 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003789 int error = FALSE;
3790
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003791 if (tv_get_number_chk(rettv, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003792 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003793 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003794 if (error)
3795 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003796 }
3797
3798 /*
3799 * Get the second variable.
3800 */
3801 *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003802 if (eval1(arg, rettv, evaluate && result) == FAIL) /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003803 return FAIL;
3804
3805 /*
3806 * Check for the ":".
3807 */
3808 if ((*arg)[0] != ':')
3809 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003810 emsg(_("E109: Missing ':' after '?'"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003811 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003812 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003813 return FAIL;
3814 }
3815
3816 /*
3817 * Get the third variable.
3818 */
3819 *arg = skipwhite(*arg + 1);
3820 if (eval1(arg, &var2, evaluate && !result) == FAIL) /* recursive! */
3821 {
3822 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003823 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003824 return FAIL;
3825 }
3826 if (evaluate && !result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003827 *rettv = var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003828 }
3829
3830 return OK;
3831}
3832
3833/*
3834 * Handle first level expression:
3835 * expr2 || expr2 || expr2 logical OR
3836 *
3837 * "arg" must point to the first non-white of the expression.
3838 * "arg" is advanced to the next non-white after the recognized expression.
3839 *
3840 * Return OK or FAIL.
3841 */
3842 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003843eval2(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003844{
Bram Moolenaar33570922005-01-25 22:26:29 +00003845 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003846 long result;
3847 int first;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003848 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003849
3850 /*
3851 * Get the first variable.
3852 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003853 if (eval3(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003854 return FAIL;
3855
3856 /*
3857 * Repeat until there is no following "||".
3858 */
3859 first = TRUE;
3860 result = FALSE;
3861 while ((*arg)[0] == '|' && (*arg)[1] == '|')
3862 {
3863 if (evaluate && first)
3864 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003865 if (tv_get_number_chk(rettv, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003866 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003867 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003868 if (error)
3869 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003870 first = FALSE;
3871 }
3872
3873 /*
3874 * Get the second variable.
3875 */
3876 *arg = skipwhite(*arg + 2);
3877 if (eval3(arg, &var2, evaluate && !result) == FAIL)
3878 return FAIL;
3879
3880 /*
3881 * Compute the result.
3882 */
3883 if (evaluate && !result)
3884 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003885 if (tv_get_number_chk(&var2, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003886 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003887 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003888 if (error)
3889 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003890 }
3891 if (evaluate)
3892 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003893 rettv->v_type = VAR_NUMBER;
3894 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003895 }
3896 }
3897
3898 return OK;
3899}
3900
3901/*
3902 * Handle second level expression:
3903 * expr3 && expr3 && expr3 logical AND
3904 *
3905 * "arg" must point to the first non-white of the expression.
3906 * "arg" is advanced to the next non-white after the recognized expression.
3907 *
3908 * Return OK or FAIL.
3909 */
3910 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003911eval3(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003912{
Bram Moolenaar33570922005-01-25 22:26:29 +00003913 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003914 long result;
3915 int first;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003916 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003917
3918 /*
3919 * Get the first variable.
3920 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003921 if (eval4(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003922 return FAIL;
3923
3924 /*
3925 * Repeat until there is no following "&&".
3926 */
3927 first = TRUE;
3928 result = TRUE;
3929 while ((*arg)[0] == '&' && (*arg)[1] == '&')
3930 {
3931 if (evaluate && first)
3932 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003933 if (tv_get_number_chk(rettv, &error) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003934 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003935 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003936 if (error)
3937 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003938 first = FALSE;
3939 }
3940
3941 /*
3942 * Get the second variable.
3943 */
3944 *arg = skipwhite(*arg + 2);
3945 if (eval4(arg, &var2, evaluate && result) == FAIL)
3946 return FAIL;
3947
3948 /*
3949 * Compute the result.
3950 */
3951 if (evaluate && result)
3952 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01003953 if (tv_get_number_chk(&var2, &error) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003954 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003955 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003956 if (error)
3957 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003958 }
3959 if (evaluate)
3960 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003961 rettv->v_type = VAR_NUMBER;
3962 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003963 }
3964 }
3965
3966 return OK;
3967}
3968
3969/*
3970 * Handle third level expression:
3971 * var1 == var2
3972 * var1 =~ var2
3973 * var1 != var2
3974 * var1 !~ var2
3975 * var1 > var2
3976 * var1 >= var2
3977 * var1 < var2
3978 * var1 <= var2
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003979 * var1 is var2
3980 * var1 isnot var2
Bram Moolenaar071d4272004-06-13 20:20:40 +00003981 *
3982 * "arg" must point to the first non-white of the expression.
3983 * "arg" is advanced to the next non-white after the recognized expression.
3984 *
3985 * Return OK or FAIL.
3986 */
3987 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003988eval4(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003989{
Bram Moolenaar33570922005-01-25 22:26:29 +00003990 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003991 char_u *p;
3992 int i;
3993 exptype_T type = TYPE_UNKNOWN;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003994 int type_is = FALSE; /* TRUE for "is" and "isnot" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003995 int len = 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003996 int ic;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003997
3998 /*
3999 * Get the first variable.
4000 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004001 if (eval5(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004002 return FAIL;
4003
4004 p = *arg;
4005 switch (p[0])
4006 {
4007 case '=': if (p[1] == '=')
4008 type = TYPE_EQUAL;
4009 else if (p[1] == '~')
4010 type = TYPE_MATCH;
4011 break;
4012 case '!': if (p[1] == '=')
4013 type = TYPE_NEQUAL;
4014 else if (p[1] == '~')
4015 type = TYPE_NOMATCH;
4016 break;
4017 case '>': if (p[1] != '=')
4018 {
4019 type = TYPE_GREATER;
4020 len = 1;
4021 }
4022 else
4023 type = TYPE_GEQUAL;
4024 break;
4025 case '<': if (p[1] != '=')
4026 {
4027 type = TYPE_SMALLER;
4028 len = 1;
4029 }
4030 else
4031 type = TYPE_SEQUAL;
4032 break;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004033 case 'i': if (p[1] == 's')
4034 {
4035 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
4036 len = 5;
Bram Moolenaar37a8de12015-09-01 16:05:00 +02004037 i = p[len];
4038 if (!isalnum(i) && i != '_')
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004039 {
4040 type = len == 2 ? TYPE_EQUAL : TYPE_NEQUAL;
4041 type_is = TRUE;
4042 }
4043 }
4044 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004045 }
4046
4047 /*
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004048 * If there is a comparative operator, use it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004049 */
4050 if (type != TYPE_UNKNOWN)
4051 {
4052 /* extra question mark appended: ignore case */
4053 if (p[len] == '?')
4054 {
4055 ic = TRUE;
4056 ++len;
4057 }
4058 /* extra '#' appended: match case */
4059 else if (p[len] == '#')
4060 {
4061 ic = FALSE;
4062 ++len;
4063 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004064 /* nothing appended: use 'ignorecase' */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004065 else
4066 ic = p_ic;
4067
4068 /*
4069 * Get the second variable.
4070 */
4071 *arg = skipwhite(p + len);
4072 if (eval5(arg, &var2, evaluate) == FAIL)
4073 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004074 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004075 return FAIL;
4076 }
Bram Moolenaar31988702018-02-13 12:57:42 +01004077 if (evaluate)
4078 {
4079 int ret = typval_compare(rettv, &var2, type, type_is, ic);
4080
4081 clear_tv(&var2);
4082 return ret;
4083 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004084 }
4085
4086 return OK;
4087}
4088
4089/*
4090 * Handle fourth level expression:
4091 * + number addition
4092 * - number subtraction
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004093 * . string concatenation (if script version is 1)
Bram Moolenaar0f248b02019-04-04 15:36:05 +02004094 * .. string concatenation
Bram Moolenaar071d4272004-06-13 20:20:40 +00004095 *
4096 * "arg" must point to the first non-white of the expression.
4097 * "arg" is advanced to the next non-white after the recognized expression.
4098 *
4099 * Return OK or FAIL.
4100 */
4101 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004102eval5(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004103{
Bram Moolenaar33570922005-01-25 22:26:29 +00004104 typval_T var2;
4105 typval_T var3;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004106 int op;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02004107 varnumber_T n1, n2;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004108#ifdef FEAT_FLOAT
4109 float_T f1 = 0, f2 = 0;
4110#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004111 char_u *s1, *s2;
4112 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4113 char_u *p;
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004114 int concat;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004115
4116 /*
4117 * Get the first variable.
4118 */
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004119 if (eval6(arg, rettv, evaluate, FALSE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004120 return FAIL;
4121
4122 /*
4123 * Repeat computing, until no '+', '-' or '.' is following.
4124 */
4125 for (;;)
4126 {
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004127 // "." is only string concatenation when scriptversion is 1
Bram Moolenaar071d4272004-06-13 20:20:40 +00004128 op = **arg;
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004129 concat = op == '.'
4130 && (*(*arg + 1) == '.' || current_sctx.sc_version < 2);
4131 if (op != '+' && op != '-' && !concat)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004132 break;
4133
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004134 if ((op != '+' || (rettv->v_type != VAR_LIST
4135 && rettv->v_type != VAR_BLOB))
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004136#ifdef FEAT_FLOAT
4137 && (op == '.' || rettv->v_type != VAR_FLOAT)
4138#endif
4139 )
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004140 {
4141 /* For "list + ...", an illegal use of the first operand as
4142 * a number cannot be determined before evaluating the 2nd
4143 * operand: if this is also a list, all is ok.
4144 * For "something . ...", "something - ..." or "non-list + ...",
4145 * we know that the first operand needs to be a string or number
4146 * without evaluating the 2nd operand. So check before to avoid
4147 * side effects after an error. */
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004148 if (evaluate && tv_get_string_chk(rettv) == NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004149 {
4150 clear_tv(rettv);
4151 return FAIL;
4152 }
4153 }
4154
Bram Moolenaar071d4272004-06-13 20:20:40 +00004155 /*
4156 * Get the second variable.
4157 */
Bram Moolenaar0f248b02019-04-04 15:36:05 +02004158 if (op == '.' && *(*arg + 1) == '.') // .. string concatenation
4159 ++*arg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004160 *arg = skipwhite(*arg + 1);
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004161 if (eval6(arg, &var2, evaluate, op == '.') == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004162 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004163 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004164 return FAIL;
4165 }
4166
4167 if (evaluate)
4168 {
4169 /*
4170 * Compute the result.
4171 */
4172 if (op == '.')
4173 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004174 s1 = tv_get_string_buf(rettv, buf1); /* already checked */
4175 s2 = tv_get_string_buf_chk(&var2, buf2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004176 if (s2 == NULL) /* type error ? */
4177 {
4178 clear_tv(rettv);
4179 clear_tv(&var2);
4180 return FAIL;
4181 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004182 p = concat_str(s1, s2);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004183 clear_tv(rettv);
4184 rettv->v_type = VAR_STRING;
4185 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004186 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004187 else if (op == '+' && rettv->v_type == VAR_BLOB
4188 && var2.v_type == VAR_BLOB)
4189 {
4190 blob_T *b1 = rettv->vval.v_blob;
4191 blob_T *b2 = var2.vval.v_blob;
4192 blob_T *b = blob_alloc();
4193 int i;
4194
4195 if (b != NULL)
4196 {
4197 for (i = 0; i < blob_len(b1); i++)
4198 ga_append(&b->bv_ga, blob_get(b1, i));
4199 for (i = 0; i < blob_len(b2); i++)
4200 ga_append(&b->bv_ga, blob_get(b2, i));
4201
4202 clear_tv(rettv);
4203 rettv_blob_set(rettv, b);
4204 }
4205 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00004206 else if (op == '+' && rettv->v_type == VAR_LIST
4207 && var2.v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004208 {
4209 /* concatenate Lists */
4210 if (list_concat(rettv->vval.v_list, var2.vval.v_list,
4211 &var3) == FAIL)
4212 {
4213 clear_tv(rettv);
4214 clear_tv(&var2);
4215 return FAIL;
4216 }
4217 clear_tv(rettv);
4218 *rettv = var3;
4219 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004220 else
4221 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004222 int error = FALSE;
4223
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004224#ifdef FEAT_FLOAT
4225 if (rettv->v_type == VAR_FLOAT)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004226 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004227 f1 = rettv->vval.v_float;
4228 n1 = 0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004229 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004230 else
4231#endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004232 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004233 n1 = tv_get_number_chk(rettv, &error);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004234 if (error)
4235 {
4236 /* This can only happen for "list + non-list". For
4237 * "non-list + ..." or "something - ...", we returned
4238 * before evaluating the 2nd operand. */
4239 clear_tv(rettv);
4240 return FAIL;
4241 }
4242#ifdef FEAT_FLOAT
4243 if (var2.v_type == VAR_FLOAT)
4244 f1 = n1;
4245#endif
4246 }
4247#ifdef FEAT_FLOAT
4248 if (var2.v_type == VAR_FLOAT)
4249 {
4250 f2 = var2.vval.v_float;
4251 n2 = 0;
4252 }
4253 else
4254#endif
4255 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004256 n2 = tv_get_number_chk(&var2, &error);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004257 if (error)
4258 {
4259 clear_tv(rettv);
4260 clear_tv(&var2);
4261 return FAIL;
4262 }
4263#ifdef FEAT_FLOAT
4264 if (rettv->v_type == VAR_FLOAT)
4265 f2 = n2;
4266#endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004267 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004268 clear_tv(rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004269
4270#ifdef FEAT_FLOAT
4271 /* If there is a float on either side the result is a float. */
4272 if (rettv->v_type == VAR_FLOAT || var2.v_type == VAR_FLOAT)
4273 {
4274 if (op == '+')
4275 f1 = f1 + f2;
4276 else
4277 f1 = f1 - f2;
4278 rettv->v_type = VAR_FLOAT;
4279 rettv->vval.v_float = f1;
4280 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004281 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004282#endif
4283 {
4284 if (op == '+')
4285 n1 = n1 + n2;
4286 else
4287 n1 = n1 - n2;
4288 rettv->v_type = VAR_NUMBER;
4289 rettv->vval.v_number = n1;
4290 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004291 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004292 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004293 }
4294 }
4295 return OK;
4296}
4297
4298/*
4299 * Handle fifth level expression:
4300 * * number multiplication
4301 * / number division
4302 * % number modulo
4303 *
4304 * "arg" must point to the first non-white of the expression.
4305 * "arg" is advanced to the next non-white after the recognized expression.
4306 *
4307 * Return OK or FAIL.
4308 */
4309 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004310eval6(
4311 char_u **arg,
4312 typval_T *rettv,
4313 int evaluate,
4314 int want_string) /* after "." operator */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004315{
Bram Moolenaar33570922005-01-25 22:26:29 +00004316 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004317 int op;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02004318 varnumber_T n1, n2;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004319#ifdef FEAT_FLOAT
4320 int use_float = FALSE;
Bram Moolenaar1f3601e2019-04-26 20:33:00 +02004321 float_T f1 = 0, f2 = 0;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004322#endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004323 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004324
4325 /*
4326 * Get the first variable.
4327 */
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004328 if (eval7(arg, rettv, evaluate, want_string) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004329 return FAIL;
4330
4331 /*
4332 * Repeat computing, until no '*', '/' or '%' is following.
4333 */
4334 for (;;)
4335 {
4336 op = **arg;
Bram Moolenaarb8be54d2019-07-14 18:22:59 +02004337 if (op != '*' && op != '/' && op != '%')
Bram Moolenaar071d4272004-06-13 20:20:40 +00004338 break;
4339
4340 if (evaluate)
4341 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004342#ifdef FEAT_FLOAT
4343 if (rettv->v_type == VAR_FLOAT)
4344 {
4345 f1 = rettv->vval.v_float;
4346 use_float = TRUE;
4347 n1 = 0;
4348 }
4349 else
4350#endif
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004351 n1 = tv_get_number_chk(rettv, &error);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004352 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004353 if (error)
4354 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004355 }
4356 else
4357 n1 = 0;
4358
4359 /*
4360 * Get the second variable.
4361 */
4362 *arg = skipwhite(*arg + 1);
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004363 if (eval7(arg, &var2, evaluate, FALSE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004364 return FAIL;
4365
4366 if (evaluate)
4367 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004368#ifdef FEAT_FLOAT
4369 if (var2.v_type == VAR_FLOAT)
4370 {
4371 if (!use_float)
4372 {
4373 f1 = n1;
4374 use_float = TRUE;
4375 }
4376 f2 = var2.vval.v_float;
4377 n2 = 0;
4378 }
4379 else
4380#endif
4381 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01004382 n2 = tv_get_number_chk(&var2, &error);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004383 clear_tv(&var2);
4384 if (error)
4385 return FAIL;
4386#ifdef FEAT_FLOAT
4387 if (use_float)
4388 f2 = n2;
4389#endif
4390 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004391
4392 /*
4393 * Compute the result.
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004394 * When either side is a float the result is a float.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004395 */
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004396#ifdef FEAT_FLOAT
4397 if (use_float)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004398 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004399 if (op == '*')
4400 f1 = f1 * f2;
4401 else if (op == '/')
4402 {
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004403# ifdef VMS
4404 /* VMS crashes on divide by zero, work around it */
4405 if (f2 == 0.0)
4406 {
4407 if (f1 == 0)
Bram Moolenaar314f11d2010-08-09 22:07:08 +02004408 f1 = -1 * __F_FLT_MAX - 1L; /* similar to NaN */
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004409 else if (f1 < 0)
Bram Moolenaar314f11d2010-08-09 22:07:08 +02004410 f1 = -1 * __F_FLT_MAX;
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004411 else
Bram Moolenaar314f11d2010-08-09 22:07:08 +02004412 f1 = __F_FLT_MAX;
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004413 }
4414 else
4415 f1 = f1 / f2;
4416# else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004417 /* We rely on the floating point library to handle divide
4418 * by zero to result in "inf" and not a crash. */
4419 f1 = f1 / f2;
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004420# endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004421 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004422 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004423 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004424 emsg(_("E804: Cannot use '%' with Float"));
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004425 return FAIL;
4426 }
4427 rettv->v_type = VAR_FLOAT;
4428 rettv->vval.v_float = f1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004429 }
4430 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004431#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004432 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004433 if (op == '*')
4434 n1 = n1 * n2;
4435 else if (op == '/')
Bram Moolenaare21c1582019-03-02 11:57:09 +01004436 n1 = num_divide(n1, n2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004437 else
Bram Moolenaare21c1582019-03-02 11:57:09 +01004438 n1 = num_modulus(n1, n2);
4439
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004440 rettv->v_type = VAR_NUMBER;
4441 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004442 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004443 }
4444 }
4445
4446 return OK;
4447}
4448
4449/*
4450 * Handle sixth level expression:
4451 * number number constant
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004452 * 0zFFFFFFFF Blob constant
Bram Moolenaarbae0c162007-05-10 19:30:25 +00004453 * "string" string constant
4454 * 'string' literal string constant
Bram Moolenaar071d4272004-06-13 20:20:40 +00004455 * &option-name option value
4456 * @r register contents
4457 * identifier variable value
4458 * function() function call
4459 * $VAR environment variable
4460 * (expression) nested expression
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00004461 * [expr, expr] List
Bram Moolenaard5abb4c2019-07-13 22:46:10 +02004462 * {key: val, key: val} Dictionary
Bram Moolenaar4c6d9042019-07-16 22:04:02 +02004463 * #{key: val, key: val} Dictionary with literal keys
Bram Moolenaar071d4272004-06-13 20:20:40 +00004464 *
4465 * Also handle:
4466 * ! in front logical NOT
4467 * - in front unary minus
4468 * + in front unary plus (ignored)
Bram Moolenaar8c711452005-01-14 21:53:12 +00004469 * trailing [] subscript in String or List
4470 * trailing .name entry in Dictionary
Bram Moolenaarac92e252019-08-03 21:58:38 +02004471 * trailing ->name() method call
Bram Moolenaar071d4272004-06-13 20:20:40 +00004472 *
4473 * "arg" must point to the first non-white of the expression.
4474 * "arg" is advanced to the next non-white after the recognized expression.
4475 *
4476 * Return OK or FAIL.
4477 */
4478 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004479eval7(
4480 char_u **arg,
4481 typval_T *rettv,
4482 int evaluate,
4483 int want_string UNUSED) /* after "." operator */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004484{
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02004485 varnumber_T n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004486 int len;
4487 char_u *s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004488 char_u *start_leader, *end_leader;
4489 int ret = OK;
4490 char_u *alias;
4491
4492 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004493 * Initialise variable so that clear_tv() can't mistake this for a
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004494 * string and free a string that isn't there.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004495 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004496 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004497
4498 /*
Bram Moolenaaredf3f972016-08-29 22:49:24 +02004499 * Skip '!', '-' and '+' characters. They are handled later.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004500 */
4501 start_leader = *arg;
4502 while (**arg == '!' || **arg == '-' || **arg == '+')
4503 *arg = skipwhite(*arg + 1);
4504 end_leader = *arg;
4505
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004506 if (**arg == '.' && (!isdigit(*(*arg + 1))
4507#ifdef FEAT_FLOAT
4508 || current_sctx.sc_version < 2
4509#endif
4510 ))
4511 {
4512 semsg(_(e_invexpr2), *arg);
4513 ++*arg;
4514 return FAIL;
4515 }
4516
Bram Moolenaar071d4272004-06-13 20:20:40 +00004517 switch (**arg)
4518 {
4519 /*
4520 * Number constant.
4521 */
4522 case '0':
4523 case '1':
4524 case '2':
4525 case '3':
4526 case '4':
4527 case '5':
4528 case '6':
4529 case '7':
4530 case '8':
4531 case '9':
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004532 case '.':
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004533 {
4534#ifdef FEAT_FLOAT
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004535 char_u *p;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004536 int get_float = FALSE;
4537
4538 /* We accept a float when the format matches
4539 * "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004540 * strict to avoid backwards compatibility problems.
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004541 * With script version 2 and later the leading digit can be
4542 * omitted.
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004543 * Don't look for a float after the "." operator, so that
4544 * ":let vers = 1.2.3" doesn't fail. */
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004545 if (**arg == '.')
4546 p = *arg;
4547 else
4548 p = skipdigits(*arg + 1);
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004549 if (!want_string && p[0] == '.' && vim_isdigit(p[1]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004550 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004551 get_float = TRUE;
4552 p = skipdigits(p + 2);
4553 if (*p == 'e' || *p == 'E')
4554 {
4555 ++p;
4556 if (*p == '-' || *p == '+')
4557 ++p;
4558 if (!vim_isdigit(*p))
4559 get_float = FALSE;
4560 else
4561 p = skipdigits(p + 1);
4562 }
4563 if (ASCII_ISALPHA(*p) || *p == '.')
4564 get_float = FALSE;
4565 }
4566 if (get_float)
4567 {
4568 float_T f;
4569
4570 *arg += string2float(*arg, &f);
4571 if (evaluate)
4572 {
4573 rettv->v_type = VAR_FLOAT;
4574 rettv->vval.v_float = f;
4575 }
4576 }
4577 else
4578#endif
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004579 if (**arg == '0' && ((*arg)[1] == 'z' || (*arg)[1] == 'Z'))
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004580 {
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004581 char_u *bp;
Bram Moolenaare519dfd2019-01-13 15:42:02 +01004582 blob_T *blob = NULL; // init for gcc
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004583
4584 // Blob constant: 0z0123456789abcdef
4585 if (evaluate)
4586 blob = blob_alloc();
4587 for (bp = *arg + 2; vim_isxdigit(bp[0]); bp += 2)
4588 {
4589 if (!vim_isxdigit(bp[1]))
4590 {
Bram Moolenaarecc8bc42019-01-13 16:07:21 +01004591 if (blob != NULL)
4592 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004593 emsg(_("E973: Blob literal should have an even number of hex characters"));
Bram Moolenaarecc8bc42019-01-13 16:07:21 +01004594 ga_clear(&blob->bv_ga);
4595 VIM_CLEAR(blob);
4596 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004597 ret = FAIL;
4598 break;
4599 }
4600 if (blob != NULL)
4601 ga_append(&blob->bv_ga,
4602 (hex2nr(*bp) << 4) + hex2nr(*(bp+1)));
Bram Moolenaar4131fd52019-01-17 16:32:53 +01004603 if (bp[2] == '.' && vim_isxdigit(bp[3]))
4604 ++bp;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004605 }
4606 if (blob != NULL)
Bram Moolenaarecc8bc42019-01-13 16:07:21 +01004607 rettv_blob_set(rettv, blob);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004608 *arg = bp;
4609 }
4610 else
4611 {
4612 // decimal, hex or octal number
Bram Moolenaar16e9b852019-05-19 19:59:35 +02004613 vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0, TRUE);
4614 if (len == 0)
4615 {
4616 semsg(_(e_invexpr2), *arg);
4617 ret = FAIL;
4618 break;
4619 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004620 *arg += len;
4621 if (evaluate)
4622 {
4623 rettv->v_type = VAR_NUMBER;
4624 rettv->vval.v_number = n;
4625 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004626 }
4627 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004628 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004629
4630 /*
4631 * String constant: "string".
4632 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004633 case '"': ret = get_string_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004634 break;
4635
4636 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004637 * Literal string constant: 'str''ing'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004638 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004639 case '\'': ret = get_lit_string_tv(arg, rettv, evaluate);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004640 break;
4641
4642 /*
4643 * List: [expr, expr]
4644 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004645 case '[': ret = get_list_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004646 break;
4647
4648 /*
Bram Moolenaar4c6d9042019-07-16 22:04:02 +02004649 * Dictionary: #{key: val, key: val}
Bram Moolenaard5abb4c2019-07-13 22:46:10 +02004650 */
Bram Moolenaar4c6d9042019-07-16 22:04:02 +02004651 case '#': if ((*arg)[1] == '{')
Bram Moolenaard5abb4c2019-07-13 22:46:10 +02004652 {
4653 ++*arg;
4654 ret = dict_get_tv(arg, rettv, evaluate, TRUE);
4655 }
4656 else
4657 ret = NOTDONE;
4658 break;
4659
4660 /*
Bram Moolenaar069c1e72016-07-15 21:25:08 +02004661 * Lambda: {arg, arg -> expr}
Bram Moolenaard5abb4c2019-07-13 22:46:10 +02004662 * Dictionary: {'key': val, 'key': val}
Bram Moolenaar8c711452005-01-14 21:53:12 +00004663 */
Bram Moolenaar069c1e72016-07-15 21:25:08 +02004664 case '{': ret = get_lambda_tv(arg, rettv, evaluate);
4665 if (ret == NOTDONE)
Bram Moolenaard5abb4c2019-07-13 22:46:10 +02004666 ret = dict_get_tv(arg, rettv, evaluate, FALSE);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004667 break;
4668
4669 /*
Bram Moolenaare9a41262005-01-15 22:18:47 +00004670 * Option value: &name
Bram Moolenaar071d4272004-06-13 20:20:40 +00004671 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00004672 case '&': ret = get_option_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004673 break;
4674
4675 /*
4676 * Environment variable: $VAR.
4677 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004678 case '$': ret = get_env_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004679 break;
4680
4681 /*
4682 * Register contents: @r.
4683 */
4684 case '@': ++*arg;
4685 if (evaluate)
4686 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004687 rettv->v_type = VAR_STRING;
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +02004688 rettv->vval.v_string = get_reg_contents(**arg,
4689 GREG_EXPR_SRC);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004690 }
4691 if (**arg != NUL)
4692 ++*arg;
4693 break;
4694
4695 /*
4696 * nested expression: (expression).
4697 */
4698 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004699 ret = eval1(arg, rettv, evaluate); /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004700 if (**arg == ')')
4701 ++*arg;
4702 else if (ret == OK)
4703 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004704 emsg(_("E110: Missing ')'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004705 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004706 ret = FAIL;
4707 }
4708 break;
4709
Bram Moolenaar8c711452005-01-14 21:53:12 +00004710 default: ret = NOTDONE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004711 break;
4712 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004713
4714 if (ret == NOTDONE)
4715 {
4716 /*
4717 * Must be a variable or function name.
4718 * Can also be a curly-braces kind of name: {expr}.
4719 */
4720 s = *arg;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004721 len = get_name_len(arg, &alias, evaluate, TRUE);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004722 if (alias != NULL)
4723 s = alias;
4724
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004725 if (len <= 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00004726 ret = FAIL;
4727 else
4728 {
4729 if (**arg == '(') /* recursive! */
Bram Moolenaar761fdf02019-08-05 23:10:16 +02004730 ret = eval_func(arg, s, len, rettv, evaluate, NULL);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004731 else if (evaluate)
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02004732 ret = get_var_tv(s, len, rettv, NULL, TRUE, FALSE);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004733 else
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02004734 {
4735 check_vars(s, len);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004736 ret = OK;
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02004737 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004738 }
Bram Moolenaar3c2d6532011-02-01 13:48:53 +01004739 vim_free(alias);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004740 }
4741
Bram Moolenaar071d4272004-06-13 20:20:40 +00004742 *arg = skipwhite(*arg);
4743
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004744 /* Handle following '[', '(' and '.' for expr[expr], expr.name,
Bram Moolenaarfcfe1a92019-08-04 23:04:39 +02004745 * expr(expr), expr->name(expr) */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004746 if (ret == OK)
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02004747 ret = handle_subscript(arg, rettv, evaluate, TRUE,
4748 start_leader, &end_leader);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004749
4750 /*
4751 * Apply logical NOT and unary '-', from right to left, ignore '+'.
4752 */
4753 if (ret == OK && evaluate && end_leader > start_leader)
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02004754 ret = eval7_leader(rettv, start_leader, &end_leader);
4755 return ret;
4756}
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004757
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02004758/*
4759 * Apply the leading "!" and "-" before an eval7 expression to "rettv".
4760 * Adjusts "end_leaderp" until it is at "start_leader".
4761 */
4762 static int
4763eval7_leader(typval_T *rettv, char_u *start_leader, char_u **end_leaderp)
4764{
4765 char_u *end_leader = *end_leaderp;
4766 int ret = OK;
4767 int error = FALSE;
4768 varnumber_T val = 0;
4769#ifdef FEAT_FLOAT
4770 float_T f = 0.0;
4771
4772 if (rettv->v_type == VAR_FLOAT)
4773 f = rettv->vval.v_float;
4774 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004775#endif
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02004776 val = tv_get_number_chk(rettv, &error);
4777 if (error)
4778 {
4779 clear_tv(rettv);
4780 ret = FAIL;
4781 }
4782 else
4783 {
4784 while (end_leader > start_leader)
4785 {
4786 --end_leader;
4787 if (*end_leader == '!')
4788 {
4789#ifdef FEAT_FLOAT
4790 if (rettv->v_type == VAR_FLOAT)
4791 f = !f;
4792 else
4793#endif
4794 val = !val;
4795 }
4796 else if (*end_leader == '-')
4797 {
4798#ifdef FEAT_FLOAT
4799 if (rettv->v_type == VAR_FLOAT)
4800 f = -f;
4801 else
4802#endif
4803 val = -val;
4804 }
4805 }
4806#ifdef FEAT_FLOAT
4807 if (rettv->v_type == VAR_FLOAT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004808 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004809 clear_tv(rettv);
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02004810 rettv->vval.v_float = f;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004811 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004812 else
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02004813#endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004814 {
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02004815 clear_tv(rettv);
4816 rettv->v_type = VAR_NUMBER;
4817 rettv->vval.v_number = val;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004818 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004819 }
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02004820 *end_leaderp = end_leader;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004821 return ret;
4822}
4823
4824/*
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02004825 * Call the function referred to in "rettv".
4826 */
4827 static int
4828call_func_rettv(
4829 char_u **arg,
4830 typval_T *rettv,
4831 int evaluate,
4832 dict_T *selfdict,
4833 typval_T *basetv)
4834{
4835 partial_T *pt = NULL;
4836 funcexe_T funcexe;
4837 typval_T functv;
4838 char_u *s;
4839 int ret;
4840
4841 // need to copy the funcref so that we can clear rettv
4842 if (evaluate)
4843 {
4844 functv = *rettv;
4845 rettv->v_type = VAR_UNKNOWN;
4846
4847 /* Invoke the function. Recursive! */
4848 if (functv.v_type == VAR_PARTIAL)
4849 {
4850 pt = functv.vval.v_partial;
4851 s = partial_name(pt);
4852 }
4853 else
4854 s = functv.vval.v_string;
4855 }
4856 else
4857 s = (char_u *)"";
4858
4859 vim_memset(&funcexe, 0, sizeof(funcexe));
4860 funcexe.firstline = curwin->w_cursor.lnum;
4861 funcexe.lastline = curwin->w_cursor.lnum;
4862 funcexe.evaluate = evaluate;
4863 funcexe.partial = pt;
4864 funcexe.selfdict = selfdict;
4865 funcexe.basetv = basetv;
4866 ret = get_func_tv(s, -1, rettv, arg, &funcexe);
4867
4868 /* Clear the funcref afterwards, so that deleting it while
4869 * evaluating the arguments is possible (see test55). */
4870 if (evaluate)
4871 clear_tv(&functv);
4872
4873 return ret;
4874}
4875
4876/*
4877 * Evaluate "->method()".
4878 * "*arg" points to the '-'.
4879 * Returns FAIL or OK. "*arg" is advanced to after the ')'.
4880 */
4881 static int
4882eval_lambda(
4883 char_u **arg,
4884 typval_T *rettv,
4885 int evaluate,
4886 int verbose) /* give error messages */
4887{
4888 typval_T base = *rettv;
4889 int ret;
4890
4891 // Skip over the ->.
4892 *arg += 2;
4893 rettv->v_type = VAR_UNKNOWN;
4894
4895 ret = get_lambda_tv(arg, rettv, evaluate);
4896 if (ret == NOTDONE)
4897 return FAIL;
4898 else if (**arg != '(')
4899 {
4900 if (verbose)
4901 {
4902 if (*skipwhite(*arg) == '(')
4903 semsg(_(e_nowhitespace));
4904 else
4905 semsg(_(e_missingparen), "lambda");
4906 }
4907 clear_tv(rettv);
4908 return FAIL;
4909 }
4910 return call_func_rettv(arg, rettv, evaluate, NULL, &base);
4911}
4912
4913/*
Bram Moolenaarac92e252019-08-03 21:58:38 +02004914 * Evaluate "->method()".
4915 * "*arg" points to the '-'.
4916 * Returns FAIL or OK. "*arg" is advanced to after the ')'.
4917 */
4918 static int
4919eval_method(
4920 char_u **arg,
4921 typval_T *rettv,
4922 int evaluate,
4923 int verbose) /* give error messages */
4924{
4925 char_u *name;
4926 long len;
Bram Moolenaar761fdf02019-08-05 23:10:16 +02004927 char_u *alias;
Bram Moolenaarac92e252019-08-03 21:58:38 +02004928 typval_T base = *rettv;
Bram Moolenaar761fdf02019-08-05 23:10:16 +02004929 int ret;
Bram Moolenaarac92e252019-08-03 21:58:38 +02004930
4931 // Skip over the ->.
4932 *arg += 2;
Bram Moolenaar761fdf02019-08-05 23:10:16 +02004933 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaarac92e252019-08-03 21:58:38 +02004934
Bram Moolenaarac92e252019-08-03 21:58:38 +02004935 name = *arg;
Bram Moolenaar761fdf02019-08-05 23:10:16 +02004936 len = get_name_len(arg, &alias, evaluate, TRUE);
4937 if (alias != NULL)
4938 name = alias;
4939
4940 if (len <= 0)
Bram Moolenaarac92e252019-08-03 21:58:38 +02004941 {
4942 if (verbose)
4943 emsg(_("E260: Missing name after ->"));
Bram Moolenaar761fdf02019-08-05 23:10:16 +02004944 ret = FAIL;
Bram Moolenaarac92e252019-08-03 21:58:38 +02004945 }
Bram Moolenaar761fdf02019-08-05 23:10:16 +02004946 else
Bram Moolenaarac92e252019-08-03 21:58:38 +02004947 {
Bram Moolenaar761fdf02019-08-05 23:10:16 +02004948 if (**arg != '(')
4949 {
4950 if (verbose)
4951 semsg(_(e_missingparen), name);
4952 ret = FAIL;
4953 }
Bram Moolenaar51841322019-08-08 21:10:01 +02004954 else if (VIM_ISWHITE((*arg)[-1]))
4955 {
4956 if (verbose)
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02004957 semsg(_(e_nowhitespace));
Bram Moolenaar51841322019-08-08 21:10:01 +02004958 ret = FAIL;
4959 }
Bram Moolenaar761fdf02019-08-05 23:10:16 +02004960 else
4961 ret = eval_func(arg, name, len, rettv, evaluate, &base);
Bram Moolenaarac92e252019-08-03 21:58:38 +02004962 }
Bram Moolenaarac92e252019-08-03 21:58:38 +02004963
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02004964 // Clear the funcref afterwards, so that deleting it while
4965 // evaluating the arguments is possible (see test55).
Bram Moolenaarac92e252019-08-03 21:58:38 +02004966 if (evaluate)
4967 clear_tv(&base);
4968
Bram Moolenaarac92e252019-08-03 21:58:38 +02004969 return ret;
4970}
4971
4972/*
Bram Moolenaar9e54a0e2006-04-14 20:42:25 +00004973 * Evaluate an "[expr]" or "[expr:expr]" index. Also "dict.key".
4974 * "*arg" points to the '[' or '.'.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004975 * Returns FAIL or OK. "*arg" is advanced to after the ']'.
4976 */
4977 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004978eval_index(
4979 char_u **arg,
4980 typval_T *rettv,
4981 int evaluate,
4982 int verbose) /* give error messages */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004983{
4984 int empty1 = FALSE, empty2 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00004985 typval_T var1, var2;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004986 long i;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004987 long n1, n2 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004988 long len = -1;
4989 int range = FALSE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004990 char_u *s;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004991 char_u *key = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004992
Bram Moolenaara03f2332016-02-06 18:09:59 +01004993 switch (rettv->v_type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004994 {
Bram Moolenaara03f2332016-02-06 18:09:59 +01004995 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01004996 case VAR_PARTIAL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01004997 if (verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004998 emsg(_("E695: Cannot index a Funcref"));
Bram Moolenaara03f2332016-02-06 18:09:59 +01004999 return FAIL;
5000 case VAR_FLOAT:
Bram Moolenaar2a876e42013-06-12 22:08:58 +02005001#ifdef FEAT_FLOAT
Bram Moolenaara03f2332016-02-06 18:09:59 +01005002 if (verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005003 emsg(_(e_float_as_string));
Bram Moolenaara03f2332016-02-06 18:09:59 +01005004 return FAIL;
Bram Moolenaar2a876e42013-06-12 22:08:58 +02005005#endif
Bram Moolenaara03f2332016-02-06 18:09:59 +01005006 case VAR_SPECIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01005007 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01005008 case VAR_CHANNEL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01005009 if (verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005010 emsg(_("E909: Cannot index a special variable"));
Bram Moolenaara03f2332016-02-06 18:09:59 +01005011 return FAIL;
5012 case VAR_UNKNOWN:
5013 if (evaluate)
5014 return FAIL;
5015 /* FALLTHROUGH */
5016
5017 case VAR_STRING:
5018 case VAR_NUMBER:
5019 case VAR_LIST:
5020 case VAR_DICT:
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01005021 case VAR_BLOB:
Bram Moolenaara03f2332016-02-06 18:09:59 +01005022 break;
Bram Moolenaar520e1e42016-01-23 19:46:28 +01005023 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005024
Bram Moolenaar0a38dd22015-08-25 16:49:01 +02005025 init_tv(&var1);
5026 init_tv(&var2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005027 if (**arg == '.')
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005028 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005029 /*
5030 * dict.name
5031 */
5032 key = *arg + 1;
5033 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
5034 ;
5035 if (len == 0)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005036 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005037 *arg = skipwhite(key + len);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005038 }
5039 else
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005040 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005041 /*
5042 * something[idx]
5043 *
5044 * Get the (first) variable from inside the [].
5045 */
5046 *arg = skipwhite(*arg + 1);
5047 if (**arg == ':')
5048 empty1 = TRUE;
5049 else if (eval1(arg, &var1, evaluate) == FAIL) /* recursive! */
5050 return FAIL;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01005051 else if (evaluate && tv_get_string_chk(&var1) == NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005052 {
5053 /* not a number or string */
5054 clear_tv(&var1);
5055 return FAIL;
5056 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005057
5058 /*
5059 * Get the second variable from inside the [:].
5060 */
5061 if (**arg == ':')
5062 {
5063 range = TRUE;
5064 *arg = skipwhite(*arg + 1);
5065 if (**arg == ']')
5066 empty2 = TRUE;
5067 else if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */
5068 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005069 if (!empty1)
5070 clear_tv(&var1);
5071 return FAIL;
5072 }
Bram Moolenaard155d7a2018-12-21 16:04:21 +01005073 else if (evaluate && tv_get_string_chk(&var2) == NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005074 {
5075 /* not a number or string */
5076 if (!empty1)
5077 clear_tv(&var1);
5078 clear_tv(&var2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005079 return FAIL;
5080 }
5081 }
5082
5083 /* Check for the ']'. */
5084 if (**arg != ']')
5085 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005086 if (verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005087 emsg(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00005088 clear_tv(&var1);
5089 if (range)
5090 clear_tv(&var2);
5091 return FAIL;
5092 }
5093 *arg = skipwhite(*arg + 1); /* skip the ']' */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005094 }
5095
5096 if (evaluate)
5097 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005098 n1 = 0;
5099 if (!empty1 && rettv->v_type != VAR_DICT)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005100 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01005101 n1 = tv_get_number(&var1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005102 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005103 }
5104 if (range)
5105 {
5106 if (empty2)
5107 n2 = -1;
5108 else
5109 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01005110 n2 = tv_get_number(&var2);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005111 clear_tv(&var2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005112 }
5113 }
5114
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005115 switch (rettv->v_type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005116 {
Bram Moolenaar835dc632016-02-07 14:27:38 +01005117 case VAR_UNKNOWN:
Bram Moolenaara03f2332016-02-06 18:09:59 +01005118 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01005119 case VAR_PARTIAL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01005120 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01005121 case VAR_SPECIAL:
5122 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01005123 case VAR_CHANNEL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01005124 break; /* not evaluating, skipping over subscript */
5125
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005126 case VAR_NUMBER:
5127 case VAR_STRING:
Bram Moolenaard155d7a2018-12-21 16:04:21 +01005128 s = tv_get_string(rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005129 len = (long)STRLEN(s);
5130 if (range)
5131 {
5132 /* The resulting variable is a substring. If the indexes
5133 * are out of range the result is empty. */
5134 if (n1 < 0)
5135 {
5136 n1 = len + n1;
5137 if (n1 < 0)
5138 n1 = 0;
5139 }
5140 if (n2 < 0)
5141 n2 = len + n2;
5142 else if (n2 >= len)
5143 n2 = len;
5144 if (n1 >= len || n2 < 0 || n1 > n2)
5145 s = NULL;
5146 else
5147 s = vim_strnsave(s + n1, (int)(n2 - n1 + 1));
5148 }
5149 else
5150 {
5151 /* The resulting variable is a string of a single
5152 * character. If the index is too big or negative the
5153 * result is empty. */
5154 if (n1 >= len || n1 < 0)
5155 s = NULL;
5156 else
5157 s = vim_strnsave(s + n1, 1);
5158 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005159 clear_tv(rettv);
5160 rettv->v_type = VAR_STRING;
5161 rettv->vval.v_string = s;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005162 break;
5163
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01005164 case VAR_BLOB:
5165 len = blob_len(rettv->vval.v_blob);
5166 if (range)
5167 {
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01005168 // The resulting variable is a sub-blob. If the indexes
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01005169 // are out of range the result is empty.
5170 if (n1 < 0)
5171 {
5172 n1 = len + n1;
5173 if (n1 < 0)
5174 n1 = 0;
5175 }
5176 if (n2 < 0)
5177 n2 = len + n2;
5178 else if (n2 >= len)
5179 n2 = len - 1;
5180 if (n1 >= len || n2 < 0 || n1 > n2)
5181 {
5182 clear_tv(rettv);
5183 rettv->v_type = VAR_BLOB;
5184 rettv->vval.v_blob = NULL;
5185 }
5186 else
5187 {
5188 blob_T *blob = blob_alloc();
5189
5190 if (blob != NULL)
5191 {
5192 if (ga_grow(&blob->bv_ga, n2 - n1 + 1) == FAIL)
5193 {
5194 blob_free(blob);
5195 return FAIL;
5196 }
5197 blob->bv_ga.ga_len = n2 - n1 + 1;
5198 for (i = n1; i <= n2; i++)
5199 blob_set(blob, i - n1,
5200 blob_get(rettv->vval.v_blob, i));
5201
5202 clear_tv(rettv);
5203 rettv_blob_set(rettv, blob);
5204 }
5205 }
5206 }
5207 else
5208 {
Bram Moolenaara5be9b62019-01-24 12:31:44 +01005209 // The resulting variable is a byte value.
5210 // If the index is too big or negative that is an error.
5211 if (n1 < 0)
5212 n1 = len + n1;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01005213 if (n1 < len && n1 >= 0)
5214 {
Bram Moolenaara5be9b62019-01-24 12:31:44 +01005215 int v = blob_get(rettv->vval.v_blob, n1);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01005216
5217 clear_tv(rettv);
5218 rettv->v_type = VAR_NUMBER;
5219 rettv->vval.v_number = v;
5220 }
5221 else
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005222 semsg(_(e_blobidx), n1);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01005223 }
5224 break;
5225
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005226 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005227 len = list_len(rettv->vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005228 if (n1 < 0)
5229 n1 = len + n1;
5230 if (!empty1 && (n1 < 0 || n1 >= len))
5231 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00005232 /* For a range we allow invalid values and return an empty
5233 * list. A list index out of range is an error. */
5234 if (!range)
5235 {
5236 if (verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005237 semsg(_(e_listidx), n1);
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00005238 return FAIL;
5239 }
5240 n1 = len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005241 }
5242 if (range)
5243 {
Bram Moolenaar33570922005-01-25 22:26:29 +00005244 list_T *l;
5245 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005246
5247 if (n2 < 0)
5248 n2 = len + n2;
Bram Moolenaar9e54a0e2006-04-14 20:42:25 +00005249 else if (n2 >= len)
5250 n2 = len - 1;
5251 if (!empty2 && (n2 < 0 || n2 + 1 < n1))
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00005252 n2 = -1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005253 l = list_alloc();
5254 if (l == NULL)
5255 return FAIL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005256 for (item = list_find(rettv->vval.v_list, n1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005257 n1 <= n2; ++n1)
5258 {
5259 if (list_append_tv(l, &item->li_tv) == FAIL)
5260 {
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005261 list_free(l);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005262 return FAIL;
5263 }
5264 item = item->li_next;
5265 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005266 clear_tv(rettv);
Bram Moolenaar45cf6e92017-04-30 20:25:19 +02005267 rettv_list_set(rettv, l);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005268 }
5269 else
5270 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00005271 copy_tv(&list_find(rettv->vval.v_list, n1)->li_tv, &var1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005272 clear_tv(rettv);
5273 *rettv = var1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005274 }
5275 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005276
5277 case VAR_DICT:
5278 if (range)
5279 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005280 if (verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005281 emsg(_(e_dictrange));
Bram Moolenaar8c711452005-01-14 21:53:12 +00005282 if (len == -1)
5283 clear_tv(&var1);
5284 return FAIL;
5285 }
5286 {
Bram Moolenaar33570922005-01-25 22:26:29 +00005287 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005288
5289 if (len == -1)
5290 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01005291 key = tv_get_string_chk(&var1);
Bram Moolenaar0921ecf2016-04-03 22:44:36 +02005292 if (key == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005293 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005294 clear_tv(&var1);
5295 return FAIL;
5296 }
5297 }
5298
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005299 item = dict_find(rettv->vval.v_dict, key, (int)len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005300
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005301 if (item == NULL && verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005302 semsg(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005303 if (len == -1)
5304 clear_tv(&var1);
5305 if (item == NULL)
5306 return FAIL;
5307
5308 copy_tv(&item->di_tv, &var1);
5309 clear_tv(rettv);
5310 *rettv = var1;
5311 }
5312 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005313 }
5314 }
5315
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005316 return OK;
5317}
5318
5319/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005320 * Get an option value.
5321 * "arg" points to the '&' or '+' before the option name.
5322 * "arg" is advanced to character after the option name.
5323 * Return OK or FAIL.
5324 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02005325 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005326get_option_tv(
5327 char_u **arg,
5328 typval_T *rettv, /* when NULL, only check if option exists */
5329 int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005330{
5331 char_u *option_end;
5332 long numval;
5333 char_u *stringval;
5334 int opt_type;
5335 int c;
5336 int working = (**arg == '+'); /* has("+option") */
5337 int ret = OK;
5338 int opt_flags;
5339
5340 /*
5341 * Isolate the option name and find its value.
5342 */
5343 option_end = find_option_end(arg, &opt_flags);
5344 if (option_end == NULL)
5345 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005346 if (rettv != NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005347 semsg(_("E112: Option name missing: %s"), *arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005348 return FAIL;
5349 }
5350
5351 if (!evaluate)
5352 {
5353 *arg = option_end;
5354 return OK;
5355 }
5356
5357 c = *option_end;
5358 *option_end = NUL;
5359 opt_type = get_option_value(*arg, &numval,
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005360 rettv == NULL ? NULL : &stringval, opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005361
5362 if (opt_type == -3) /* invalid name */
5363 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005364 if (rettv != NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005365 semsg(_("E113: Unknown option: %s"), *arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005366 ret = FAIL;
5367 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005368 else if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005369 {
5370 if (opt_type == -2) /* hidden string option */
5371 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005372 rettv->v_type = VAR_STRING;
5373 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005374 }
5375 else if (opt_type == -1) /* hidden number option */
5376 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005377 rettv->v_type = VAR_NUMBER;
5378 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005379 }
5380 else if (opt_type == 1) /* number option */
5381 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005382 rettv->v_type = VAR_NUMBER;
5383 rettv->vval.v_number = numval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005384 }
5385 else /* string option */
5386 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005387 rettv->v_type = VAR_STRING;
5388 rettv->vval.v_string = stringval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005389 }
5390 }
5391 else if (working && (opt_type == -2 || opt_type == -1))
5392 ret = FAIL;
5393
5394 *option_end = c; /* put back for error messages */
5395 *arg = option_end;
5396
5397 return ret;
5398}
5399
5400/*
5401 * Allocate a variable for a string constant.
5402 * Return OK or FAIL.
5403 */
5404 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005405get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005406{
5407 char_u *p;
5408 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005409 int extra = 0;
5410
5411 /*
5412 * Find the end of the string, skipping backslashed characters.
5413 */
Bram Moolenaar91acfff2017-03-12 19:22:36 +01005414 for (p = *arg + 1; *p != NUL && *p != '"'; MB_PTR_ADV(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005415 {
5416 if (*p == '\\' && p[1] != NUL)
5417 {
5418 ++p;
5419 /* A "\<x>" form occupies at least 4 characters, and produces up
5420 * to 6 characters: reserve space for 2 extra */
5421 if (*p == '<')
5422 extra += 2;
5423 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005424 }
5425
5426 if (*p != '"')
5427 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005428 semsg(_("E114: Missing quote: %s"), *arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005429 return FAIL;
5430 }
5431
5432 /* If only parsing, set *arg and return here */
5433 if (!evaluate)
5434 {
5435 *arg = p + 1;
5436 return OK;
5437 }
5438
5439 /*
5440 * Copy the string into allocated memory, handling backslashed
5441 * characters.
5442 */
Bram Moolenaar964b3742019-05-24 18:54:09 +02005443 name = alloc(p - *arg + extra);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005444 if (name == NULL)
5445 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005446 rettv->v_type = VAR_STRING;
5447 rettv->vval.v_string = name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005448
Bram Moolenaar8c711452005-01-14 21:53:12 +00005449 for (p = *arg + 1; *p != NUL && *p != '"'; )
Bram Moolenaar071d4272004-06-13 20:20:40 +00005450 {
5451 if (*p == '\\')
5452 {
5453 switch (*++p)
5454 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005455 case 'b': *name++ = BS; ++p; break;
5456 case 'e': *name++ = ESC; ++p; break;
5457 case 'f': *name++ = FF; ++p; break;
5458 case 'n': *name++ = NL; ++p; break;
5459 case 'r': *name++ = CAR; ++p; break;
5460 case 't': *name++ = TAB; ++p; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005461
5462 case 'X': /* hex: "\x1", "\x12" */
5463 case 'x':
5464 case 'u': /* Unicode: "\u0023" */
5465 case 'U':
5466 if (vim_isxdigit(p[1]))
5467 {
5468 int n, nr;
5469 int c = toupper(*p);
5470
5471 if (c == 'X')
5472 n = 2;
Bram Moolenaaracc39882015-06-19 12:08:13 +02005473 else if (*p == 'u')
Bram Moolenaar071d4272004-06-13 20:20:40 +00005474 n = 4;
Bram Moolenaaracc39882015-06-19 12:08:13 +02005475 else
5476 n = 8;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005477 nr = 0;
5478 while (--n >= 0 && vim_isxdigit(p[1]))
5479 {
5480 ++p;
5481 nr = (nr << 4) + hex2nr(*p);
5482 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005483 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005484 /* For "\u" store the number according to
5485 * 'encoding'. */
5486 if (c != 'X')
Bram Moolenaar8c711452005-01-14 21:53:12 +00005487 name += (*mb_char2bytes)(nr, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005488 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00005489 *name++ = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005490 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005491 break;
5492
5493 /* octal: "\1", "\12", "\123" */
5494 case '0':
5495 case '1':
5496 case '2':
5497 case '3':
5498 case '4':
5499 case '5':
5500 case '6':
Bram Moolenaar8c711452005-01-14 21:53:12 +00005501 case '7': *name = *p++ - '0';
5502 if (*p >= '0' && *p <= '7')
Bram Moolenaar071d4272004-06-13 20:20:40 +00005503 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005504 *name = (*name << 3) + *p++ - '0';
5505 if (*p >= '0' && *p <= '7')
5506 *name = (*name << 3) + *p++ - '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +00005507 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005508 ++name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005509 break;
5510
5511 /* Special key, e.g.: "\<C-W>" */
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +02005512 case '<': extra = trans_special(&p, name, TRUE, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005513 if (extra != 0)
5514 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005515 name += extra;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005516 break;
5517 }
5518 /* FALLTHROUGH */
5519
Bram Moolenaar8c711452005-01-14 21:53:12 +00005520 default: MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005521 break;
5522 }
5523 }
5524 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00005525 MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005526
Bram Moolenaar071d4272004-06-13 20:20:40 +00005527 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005528 *name = NUL;
Bram Moolenaardb249f22016-08-26 16:29:47 +02005529 if (*p != NUL) /* just in case */
5530 ++p;
5531 *arg = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005532
Bram Moolenaar071d4272004-06-13 20:20:40 +00005533 return OK;
5534}
5535
5536/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005537 * Allocate a variable for a 'str''ing' constant.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005538 * Return OK or FAIL.
5539 */
5540 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005541get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005542{
5543 char_u *p;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005544 char_u *str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005545 int reduce = 0;
5546
5547 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005548 * Find the end of the string, skipping ''.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005549 */
Bram Moolenaar91acfff2017-03-12 19:22:36 +01005550 for (p = *arg + 1; *p != NUL; MB_PTR_ADV(p))
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005551 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005552 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005553 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005554 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005555 break;
5556 ++reduce;
5557 ++p;
5558 }
5559 }
5560
Bram Moolenaar8c711452005-01-14 21:53:12 +00005561 if (*p != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005562 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005563 semsg(_("E115: Missing quote: %s"), *arg);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005564 return FAIL;
5565 }
5566
Bram Moolenaar8c711452005-01-14 21:53:12 +00005567 /* If only parsing return after setting "*arg" */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005568 if (!evaluate)
5569 {
5570 *arg = p + 1;
5571 return OK;
5572 }
5573
5574 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005575 * Copy the string into allocated memory, handling '' to ' reduction.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005576 */
Bram Moolenaar964b3742019-05-24 18:54:09 +02005577 str = alloc((p - *arg) - reduce);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005578 if (str == NULL)
5579 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005580 rettv->v_type = VAR_STRING;
5581 rettv->vval.v_string = str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005582
Bram Moolenaar8c711452005-01-14 21:53:12 +00005583 for (p = *arg + 1; *p != NUL; )
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005584 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005585 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005586 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005587 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005588 break;
5589 ++p;
5590 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005591 MB_COPY_CHAR(p, str);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005592 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005593 *str = NUL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005594 *arg = p + 1;
5595
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005596 return OK;
5597}
5598
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005599/*
5600 * Return the function name of the partial.
5601 */
5602 char_u *
5603partial_name(partial_T *pt)
5604{
5605 if (pt->pt_name != NULL)
5606 return pt->pt_name;
5607 return pt->pt_func->uf_name;
5608}
5609
Bram Moolenaarddecc252016-04-06 22:59:37 +02005610 static void
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005611partial_free(partial_T *pt)
Bram Moolenaarddecc252016-04-06 22:59:37 +02005612{
5613 int i;
5614
5615 for (i = 0; i < pt->pt_argc; ++i)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005616 clear_tv(&pt->pt_argv[i]);
Bram Moolenaarddecc252016-04-06 22:59:37 +02005617 vim_free(pt->pt_argv);
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005618 dict_unref(pt->pt_dict);
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005619 if (pt->pt_name != NULL)
5620 {
5621 func_unref(pt->pt_name);
5622 vim_free(pt->pt_name);
5623 }
5624 else
5625 func_ptr_unref(pt->pt_func);
Bram Moolenaarddecc252016-04-06 22:59:37 +02005626 vim_free(pt);
5627}
5628
5629/*
5630 * Unreference a closure: decrement the reference count and free it when it
5631 * becomes zero.
5632 */
5633 void
5634partial_unref(partial_T *pt)
5635{
5636 if (pt != NULL && --pt->pt_refcount <= 0)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005637 partial_free(pt);
Bram Moolenaarddecc252016-04-06 22:59:37 +02005638}
5639
Bram Moolenaar67b3f992010-11-10 20:41:57 +01005640static int tv_equal_recurse_limit;
5641
Bram Moolenaar8e759ba2016-06-02 17:46:20 +02005642 static int
5643func_equal(
5644 typval_T *tv1,
5645 typval_T *tv2,
5646 int ic) /* ignore case */
5647{
5648 char_u *s1, *s2;
5649 dict_T *d1, *d2;
5650 int a1, a2;
5651 int i;
5652
5653 /* empty and NULL function name considered the same */
5654 s1 = tv1->v_type == VAR_FUNC ? tv1->vval.v_string
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005655 : partial_name(tv1->vval.v_partial);
Bram Moolenaar8e759ba2016-06-02 17:46:20 +02005656 if (s1 != NULL && *s1 == NUL)
5657 s1 = NULL;
5658 s2 = tv2->v_type == VAR_FUNC ? tv2->vval.v_string
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005659 : partial_name(tv2->vval.v_partial);
Bram Moolenaar8e759ba2016-06-02 17:46:20 +02005660 if (s2 != NULL && *s2 == NUL)
5661 s2 = NULL;
5662 if (s1 == NULL || s2 == NULL)
5663 {
5664 if (s1 != s2)
5665 return FALSE;
5666 }
5667 else if (STRCMP(s1, s2) != 0)
5668 return FALSE;
5669
5670 /* empty dict and NULL dict is different */
5671 d1 = tv1->v_type == VAR_FUNC ? NULL : tv1->vval.v_partial->pt_dict;
5672 d2 = tv2->v_type == VAR_FUNC ? NULL : tv2->vval.v_partial->pt_dict;
5673 if (d1 == NULL || d2 == NULL)
5674 {
5675 if (d1 != d2)
5676 return FALSE;
5677 }
5678 else if (!dict_equal(d1, d2, ic, TRUE))
5679 return FALSE;
5680
5681 /* empty list and no list considered the same */
5682 a1 = tv1->v_type == VAR_FUNC ? 0 : tv1->vval.v_partial->pt_argc;
5683 a2 = tv2->v_type == VAR_FUNC ? 0 : tv2->vval.v_partial->pt_argc;
5684 if (a1 != a2)
5685 return FALSE;
5686 for (i = 0; i < a1; ++i)
5687 if (!tv_equal(tv1->vval.v_partial->pt_argv + i,
5688 tv2->vval.v_partial->pt_argv + i, ic, TRUE))
5689 return FALSE;
5690
5691 return TRUE;
5692}
5693
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005694/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005695 * Return TRUE if "tv1" and "tv2" have the same value.
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005696 * Compares the items just like "==" would compare them, but strings and
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005697 * numbers are different. Floats and numbers are also different.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005698 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02005699 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005700tv_equal(
5701 typval_T *tv1,
5702 typval_T *tv2,
5703 int ic, /* ignore case */
5704 int recursive) /* TRUE when used recursively */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005705{
5706 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005707 char_u *s1, *s2;
Bram Moolenaar67b3f992010-11-10 20:41:57 +01005708 static int recursive_cnt = 0; /* catch recursive loops */
Bram Moolenaarb47a2402006-10-15 13:09:12 +00005709 int r;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005710
Bram Moolenaar8b402a02006-10-17 13:16:39 +00005711 /* Catch lists and dicts that have an endless loop by limiting
Bram Moolenaar67b3f992010-11-10 20:41:57 +01005712 * recursiveness to a limit. We guess they are equal then.
5713 * A fixed limit has the problem of still taking an awful long time.
5714 * Reduce the limit every time running into it. That should work fine for
5715 * deeply linked structures that are not recursively linked and catch
5716 * recursiveness quickly. */
5717 if (!recursive)
5718 tv_equal_recurse_limit = 1000;
5719 if (recursive_cnt >= tv_equal_recurse_limit)
5720 {
5721 --tv_equal_recurse_limit;
Bram Moolenaar8b402a02006-10-17 13:16:39 +00005722 return TRUE;
Bram Moolenaar67b3f992010-11-10 20:41:57 +01005723 }
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005724
Bram Moolenaarb33c7eb2016-07-04 22:29:49 +02005725 /* For VAR_FUNC and VAR_PARTIAL compare the function name, bound dict and
5726 * arguments. */
Bram Moolenaar8e759ba2016-06-02 17:46:20 +02005727 if ((tv1->v_type == VAR_FUNC
5728 || (tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial != NULL))
5729 && (tv2->v_type == VAR_FUNC
5730 || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial != NULL)))
5731 {
5732 ++recursive_cnt;
5733 r = func_equal(tv1, tv2, ic);
5734 --recursive_cnt;
5735 return r;
5736 }
5737
5738 if (tv1->v_type != tv2->v_type)
5739 return FALSE;
5740
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005741 switch (tv1->v_type)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005742 {
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005743 case VAR_LIST:
Bram Moolenaar67b3f992010-11-10 20:41:57 +01005744 ++recursive_cnt;
5745 r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic, TRUE);
5746 --recursive_cnt;
Bram Moolenaarb47a2402006-10-15 13:09:12 +00005747 return r;
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005748
5749 case VAR_DICT:
Bram Moolenaar67b3f992010-11-10 20:41:57 +01005750 ++recursive_cnt;
5751 r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, TRUE);
5752 --recursive_cnt;
Bram Moolenaarb47a2402006-10-15 13:09:12 +00005753 return r;
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005754
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01005755 case VAR_BLOB:
5756 return blob_equal(tv1->vval.v_blob, tv2->vval.v_blob);
5757
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005758 case VAR_NUMBER:
5759 return tv1->vval.v_number == tv2->vval.v_number;
5760
5761 case VAR_STRING:
Bram Moolenaard155d7a2018-12-21 16:04:21 +01005762 s1 = tv_get_string_buf(tv1, buf1);
5763 s2 = tv_get_string_buf(tv2, buf2);
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005764 return ((ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2)) == 0);
Bram Moolenaar520e1e42016-01-23 19:46:28 +01005765
5766 case VAR_SPECIAL:
5767 return tv1->vval.v_number == tv2->vval.v_number;
Bram Moolenaar835dc632016-02-07 14:27:38 +01005768
5769 case VAR_FLOAT:
5770#ifdef FEAT_FLOAT
5771 return tv1->vval.v_float == tv2->vval.v_float;
5772#endif
5773 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01005774#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +01005775 return tv1->vval.v_job == tv2->vval.v_job;
5776#endif
Bram Moolenaar77073442016-02-13 23:23:53 +01005777 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01005778#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +01005779 return tv1->vval.v_channel == tv2->vval.v_channel;
5780#endif
Bram Moolenaarf0e86a02016-03-19 19:38:12 +01005781 case VAR_FUNC:
5782 case VAR_PARTIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01005783 case VAR_UNKNOWN:
5784 break;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005785 }
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005786
Bram Moolenaara03f2332016-02-06 18:09:59 +01005787 /* VAR_UNKNOWN can be the result of a invalid expression, let's say it
5788 * does not equal anything, not even itself. */
5789 return FALSE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005790}
5791
5792/*
Bram Moolenaar520e1e42016-01-23 19:46:28 +01005793 * Return the next (unique) copy ID.
5794 * Used for serializing nested structures.
5795 */
5796 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005797get_copyID(void)
Bram Moolenaar520e1e42016-01-23 19:46:28 +01005798{
5799 current_copyID += COPYID_INC;
5800 return current_copyID;
5801}
5802
5803/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005804 * Garbage collection for lists and dictionaries.
5805 *
5806 * We use reference counts to be able to free most items right away when they
5807 * are no longer used. But for composite items it's possible that it becomes
5808 * unused while the reference count is > 0: When there is a recursive
5809 * reference. Example:
5810 * :let l = [1, 2, 3]
5811 * :let d = {9: l}
5812 * :let l[1] = d
5813 *
5814 * Since this is quite unusual we handle this with garbage collection: every
5815 * once in a while find out which lists and dicts are not referenced from any
5816 * variable.
5817 *
5818 * Here is a good reference text about garbage collection (refers to Python
5819 * but it applies to all reference-counting mechanisms):
5820 * http://python.ca/nas/python/gc/
Bram Moolenaard9fba312005-06-26 22:34:35 +00005821 */
Bram Moolenaard9fba312005-06-26 22:34:35 +00005822
5823/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005824 * Do garbage collection for lists and dicts.
Bram Moolenaar574860b2016-05-24 17:33:34 +02005825 * When "testing" is TRUE this is called from test_garbagecollect_now().
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005826 * Return TRUE if some memory was freed.
Bram Moolenaard9fba312005-06-26 22:34:35 +00005827 */
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005828 int
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +02005829garbage_collect(int testing)
Bram Moolenaard9fba312005-06-26 22:34:35 +00005830{
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005831 int copyID;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005832 int abort = FALSE;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005833 buf_T *buf;
5834 win_T *wp;
5835 int i;
Bram Moolenaar934b1362015-02-04 23:06:45 +01005836 int did_free = FALSE;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00005837 tabpage_T *tp;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005838
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +02005839 if (!testing)
5840 {
5841 /* Only do this once. */
5842 want_garbage_collect = FALSE;
5843 may_garbage_collect = FALSE;
5844 garbage_collect_at_exit = FALSE;
5845 }
Bram Moolenaar9fecb462006-09-05 10:59:47 +00005846
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005847 /* We advance by two because we add one for items referenced through
5848 * previous_funccal. */
Bram Moolenaar520e1e42016-01-23 19:46:28 +01005849 copyID = get_copyID();
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005850
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005851 /*
5852 * 1. Go through all accessible variables and mark all lists and dicts
5853 * with copyID.
5854 */
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005855
5856 /* Don't free variables in the previous_funccal list unless they are only
5857 * referenced through previous_funccal. This must be first, because if
Bram Moolenaar2c2398c2009-06-03 11:22:45 +00005858 * the item is referenced elsewhere the funccal must not be freed. */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02005859 abort = abort || set_ref_in_previous_funccal(copyID);
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005860
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005861 /* script-local variables */
5862 for (i = 1; i <= ga_scripts.ga_len; ++i)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005863 abort = abort || set_ref_in_ht(&SCRIPT_VARS(i), copyID, NULL);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005864
5865 /* buffer-local variables */
Bram Moolenaar29323592016-07-24 22:04:11 +02005866 FOR_ALL_BUFFERS(buf)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005867 abort = abort || set_ref_in_item(&buf->b_bufvar.di_tv, copyID,
5868 NULL, NULL);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005869
5870 /* window-local variables */
Bram Moolenaar910f66f2006-04-05 20:41:53 +00005871 FOR_ALL_TAB_WINDOWS(tp, wp)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005872 abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
5873 NULL, NULL);
Bram Moolenaar3bb28552013-04-15 18:25:59 +02005874 if (aucmd_win != NULL)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005875 abort = abort || set_ref_in_item(&aucmd_win->w_winvar.di_tv, copyID,
5876 NULL, NULL);
Bram Moolenaar4d784b22019-05-25 19:51:39 +02005877#ifdef FEAT_TEXT_PROP
5878 for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
5879 abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
5880 NULL, NULL);
Bram Moolenaar4d784b22019-05-25 19:51:39 +02005881 FOR_ALL_TABPAGES(tp)
Bram Moolenaar9c27b1c2019-05-26 18:48:13 +02005882 for (wp = tp->tp_first_popupwin; wp != NULL; wp = wp->w_next)
Bram Moolenaar4d784b22019-05-25 19:51:39 +02005883 abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
5884 NULL, NULL);
5885#endif
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005886
Bram Moolenaar910f66f2006-04-05 20:41:53 +00005887 /* tabpage-local variables */
Bram Moolenaar29323592016-07-24 22:04:11 +02005888 FOR_ALL_TABPAGES(tp)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005889 abort = abort || set_ref_in_item(&tp->tp_winvar.di_tv, copyID,
5890 NULL, NULL);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005891 /* global variables */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005892 abort = abort || set_ref_in_ht(&globvarht, copyID, NULL);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005893
5894 /* function-local variables */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02005895 abort = abort || set_ref_in_call_stack(copyID);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005896
Bram Moolenaarbc7ce672016-08-01 22:49:22 +02005897 /* named functions (matters for closures) */
5898 abort = abort || set_ref_in_functions(copyID);
5899
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +02005900 /* function call arguments, if v:testing is set. */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02005901 abort = abort || set_ref_in_func_args(copyID);
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +02005902
Bram Moolenaard812df62008-11-09 12:46:09 +00005903 /* v: vars */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005904 abort = abort || set_ref_in_ht(&vimvarht, copyID, NULL);
Bram Moolenaard812df62008-11-09 12:46:09 +00005905
Bram Moolenaar75a1a942019-06-20 03:45:36 +02005906 // callbacks in buffers
5907 abort = abort || set_ref_in_buffers(copyID);
5908
Bram Moolenaar1dced572012-04-05 16:54:08 +02005909#ifdef FEAT_LUA
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005910 abort = abort || set_ref_in_lua(copyID);
Bram Moolenaar1dced572012-04-05 16:54:08 +02005911#endif
5912
Bram Moolenaardb913952012-06-29 12:54:53 +02005913#ifdef FEAT_PYTHON
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005914 abort = abort || set_ref_in_python(copyID);
Bram Moolenaardb913952012-06-29 12:54:53 +02005915#endif
5916
5917#ifdef FEAT_PYTHON3
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005918 abort = abort || set_ref_in_python3(copyID);
Bram Moolenaardb913952012-06-29 12:54:53 +02005919#endif
5920
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01005921#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar3780bb92016-04-12 22:18:53 +02005922 abort = abort || set_ref_in_channel(copyID);
Bram Moolenaarb8d49052016-05-01 14:22:16 +02005923 abort = abort || set_ref_in_job(copyID);
Bram Moolenaar4b6a6dc2016-02-04 22:49:49 +01005924#endif
Bram Moolenaar3266c852016-04-30 18:07:05 +02005925#ifdef FEAT_NETBEANS_INTG
5926 abort = abort || set_ref_in_nb_channel(copyID);
5927#endif
Bram Moolenaar4b6a6dc2016-02-04 22:49:49 +01005928
Bram Moolenaare3188e22016-05-31 21:13:04 +02005929#ifdef FEAT_TIMERS
5930 abort = abort || set_ref_in_timer(copyID);
5931#endif
5932
Bram Moolenaar8f77c5a2017-04-30 14:21:00 +02005933#ifdef FEAT_QUICKFIX
5934 abort = abort || set_ref_in_quickfix(copyID);
5935#endif
5936
Bram Moolenaara2c45a12017-07-27 22:14:59 +02005937#ifdef FEAT_TERMINAL
5938 abort = abort || set_ref_in_term(copyID);
5939#endif
5940
Bram Moolenaar75a1a942019-06-20 03:45:36 +02005941#ifdef FEAT_TEXT_PROP
5942 abort = abort || set_ref_in_popups(copyID);
5943#endif
5944
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005945 if (!abort)
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005946 {
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005947 /*
5948 * 2. Free lists and dictionaries that are not referenced.
5949 */
5950 did_free = free_unref_items(copyID);
5951
5952 /*
5953 * 3. Check if any funccal can be freed now.
Bram Moolenaara9b579f2016-07-17 18:29:19 +02005954 * This may call us back recursively.
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005955 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02005956 free_unref_funccal(copyID, testing);
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005957 }
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005958 else if (p_verbose > 0)
5959 {
Bram Moolenaar32526b32019-01-19 17:43:09 +01005960 verb_msg(_("Not enough memory to set references, garbage collection aborted!"));
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005961 }
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005962
5963 return did_free;
5964}
5965
5966/*
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005967 * Free lists, dictionaries, channels and jobs that are no longer referenced.
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005968 */
5969 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005970free_unref_items(int copyID)
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005971{
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00005972 int did_free = FALSE;
5973
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005974 /* Let all "free" functions know that we are here. This means no
5975 * dictionaries, lists, channels or jobs are to be freed, because we will
5976 * do that here. */
5977 in_free_unref_items = TRUE;
5978
5979 /*
5980 * PASS 1: free the contents of the items. We don't free the items
5981 * themselves yet, so that it is possible to decrement refcount counters
5982 */
5983
Bram Moolenaarcd524592016-07-17 14:57:05 +02005984 /* Go through the list of dicts and free items without the copyID. */
5985 did_free |= dict_free_nonref(copyID);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005986
Bram Moolenaarda861d62016-07-17 15:46:27 +02005987 /* Go through the list of lists and free items without the copyID. */
5988 did_free |= list_free_nonref(copyID);
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005989
5990#ifdef FEAT_JOB_CHANNEL
5991 /* Go through the list of jobs and free items without the copyID. This
5992 * must happen before doing channels, because jobs refer to channels, but
5993 * the reference from the channel to the job isn't tracked. */
5994 did_free |= free_unused_jobs_contents(copyID, COPYID_MASK);
5995
5996 /* Go through the list of channels and free items without the copyID. */
5997 did_free |= free_unused_channels_contents(copyID, COPYID_MASK);
5998#endif
5999
6000 /*
6001 * PASS 2: free the items themselves.
6002 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02006003 dict_free_items(copyID);
Bram Moolenaarda861d62016-07-17 15:46:27 +02006004 list_free_items(copyID);
Bram Moolenaar835dc632016-02-07 14:27:38 +01006005
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006006#ifdef FEAT_JOB_CHANNEL
6007 /* Go through the list of jobs and free items without the copyID. This
6008 * must happen before doing channels, because jobs refer to channels, but
6009 * the reference from the channel to the job isn't tracked. */
6010 free_unused_jobs(copyID, COPYID_MASK);
6011
6012 /* Go through the list of channels and free items without the copyID. */
6013 free_unused_channels(copyID, COPYID_MASK);
6014#endif
6015
6016 in_free_unref_items = FALSE;
6017
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006018 return did_free;
6019}
6020
6021/*
6022 * Mark all lists and dicts referenced through hashtab "ht" with "copyID".
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006023 * "list_stack" is used to add lists to be marked. Can be NULL.
6024 *
6025 * Returns TRUE if setting references failed somehow.
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006026 */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006027 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006028set_ref_in_ht(hashtab_T *ht, int copyID, list_stack_T **list_stack)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006029{
6030 int todo;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006031 int abort = FALSE;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006032 hashitem_T *hi;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006033 hashtab_T *cur_ht;
6034 ht_stack_T *ht_stack = NULL;
6035 ht_stack_T *tempitem;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006036
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006037 cur_ht = ht;
6038 for (;;)
6039 {
6040 if (!abort)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006041 {
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006042 /* Mark each item in the hashtab. If the item contains a hashtab
6043 * it is added to ht_stack, if it contains a list it is added to
6044 * list_stack. */
6045 todo = (int)cur_ht->ht_used;
6046 for (hi = cur_ht->ht_array; todo > 0; ++hi)
6047 if (!HASHITEM_EMPTY(hi))
6048 {
6049 --todo;
6050 abort = abort || set_ref_in_item(&HI2DI(hi)->di_tv, copyID,
6051 &ht_stack, list_stack);
6052 }
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006053 }
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006054
6055 if (ht_stack == NULL)
6056 break;
6057
6058 /* take an item from the stack */
6059 cur_ht = ht_stack->ht;
6060 tempitem = ht_stack;
6061 ht_stack = ht_stack->prev;
6062 free(tempitem);
6063 }
6064
6065 return abort;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006066}
6067
6068/*
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02006069 * Mark a dict and its items with "copyID".
6070 * Returns TRUE if setting references failed somehow.
6071 */
6072 int
6073set_ref_in_dict(dict_T *d, int copyID)
6074{
6075 if (d != NULL && d->dv_copyID != copyID)
6076 {
6077 d->dv_copyID = copyID;
6078 return set_ref_in_ht(&d->dv_hashtab, copyID, NULL);
6079 }
6080 return FALSE;
6081}
6082
6083/*
6084 * Mark a list and its items with "copyID".
6085 * Returns TRUE if setting references failed somehow.
6086 */
6087 int
6088set_ref_in_list(list_T *ll, int copyID)
6089{
6090 if (ll != NULL && ll->lv_copyID != copyID)
6091 {
6092 ll->lv_copyID = copyID;
6093 return set_ref_in_list_items(ll, copyID, NULL);
6094 }
6095 return FALSE;
6096}
6097
6098/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006099 * Mark all lists and dicts referenced through list "l" with "copyID".
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006100 * "ht_stack" is used to add hashtabs to be marked. Can be NULL.
6101 *
6102 * Returns TRUE if setting references failed somehow.
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006103 */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006104 int
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02006105set_ref_in_list_items(list_T *l, int copyID, ht_stack_T **ht_stack)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006106{
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006107 listitem_T *li;
6108 int abort = FALSE;
6109 list_T *cur_l;
6110 list_stack_T *list_stack = NULL;
6111 list_stack_T *tempitem;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006112
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006113 cur_l = l;
6114 for (;;)
6115 {
6116 if (!abort)
6117 /* Mark each item in the list. If the item contains a hashtab
6118 * it is added to ht_stack, if it contains a list it is added to
6119 * list_stack. */
6120 for (li = cur_l->lv_first; !abort && li != NULL; li = li->li_next)
6121 abort = abort || set_ref_in_item(&li->li_tv, copyID,
6122 ht_stack, &list_stack);
6123 if (list_stack == NULL)
6124 break;
6125
6126 /* take an item from the stack */
6127 cur_l = list_stack->list;
6128 tempitem = list_stack;
6129 list_stack = list_stack->prev;
6130 free(tempitem);
6131 }
6132
6133 return abort;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006134}
6135
6136/*
6137 * Mark all lists and dicts referenced through typval "tv" with "copyID".
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006138 * "list_stack" is used to add lists to be marked. Can be NULL.
6139 * "ht_stack" is used to add hashtabs to be marked. Can be NULL.
6140 *
6141 * Returns TRUE if setting references failed somehow.
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006142 */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006143 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006144set_ref_in_item(
6145 typval_T *tv,
6146 int copyID,
6147 ht_stack_T **ht_stack,
6148 list_stack_T **list_stack)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006149{
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006150 int abort = FALSE;
Bram Moolenaard9fba312005-06-26 22:34:35 +00006151
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006152 if (tv->v_type == VAR_DICT)
Bram Moolenaard9fba312005-06-26 22:34:35 +00006153 {
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006154 dict_T *dd = tv->vval.v_dict;
6155
Bram Moolenaara03f2332016-02-06 18:09:59 +01006156 if (dd != NULL && dd->dv_copyID != copyID)
6157 {
6158 /* Didn't see this dict yet. */
6159 dd->dv_copyID = copyID;
6160 if (ht_stack == NULL)
Bram Moolenaard9fba312005-06-26 22:34:35 +00006161 {
Bram Moolenaara03f2332016-02-06 18:09:59 +01006162 abort = set_ref_in_ht(&dd->dv_hashtab, copyID, list_stack);
6163 }
6164 else
6165 {
6166 ht_stack_T *newitem = (ht_stack_T*)malloc(sizeof(ht_stack_T));
6167 if (newitem == NULL)
6168 abort = TRUE;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006169 else
6170 {
Bram Moolenaara03f2332016-02-06 18:09:59 +01006171 newitem->ht = &dd->dv_hashtab;
6172 newitem->prev = *ht_stack;
6173 *ht_stack = newitem;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006174 }
Bram Moolenaard9fba312005-06-26 22:34:35 +00006175 }
Bram Moolenaara03f2332016-02-06 18:09:59 +01006176 }
6177 }
6178 else if (tv->v_type == VAR_LIST)
6179 {
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006180 list_T *ll = tv->vval.v_list;
6181
Bram Moolenaara03f2332016-02-06 18:09:59 +01006182 if (ll != NULL && ll->lv_copyID != copyID)
6183 {
6184 /* Didn't see this list yet. */
6185 ll->lv_copyID = copyID;
6186 if (list_stack == NULL)
Bram Moolenaard9fba312005-06-26 22:34:35 +00006187 {
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02006188 abort = set_ref_in_list_items(ll, copyID, ht_stack);
Bram Moolenaara03f2332016-02-06 18:09:59 +01006189 }
6190 else
6191 {
6192 list_stack_T *newitem = (list_stack_T*)malloc(
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006193 sizeof(list_stack_T));
Bram Moolenaara03f2332016-02-06 18:09:59 +01006194 if (newitem == NULL)
6195 abort = TRUE;
6196 else
6197 {
6198 newitem->list = ll;
6199 newitem->prev = *list_stack;
6200 *list_stack = newitem;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006201 }
Bram Moolenaard9fba312005-06-26 22:34:35 +00006202 }
Bram Moolenaara03f2332016-02-06 18:09:59 +01006203 }
Bram Moolenaard9fba312005-06-26 22:34:35 +00006204 }
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02006205 else if (tv->v_type == VAR_FUNC)
6206 {
Bram Moolenaar437bafe2016-08-01 15:40:54 +02006207 abort = set_ref_in_func(tv->vval.v_string, NULL, copyID);
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02006208 }
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006209 else if (tv->v_type == VAR_PARTIAL)
6210 {
6211 partial_T *pt = tv->vval.v_partial;
6212 int i;
6213
6214 /* A partial does not have a copyID, because it cannot contain itself.
6215 */
6216 if (pt != NULL)
6217 {
Bram Moolenaar437bafe2016-08-01 15:40:54 +02006218 abort = set_ref_in_func(pt->pt_name, pt->pt_func, copyID);
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02006219
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006220 if (pt->pt_dict != NULL)
6221 {
6222 typval_T dtv;
6223
6224 dtv.v_type = VAR_DICT;
6225 dtv.vval.v_dict = pt->pt_dict;
6226 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
6227 }
6228
6229 for (i = 0; i < pt->pt_argc; ++i)
6230 abort = abort || set_ref_in_item(&pt->pt_argv[i], copyID,
6231 ht_stack, list_stack);
6232 }
6233 }
6234#ifdef FEAT_JOB_CHANNEL
6235 else if (tv->v_type == VAR_JOB)
6236 {
6237 job_T *job = tv->vval.v_job;
6238 typval_T dtv;
6239
6240 if (job != NULL && job->jv_copyID != copyID)
6241 {
Bram Moolenaar0239acb2016-04-11 21:02:54 +02006242 job->jv_copyID = copyID;
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006243 if (job->jv_channel != NULL)
6244 {
6245 dtv.v_type = VAR_CHANNEL;
6246 dtv.vval.v_channel = job->jv_channel;
6247 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
6248 }
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006249 if (job->jv_exit_cb.cb_partial != NULL)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006250 {
6251 dtv.v_type = VAR_PARTIAL;
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006252 dtv.vval.v_partial = job->jv_exit_cb.cb_partial;
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006253 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
6254 }
6255 }
6256 }
6257 else if (tv->v_type == VAR_CHANNEL)
6258 {
6259 channel_T *ch =tv->vval.v_channel;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02006260 ch_part_T part;
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006261 typval_T dtv;
6262 jsonq_T *jq;
6263 cbq_T *cq;
6264
6265 if (ch != NULL && ch->ch_copyID != copyID)
6266 {
Bram Moolenaar0239acb2016-04-11 21:02:54 +02006267 ch->ch_copyID = copyID;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02006268 for (part = PART_SOCK; part < PART_COUNT; ++part)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006269 {
6270 for (jq = ch->ch_part[part].ch_json_head.jq_next; jq != NULL;
6271 jq = jq->jq_next)
6272 set_ref_in_item(jq->jq_value, copyID, ht_stack, list_stack);
6273 for (cq = ch->ch_part[part].ch_cb_head.cq_next; cq != NULL;
6274 cq = cq->cq_next)
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006275 if (cq->cq_callback.cb_partial != NULL)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006276 {
6277 dtv.v_type = VAR_PARTIAL;
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006278 dtv.vval.v_partial = cq->cq_callback.cb_partial;
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006279 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
6280 }
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006281 if (ch->ch_part[part].ch_callback.cb_partial != NULL)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006282 {
6283 dtv.v_type = VAR_PARTIAL;
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006284 dtv.vval.v_partial =
6285 ch->ch_part[part].ch_callback.cb_partial;
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006286 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
6287 }
6288 }
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006289 if (ch->ch_callback.cb_partial != NULL)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006290 {
6291 dtv.v_type = VAR_PARTIAL;
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006292 dtv.vval.v_partial = ch->ch_callback.cb_partial;
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006293 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
6294 }
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006295 if (ch->ch_close_cb.cb_partial != NULL)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006296 {
6297 dtv.v_type = VAR_PARTIAL;
Bram Moolenaar3a97bb32019-06-01 13:28:35 +02006298 dtv.vval.v_partial = ch->ch_close_cb.cb_partial;
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02006299 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
6300 }
6301 }
6302 }
6303#endif
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006304 return abort;
Bram Moolenaard9fba312005-06-26 22:34:35 +00006305}
6306
Bram Moolenaar17a13432016-01-24 14:22:10 +01006307 static char *
6308get_var_special_name(int nr)
6309{
6310 switch (nr)
6311 {
Bram Moolenaarf48aa162016-01-24 17:54:24 +01006312 case VVAL_FALSE: return "v:false";
Bram Moolenaar65edff82016-02-21 16:40:11 +01006313 case VVAL_TRUE: return "v:true";
6314 case VVAL_NONE: return "v:none";
6315 case VVAL_NULL: return "v:null";
Bram Moolenaar17a13432016-01-24 14:22:10 +01006316 }
Bram Moolenaar95f09602016-11-10 20:01:45 +01006317 internal_error("get_var_special_name()");
Bram Moolenaar17a13432016-01-24 14:22:10 +01006318 return "42";
6319}
6320
Bram Moolenaar8c711452005-01-14 21:53:12 +00006321/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006322 * Return a string with the string representation of a variable.
6323 * If the memory is allocated "tofree" is set to it, otherwise NULL.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006324 * "numbuf" is used for a number.
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006325 * When "copyID" is not NULL replace recursive lists and dicts with "...".
Bram Moolenaar35422f42017-08-05 16:33:56 +02006326 * When both "echo_style" and "composite_val" are FALSE, put quotes around
6327 * stings as "string()", otherwise does not put quotes around strings, as
6328 * ":echo" displays values.
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006329 * When "restore_copyID" is FALSE, repeated items in dictionaries and lists
6330 * are replaced with "...".
Bram Moolenaar92c5aba2007-08-14 20:29:31 +00006331 * May return NULL.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006332 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02006333 char_u *
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006334echo_string_core(
Bram Moolenaar7454a062016-01-30 15:14:10 +01006335 typval_T *tv,
6336 char_u **tofree,
6337 char_u *numbuf,
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006338 int copyID,
6339 int echo_style,
6340 int restore_copyID,
Bram Moolenaar35422f42017-08-05 16:33:56 +02006341 int composite_val)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006342{
Bram Moolenaare9a41262005-01-15 22:18:47 +00006343 static int recurse = 0;
6344 char_u *r = NULL;
6345
Bram Moolenaar33570922005-01-25 22:26:29 +00006346 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006347 {
Bram Moolenaar8502c702014-06-17 12:51:16 +02006348 if (!did_echo_string_emsg)
6349 {
6350 /* Only give this message once for a recursive call to avoid
6351 * flooding the user with errors. And stop iterating over lists
6352 * and dicts. */
6353 did_echo_string_emsg = TRUE;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01006354 emsg(_("E724: variable nested too deep for displaying"));
Bram Moolenaar8502c702014-06-17 12:51:16 +02006355 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006356 *tofree = NULL;
Bram Moolenaar8502c702014-06-17 12:51:16 +02006357 return (char_u *)"{E724}";
Bram Moolenaare9a41262005-01-15 22:18:47 +00006358 }
6359 ++recurse;
6360
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006361 switch (tv->v_type)
6362 {
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006363 case VAR_STRING:
Bram Moolenaar35422f42017-08-05 16:33:56 +02006364 if (echo_style && !composite_val)
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006365 {
6366 *tofree = NULL;
Bram Moolenaar35422f42017-08-05 16:33:56 +02006367 r = tv->vval.v_string;
6368 if (r == NULL)
6369 r = (char_u *)"";
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006370 }
6371 else
6372 {
6373 *tofree = string_quote(tv->vval.v_string, FALSE);
6374 r = *tofree;
6375 }
6376 break;
6377
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006378 case VAR_FUNC:
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006379 if (echo_style)
6380 {
6381 *tofree = NULL;
6382 r = tv->vval.v_string;
6383 }
6384 else
6385 {
6386 *tofree = string_quote(tv->vval.v_string, TRUE);
6387 r = *tofree;
6388 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006389 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006390
Bram Moolenaar1735bc92016-03-14 23:05:14 +01006391 case VAR_PARTIAL:
Bram Moolenaar24c77a12016-03-24 21:23:06 +01006392 {
6393 partial_T *pt = tv->vval.v_partial;
6394 char_u *fname = string_quote(pt == NULL ? NULL
Bram Moolenaar437bafe2016-08-01 15:40:54 +02006395 : partial_name(pt), FALSE);
Bram Moolenaar24c77a12016-03-24 21:23:06 +01006396 garray_T ga;
6397 int i;
6398 char_u *tf;
6399
6400 ga_init2(&ga, 1, 100);
6401 ga_concat(&ga, (char_u *)"function(");
6402 if (fname != NULL)
6403 {
6404 ga_concat(&ga, fname);
6405 vim_free(fname);
6406 }
6407 if (pt != NULL && pt->pt_argc > 0)
6408 {
6409 ga_concat(&ga, (char_u *)", [");
6410 for (i = 0; i < pt->pt_argc; ++i)
6411 {
6412 if (i > 0)
6413 ga_concat(&ga, (char_u *)", ");
6414 ga_concat(&ga,
6415 tv2string(&pt->pt_argv[i], &tf, numbuf, copyID));
6416 vim_free(tf);
6417 }
6418 ga_concat(&ga, (char_u *)"]");
6419 }
6420 if (pt != NULL && pt->pt_dict != NULL)
6421 {
6422 typval_T dtv;
6423
6424 ga_concat(&ga, (char_u *)", ");
6425 dtv.v_type = VAR_DICT;
6426 dtv.vval.v_dict = pt->pt_dict;
6427 ga_concat(&ga, tv2string(&dtv, &tf, numbuf, copyID));
6428 vim_free(tf);
6429 }
6430 ga_concat(&ga, (char_u *)")");
6431
6432 *tofree = ga.ga_data;
6433 r = *tofree;
6434 break;
6435 }
Bram Moolenaar1735bc92016-03-14 23:05:14 +01006436
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01006437 case VAR_BLOB:
Bram Moolenaar8c8b8bb2019-01-13 17:48:04 +01006438 r = blob2string(tv->vval.v_blob, tofree, numbuf);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01006439 break;
6440
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006441 case VAR_LIST:
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006442 if (tv->vval.v_list == NULL)
6443 {
6444 *tofree = NULL;
6445 r = NULL;
6446 }
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006447 else if (copyID != 0 && tv->vval.v_list->lv_copyID == copyID
6448 && tv->vval.v_list->lv_len > 0)
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006449 {
6450 *tofree = NULL;
6451 r = (char_u *)"[...]";
6452 }
6453 else
6454 {
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006455 int old_copyID = tv->vval.v_list->lv_copyID;
6456
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006457 tv->vval.v_list->lv_copyID = copyID;
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006458 *tofree = list2string(tv, copyID, restore_copyID);
6459 if (restore_copyID)
6460 tv->vval.v_list->lv_copyID = old_copyID;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006461 r = *tofree;
6462 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006463 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006464
Bram Moolenaar8c711452005-01-14 21:53:12 +00006465 case VAR_DICT:
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006466 if (tv->vval.v_dict == NULL)
6467 {
6468 *tofree = NULL;
6469 r = NULL;
6470 }
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006471 else if (copyID != 0 && tv->vval.v_dict->dv_copyID == copyID
6472 && tv->vval.v_dict->dv_hashtab.ht_used != 0)
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006473 {
6474 *tofree = NULL;
6475 r = (char_u *)"{...}";
6476 }
6477 else
6478 {
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006479 int old_copyID = tv->vval.v_dict->dv_copyID;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006480 tv->vval.v_dict->dv_copyID = copyID;
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006481 *tofree = dict2string(tv, copyID, restore_copyID);
6482 if (restore_copyID)
6483 tv->vval.v_dict->dv_copyID = old_copyID;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006484 r = *tofree;
6485 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006486 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006487
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006488 case VAR_NUMBER:
Bram Moolenaara03f2332016-02-06 18:09:59 +01006489 case VAR_UNKNOWN:
Bram Moolenaar35422f42017-08-05 16:33:56 +02006490 *tofree = NULL;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01006491 r = tv_get_string_buf(tv, numbuf);
Bram Moolenaar35422f42017-08-05 16:33:56 +02006492 break;
6493
Bram Moolenaar835dc632016-02-07 14:27:38 +01006494 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01006495 case VAR_CHANNEL:
Bram Moolenaare9a41262005-01-15 22:18:47 +00006496 *tofree = NULL;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01006497 r = tv_get_string_buf(tv, numbuf);
Bram Moolenaar35422f42017-08-05 16:33:56 +02006498 if (composite_val)
6499 {
6500 *tofree = string_quote(r, FALSE);
6501 r = *tofree;
6502 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006503 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006504
Bram Moolenaar8c8de832008-06-24 22:58:06 +00006505 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01006506#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +00006507 *tofree = NULL;
6508 vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv->vval.v_float);
6509 r = numbuf;
6510 break;
6511#endif
6512
Bram Moolenaar520e1e42016-01-23 19:46:28 +01006513 case VAR_SPECIAL:
6514 *tofree = NULL;
Bram Moolenaar17a13432016-01-24 14:22:10 +01006515 r = (char_u *)get_var_special_name(tv->vval.v_number);
Bram Moolenaar520e1e42016-01-23 19:46:28 +01006516 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006517 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006518
Bram Moolenaar8502c702014-06-17 12:51:16 +02006519 if (--recurse == 0)
6520 did_echo_string_emsg = FALSE;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006521 return r;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006522}
6523
6524/*
6525 * Return a string with the string representation of a variable.
6526 * If the memory is allocated "tofree" is set to it, otherwise NULL.
6527 * "numbuf" is used for a number.
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006528 * Does not put quotes around strings, as ":echo" displays values.
6529 * When "copyID" is not NULL replace recursive lists and dicts with "...".
6530 * May return NULL.
6531 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02006532 char_u *
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006533echo_string(
6534 typval_T *tv,
6535 char_u **tofree,
6536 char_u *numbuf,
6537 int copyID)
6538{
6539 return echo_string_core(tv, tofree, numbuf, copyID, TRUE, FALSE, FALSE);
6540}
6541
6542/*
6543 * Return a string with the string representation of a variable.
6544 * If the memory is allocated "tofree" is set to it, otherwise NULL.
6545 * "numbuf" is used for a number.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006546 * Puts quotes around strings, so that they can be parsed back by eval().
Bram Moolenaar92c5aba2007-08-14 20:29:31 +00006547 * May return NULL.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006548 */
Bram Moolenaar8110a092016-04-14 15:56:09 +02006549 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006550tv2string(
6551 typval_T *tv,
6552 char_u **tofree,
6553 char_u *numbuf,
6554 int copyID)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006555{
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006556 return echo_string_core(tv, tofree, numbuf, copyID, FALSE, TRUE, FALSE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006557}
6558
6559/*
Bram Moolenaar33570922005-01-25 22:26:29 +00006560 * Return string "str" in ' quotes, doubling ' characters.
6561 * If "str" is NULL an empty string is assumed.
Bram Moolenaar8c711452005-01-14 21:53:12 +00006562 * If "function" is TRUE make it function('string').
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006563 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02006564 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006565string_quote(char_u *str, int function)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006566{
Bram Moolenaar33570922005-01-25 22:26:29 +00006567 unsigned len;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006568 char_u *p, *r, *s;
6569
Bram Moolenaar33570922005-01-25 22:26:29 +00006570 len = (function ? 13 : 3);
6571 if (str != NULL)
6572 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00006573 len += (unsigned)STRLEN(str);
Bram Moolenaar91acfff2017-03-12 19:22:36 +01006574 for (p = str; *p != NUL; MB_PTR_ADV(p))
Bram Moolenaar33570922005-01-25 22:26:29 +00006575 if (*p == '\'')
6576 ++len;
6577 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006578 s = r = alloc(len);
6579 if (r != NULL)
6580 {
6581 if (function)
6582 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00006583 STRCPY(r, "function('");
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006584 r += 10;
6585 }
6586 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00006587 *r++ = '\'';
Bram Moolenaar33570922005-01-25 22:26:29 +00006588 if (str != NULL)
6589 for (p = str; *p != NUL; )
6590 {
6591 if (*p == '\'')
6592 *r++ = '\'';
6593 MB_COPY_CHAR(p, r);
6594 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006595 *r++ = '\'';
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006596 if (function)
6597 *r++ = ')';
6598 *r++ = NUL;
6599 }
6600 return s;
6601}
6602
Bram Moolenaar520e1e42016-01-23 19:46:28 +01006603#if defined(FEAT_FLOAT) || defined(PROTO)
Bram Moolenaar8c8de832008-06-24 22:58:06 +00006604/*
6605 * Convert the string "text" to a floating point number.
6606 * This uses strtod(). setlocale(LC_NUMERIC, "C") has been used to make sure
6607 * this always uses a decimal point.
6608 * Returns the length of the text that was consumed.
6609 */
Bram Moolenaar520e1e42016-01-23 19:46:28 +01006610 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006611string2float(
6612 char_u *text,
6613 float_T *value) /* result stored here */
Bram Moolenaar8c8de832008-06-24 22:58:06 +00006614{
6615 char *s = (char *)text;
6616 float_T f;
6617
Bram Moolenaar62473612017-01-08 19:25:40 +01006618 /* MS-Windows does not deal with "inf" and "nan" properly. */
6619 if (STRNICMP(text, "inf", 3) == 0)
6620 {
6621 *value = INFINITY;
6622 return 3;
6623 }
6624 if (STRNICMP(text, "-inf", 3) == 0)
6625 {
6626 *value = -INFINITY;
6627 return 4;
6628 }
6629 if (STRNICMP(text, "nan", 3) == 0)
6630 {
6631 *value = NAN;
6632 return 3;
6633 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00006634 f = strtod(s, &s);
6635 *value = f;
6636 return (int)((char_u *)s - text);
6637}
6638#endif
6639
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006640/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006641 * Get the value of an environment variable.
6642 * "arg" is pointing to the '$'. It is advanced to after the name.
6643 * If the environment variable was not set, silently assume it is empty.
Bram Moolenaare512c8c2014-04-29 17:41:22 +02006644 * Return FAIL if the name is invalid.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006645 */
6646 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006647get_env_tv(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006648{
6649 char_u *string = NULL;
6650 int len;
6651 int cc;
6652 char_u *name;
Bram Moolenaar05159a02005-02-26 23:04:13 +00006653 int mustfree = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006654
6655 ++*arg;
6656 name = *arg;
6657 len = get_env_len(arg);
6658 if (evaluate)
6659 {
Bram Moolenaare512c8c2014-04-29 17:41:22 +02006660 if (len == 0)
Bram Moolenaar615b9972015-01-14 17:15:05 +01006661 return FAIL; /* invalid empty name */
Bram Moolenaar05159a02005-02-26 23:04:13 +00006662
Bram Moolenaare512c8c2014-04-29 17:41:22 +02006663 cc = name[len];
6664 name[len] = NUL;
6665 /* first try vim_getenv(), fast for normal environment vars */
6666 string = vim_getenv(name, &mustfree);
6667 if (string != NULL && *string != NUL)
6668 {
6669 if (!mustfree)
6670 string = vim_strsave(string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006671 }
Bram Moolenaare512c8c2014-04-29 17:41:22 +02006672 else
6673 {
6674 if (mustfree)
6675 vim_free(string);
6676
6677 /* next try expanding things like $VIM and ${HOME} */
6678 string = expand_env_save(name - 1);
6679 if (string != NULL && *string == '$')
Bram Moolenaard23a8232018-02-10 18:45:26 +01006680 VIM_CLEAR(string);
Bram Moolenaare512c8c2014-04-29 17:41:22 +02006681 }
6682 name[len] = cc;
6683
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006684 rettv->v_type = VAR_STRING;
6685 rettv->vval.v_string = string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006686 }
6687
6688 return OK;
6689}
6690
Bram Moolenaard6e256c2011-12-14 15:32:50 +01006691
6692
6693/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006694 * Translate a String variable into a position.
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006695 * Returns NULL when there is an error.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006696 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006697 pos_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006698var2fpos(
6699 typval_T *varp,
6700 int dollar_lnum, /* TRUE when $ is last line */
6701 int *fnum) /* set to fnum for '0, 'A, etc. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006702{
Bram Moolenaar261bfea2006-03-01 22:12:31 +00006703 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006704 static pos_T pos;
Bram Moolenaar261bfea2006-03-01 22:12:31 +00006705 pos_T *pp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006706
Bram Moolenaara5525202006-03-02 22:52:09 +00006707 /* Argument can be [lnum, col, coladd]. */
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006708 if (varp->v_type == VAR_LIST)
6709 {
6710 list_T *l;
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006711 int len;
Bram Moolenaara5525202006-03-02 22:52:09 +00006712 int error = FALSE;
Bram Moolenaar477933c2007-07-17 14:32:23 +00006713 listitem_T *li;
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006714
6715 l = varp->vval.v_list;
6716 if (l == NULL)
6717 return NULL;
6718
6719 /* Get the line number */
Bram Moolenaara5525202006-03-02 22:52:09 +00006720 pos.lnum = list_find_nr(l, 0L, &error);
6721 if (error || pos.lnum <= 0 || pos.lnum > curbuf->b_ml.ml_line_count)
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006722 return NULL; /* invalid line number */
6723
6724 /* Get the column number */
Bram Moolenaara5525202006-03-02 22:52:09 +00006725 pos.col = list_find_nr(l, 1L, &error);
6726 if (error)
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006727 return NULL;
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006728 len = (long)STRLEN(ml_get(pos.lnum));
Bram Moolenaar477933c2007-07-17 14:32:23 +00006729
6730 /* We accept "$" for the column number: last column. */
6731 li = list_find(l, 1L);
6732 if (li != NULL && li->li_tv.v_type == VAR_STRING
6733 && li->li_tv.vval.v_string != NULL
6734 && STRCMP(li->li_tv.vval.v_string, "$") == 0)
6735 pos.col = len + 1;
6736
Bram Moolenaara5525202006-03-02 22:52:09 +00006737 /* Accept a position up to the NUL after the line. */
Bram Moolenaar4c3f5362006-04-11 21:38:50 +00006738 if (pos.col == 0 || (int)pos.col > len + 1)
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006739 return NULL; /* invalid column number */
Bram Moolenaara5525202006-03-02 22:52:09 +00006740 --pos.col;
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006741
Bram Moolenaara5525202006-03-02 22:52:09 +00006742 /* Get the virtual offset. Defaults to zero. */
6743 pos.coladd = list_find_nr(l, 2L, &error);
6744 if (error)
6745 pos.coladd = 0;
Bram Moolenaara5525202006-03-02 22:52:09 +00006746
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006747 return &pos;
6748 }
6749
Bram Moolenaard155d7a2018-12-21 16:04:21 +01006750 name = tv_get_string_chk(varp);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006751 if (name == NULL)
6752 return NULL;
Bram Moolenaar9ecd0232008-06-20 15:31:51 +00006753 if (name[0] == '.') /* cursor */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006754 return &curwin->w_cursor;
Bram Moolenaar9ecd0232008-06-20 15:31:51 +00006755 if (name[0] == 'v' && name[1] == NUL) /* Visual start */
6756 {
6757 if (VIsual_active)
6758 return &VIsual;
6759 return &curwin->w_cursor;
6760 }
Bram Moolenaar9ecd0232008-06-20 15:31:51 +00006761 if (name[0] == '\'') /* mark */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006762 {
Bram Moolenaar9d182dd2013-01-23 15:53:15 +01006763 pp = getmark_buf_fnum(curbuf, name[1], FALSE, fnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006764 if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
6765 return NULL;
6766 return pp;
6767 }
Bram Moolenaara5525202006-03-02 22:52:09 +00006768
Bram Moolenaara5525202006-03-02 22:52:09 +00006769 pos.coladd = 0;
Bram Moolenaara5525202006-03-02 22:52:09 +00006770
Bram Moolenaar477933c2007-07-17 14:32:23 +00006771 if (name[0] == 'w' && dollar_lnum)
Bram Moolenaarf52c7252006-02-10 23:23:57 +00006772 {
6773 pos.col = 0;
6774 if (name[1] == '0') /* "w0": first visible line */
6775 {
Bram Moolenaarf740b292006-02-16 22:11:02 +00006776 update_topline();
Bram Moolenaara1d5fa62017-04-03 22:02:55 +02006777 /* In silent Ex mode topline is zero, but that's not a valid line
6778 * number; use one instead. */
6779 pos.lnum = curwin->w_topline > 0 ? curwin->w_topline : 1;
Bram Moolenaarf52c7252006-02-10 23:23:57 +00006780 return &pos;
6781 }
6782 else if (name[1] == '$') /* "w$": last visible line */
6783 {
Bram Moolenaarf740b292006-02-16 22:11:02 +00006784 validate_botline();
Bram Moolenaara1d5fa62017-04-03 22:02:55 +02006785 /* In silent Ex mode botline is zero, return zero then. */
6786 pos.lnum = curwin->w_botline > 0 ? curwin->w_botline - 1 : 0;
Bram Moolenaarf52c7252006-02-10 23:23:57 +00006787 return &pos;
6788 }
6789 }
6790 else if (name[0] == '$') /* last column or line */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006791 {
Bram Moolenaar477933c2007-07-17 14:32:23 +00006792 if (dollar_lnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006793 {
6794 pos.lnum = curbuf->b_ml.ml_line_count;
6795 pos.col = 0;
6796 }
6797 else
6798 {
6799 pos.lnum = curwin->w_cursor.lnum;
6800 pos.col = (colnr_T)STRLEN(ml_get_curline());
6801 }
6802 return &pos;
6803 }
6804 return NULL;
6805}
6806
6807/*
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006808 * Convert list in "arg" into a position and optional file number.
6809 * When "fnump" is NULL there is no file number, only 3 items.
6810 * Note that the column is passed on as-is, the caller may want to decrement
6811 * it to use 1 for the first column.
6812 * Return FAIL when conversion is not possible, doesn't check the position for
6813 * validity.
6814 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006815 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006816list2fpos(
6817 typval_T *arg,
6818 pos_T *posp,
6819 int *fnump,
6820 colnr_T *curswantp)
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006821{
6822 list_T *l = arg->vval.v_list;
6823 long i = 0;
6824 long n;
6825
Bram Moolenaar493c1782014-05-28 14:34:46 +02006826 /* List must be: [fnum, lnum, col, coladd, curswant], where "fnum" is only
6827 * there when "fnump" isn't NULL; "coladd" and "curswant" are optional. */
Bram Moolenaarbde35262006-07-23 20:12:24 +00006828 if (arg->v_type != VAR_LIST
6829 || l == NULL
6830 || l->lv_len < (fnump == NULL ? 2 : 3)
Bram Moolenaar493c1782014-05-28 14:34:46 +02006831 || l->lv_len > (fnump == NULL ? 4 : 5))
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006832 return FAIL;
6833
6834 if (fnump != NULL)
6835 {
6836 n = list_find_nr(l, i++, NULL); /* fnum */
6837 if (n < 0)
6838 return FAIL;
6839 if (n == 0)
6840 n = curbuf->b_fnum; /* current buffer */
6841 *fnump = n;
6842 }
6843
6844 n = list_find_nr(l, i++, NULL); /* lnum */
6845 if (n < 0)
6846 return FAIL;
6847 posp->lnum = n;
6848
6849 n = list_find_nr(l, i++, NULL); /* col */
6850 if (n < 0)
6851 return FAIL;
6852 posp->col = n;
6853
Bram Moolenaar493c1782014-05-28 14:34:46 +02006854 n = list_find_nr(l, i, NULL); /* off */
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006855 if (n < 0)
Bram Moolenaarbde35262006-07-23 20:12:24 +00006856 posp->coladd = 0;
6857 else
6858 posp->coladd = n;
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006859
Bram Moolenaar493c1782014-05-28 14:34:46 +02006860 if (curswantp != NULL)
6861 *curswantp = list_find_nr(l, i + 1, NULL); /* curswant */
6862
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006863 return OK;
6864}
6865
6866/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006867 * Get the length of an environment variable name.
6868 * Advance "arg" to the first character after the name.
6869 * Return 0 for error.
6870 */
6871 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006872get_env_len(char_u **arg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006873{
6874 char_u *p;
6875 int len;
6876
6877 for (p = *arg; vim_isIDc(*p); ++p)
6878 ;
6879 if (p == *arg) /* no name found */
6880 return 0;
6881
6882 len = (int)(p - *arg);
6883 *arg = p;
6884 return len;
6885}
6886
6887/*
6888 * Get the length of the name of a function or internal variable.
6889 * "arg" is advanced to the first non-white character after the name.
6890 * Return 0 if something is wrong.
6891 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02006892 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006893get_id_len(char_u **arg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006894{
6895 char_u *p;
6896 int len;
6897
6898 /* Find the end of the name. */
6899 for (p = *arg; eval_isnamec(*p); ++p)
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01006900 {
6901 if (*p == ':')
6902 {
6903 /* "s:" is start of "s:var", but "n:" is not and can be used in
6904 * slice "[n:]". Also "xx:" is not a namespace. */
6905 len = (int)(p - *arg);
6906 if ((len == 1 && vim_strchr(NAMESPACE_CHAR, **arg) == NULL)
6907 || len > 1)
6908 break;
6909 }
6910 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006911 if (p == *arg) /* no name found */
6912 return 0;
6913
6914 len = (int)(p - *arg);
6915 *arg = skipwhite(p);
6916
6917 return len;
6918}
6919
6920/*
Bram Moolenaara7043832005-01-21 11:56:39 +00006921 * Get the length of the name of a variable or function.
6922 * Only the name is recognized, does not handle ".key" or "[idx]".
Bram Moolenaar071d4272004-06-13 20:20:40 +00006923 * "arg" is advanced to the first non-white character after the name.
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006924 * Return -1 if curly braces expansion failed.
6925 * Return 0 if something else is wrong.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006926 * If the name contains 'magic' {}'s, expand them and return the
6927 * expanded name in an allocated string via 'alias' - caller must free.
6928 */
Bram Moolenaar5843f5f2019-08-20 20:13:45 +02006929 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006930get_name_len(
6931 char_u **arg,
6932 char_u **alias,
6933 int evaluate,
6934 int verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006935{
6936 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006937 char_u *p;
6938 char_u *expr_start;
6939 char_u *expr_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006940
6941 *alias = NULL; /* default to no alias */
6942
6943 if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
6944 && (*arg)[2] == (int)KE_SNR)
6945 {
6946 /* hard coded <SNR>, already translated */
6947 *arg += 3;
6948 return get_id_len(arg) + 3;
6949 }
6950 len = eval_fname_script(*arg);
6951 if (len > 0)
6952 {
6953 /* literal "<SID>", "s:" or "<SNR>" */
6954 *arg += len;
6955 }
6956
Bram Moolenaar071d4272004-06-13 20:20:40 +00006957 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006958 * Find the end of the name; check for {} construction.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006959 */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00006960 p = find_name_end(*arg, &expr_start, &expr_end,
6961 len > 0 ? 0 : FNE_CHECK_START);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006962 if (expr_start != NULL)
6963 {
6964 char_u *temp_string;
6965
6966 if (!evaluate)
6967 {
6968 len += (int)(p - *arg);
6969 *arg = skipwhite(p);
6970 return len;
6971 }
6972
6973 /*
6974 * Include any <SID> etc in the expanded string:
6975 * Thus the -len here.
6976 */
6977 temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
6978 if (temp_string == NULL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006979 return -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006980 *alias = temp_string;
6981 *arg = skipwhite(p);
6982 return (int)STRLEN(temp_string);
6983 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006984
6985 len += get_id_len(arg);
Bram Moolenaar8309b052019-01-13 16:46:22 +01006986 // Only give an error when there is something, otherwise it will be
6987 // reported at a higher level.
6988 if (len == 0 && verbose && **arg != NUL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01006989 semsg(_(e_invexpr2), *arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006990
6991 return len;
6992}
6993
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006994/*
6995 * Find the end of a variable or function name, taking care of magic braces.
6996 * If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the
6997 * start and end of the first magic braces item.
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00006998 * "flags" can have FNE_INCL_BR and FNE_CHECK_START.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006999 * Return a pointer to just after the name. Equal to "arg" if there is no
7000 * valid name.
7001 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02007002 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007003find_name_end(
7004 char_u *arg,
7005 char_u **expr_start,
7006 char_u **expr_end,
7007 int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007008{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007009 int mb_nest = 0;
7010 int br_nest = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007011 char_u *p;
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01007012 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007013
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007014 if (expr_start != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007015 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007016 *expr_start = NULL;
7017 *expr_end = NULL;
7018 }
7019
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00007020 /* Quick check for valid starting character. */
7021 if ((flags & FNE_CHECK_START) && !eval_isnamec1(*arg) && *arg != '{')
7022 return arg;
7023
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007024 for (p = arg; *p != NUL
7025 && (eval_isnamec(*p)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007026 || *p == '{'
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00007027 || ((flags & FNE_INCL_BR) && (*p == '[' || *p == '.'))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007028 || mb_nest != 0
Bram Moolenaar91acfff2017-03-12 19:22:36 +01007029 || br_nest != 0); MB_PTR_ADV(p))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007030 {
Bram Moolenaar8af24422005-08-08 22:06:28 +00007031 if (*p == '\'')
7032 {
7033 /* skip over 'string' to avoid counting [ and ] inside it. */
Bram Moolenaar91acfff2017-03-12 19:22:36 +01007034 for (p = p + 1; *p != NUL && *p != '\''; MB_PTR_ADV(p))
Bram Moolenaar8af24422005-08-08 22:06:28 +00007035 ;
7036 if (*p == NUL)
7037 break;
7038 }
7039 else if (*p == '"')
7040 {
7041 /* skip over "str\"ing" to avoid counting [ and ] inside it. */
Bram Moolenaar91acfff2017-03-12 19:22:36 +01007042 for (p = p + 1; *p != NUL && *p != '"'; MB_PTR_ADV(p))
Bram Moolenaar8af24422005-08-08 22:06:28 +00007043 if (*p == '\\' && p[1] != NUL)
7044 ++p;
7045 if (*p == NUL)
7046 break;
7047 }
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01007048 else if (br_nest == 0 && mb_nest == 0 && *p == ':')
7049 {
7050 /* "s:" is start of "s:var", but "n:" is not and can be used in
Bram Moolenaar4119cf82016-01-17 14:59:01 +01007051 * slice "[n:]". Also "xx:" is not a namespace. But {ns}: is. */
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01007052 len = (int)(p - arg);
7053 if ((len == 1 && vim_strchr(NAMESPACE_CHAR, *arg) == NULL)
Bram Moolenaar4119cf82016-01-17 14:59:01 +01007054 || (len > 1 && p[-1] != '}'))
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01007055 break;
7056 }
Bram Moolenaar8af24422005-08-08 22:06:28 +00007057
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007058 if (mb_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007059 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007060 if (*p == '[')
7061 ++br_nest;
7062 else if (*p == ']')
7063 --br_nest;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007064 }
Bram Moolenaar8af24422005-08-08 22:06:28 +00007065
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007066 if (br_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007067 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007068 if (*p == '{')
7069 {
7070 mb_nest++;
7071 if (expr_start != NULL && *expr_start == NULL)
7072 *expr_start = p;
7073 }
7074 else if (*p == '}')
7075 {
7076 mb_nest--;
7077 if (expr_start != NULL && mb_nest == 0 && *expr_end == NULL)
7078 *expr_end = p;
7079 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007080 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007081 }
7082
7083 return p;
7084}
7085
7086/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007087 * Expands out the 'magic' {}'s in a variable/function name.
7088 * Note that this can call itself recursively, to deal with
7089 * constructs like foo{bar}{baz}{bam}
7090 * The four pointer arguments point to "foo{expre}ss{ion}bar"
7091 * "in_start" ^
7092 * "expr_start" ^
7093 * "expr_end" ^
7094 * "in_end" ^
7095 *
7096 * Returns a new allocated string, which the caller must free.
7097 * Returns NULL for failure.
7098 */
7099 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007100make_expanded_name(
7101 char_u *in_start,
7102 char_u *expr_start,
7103 char_u *expr_end,
7104 char_u *in_end)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007105{
7106 char_u c1;
7107 char_u *retval = NULL;
7108 char_u *temp_result;
7109 char_u *nextcmd = NULL;
7110
7111 if (expr_end == NULL || in_end == NULL)
7112 return NULL;
7113 *expr_start = NUL;
7114 *expr_end = NUL;
7115 c1 = *in_end;
7116 *in_end = NUL;
7117
Bram Moolenaar362e1a32006-03-06 23:29:24 +00007118 temp_result = eval_to_string(expr_start + 1, &nextcmd, FALSE);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007119 if (temp_result != NULL && nextcmd == NULL)
7120 {
Bram Moolenaar964b3742019-05-24 18:54:09 +02007121 retval = alloc(STRLEN(temp_result) + (expr_start - in_start)
7122 + (in_end - expr_end) + 1);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007123 if (retval != NULL)
7124 {
7125 STRCPY(retval, in_start);
7126 STRCAT(retval, temp_result);
7127 STRCAT(retval, expr_end + 1);
7128 }
7129 }
7130 vim_free(temp_result);
7131
7132 *in_end = c1; /* put char back for error messages */
7133 *expr_start = '{';
7134 *expr_end = '}';
7135
7136 if (retval != NULL)
7137 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00007138 temp_result = find_name_end(retval, &expr_start, &expr_end, 0);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007139 if (expr_start != NULL)
7140 {
7141 /* Further expansion! */
7142 temp_result = make_expanded_name(retval, expr_start,
7143 expr_end, temp_result);
7144 vim_free(retval);
7145 retval = temp_result;
7146 }
7147 }
7148
7149 return retval;
7150}
7151
7152/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007153 * Return TRUE if character "c" can be used in a variable or function name.
Bram Moolenaare9a41262005-01-15 22:18:47 +00007154 * Does not include '{' or '}' for magic braces.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007155 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02007156 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007157eval_isnamec(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007158{
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00007159 return (ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR);
7160}
7161
7162/*
7163 * Return TRUE if character "c" can be used as the first character in a
7164 * variable or function name (excluding '{' and '}').
7165 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02007166 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007167eval_isnamec1(int c)
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00007168{
7169 return (ASCII_ISALPHA(c) || c == '_');
Bram Moolenaar071d4272004-06-13 20:20:40 +00007170}
7171
7172/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007173 * Set number v: variable to "val".
7174 */
7175 void
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02007176set_vim_var_nr(int idx, varnumber_T val)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007177{
Bram Moolenaare9a41262005-01-15 22:18:47 +00007178 vimvars[idx].vv_nr = val;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007179}
7180
7181/*
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02007182 * Get typval_T v: variable value.
7183 */
7184 typval_T *
7185get_vim_var_tv(int idx)
7186{
7187 return &vimvars[idx].vv_tv;
7188}
7189
7190/*
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007191 * Get number v: variable value.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007192 */
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02007193 varnumber_T
Bram Moolenaar7454a062016-01-30 15:14:10 +01007194get_vim_var_nr(int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007195{
Bram Moolenaare9a41262005-01-15 22:18:47 +00007196 return vimvars[idx].vv_nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007197}
7198
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007199/*
7200 * Get string v: variable value. Uses a static buffer, can only be used once.
Bram Moolenaar6e65d592017-12-07 22:11:27 +01007201 * If the String variable has never been set, return an empty string.
7202 * Never returns NULL;
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007203 */
7204 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007205get_vim_var_str(int idx)
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007206{
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007207 return tv_get_string(&vimvars[idx].vv_tv);
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007208}
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007209
Bram Moolenaar071d4272004-06-13 20:20:40 +00007210/*
Bram Moolenaard812df62008-11-09 12:46:09 +00007211 * Get List v: variable value. Caller must take care of reference count when
7212 * needed.
7213 */
7214 list_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007215get_vim_var_list(int idx)
Bram Moolenaard812df62008-11-09 12:46:09 +00007216{
7217 return vimvars[idx].vv_list;
7218}
7219
7220/*
Bram Moolenaar7e1652c2017-12-16 18:27:02 +01007221 * Get Dict v: variable value. Caller must take care of reference count when
7222 * needed.
7223 */
7224 dict_T *
7225get_vim_var_dict(int idx)
7226{
7227 return vimvars[idx].vv_dict;
7228}
7229
7230/*
Bram Moolenaarda9591e2009-09-30 13:17:02 +00007231 * Set v:char to character "c".
7232 */
7233 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007234set_vim_var_char(int c)
Bram Moolenaarda9591e2009-09-30 13:17:02 +00007235{
Bram Moolenaar9a920d82012-06-01 15:21:02 +02007236 char_u buf[MB_MAXBYTES + 1];
Bram Moolenaarda9591e2009-09-30 13:17:02 +00007237
Bram Moolenaarda9591e2009-09-30 13:17:02 +00007238 if (has_mbyte)
7239 buf[(*mb_char2bytes)(c, buf)] = NUL;
7240 else
Bram Moolenaarda9591e2009-09-30 13:17:02 +00007241 {
7242 buf[0] = c;
7243 buf[1] = NUL;
7244 }
7245 set_vim_var_string(VV_CHAR, buf, -1);
7246}
7247
7248/*
Bram Moolenaar8df74be2008-11-20 15:12:02 +00007249 * Set v:count to "count" and v:count1 to "count1".
7250 * When "set_prevcount" is TRUE first set v:prevcount from v:count.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007251 */
7252 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007253set_vcount(
7254 long count,
7255 long count1,
7256 int set_prevcount)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007257{
Bram Moolenaar8df74be2008-11-20 15:12:02 +00007258 if (set_prevcount)
7259 vimvars[VV_PREVCOUNT].vv_nr = vimvars[VV_COUNT].vv_nr;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007260 vimvars[VV_COUNT].vv_nr = count;
7261 vimvars[VV_COUNT1].vv_nr = count1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007262}
7263
7264/*
Bram Moolenaarb0f42ba2018-05-12 15:38:26 +02007265 * Save variables that might be changed as a side effect. Used when executing
7266 * a timer callback.
7267 */
7268 void
7269save_vimvars(vimvars_save_T *vvsave)
7270{
7271 vvsave->vv_prevcount = vimvars[VV_PREVCOUNT].vv_nr;
7272 vvsave->vv_count = vimvars[VV_COUNT].vv_nr;
7273 vvsave->vv_count1 = vimvars[VV_COUNT1].vv_nr;
7274}
7275
7276/*
7277 * Restore variables saved by save_vimvars().
7278 */
7279 void
7280restore_vimvars(vimvars_save_T *vvsave)
7281{
7282 vimvars[VV_PREVCOUNT].vv_nr = vvsave->vv_prevcount;
7283 vimvars[VV_COUNT].vv_nr = vvsave->vv_count;
7284 vimvars[VV_COUNT1].vv_nr = vvsave->vv_count1;
7285}
7286
7287/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007288 * Set string v: variable to a copy of "val".
7289 */
7290 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007291set_vim_var_string(
7292 int idx,
7293 char_u *val,
7294 int len) /* length of "val" to use or -1 (whole string) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007295{
Bram Moolenaara542c682016-01-31 16:28:04 +01007296 clear_tv(&vimvars[idx].vv_di.di_tv);
7297 vimvars[idx].vv_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007298 if (val == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007299 vimvars[idx].vv_str = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007300 else if (len == -1)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007301 vimvars[idx].vv_str = vim_strsave(val);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007302 else
Bram Moolenaare9a41262005-01-15 22:18:47 +00007303 vimvars[idx].vv_str = vim_strnsave(val, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007304}
7305
7306/*
Bram Moolenaard812df62008-11-09 12:46:09 +00007307 * Set List v: variable to "val".
7308 */
7309 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007310set_vim_var_list(int idx, list_T *val)
Bram Moolenaard812df62008-11-09 12:46:09 +00007311{
Bram Moolenaara542c682016-01-31 16:28:04 +01007312 clear_tv(&vimvars[idx].vv_di.di_tv);
7313 vimvars[idx].vv_type = VAR_LIST;
Bram Moolenaard812df62008-11-09 12:46:09 +00007314 vimvars[idx].vv_list = val;
7315 if (val != NULL)
7316 ++val->lv_refcount;
7317}
7318
7319/*
Bram Moolenaar42a45122015-07-10 17:56:23 +02007320 * Set Dictionary v: variable to "val".
7321 */
7322 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007323set_vim_var_dict(int idx, dict_T *val)
Bram Moolenaar42a45122015-07-10 17:56:23 +02007324{
Bram Moolenaara542c682016-01-31 16:28:04 +01007325 clear_tv(&vimvars[idx].vv_di.di_tv);
7326 vimvars[idx].vv_type = VAR_DICT;
Bram Moolenaar42a45122015-07-10 17:56:23 +02007327 vimvars[idx].vv_dict = val;
7328 if (val != NULL)
7329 {
7330 ++val->dv_refcount;
Bram Moolenaar7e1652c2017-12-16 18:27:02 +01007331 dict_set_items_ro(val);
Bram Moolenaar42a45122015-07-10 17:56:23 +02007332 }
7333}
7334
7335/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007336 * Set v:register if needed.
7337 */
7338 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007339set_reg_var(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007340{
7341 char_u regname;
7342
7343 if (c == 0 || c == ' ')
7344 regname = '"';
7345 else
7346 regname = c;
7347 /* Avoid free/alloc when the value is already right. */
Bram Moolenaare9a41262005-01-15 22:18:47 +00007348 if (vimvars[VV_REG].vv_str == NULL || vimvars[VV_REG].vv_str[0] != c)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007349 set_vim_var_string(VV_REG, &regname, 1);
7350}
7351
7352/*
7353 * Get or set v:exception. If "oldval" == NULL, return the current value.
7354 * Otherwise, restore the value to "oldval" and return NULL.
7355 * Must always be called in pairs to save and restore v:exception! Does not
7356 * take care of memory allocations.
7357 */
7358 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007359v_exception(char_u *oldval)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007360{
7361 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007362 return vimvars[VV_EXCEPTION].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007363
Bram Moolenaare9a41262005-01-15 22:18:47 +00007364 vimvars[VV_EXCEPTION].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007365 return NULL;
7366}
7367
7368/*
7369 * Get or set v:throwpoint. If "oldval" == NULL, return the current value.
7370 * Otherwise, restore the value to "oldval" and return NULL.
7371 * Must always be called in pairs to save and restore v:throwpoint! Does not
7372 * take care of memory allocations.
7373 */
7374 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007375v_throwpoint(char_u *oldval)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007376{
7377 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007378 return vimvars[VV_THROWPOINT].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007379
Bram Moolenaare9a41262005-01-15 22:18:47 +00007380 vimvars[VV_THROWPOINT].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007381 return NULL;
7382}
7383
Bram Moolenaar071d4272004-06-13 20:20:40 +00007384/*
7385 * Set v:cmdarg.
7386 * If "eap" != NULL, use "eap" to generate the value and return the old value.
7387 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
7388 * Must always be called in pairs!
7389 */
7390 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007391set_cmdarg(exarg_T *eap, char_u *oldarg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007392{
7393 char_u *oldval;
7394 char_u *newval;
7395 unsigned len;
7396
Bram Moolenaare9a41262005-01-15 22:18:47 +00007397 oldval = vimvars[VV_CMDARG].vv_str;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007398 if (eap == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007399 {
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007400 vim_free(oldval);
Bram Moolenaare9a41262005-01-15 22:18:47 +00007401 vimvars[VV_CMDARG].vv_str = oldarg;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007402 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007403 }
7404
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007405 if (eap->force_bin == FORCE_BIN)
7406 len = 6;
7407 else if (eap->force_bin == FORCE_NOBIN)
7408 len = 8;
7409 else
7410 len = 0;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00007411
7412 if (eap->read_edit)
7413 len += 7;
7414
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007415 if (eap->force_ff != 0)
Bram Moolenaar333b80a2018-04-04 22:57:29 +02007416 len += 10; /* " ++ff=unix" */
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007417 if (eap->force_enc != 0)
7418 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
Bram Moolenaar34b4daf2010-05-16 13:26:25 +02007419 if (eap->bad_char != 0)
7420 len += 7 + 4; /* " ++bad=" + "keep" or "drop" */
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007421
7422 newval = alloc(len + 1);
7423 if (newval == NULL)
7424 return NULL;
7425
7426 if (eap->force_bin == FORCE_BIN)
7427 sprintf((char *)newval, " ++bin");
7428 else if (eap->force_bin == FORCE_NOBIN)
7429 sprintf((char *)newval, " ++nobin");
7430 else
7431 *newval = NUL;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00007432
7433 if (eap->read_edit)
7434 STRCAT(newval, " ++edit");
7435
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007436 if (eap->force_ff != 0)
7437 sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
Bram Moolenaar333b80a2018-04-04 22:57:29 +02007438 eap->force_ff == 'u' ? "unix"
7439 : eap->force_ff == 'd' ? "dos"
7440 : "mac");
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007441 if (eap->force_enc != 0)
7442 sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
7443 eap->cmd + eap->force_enc);
Bram Moolenaar34b4daf2010-05-16 13:26:25 +02007444 if (eap->bad_char == BAD_KEEP)
7445 STRCPY(newval + STRLEN(newval), " ++bad=keep");
7446 else if (eap->bad_char == BAD_DROP)
7447 STRCPY(newval + STRLEN(newval), " ++bad=drop");
7448 else if (eap->bad_char != 0)
7449 sprintf((char *)newval + STRLEN(newval), " ++bad=%c", eap->bad_char);
Bram Moolenaare9a41262005-01-15 22:18:47 +00007450 vimvars[VV_CMDARG].vv_str = newval;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00007451 return oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007452}
Bram Moolenaar071d4272004-06-13 20:20:40 +00007453
7454/*
7455 * Get the value of internal variable "name".
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01007456 * Return OK or FAIL. If OK is returned "rettv" must be cleared.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007457 */
Bram Moolenaar5843f5f2019-08-20 20:13:45 +02007458 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007459get_var_tv(
7460 char_u *name,
7461 int len, /* length of "name" */
7462 typval_T *rettv, /* NULL when only checking existence */
7463 dictitem_T **dip, /* non-NULL when typval's dict item is needed */
7464 int verbose, /* may give error message */
7465 int no_autoload) /* do not use script autoloading */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007466{
7467 int ret = OK;
Bram Moolenaar33570922005-01-25 22:26:29 +00007468 typval_T *tv = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00007469 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007470 int cc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007471
7472 /* truncate the name, so that we can use strcmp() */
7473 cc = name[len];
7474 name[len] = NUL;
7475
7476 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007477 * Check for user-defined variables.
7478 */
Bram Moolenaar79518e22017-02-17 16:31:35 +01007479 v = find_var(name, NULL, no_autoload);
7480 if (v != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007481 {
Bram Moolenaar79518e22017-02-17 16:31:35 +01007482 tv = &v->di_tv;
7483 if (dip != NULL)
7484 *dip = v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007485 }
7486
Bram Moolenaare9a41262005-01-15 22:18:47 +00007487 if (tv == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007488 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007489 if (rettv != NULL && verbose)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007490 semsg(_(e_undefvar), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007491 ret = FAIL;
7492 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007493 else if (rettv != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007494 copy_tv(tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007495
7496 name[len] = cc;
7497
7498 return ret;
7499}
7500
7501/*
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02007502 * Check if variable "name[len]" is a local variable or an argument.
7503 * If so, "*eval_lavars_used" is set to TRUE.
7504 */
7505 static void
7506check_vars(char_u *name, int len)
7507{
7508 int cc;
7509 char_u *varname;
7510 hashtab_T *ht;
7511
7512 if (eval_lavars_used == NULL)
7513 return;
7514
7515 /* truncate the name, so that we can use strcmp() */
7516 cc = name[len];
7517 name[len] = NUL;
7518
7519 ht = find_var_ht(name, &varname);
7520 if (ht == get_funccal_local_ht() || ht == get_funccal_args_ht())
7521 {
7522 if (find_var(name, NULL, TRUE) != NULL)
7523 *eval_lavars_used = TRUE;
7524 }
7525
7526 name[len] = cc;
7527}
7528
7529/*
Bram Moolenaarac92e252019-08-03 21:58:38 +02007530 * Handle:
7531 * - expr[expr], expr[expr:expr] subscript
7532 * - ".name" lookup
7533 * - function call with Funcref variable: func(expr)
7534 * - method call: var->method()
7535 *
7536 * Can all be combined in any order: dict.func(expr)[idx]['func'](expr)->len()
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007537 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02007538 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007539handle_subscript(
7540 char_u **arg,
7541 typval_T *rettv,
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02007542 int evaluate, // do more than finding the end
7543 int verbose, // give error messages
7544 char_u *start_leader, // start of '!' and '-' prefixes
7545 char_u **end_leaderp) // end of '!' and '-' prefixes
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007546{
7547 int ret = OK;
7548 dict_T *selfdict = NULL;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007549
Bram Moolenaar61343f02019-07-20 21:11:13 +02007550 // "." is ".name" lookup when we found a dict or when evaluating and
7551 // scriptversion is at least 2, where string concatenation is "..".
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007552 while (ret == OK
Bram Moolenaarac92e252019-08-03 21:58:38 +02007553 && (((**arg == '['
7554 || (**arg == '.' && (rettv->v_type == VAR_DICT
Bram Moolenaar61343f02019-07-20 21:11:13 +02007555 || (!evaluate
7556 && (*arg)[1] != '.'
7557 && current_sctx.sc_version >= 2)))
Bram Moolenaarac92e252019-08-03 21:58:38 +02007558 || (**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007559 || rettv->v_type == VAR_PARTIAL)))
Bram Moolenaarac92e252019-08-03 21:58:38 +02007560 && !VIM_ISWHITE(*(*arg - 1)))
7561 || (**arg == '-' && (*arg)[1] == '>')))
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007562 {
7563 if (**arg == '(')
7564 {
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02007565 ret = call_func_rettv(arg, rettv, evaluate, selfdict, NULL);
Bram Moolenaar3f242a82016-03-18 19:39:25 +01007566
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02007567 // Stop the expression evaluation when immediately aborting on
7568 // error, or when an interrupt occurred or an exception was thrown
7569 // but not caught.
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007570 if (aborting())
7571 {
7572 if (ret == OK)
7573 clear_tv(rettv);
7574 ret = FAIL;
7575 }
7576 dict_unref(selfdict);
7577 selfdict = NULL;
7578 }
Bram Moolenaarac92e252019-08-03 21:58:38 +02007579 else if (**arg == '-')
7580 {
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02007581 // Expression "-1.0->method()" applies the leader "-" before
7582 // applying ->.
7583 if (evaluate && *end_leaderp > start_leader)
7584 ret = eval7_leader(rettv, start_leader, end_leaderp);
7585 if (ret == OK)
7586 {
7587 if ((*arg)[2] == '{')
7588 // expr->{lambda}()
7589 ret = eval_lambda(arg, rettv, evaluate, verbose);
7590 else
7591 // expr->name()
7592 ret = eval_method(arg, rettv, evaluate, verbose);
7593 }
Bram Moolenaarac92e252019-08-03 21:58:38 +02007594 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007595 else /* **arg == '[' || **arg == '.' */
7596 {
7597 dict_unref(selfdict);
7598 if (rettv->v_type == VAR_DICT)
7599 {
7600 selfdict = rettv->vval.v_dict;
7601 if (selfdict != NULL)
7602 ++selfdict->dv_refcount;
7603 }
7604 else
7605 selfdict = NULL;
7606 if (eval_index(arg, rettv, evaluate, verbose) == FAIL)
7607 {
7608 clear_tv(rettv);
7609 ret = FAIL;
7610 }
7611 }
7612 }
Bram Moolenaarab1fa392016-03-15 19:33:34 +01007613
Bram Moolenaar1d429612016-05-24 15:44:17 +02007614 /* Turn "dict.Func" into a partial for "Func" bound to "dict".
7615 * Don't do this when "Func" is already a partial that was bound
7616 * explicitly (pt_auto is FALSE). */
7617 if (selfdict != NULL
7618 && (rettv->v_type == VAR_FUNC
7619 || (rettv->v_type == VAR_PARTIAL
7620 && (rettv->vval.v_partial->pt_auto
7621 || rettv->vval.v_partial->pt_dict == NULL))))
Bram Moolenaara9b579f2016-07-17 18:29:19 +02007622 selfdict = make_partial(selfdict, rettv);
Bram Moolenaarab1fa392016-03-15 19:33:34 +01007623
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007624 dict_unref(selfdict);
7625 return ret;
7626}
7627
7628/*
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007629 * Allocate memory for a variable type-value, and make it empty (0 or NULL
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007630 * value).
7631 */
Bram Moolenaar11e0afa2016-02-01 22:41:00 +01007632 typval_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007633alloc_tv(void)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007634{
Bram Moolenaarc799fe22019-05-28 23:08:19 +02007635 return ALLOC_CLEAR_ONE(typval_T);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007636}
7637
7638/*
7639 * Allocate memory for a variable type-value, and assign a string to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007640 * The string "s" must have been allocated, it is consumed.
7641 * Return NULL for out of memory, the variable otherwise.
7642 */
Bram Moolenaar33570922005-01-25 22:26:29 +00007643 static typval_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007644alloc_string_tv(char_u *s)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007645{
Bram Moolenaar33570922005-01-25 22:26:29 +00007646 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007647
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007648 rettv = alloc_tv();
7649 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007650 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007651 rettv->v_type = VAR_STRING;
7652 rettv->vval.v_string = s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007653 }
7654 else
7655 vim_free(s);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007656 return rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007657}
7658
7659/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007660 * Free the memory for a variable type-value.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007661 */
Bram Moolenaar4770d092006-01-12 23:22:24 +00007662 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007663free_tv(typval_T *varp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007664{
7665 if (varp != NULL)
7666 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007667 switch (varp->v_type)
7668 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007669 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007670 func_unref(varp->vval.v_string);
Bram Moolenaar2f40d122017-10-24 21:49:36 +02007671 /* FALLTHROUGH */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007672 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007673 vim_free(varp->vval.v_string);
7674 break;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007675 case VAR_PARTIAL:
7676 partial_unref(varp->vval.v_partial);
7677 break;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01007678 case VAR_BLOB:
7679 blob_unref(varp->vval.v_blob);
7680 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007681 case VAR_LIST:
7682 list_unref(varp->vval.v_list);
7683 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007684 case VAR_DICT:
7685 dict_unref(varp->vval.v_dict);
7686 break;
Bram Moolenaar835dc632016-02-07 14:27:38 +01007687 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007688#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +01007689 job_unref(varp->vval.v_job);
7690 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007691#endif
Bram Moolenaar77073442016-02-13 23:23:53 +01007692 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007693#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +01007694 channel_unref(varp->vval.v_channel);
7695 break;
7696#endif
Bram Moolenaar835dc632016-02-07 14:27:38 +01007697 case VAR_NUMBER:
7698 case VAR_FLOAT:
Bram Moolenaar758711c2005-02-02 23:11:38 +00007699 case VAR_UNKNOWN:
Bram Moolenaar6650a692016-01-26 19:59:10 +01007700 case VAR_SPECIAL:
Bram Moolenaar758711c2005-02-02 23:11:38 +00007701 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007702 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007703 vim_free(varp);
7704 }
7705}
7706
7707/*
7708 * Free the memory for a variable value and set the value to NULL or 0.
7709 */
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00007710 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007711clear_tv(typval_T *varp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007712{
7713 if (varp != NULL)
7714 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007715 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007716 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007717 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007718 func_unref(varp->vval.v_string);
Bram Moolenaar2f40d122017-10-24 21:49:36 +02007719 /* FALLTHROUGH */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007720 case VAR_STRING:
Bram Moolenaard23a8232018-02-10 18:45:26 +01007721 VIM_CLEAR(varp->vval.v_string);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007722 break;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007723 case VAR_PARTIAL:
7724 partial_unref(varp->vval.v_partial);
7725 varp->vval.v_partial = NULL;
7726 break;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01007727 case VAR_BLOB:
7728 blob_unref(varp->vval.v_blob);
7729 varp->vval.v_blob = NULL;
7730 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007731 case VAR_LIST:
7732 list_unref(varp->vval.v_list);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007733 varp->vval.v_list = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007734 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007735 case VAR_DICT:
7736 dict_unref(varp->vval.v_dict);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007737 varp->vval.v_dict = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007738 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007739 case VAR_NUMBER:
Bram Moolenaar520e1e42016-01-23 19:46:28 +01007740 case VAR_SPECIAL:
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007741 varp->vval.v_number = 0;
7742 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007743 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01007744#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007745 varp->vval.v_float = 0.0;
7746 break;
7747#endif
Bram Moolenaar835dc632016-02-07 14:27:38 +01007748 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007749#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +01007750 job_unref(varp->vval.v_job);
7751 varp->vval.v_job = NULL;
7752#endif
7753 break;
Bram Moolenaar77073442016-02-13 23:23:53 +01007754 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007755#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +01007756 channel_unref(varp->vval.v_channel);
7757 varp->vval.v_channel = NULL;
7758#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007759 case VAR_UNKNOWN:
7760 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007761 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007762 varp->v_lock = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007763 }
7764}
7765
7766/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007767 * Set the value of a variable to NULL without freeing items.
7768 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007769 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007770init_tv(typval_T *varp)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007771{
7772 if (varp != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +00007773 vim_memset(varp, 0, sizeof(typval_T));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007774}
7775
7776/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007777 * Get the number value of a variable.
7778 * If it is a String variable, uses vim_str2nr().
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007779 * For incompatible types, return 0.
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007780 * tv_get_number_chk() is similar to tv_get_number(), but informs the
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007781 * caller of incompatible types: it sets *denote to TRUE if "denote"
7782 * is not NULL or returns -1 otherwise.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007783 */
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02007784 varnumber_T
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007785tv_get_number(typval_T *varp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007786{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007787 int error = FALSE;
7788
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007789 return tv_get_number_chk(varp, &error); /* return 0L on error */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007790}
7791
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02007792 varnumber_T
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007793tv_get_number_chk(typval_T *varp, int *denote)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007794{
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02007795 varnumber_T n = 0L;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007796
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007797 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007798 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007799 case VAR_NUMBER:
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02007800 return varp->vval.v_number;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007801 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01007802#ifdef FEAT_FLOAT
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007803 emsg(_("E805: Using a Float as a Number"));
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007804 break;
7805#endif
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007806 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007807 case VAR_PARTIAL:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007808 emsg(_("E703: Using a Funcref as a Number"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007809 break;
7810 case VAR_STRING:
7811 if (varp->vval.v_string != NULL)
7812 vim_str2nr(varp->vval.v_string, NULL, NULL,
Bram Moolenaar16e9b852019-05-19 19:59:35 +02007813 STR2NR_ALL, &n, NULL, 0, FALSE);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007814 return n;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007815 case VAR_LIST:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007816 emsg(_("E745: Using a List as a Number"));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007817 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007818 case VAR_DICT:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007819 emsg(_("E728: Using a Dictionary as a Number"));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007820 break;
Bram Moolenaar17a13432016-01-24 14:22:10 +01007821 case VAR_SPECIAL:
7822 return varp->vval.v_number == VVAL_TRUE ? 1 : 0;
7823 break;
Bram Moolenaar835dc632016-02-07 14:27:38 +01007824 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007825#ifdef FEAT_JOB_CHANNEL
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007826 emsg(_("E910: Using a Job as a Number"));
Bram Moolenaar835dc632016-02-07 14:27:38 +01007827 break;
7828#endif
Bram Moolenaar77073442016-02-13 23:23:53 +01007829 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007830#ifdef FEAT_JOB_CHANNEL
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007831 emsg(_("E913: Using a Channel as a Number"));
Bram Moolenaar77073442016-02-13 23:23:53 +01007832 break;
7833#endif
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01007834 case VAR_BLOB:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007835 emsg(_("E974: Using a Blob as a Number"));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01007836 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +01007837 case VAR_UNKNOWN:
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007838 internal_error("tv_get_number(UNKNOWN)");
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007839 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007840 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007841 if (denote == NULL) /* useful for values that must be unsigned */
7842 n = -1;
7843 else
7844 *denote = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007845 return n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007846}
7847
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007848#ifdef FEAT_FLOAT
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02007849 float_T
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007850tv_get_float(typval_T *varp)
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007851{
7852 switch (varp->v_type)
7853 {
7854 case VAR_NUMBER:
7855 return (float_T)(varp->vval.v_number);
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007856 case VAR_FLOAT:
7857 return varp->vval.v_float;
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007858 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007859 case VAR_PARTIAL:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007860 emsg(_("E891: Using a Funcref as a Float"));
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007861 break;
7862 case VAR_STRING:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007863 emsg(_("E892: Using a String as a Float"));
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007864 break;
7865 case VAR_LIST:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007866 emsg(_("E893: Using a List as a Float"));
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007867 break;
7868 case VAR_DICT:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007869 emsg(_("E894: Using a Dictionary as a Float"));
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007870 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +01007871 case VAR_SPECIAL:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007872 emsg(_("E907: Using a special value as a Float"));
Bram Moolenaara03f2332016-02-06 18:09:59 +01007873 break;
Bram Moolenaar835dc632016-02-07 14:27:38 +01007874 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007875# ifdef FEAT_JOB_CHANNEL
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007876 emsg(_("E911: Using a Job as a Float"));
Bram Moolenaar835dc632016-02-07 14:27:38 +01007877 break;
7878# endif
Bram Moolenaar77073442016-02-13 23:23:53 +01007879 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007880# ifdef FEAT_JOB_CHANNEL
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007881 emsg(_("E914: Using a Channel as a Float"));
Bram Moolenaar77073442016-02-13 23:23:53 +01007882 break;
7883# endif
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01007884 case VAR_BLOB:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007885 emsg(_("E975: Using a Blob as a Float"));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01007886 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +01007887 case VAR_UNKNOWN:
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007888 internal_error("tv_get_float(UNKNOWN)");
Bram Moolenaarf7edf402016-01-19 23:36:15 +01007889 break;
7890 }
7891 return 0;
7892}
7893#endif
7894
Bram Moolenaar071d4272004-06-13 20:20:40 +00007895/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007896 * Get the string value of a variable.
7897 * If it is a Number variable, the number is converted into a string.
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007898 * tv_get_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
7899 * tv_get_string_buf() uses a given buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007900 * If the String variable has never been set, return an empty string.
7901 * Never returns NULL;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007902 * tv_get_string_chk() and tv_get_string_buf_chk() are similar, but return
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007903 * NULL on error.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007904 */
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01007905 char_u *
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007906tv_get_string(typval_T *varp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007907{
7908 static char_u mybuf[NUMBUFLEN];
7909
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007910 return tv_get_string_buf(varp, mybuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007911}
7912
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01007913 char_u *
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007914tv_get_string_buf(typval_T *varp, char_u *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007915{
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007916 char_u *res = tv_get_string_buf_chk(varp, buf);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007917
7918 return res != NULL ? res : (char_u *)"";
7919}
7920
Bram Moolenaar7d647822014-04-05 21:28:56 +02007921/*
7922 * Careful: This uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
7923 */
Bram Moolenaar4be06f92005-07-29 22:36:03 +00007924 char_u *
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007925tv_get_string_chk(typval_T *varp)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007926{
7927 static char_u mybuf[NUMBUFLEN];
7928
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007929 return tv_get_string_buf_chk(varp, mybuf);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007930}
7931
Bram Moolenaar520e1e42016-01-23 19:46:28 +01007932 char_u *
Bram Moolenaard155d7a2018-12-21 16:04:21 +01007933tv_get_string_buf_chk(typval_T *varp, char_u *buf)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007934{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007935 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007936 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007937 case VAR_NUMBER:
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02007938 vim_snprintf((char *)buf, NUMBUFLEN, "%lld",
Bram Moolenaar88c86eb2019-01-17 17:13:30 +01007939 (long_long_T)varp->vval.v_number);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007940 return buf;
7941 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007942 case VAR_PARTIAL:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007943 emsg(_("E729: using Funcref as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007944 break;
7945 case VAR_LIST:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007946 emsg(_("E730: using List as a String"));
Bram Moolenaar8c711452005-01-14 21:53:12 +00007947 break;
7948 case VAR_DICT:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007949 emsg(_("E731: using Dictionary as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007950 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007951 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01007952#ifdef FEAT_FLOAT
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007953 emsg(_(e_float_as_string));
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007954 break;
7955#endif
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007956 case VAR_STRING:
7957 if (varp->vval.v_string != NULL)
7958 return varp->vval.v_string;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007959 return (char_u *)"";
Bram Moolenaar17a13432016-01-24 14:22:10 +01007960 case VAR_SPECIAL:
7961 STRCPY(buf, get_var_special_name(varp->vval.v_number));
7962 return buf;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01007963 case VAR_BLOB:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007964 emsg(_("E976: using Blob as a String"));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01007965 break;
Bram Moolenaar835dc632016-02-07 14:27:38 +01007966 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007967#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +01007968 {
7969 job_T *job = varp->vval.v_job;
Bram Moolenaar839fd112016-03-06 21:34:03 +01007970 char *status;
7971
7972 if (job == NULL)
7973 return (char_u *)"no process";
7974 status = job->jv_status == JOB_FAILED ? "fail"
Bram Moolenaar7df915d2016-11-17 17:25:32 +01007975 : job->jv_status >= JOB_ENDED ? "dead"
Bram Moolenaar835dc632016-02-07 14:27:38 +01007976 : "run";
7977# ifdef UNIX
7978 vim_snprintf((char *)buf, NUMBUFLEN,
7979 "process %ld %s", (long)job->jv_pid, status);
Bram Moolenaar4f974752019-02-17 17:44:42 +01007980# elif defined(MSWIN)
Bram Moolenaar4d8747c2016-02-09 20:39:26 +01007981 vim_snprintf((char *)buf, NUMBUFLEN,
Bram Moolenaar76467df2016-02-12 19:30:26 +01007982 "process %ld %s",
7983 (long)job->jv_proc_info.dwProcessId,
Bram Moolenaar4d8747c2016-02-09 20:39:26 +01007984 status);
Bram Moolenaar835dc632016-02-07 14:27:38 +01007985# else
Bram Moolenaar4d8747c2016-02-09 20:39:26 +01007986 /* fall-back */
Bram Moolenaar835dc632016-02-07 14:27:38 +01007987 vim_snprintf((char *)buf, NUMBUFLEN, "process ? %s", status);
7988# endif
7989 return buf;
7990 }
7991#endif
7992 break;
Bram Moolenaar77073442016-02-13 23:23:53 +01007993 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007994#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +01007995 {
7996 channel_T *channel = varp->vval.v_channel;
Bram Moolenaar0e77b762016-09-26 22:58:58 +02007997 char *status = channel_status(channel, -1);
Bram Moolenaar77073442016-02-13 23:23:53 +01007998
Bram Moolenaar5cefd402016-02-16 12:44:26 +01007999 if (channel == NULL)
8000 vim_snprintf((char *)buf, NUMBUFLEN, "channel %s", status);
8001 else
8002 vim_snprintf((char *)buf, NUMBUFLEN,
Bram Moolenaar77073442016-02-13 23:23:53 +01008003 "channel %d %s", channel->ch_id, status);
8004 return buf;
8005 }
8006#endif
8007 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +01008008 case VAR_UNKNOWN:
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008009 emsg(_("E908: using an invalid value as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008010 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008011 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008012 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008013}
8014
8015/*
Bram Moolenaar461a7fc2018-12-22 13:28:07 +01008016 * Turn a typeval into a string. Similar to tv_get_string_buf() but uses
8017 * string() on Dict, List, etc.
8018 */
Bram Moolenaar5843f5f2019-08-20 20:13:45 +02008019 static char_u *
Bram Moolenaar461a7fc2018-12-22 13:28:07 +01008020tv_stringify(typval_T *varp, char_u *buf)
8021{
8022 if (varp->v_type == VAR_LIST
8023 || varp->v_type == VAR_DICT
8024 || varp->v_type == VAR_FUNC
8025 || varp->v_type == VAR_PARTIAL
8026 || varp->v_type == VAR_FLOAT)
8027 {
8028 typval_T tmp;
8029
8030 f_string(varp, &tmp);
8031 tv_get_string_buf(&tmp, buf);
8032 clear_tv(varp);
8033 *varp = tmp;
8034 return tmp.vval.v_string;
8035 }
8036 return tv_get_string_buf(varp, buf);
8037}
8038
8039/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008040 * Find variable "name" in the list of variables.
8041 * Return a pointer to it if found, NULL if not found.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008042 * Careful: "a:0" variables don't have a name.
Bram Moolenaara7043832005-01-21 11:56:39 +00008043 * When "htp" is not NULL we are writing to the variable, set "htp" to the
Bram Moolenaar33570922005-01-25 22:26:29 +00008044 * hashtab_T used.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008045 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008046 dictitem_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01008047find_var(char_u *name, hashtab_T **htp, int no_autoload)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008048{
Bram Moolenaar071d4272004-06-13 20:20:40 +00008049 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +00008050 hashtab_T *ht;
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02008051 dictitem_T *ret = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008052
Bram Moolenaara7043832005-01-21 11:56:39 +00008053 ht = find_var_ht(name, &varname);
8054 if (htp != NULL)
8055 *htp = ht;
8056 if (ht == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008057 return NULL;
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02008058 ret = find_var_in_ht(ht, *name, varname, no_autoload || htp != NULL);
8059 if (ret != NULL)
8060 return ret;
8061
8062 /* Search in parent scope for lambda */
Bram Moolenaarba96e9a2016-08-01 17:10:20 +02008063 return find_var_in_scoped_ht(name, no_autoload || htp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008064}
8065
8066/*
Bram Moolenaar332ac062013-04-15 13:06:21 +02008067 * Find variable "varname" in hashtab "ht" with name "htname".
Bram Moolenaara7043832005-01-21 11:56:39 +00008068 * Returns NULL if not found.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008069 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008070 dictitem_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01008071find_var_in_ht(
8072 hashtab_T *ht,
8073 int htname,
8074 char_u *varname,
8075 int no_autoload)
Bram Moolenaara7043832005-01-21 11:56:39 +00008076{
Bram Moolenaar33570922005-01-25 22:26:29 +00008077 hashitem_T *hi;
8078
8079 if (*varname == NUL)
8080 {
8081 /* Must be something like "s:", otherwise "ht" would be NULL. */
Bram Moolenaar332ac062013-04-15 13:06:21 +02008082 switch (htname)
Bram Moolenaar33570922005-01-25 22:26:29 +00008083 {
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02008084 case 's': return &SCRIPT_SV(current_sctx.sc_sid)->sv_var;
Bram Moolenaar33570922005-01-25 22:26:29 +00008085 case 'g': return &globvars_var;
8086 case 'v': return &vimvars_var;
8087 case 'b': return &curbuf->b_bufvar;
8088 case 'w': return &curwin->w_winvar;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00008089 case 't': return &curtab->tp_winvar;
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008090 case 'l': return get_funccal_local_var();
8091 case 'a': return get_funccal_args_var();
Bram Moolenaar33570922005-01-25 22:26:29 +00008092 }
8093 return NULL;
8094 }
Bram Moolenaara7043832005-01-21 11:56:39 +00008095
8096 hi = hash_find(ht, varname);
8097 if (HASHITEM_EMPTY(hi))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008098 {
8099 /* For global variables we may try auto-loading the script. If it
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00008100 * worked find the variable again. Don't auto-load a script if it was
8101 * loaded already, otherwise it would be loaded every time when
8102 * checking if a function name is a Funcref variable. */
Bram Moolenaar6d977d62014-01-14 15:24:39 +01008103 if (ht == &globvarht && !no_autoload)
Bram Moolenaar8000baf2011-11-30 15:19:28 +01008104 {
8105 /* Note: script_autoload() may make "hi" invalid. It must either
8106 * be obtained again or not used. */
8107 if (!script_autoload(varname, FALSE) || aborting())
8108 return NULL;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008109 hi = hash_find(ht, varname);
Bram Moolenaar8000baf2011-11-30 15:19:28 +01008110 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008111 if (HASHITEM_EMPTY(hi))
8112 return NULL;
8113 }
Bram Moolenaar33570922005-01-25 22:26:29 +00008114 return HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +00008115}
8116
8117/*
Bram Moolenaar33570922005-01-25 22:26:29 +00008118 * Find the hashtab used for a variable name.
Bram Moolenaar73627d02015-08-11 15:46:09 +02008119 * Return NULL if the name is not valid.
Bram Moolenaara7043832005-01-21 11:56:39 +00008120 * Set "varname" to the start of name without ':'.
8121 */
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02008122 hashtab_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01008123find_var_ht(char_u *name, char_u **varname)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008124{
Bram Moolenaar75c50c42005-06-04 22:06:24 +00008125 hashitem_T *hi;
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008126 hashtab_T *ht;
Bram Moolenaar75c50c42005-06-04 22:06:24 +00008127
Bram Moolenaar73627d02015-08-11 15:46:09 +02008128 if (name[0] == NUL)
8129 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008130 if (name[1] != ':')
8131 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00008132 /* The name must not start with a colon or #. */
8133 if (name[0] == ':' || name[0] == AUTOLOAD_CHAR)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008134 return NULL;
8135 *varname = name;
Bram Moolenaar532c7802005-01-27 14:44:31 +00008136
Bram Moolenaard2e716e2019-04-20 14:39:52 +02008137 // "version" is "v:version" in all scopes if scriptversion < 3.
8138 // Same for a few other variables marked with VV_COMPAT.
8139 if (current_sctx.sc_version < 3)
8140 {
8141 hi = hash_find(&compat_hashtab, name);
8142 if (!HASHITEM_EMPTY(hi))
8143 return &compat_hashtab;
8144 }
Bram Moolenaar532c7802005-01-27 14:44:31 +00008145
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008146 ht = get_funccal_local_ht();
8147 if (ht == NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +00008148 return &globvarht; /* global variable */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008149 return ht; /* local variable */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008150 }
8151 *varname = name + 2;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008152 if (*name == 'g') /* global variable */
8153 return &globvarht;
Bram Moolenaar4c6d9042019-07-16 22:04:02 +02008154 // There must be no ':' or '#' in the rest of the name, unless g: is used
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00008155 if (vim_strchr(name + 2, ':') != NULL
8156 || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008157 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008158 if (*name == 'b') /* buffer variable */
Bram Moolenaar429fa852013-04-15 12:27:36 +02008159 return &curbuf->b_vars->dv_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008160 if (*name == 'w') /* window variable */
Bram Moolenaar429fa852013-04-15 12:27:36 +02008161 return &curwin->w_vars->dv_hashtab;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00008162 if (*name == 't') /* tab page variable */
Bram Moolenaar429fa852013-04-15 12:27:36 +02008163 return &curtab->tp_vars->dv_hashtab;
Bram Moolenaar33570922005-01-25 22:26:29 +00008164 if (*name == 'v') /* v: variable */
8165 return &vimvarht;
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008166 if (*name == 'a') /* a: function argument */
8167 return get_funccal_args_ht();
8168 if (*name == 'l') /* l: local function variable */
8169 return get_funccal_local_ht();
Bram Moolenaar071d4272004-06-13 20:20:40 +00008170 if (*name == 's' /* script variable */
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02008171 && current_sctx.sc_sid > 0 && current_sctx.sc_sid <= ga_scripts.ga_len)
8172 return &SCRIPT_VARS(current_sctx.sc_sid);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008173 return NULL;
8174}
8175
8176/*
8177 * Get the string value of a (global/local) variable.
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008178 * Note: see tv_get_string() for how long the pointer remains valid.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008179 * Returns NULL when it doesn't exist.
8180 */
8181 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01008182get_var_value(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008183{
Bram Moolenaar33570922005-01-25 22:26:29 +00008184 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008185
Bram Moolenaar6d977d62014-01-14 15:24:39 +01008186 v = find_var(name, NULL, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008187 if (v == NULL)
8188 return NULL;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008189 return tv_get_string(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008190}
8191
8192/*
Bram Moolenaar33570922005-01-25 22:26:29 +00008193 * Allocate a new hashtab for a sourced script. It will be used while
Bram Moolenaar071d4272004-06-13 20:20:40 +00008194 * sourcing this script and when executing functions defined in the script.
8195 */
8196 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008197new_script_vars(scid_T id)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008198{
Bram Moolenaara7043832005-01-21 11:56:39 +00008199 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00008200 hashtab_T *ht;
8201 scriptvar_T *sv;
Bram Moolenaara7043832005-01-21 11:56:39 +00008202
Bram Moolenaar071d4272004-06-13 20:20:40 +00008203 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
8204 {
Bram Moolenaara7043832005-01-21 11:56:39 +00008205 /* Re-allocating ga_data means that an ht_array pointing to
8206 * ht_smallarray becomes invalid. We can recognize this: ht_mask is
Bram Moolenaar33570922005-01-25 22:26:29 +00008207 * at its init value. Also reset "v_dict", it's always the same. */
Bram Moolenaara7043832005-01-21 11:56:39 +00008208 for (i = 1; i <= ga_scripts.ga_len; ++i)
8209 {
8210 ht = &SCRIPT_VARS(i);
8211 if (ht->ht_mask == HT_INIT_SIZE - 1)
8212 ht->ht_array = ht->ht_smallarray;
Bram Moolenaar9577c3e2010-05-14 12:16:25 +02008213 sv = SCRIPT_SV(i);
Bram Moolenaar33570922005-01-25 22:26:29 +00008214 sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict;
Bram Moolenaara7043832005-01-21 11:56:39 +00008215 }
8216
Bram Moolenaar071d4272004-06-13 20:20:40 +00008217 while (ga_scripts.ga_len < id)
8218 {
Bram Moolenaar2c704a72010-06-03 21:17:25 +02008219 sv = SCRIPT_SV(ga_scripts.ga_len + 1) =
Bram Moolenaarc799fe22019-05-28 23:08:19 +02008220 ALLOC_CLEAR_ONE(scriptvar_T);
Bram Moolenaarbdb62052012-07-16 17:31:53 +02008221 init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008222 ++ga_scripts.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008223 }
8224 }
8225}
8226
8227/*
Bram Moolenaar33570922005-01-25 22:26:29 +00008228 * Initialize dictionary "dict" as a scope and set variable "dict_var" to
8229 * point to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008230 */
8231 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008232init_var_dict(dict_T *dict, dictitem_T *dict_var, int scope)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008233{
Bram Moolenaar33570922005-01-25 22:26:29 +00008234 hash_init(&dict->dv_hashtab);
Bram Moolenaared465602012-06-20 14:13:06 +02008235 dict->dv_lock = 0;
Bram Moolenaarbdb62052012-07-16 17:31:53 +02008236 dict->dv_scope = scope;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +00008237 dict->dv_refcount = DO_NOT_FREE_CNT;
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00008238 dict->dv_copyID = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00008239 dict_var->di_tv.vval.v_dict = dict;
8240 dict_var->di_tv.v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008241 dict_var->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +00008242 dict_var->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
8243 dict_var->di_key[0] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008244}
8245
8246/*
Bram Moolenaar429fa852013-04-15 12:27:36 +02008247 * Unreference a dictionary initialized by init_var_dict().
8248 */
8249 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008250unref_var_dict(dict_T *dict)
Bram Moolenaar429fa852013-04-15 12:27:36 +02008251{
8252 /* Now the dict needs to be freed if no one else is using it, go back to
8253 * normal reference counting. */
8254 dict->dv_refcount -= DO_NOT_FREE_CNT - 1;
8255 dict_unref(dict);
8256}
8257
8258/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008259 * Clean up a list of internal variables.
Bram Moolenaar33570922005-01-25 22:26:29 +00008260 * Frees all allocated variables and the value they contain.
8261 * Clears hashtab "ht", does not free it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008262 */
8263 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008264vars_clear(hashtab_T *ht)
Bram Moolenaar33570922005-01-25 22:26:29 +00008265{
8266 vars_clear_ext(ht, TRUE);
8267}
8268
8269/*
8270 * Like vars_clear(), but only free the value if "free_val" is TRUE.
8271 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02008272 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008273vars_clear_ext(hashtab_T *ht, int free_val)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008274{
Bram Moolenaara7043832005-01-21 11:56:39 +00008275 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00008276 hashitem_T *hi;
8277 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008278
Bram Moolenaar33570922005-01-25 22:26:29 +00008279 hash_lock(ht);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008280 todo = (int)ht->ht_used;
Bram Moolenaara7043832005-01-21 11:56:39 +00008281 for (hi = ht->ht_array; todo > 0; ++hi)
8282 {
8283 if (!HASHITEM_EMPTY(hi))
8284 {
8285 --todo;
8286
Bram Moolenaar33570922005-01-25 22:26:29 +00008287 /* Free the variable. Don't remove it from the hashtab,
Bram Moolenaara7043832005-01-21 11:56:39 +00008288 * ht_array might change then. hash_clear() takes care of it
8289 * later. */
Bram Moolenaar33570922005-01-25 22:26:29 +00008290 v = HI2DI(hi);
8291 if (free_val)
8292 clear_tv(&v->di_tv);
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02008293 if (v->di_flags & DI_FLAGS_ALLOC)
Bram Moolenaar33570922005-01-25 22:26:29 +00008294 vim_free(v);
Bram Moolenaara7043832005-01-21 11:56:39 +00008295 }
8296 }
8297 hash_clear(ht);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00008298 ht->ht_used = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008299}
8300
Bram Moolenaara7043832005-01-21 11:56:39 +00008301/*
Bram Moolenaar33570922005-01-25 22:26:29 +00008302 * Delete a variable from hashtab "ht" at item "hi".
8303 * Clear the variable value and free the dictitem.
Bram Moolenaara7043832005-01-21 11:56:39 +00008304 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008305 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008306delete_var(hashtab_T *ht, hashitem_T *hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008307{
Bram Moolenaar33570922005-01-25 22:26:29 +00008308 dictitem_T *di = HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +00008309
8310 hash_remove(ht, hi);
Bram Moolenaar33570922005-01-25 22:26:29 +00008311 clear_tv(&di->di_tv);
8312 vim_free(di);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008313}
8314
8315/*
8316 * List the value of one internal variable.
8317 */
8318 static void
Bram Moolenaar32526b32019-01-19 17:43:09 +01008319list_one_var(dictitem_T *v, char *prefix, int *first)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008320{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008321 char_u *tofree;
8322 char_u *s;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008323 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008324
Bram Moolenaar520e1e42016-01-23 19:46:28 +01008325 s = echo_string(&v->di_tv, &tofree, numbuf, get_copyID());
Bram Moolenaar33570922005-01-25 22:26:29 +00008326 list_one_var_a(prefix, v->di_key, v->di_tv.v_type,
Bram Moolenaar7d61a922007-08-30 09:12:23 +00008327 s == NULL ? (char_u *)"" : s, first);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008328 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008329}
8330
Bram Moolenaar071d4272004-06-13 20:20:40 +00008331 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008332list_one_var_a(
Bram Moolenaar32526b32019-01-19 17:43:09 +01008333 char *prefix,
Bram Moolenaar7454a062016-01-30 15:14:10 +01008334 char_u *name,
8335 int type,
8336 char_u *string,
8337 int *first) /* when TRUE clear rest of screen and set to FALSE */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008338{
Bram Moolenaar31859182007-08-14 20:41:13 +00008339 /* don't use msg() or msg_attr() to avoid overwriting "v:statusmsg" */
8340 msg_start();
8341 msg_puts(prefix);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008342 if (name != NULL) /* "a:" vars don't have a name stored */
Bram Moolenaar32526b32019-01-19 17:43:09 +01008343 msg_puts((char *)name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008344 msg_putchar(' ');
8345 msg_advance(22);
8346 if (type == VAR_NUMBER)
8347 msg_putchar('#');
Bram Moolenaar1735bc92016-03-14 23:05:14 +01008348 else if (type == VAR_FUNC || type == VAR_PARTIAL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008349 msg_putchar('*');
8350 else if (type == VAR_LIST)
8351 {
8352 msg_putchar('[');
8353 if (*string == '[')
8354 ++string;
8355 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00008356 else if (type == VAR_DICT)
8357 {
8358 msg_putchar('{');
8359 if (*string == '{')
8360 ++string;
8361 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008362 else
8363 msg_putchar(' ');
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008364
Bram Moolenaar071d4272004-06-13 20:20:40 +00008365 msg_outtrans(string);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008366
Bram Moolenaar1735bc92016-03-14 23:05:14 +01008367 if (type == VAR_FUNC || type == VAR_PARTIAL)
Bram Moolenaar32526b32019-01-19 17:43:09 +01008368 msg_puts("()");
Bram Moolenaar7d61a922007-08-30 09:12:23 +00008369 if (*first)
8370 {
8371 msg_clr_eos();
8372 *first = FALSE;
8373 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008374}
8375
8376/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008377 * Set variable "name" to value in "tv".
Bram Moolenaar071d4272004-06-13 20:20:40 +00008378 * If the variable already exists, the value is updated.
8379 * Otherwise the variable is created.
8380 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008381 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008382set_var(
8383 char_u *name,
8384 typval_T *tv,
Bram Moolenaar9937a052019-06-15 15:45:06 +02008385 int copy) // make copy of value in "tv"
8386{
8387 set_var_const(name, tv, copy, FALSE);
8388}
8389
8390/*
8391 * Set variable "name" to value in "tv".
8392 * If the variable already exists and "is_const" is FALSE the value is updated.
8393 * Otherwise the variable is created.
8394 */
8395 static void
8396set_var_const(
8397 char_u *name,
8398 typval_T *tv,
8399 int copy, // make copy of value in "tv"
8400 int is_const) // disallow to modify existing variable
Bram Moolenaar071d4272004-06-13 20:20:40 +00008401{
Bram Moolenaar33570922005-01-25 22:26:29 +00008402 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008403 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +00008404 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008405
Bram Moolenaarbaff0fe2010-03-17 19:53:49 +01008406 ht = find_var_ht(name, &varname);
8407 if (ht == NULL || *varname == NUL)
8408 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008409 semsg(_(e_illvar), name);
Bram Moolenaarbaff0fe2010-03-17 19:53:49 +01008410 return;
8411 }
Bram Moolenaar332ac062013-04-15 13:06:21 +02008412 v = find_var_in_ht(ht, 0, varname, TRUE);
Bram Moolenaarbaff0fe2010-03-17 19:53:49 +01008413
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02008414 /* Search in parent scope which is possible to reference from lambda */
8415 if (v == NULL)
Bram Moolenaarba96e9a2016-08-01 17:10:20 +02008416 v = find_var_in_scoped_ht(name, TRUE);
Bram Moolenaar1e96d9b2016-07-29 22:15:09 +02008417
Bram Moolenaar1735bc92016-03-14 23:05:14 +01008418 if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL)
8419 && var_check_func_name(name, v == NULL))
Bram Moolenaar4228bec2011-03-27 16:03:15 +02008420 return;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008421
Bram Moolenaar33570922005-01-25 22:26:29 +00008422 if (v != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008423 {
Bram Moolenaar9937a052019-06-15 15:45:06 +02008424 if (is_const)
8425 {
8426 emsg(_(e_cannot_mod));
8427 return;
8428 }
8429
Bram Moolenaar33570922005-01-25 22:26:29 +00008430 /* existing variable, need to clear the value */
Bram Moolenaar77354e72015-04-21 16:49:05 +02008431 if (var_check_ro(v->di_flags, name, FALSE)
Bram Moolenaar05c00c02019-02-11 22:00:11 +01008432 || var_check_lock(v->di_tv.v_lock, name, FALSE))
Bram Moolenaar33570922005-01-25 22:26:29 +00008433 return;
Bram Moolenaar33570922005-01-25 22:26:29 +00008434
8435 /*
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02008436 * Handle setting internal v: variables separately where needed to
8437 * prevent changing the type.
Bram Moolenaar33570922005-01-25 22:26:29 +00008438 */
8439 if (ht == &vimvarht)
8440 {
8441 if (v->di_tv.v_type == VAR_STRING)
8442 {
Bram Moolenaar4b9e91f2019-01-24 13:58:11 +01008443 VIM_CLEAR(v->di_tv.vval.v_string);
Bram Moolenaar33570922005-01-25 22:26:29 +00008444 if (copy || tv->v_type != VAR_STRING)
Bram Moolenaar4b9e91f2019-01-24 13:58:11 +01008445 {
8446 char_u *val = tv_get_string(tv);
8447
8448 // Careful: when assigning to v:errmsg and tv_get_string()
8449 // causes an error message the variable will alrady be set.
8450 if (v->di_tv.vval.v_string == NULL)
8451 v->di_tv.vval.v_string = vim_strsave(val);
8452 }
Bram Moolenaar33570922005-01-25 22:26:29 +00008453 else
8454 {
8455 /* Take over the string to avoid an extra alloc/free. */
8456 v->di_tv.vval.v_string = tv->vval.v_string;
8457 tv->vval.v_string = NULL;
8458 }
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02008459 return;
Bram Moolenaar33570922005-01-25 22:26:29 +00008460 }
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02008461 else if (v->di_tv.v_type == VAR_NUMBER)
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008462 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008463 v->di_tv.vval.v_number = tv_get_number(tv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008464 if (STRCMP(varname, "searchforward") == 0)
8465 set_search_direction(v->di_tv.vval.v_number ? '/' : '?');
Bram Moolenaar8050efa2013-11-08 04:30:20 +01008466#ifdef FEAT_SEARCH_EXTRA
8467 else if (STRCMP(varname, "hlsearch") == 0)
8468 {
8469 no_hlsearch = !v->di_tv.vval.v_number;
8470 redraw_all_later(SOME_VALID);
8471 }
8472#endif
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02008473 return;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008474 }
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02008475 else if (v->di_tv.v_type != tv->v_type)
Bram Moolenaar88b53fd2018-12-05 18:43:28 +01008476 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008477 semsg(_("E963: setting %s to value with wrong type"), name);
Bram Moolenaar88b53fd2018-12-05 18:43:28 +01008478 return;
8479 }
Bram Moolenaar33570922005-01-25 22:26:29 +00008480 }
8481
8482 clear_tv(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008483 }
8484 else /* add a new variable */
8485 {
Bram Moolenaar31b81602019-02-10 22:14:27 +01008486 // Can't add "v:" or "a:" variable.
8487 if (ht == &vimvarht || ht == get_funccal_args_ht())
Bram Moolenaar5fcc3fe2006-06-22 15:35:14 +00008488 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008489 semsg(_(e_illvar), name);
Bram Moolenaar5fcc3fe2006-06-22 15:35:14 +00008490 return;
8491 }
8492
Bram Moolenaar31b81602019-02-10 22:14:27 +01008493 // Make sure the variable name is valid.
Bram Moolenaar4228bec2011-03-27 16:03:15 +02008494 if (!valid_varname(varname))
8495 return;
Bram Moolenaar92124a32005-06-17 22:03:40 +00008496
Bram Moolenaarc799fe22019-05-28 23:08:19 +02008497 v = alloc(sizeof(dictitem_T) + STRLEN(varname));
Bram Moolenaara7043832005-01-21 11:56:39 +00008498 if (v == NULL)
8499 return;
Bram Moolenaar33570922005-01-25 22:26:29 +00008500 STRCPY(v->di_key, varname);
Bram Moolenaar33570922005-01-25 22:26:29 +00008501 if (hash_add(ht, DI2HIKEY(v)) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008502 {
Bram Moolenaara7043832005-01-21 11:56:39 +00008503 vim_free(v);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008504 return;
8505 }
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02008506 v->di_flags = DI_FLAGS_ALLOC;
Bram Moolenaar9937a052019-06-15 15:45:06 +02008507 if (is_const)
8508 v->di_flags |= DI_FLAGS_LOCK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008509 }
Bram Moolenaara7043832005-01-21 11:56:39 +00008510
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008511 if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT)
Bram Moolenaar33570922005-01-25 22:26:29 +00008512 copy_tv(tv, &v->di_tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +00008513 else
8514 {
Bram Moolenaar33570922005-01-25 22:26:29 +00008515 v->di_tv = *tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008516 v->di_tv.v_lock = 0;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008517 init_tv(tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +00008518 }
Bram Moolenaar9937a052019-06-15 15:45:06 +02008519
8520 if (is_const)
8521 v->di_tv.v_lock |= VAR_LOCKED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008522}
8523
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008524/*
Bram Moolenaar4e957af2006-09-02 11:41:07 +00008525 * Return TRUE if di_flags "flags" indicates variable "name" is read-only.
Bram Moolenaar33570922005-01-25 22:26:29 +00008526 * Also give an error message.
8527 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02008528 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01008529var_check_ro(int flags, char_u *name, int use_gettext)
Bram Moolenaar33570922005-01-25 22:26:29 +00008530{
8531 if (flags & DI_FLAGS_RO)
8532 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008533 semsg(_(e_readonlyvar), use_gettext ? (char_u *)_(name) : name);
Bram Moolenaar33570922005-01-25 22:26:29 +00008534 return TRUE;
8535 }
8536 if ((flags & DI_FLAGS_RO_SBX) && sandbox)
8537 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008538 semsg(_(e_readonlysbx), use_gettext ? (char_u *)_(name) : name);
Bram Moolenaar33570922005-01-25 22:26:29 +00008539 return TRUE;
8540 }
8541 return FALSE;
8542}
8543
8544/*
Bram Moolenaar4e957af2006-09-02 11:41:07 +00008545 * Return TRUE if di_flags "flags" indicates variable "name" is fixed.
8546 * Also give an error message.
8547 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008548 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01008549var_check_fixed(int flags, char_u *name, int use_gettext)
Bram Moolenaar4e957af2006-09-02 11:41:07 +00008550{
8551 if (flags & DI_FLAGS_FIX)
8552 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008553 semsg(_("E795: Cannot delete variable %s"),
Bram Moolenaar77354e72015-04-21 16:49:05 +02008554 use_gettext ? (char_u *)_(name) : name);
Bram Moolenaar4e957af2006-09-02 11:41:07 +00008555 return TRUE;
8556 }
8557 return FALSE;
8558}
8559
8560/*
Bram Moolenaar4228bec2011-03-27 16:03:15 +02008561 * Check if a funcref is assigned to a valid variable name.
8562 * Return TRUE and give an error if not.
8563 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02008564 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01008565var_check_func_name(
8566 char_u *name, /* points to start of variable name */
8567 int new_var) /* TRUE when creating the variable */
Bram Moolenaar4228bec2011-03-27 16:03:15 +02008568{
Bram Moolenaarcbc67722014-05-22 14:19:56 +02008569 /* Allow for w: b: s: and t:. */
8570 if (!(vim_strchr((char_u *)"wbst", name[0]) != NULL && name[1] == ':')
Bram Moolenaar4228bec2011-03-27 16:03:15 +02008571 && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
8572 ? name[2] : name[0]))
8573 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008574 semsg(_("E704: Funcref variable name must start with a capital: %s"),
Bram Moolenaar4228bec2011-03-27 16:03:15 +02008575 name);
8576 return TRUE;
8577 }
8578 /* Don't allow hiding a function. When "v" is not NULL we might be
8579 * assigning another function to the same var, the type is checked
8580 * below. */
Bram Moolenaarb54c3ff2016-07-31 14:11:58 +02008581 if (new_var && function_exists(name, FALSE))
Bram Moolenaar4228bec2011-03-27 16:03:15 +02008582 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008583 semsg(_("E705: Variable name conflicts with existing function: %s"),
Bram Moolenaar4228bec2011-03-27 16:03:15 +02008584 name);
8585 return TRUE;
8586 }
8587 return FALSE;
8588}
8589
8590/*
Bram Moolenaar05c00c02019-02-11 22:00:11 +01008591 * Return TRUE if "flags" indicates variable "name" is locked (immutable).
Bram Moolenaar77354e72015-04-21 16:49:05 +02008592 * Also give an error message, using "name" or _("name") when use_gettext is
8593 * TRUE.
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008594 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02008595 int
Bram Moolenaar05c00c02019-02-11 22:00:11 +01008596var_check_lock(int lock, char_u *name, int use_gettext)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008597{
8598 if (lock & VAR_LOCKED)
8599 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008600 semsg(_("E741: Value is locked: %s"),
Bram Moolenaar77354e72015-04-21 16:49:05 +02008601 name == NULL ? (char_u *)_("Unknown")
8602 : use_gettext ? (char_u *)_(name)
8603 : name);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008604 return TRUE;
8605 }
8606 if (lock & VAR_FIXED)
8607 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008608 semsg(_("E742: Cannot change value of %s"),
Bram Moolenaar77354e72015-04-21 16:49:05 +02008609 name == NULL ? (char_u *)_("Unknown")
8610 : use_gettext ? (char_u *)_(name)
8611 : name);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008612 return TRUE;
8613 }
8614 return FALSE;
8615}
8616
8617/*
Bram Moolenaar05c00c02019-02-11 22:00:11 +01008618 * Return TRUE if typeval "tv" and its value are set to be locked (immutable).
8619 * Also give an error message, using "name" or _("name") when use_gettext is
8620 * TRUE.
8621 */
8622 static int
8623tv_check_lock(typval_T *tv, char_u *name, int use_gettext)
8624{
8625 int lock = 0;
8626
8627 switch (tv->v_type)
8628 {
8629 case VAR_BLOB:
8630 if (tv->vval.v_blob != NULL)
8631 lock = tv->vval.v_blob->bv_lock;
8632 break;
8633 case VAR_LIST:
8634 if (tv->vval.v_list != NULL)
8635 lock = tv->vval.v_list->lv_lock;
8636 break;
8637 case VAR_DICT:
8638 if (tv->vval.v_dict != NULL)
8639 lock = tv->vval.v_dict->dv_lock;
8640 break;
8641 default:
8642 break;
8643 }
8644 return var_check_lock(tv->v_lock, name, use_gettext)
8645 || (lock != 0 && var_check_lock(lock, name, use_gettext));
8646}
8647
8648/*
8649 * Check if a variable name is valid.
8650 * Return FALSE and give an error if not.
8651 */
8652 int
8653valid_varname(char_u *varname)
8654{
8655 char_u *p;
8656
8657 for (p = varname; *p != NUL; ++p)
8658 if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p))
8659 && *p != AUTOLOAD_CHAR)
8660 {
8661 semsg(_(e_illvar), varname);
8662 return FALSE;
8663 }
8664 return TRUE;
8665}
8666
8667/*
Bram Moolenaar33570922005-01-25 22:26:29 +00008668 * Copy the values from typval_T "from" to typval_T "to".
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008669 * When needed allocates string or increases reference count.
Bram Moolenaardd29ea12019-01-23 21:56:21 +01008670 * Does not make a copy of a list, blob or dict but copies the reference!
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +00008671 * It is OK for "from" and "to" to point to the same item. This is used to
8672 * make a copy later.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008673 */
Bram Moolenaar7e506b62010-01-19 15:55:06 +01008674 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008675copy_tv(typval_T *from, typval_T *to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008676{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008677 to->v_type = from->v_type;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008678 to->v_lock = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008679 switch (from->v_type)
8680 {
8681 case VAR_NUMBER:
Bram Moolenaar520e1e42016-01-23 19:46:28 +01008682 case VAR_SPECIAL:
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008683 to->vval.v_number = from->vval.v_number;
8684 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008685 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01008686#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008687 to->vval.v_float = from->vval.v_float;
8688 break;
8689#endif
Bram Moolenaar835dc632016-02-07 14:27:38 +01008690 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01008691#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +01008692 to->vval.v_job = from->vval.v_job;
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01008693 if (to->vval.v_job != NULL)
8694 ++to->vval.v_job->jv_refcount;
Bram Moolenaar835dc632016-02-07 14:27:38 +01008695 break;
8696#endif
Bram Moolenaar77073442016-02-13 23:23:53 +01008697 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01008698#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +01008699 to->vval.v_channel = from->vval.v_channel;
Bram Moolenaar5cefd402016-02-16 12:44:26 +01008700 if (to->vval.v_channel != NULL)
8701 ++to->vval.v_channel->ch_refcount;
Bram Moolenaar77073442016-02-13 23:23:53 +01008702 break;
8703#endif
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008704 case VAR_STRING:
8705 case VAR_FUNC:
8706 if (from->vval.v_string == NULL)
8707 to->vval.v_string = NULL;
8708 else
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00008709 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008710 to->vval.v_string = vim_strsave(from->vval.v_string);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00008711 if (from->v_type == VAR_FUNC)
8712 func_ref(to->vval.v_string);
8713 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008714 break;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01008715 case VAR_PARTIAL:
8716 if (from->vval.v_partial == NULL)
8717 to->vval.v_partial = NULL;
8718 else
8719 {
8720 to->vval.v_partial = from->vval.v_partial;
8721 ++to->vval.v_partial->pt_refcount;
8722 }
8723 break;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01008724 case VAR_BLOB:
8725 if (from->vval.v_blob == NULL)
8726 to->vval.v_blob = NULL;
8727 else
8728 {
8729 to->vval.v_blob = from->vval.v_blob;
8730 ++to->vval.v_blob->bv_refcount;
8731 }
8732 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008733 case VAR_LIST:
8734 if (from->vval.v_list == NULL)
8735 to->vval.v_list = NULL;
8736 else
8737 {
8738 to->vval.v_list = from->vval.v_list;
8739 ++to->vval.v_list->lv_refcount;
8740 }
8741 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00008742 case VAR_DICT:
8743 if (from->vval.v_dict == NULL)
8744 to->vval.v_dict = NULL;
8745 else
8746 {
8747 to->vval.v_dict = from->vval.v_dict;
8748 ++to->vval.v_dict->dv_refcount;
8749 }
8750 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +01008751 case VAR_UNKNOWN:
Bram Moolenaar95f09602016-11-10 20:01:45 +01008752 internal_error("copy_tv(UNKNOWN)");
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008753 break;
8754 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008755}
8756
8757/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00008758 * Make a copy of an item.
8759 * Lists and Dictionaries are also copied. A deep copy if "deep" is set.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008760 * For deepcopy() "copyID" is zero for a full copy or the ID for when a
8761 * reference to an already copied list/dict can be used.
8762 * Returns FAIL or OK.
Bram Moolenaare9a41262005-01-15 22:18:47 +00008763 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02008764 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01008765item_copy(
8766 typval_T *from,
8767 typval_T *to,
8768 int deep,
8769 int copyID)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008770{
8771 static int recurse = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008772 int ret = OK;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008773
Bram Moolenaar33570922005-01-25 22:26:29 +00008774 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008775 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008776 emsg(_("E698: variable nested too deep for making a copy"));
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008777 return FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008778 }
8779 ++recurse;
8780
8781 switch (from->v_type)
8782 {
8783 case VAR_NUMBER:
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008784 case VAR_FLOAT:
Bram Moolenaare9a41262005-01-15 22:18:47 +00008785 case VAR_STRING:
8786 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01008787 case VAR_PARTIAL:
Bram Moolenaar15550002016-01-31 18:45:24 +01008788 case VAR_SPECIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01008789 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01008790 case VAR_CHANNEL:
Bram Moolenaare9a41262005-01-15 22:18:47 +00008791 copy_tv(from, to);
8792 break;
8793 case VAR_LIST:
8794 to->v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008795 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008796 if (from->vval.v_list == NULL)
8797 to->vval.v_list = NULL;
8798 else if (copyID != 0 && from->vval.v_list->lv_copyID == copyID)
8799 {
8800 /* use the copy made earlier */
8801 to->vval.v_list = from->vval.v_list->lv_copylist;
8802 ++to->vval.v_list->lv_refcount;
8803 }
8804 else
8805 to->vval.v_list = list_copy(from->vval.v_list, deep, copyID);
8806 if (to->vval.v_list == NULL)
8807 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008808 break;
Bram Moolenaar3d28b582019-01-15 22:44:17 +01008809 case VAR_BLOB:
Bram Moolenaardd29ea12019-01-23 21:56:21 +01008810 ret = blob_copy(from, to);
Bram Moolenaar3d28b582019-01-15 22:44:17 +01008811 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008812 case VAR_DICT:
8813 to->v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008814 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008815 if (from->vval.v_dict == NULL)
8816 to->vval.v_dict = NULL;
8817 else if (copyID != 0 && from->vval.v_dict->dv_copyID == copyID)
8818 {
8819 /* use the copy made earlier */
8820 to->vval.v_dict = from->vval.v_dict->dv_copydict;
8821 ++to->vval.v_dict->dv_refcount;
8822 }
8823 else
8824 to->vval.v_dict = dict_copy(from->vval.v_dict, deep, copyID);
8825 if (to->vval.v_dict == NULL)
8826 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008827 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +01008828 case VAR_UNKNOWN:
Bram Moolenaar95f09602016-11-10 20:01:45 +01008829 internal_error("item_copy(UNKNOWN)");
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008830 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008831 }
8832 --recurse;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008833 return ret;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008834}
8835
8836/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008837 * This function is used by f_input() and f_inputdialog() functions. The third
8838 * argument to f_input() specifies the type of completion to use at the
8839 * prompt. The third argument to f_inputdialog() specifies the value to return
8840 * when the user cancels the prompt.
8841 */
8842 void
8843get_user_input(
8844 typval_T *argvars,
8845 typval_T *rettv,
8846 int inputdialog,
8847 int secret)
8848{
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008849 char_u *prompt = tv_get_string_chk(&argvars[0]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008850 char_u *p = NULL;
8851 int c;
8852 char_u buf[NUMBUFLEN];
8853 int cmd_silent_save = cmd_silent;
8854 char_u *defstr = (char_u *)"";
8855 int xp_type = EXPAND_NOTHING;
8856 char_u *xp_arg = NULL;
8857
8858 rettv->v_type = VAR_STRING;
8859 rettv->vval.v_string = NULL;
8860
8861#ifdef NO_CONSOLE_INPUT
Bram Moolenaar91d348a2017-07-29 20:16:03 +02008862 /* While starting up, there is no place to enter text. When running tests
8863 * with --not-a-term we assume feedkeys() will be used. */
8864 if (no_console_input() && !is_not_a_term())
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008865 return;
8866#endif
8867
8868 cmd_silent = FALSE; /* Want to see the prompt. */
8869 if (prompt != NULL)
8870 {
8871 /* Only the part of the message after the last NL is considered as
8872 * prompt for the command line */
8873 p = vim_strrchr(prompt, '\n');
8874 if (p == NULL)
8875 p = prompt;
8876 else
8877 {
8878 ++p;
8879 c = *p;
8880 *p = NUL;
8881 msg_start();
8882 msg_clr_eos();
Bram Moolenaar32526b32019-01-19 17:43:09 +01008883 msg_puts_attr((char *)prompt, echo_attr);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008884 msg_didout = FALSE;
8885 msg_starthere();
8886 *p = c;
8887 }
8888 cmdline_row = msg_row;
8889
8890 if (argvars[1].v_type != VAR_UNKNOWN)
8891 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008892 defstr = tv_get_string_buf_chk(&argvars[1], buf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008893 if (defstr != NULL)
8894 stuffReadbuffSpec(defstr);
8895
8896 if (!inputdialog && argvars[2].v_type != VAR_UNKNOWN)
8897 {
8898 char_u *xp_name;
8899 int xp_namelen;
8900 long argt;
8901
8902 /* input() with a third argument: completion */
8903 rettv->vval.v_string = NULL;
8904
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008905 xp_name = tv_get_string_buf_chk(&argvars[2], buf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008906 if (xp_name == NULL)
8907 return;
8908
8909 xp_namelen = (int)STRLEN(xp_name);
8910
8911 if (parse_compl_arg(xp_name, xp_namelen, &xp_type, &argt,
8912 &xp_arg) == FAIL)
8913 return;
8914 }
8915 }
8916
8917 if (defstr != NULL)
8918 {
8919 int save_ex_normal_busy = ex_normal_busy;
Bram Moolenaar6dff58f2018-09-30 21:43:26 +02008920
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008921 ex_normal_busy = 0;
8922 rettv->vval.v_string =
8923 getcmdline_prompt(secret ? NUL : '@', p, echo_attr,
8924 xp_type, xp_arg);
8925 ex_normal_busy = save_ex_normal_busy;
8926 }
8927 if (inputdialog && rettv->vval.v_string == NULL
8928 && argvars[1].v_type != VAR_UNKNOWN
8929 && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaard155d7a2018-12-21 16:04:21 +01008930 rettv->vval.v_string = vim_strsave(tv_get_string_buf(
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02008931 &argvars[2], buf));
8932
8933 vim_free(xp_arg);
8934
8935 /* since the user typed this, no need to wait for return */
8936 need_wait_return = FALSE;
8937 msg_didout = FALSE;
8938 }
8939 cmd_silent = cmd_silent_save;
8940}
8941
8942/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008943 * ":echo expr1 ..." print each argument separated with a space, add a
8944 * newline at the end.
8945 * ":echon expr1 ..." print each argument plain.
8946 */
8947 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008948ex_echo(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008949{
8950 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00008951 typval_T rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008952 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008953 char_u *p;
8954 int needclr = TRUE;
8955 int atstart = TRUE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008956 char_u numbuf[NUMBUFLEN];
Bram Moolenaar76a63452018-11-28 20:38:37 +01008957 int did_emsg_before = did_emsg;
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01008958 int called_emsg_before = called_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008959
8960 if (eap->skip)
8961 ++emsg_skip;
8962 while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int)
8963 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008964 /* If eval1() causes an error message the text from the command may
8965 * still need to be cleared. E.g., "echo 22,44". */
8966 need_clr_eos = needclr;
8967
Bram Moolenaar071d4272004-06-13 20:20:40 +00008968 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008969 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008970 {
8971 /*
8972 * Report the invalid expression unless the expression evaluation
8973 * has been cancelled due to an aborting error, an interrupt, or an
8974 * exception.
8975 */
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01008976 if (!aborting() && did_emsg == did_emsg_before
8977 && called_emsg == called_emsg_before)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01008978 semsg(_(e_invexpr2), p);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008979 need_clr_eos = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008980 break;
8981 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008982 need_clr_eos = FALSE;
8983
Bram Moolenaar071d4272004-06-13 20:20:40 +00008984 if (!eap->skip)
8985 {
8986 if (atstart)
8987 {
8988 atstart = FALSE;
8989 /* Call msg_start() after eval1(), evaluating the expression
8990 * may cause a message to appear. */
8991 if (eap->cmdidx == CMD_echo)
Bram Moolenaar12b02902012-03-23 15:18:24 +01008992 {
Bram Moolenaar6df5e5a2012-03-28 16:49:29 +02008993 /* Mark the saved text as finishing the line, so that what
8994 * follows is displayed on a new line when scrolling back
8995 * at the more prompt. */
8996 msg_sb_eol();
Bram Moolenaar071d4272004-06-13 20:20:40 +00008997 msg_start();
Bram Moolenaar12b02902012-03-23 15:18:24 +01008998 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008999 }
9000 else if (eap->cmdidx == CMD_echo)
Bram Moolenaar32526b32019-01-19 17:43:09 +01009001 msg_puts_attr(" ", echo_attr);
Bram Moolenaar520e1e42016-01-23 19:46:28 +01009002 p = echo_string(&rettv, &tofree, numbuf, get_copyID());
Bram Moolenaar81bf7082005-02-12 14:31:42 +00009003 if (p != NULL)
9004 for ( ; *p != NUL && !got_int; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009005 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00009006 if (*p == '\n' || *p == '\r' || *p == TAB)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009007 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00009008 if (*p != TAB && needclr)
9009 {
9010 /* remove any text still there from the command */
9011 msg_clr_eos();
9012 needclr = FALSE;
9013 }
9014 msg_putchar_attr(*p, echo_attr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009015 }
9016 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +00009017 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00009018 if (has_mbyte)
9019 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00009020 int i = (*mb_ptr2len)(p);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00009021
9022 (void)msg_outtrans_len_attr(p, i, echo_attr);
9023 p += i - 1;
9024 }
9025 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +00009026 (void)msg_outtrans_len_attr(p, 1, echo_attr);
9027 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009028 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009029 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009030 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009031 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009032 arg = skipwhite(arg);
9033 }
9034 eap->nextcmd = check_nextcmd(arg);
9035
9036 if (eap->skip)
9037 --emsg_skip;
9038 else
9039 {
9040 /* remove text that may still be there from the command */
9041 if (needclr)
9042 msg_clr_eos();
9043 if (eap->cmdidx == CMD_echo)
9044 msg_end();
9045 }
9046}
9047
9048/*
9049 * ":echohl {name}".
9050 */
9051 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009052ex_echohl(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009053{
Bram Moolenaar1b9645d2017-09-17 23:03:31 +02009054 echo_attr = syn_name2attr(eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009055}
9056
9057/*
9058 * ":execute expr1 ..." execute the result of an expression.
9059 * ":echomsg expr1 ..." Print a message
9060 * ":echoerr expr1 ..." Print an error
9061 * Each gets spaces around each argument and a newline at the end for
9062 * echo commands
9063 */
9064 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009065ex_execute(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009066{
9067 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00009068 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009069 int ret = OK;
9070 char_u *p;
9071 garray_T ga;
9072 int len;
Bram Moolenaar2c519cf2019-03-21 21:45:34 +01009073 int save_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009074
9075 ga_init2(&ga, 1, 80);
9076
9077 if (eap->skip)
9078 ++emsg_skip;
9079 while (*arg != NUL && *arg != '|' && *arg != '\n')
9080 {
Bram Moolenaarce9d50d2019-01-14 22:22:29 +01009081 ret = eval1_emsg(&arg, &rettv, !eap->skip);
9082 if (ret == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009083 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009084
9085 if (!eap->skip)
9086 {
Bram Moolenaar461a7fc2018-12-22 13:28:07 +01009087 char_u buf[NUMBUFLEN];
9088
9089 if (eap->cmdidx == CMD_execute)
9090 p = tv_get_string_buf(&rettv, buf);
9091 else
9092 p = tv_stringify(&rettv, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009093 len = (int)STRLEN(p);
9094 if (ga_grow(&ga, len + 2) == FAIL)
9095 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009096 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009097 ret = FAIL;
9098 break;
9099 }
9100 if (ga.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009101 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
Bram Moolenaar071d4272004-06-13 20:20:40 +00009102 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009103 ga.ga_len += len;
9104 }
9105
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009106 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009107 arg = skipwhite(arg);
9108 }
9109
9110 if (ret != FAIL && ga.ga_data != NULL)
9111 {
Bram Moolenaar57002ad2017-03-16 19:04:19 +01009112 if (eap->cmdidx == CMD_echomsg || eap->cmdidx == CMD_echoerr)
9113 {
9114 /* Mark the already saved text as finishing the line, so that what
9115 * follows is displayed on a new line when scrolling back at the
9116 * more prompt. */
9117 msg_sb_eol();
Bram Moolenaar57002ad2017-03-16 19:04:19 +01009118 }
9119
Bram Moolenaar071d4272004-06-13 20:20:40 +00009120 if (eap->cmdidx == CMD_echomsg)
Bram Moolenaar4770d092006-01-12 23:22:24 +00009121 {
Bram Moolenaar32526b32019-01-19 17:43:09 +01009122 msg_attr(ga.ga_data, echo_attr);
Bram Moolenaar4770d092006-01-12 23:22:24 +00009123 out_flush();
9124 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009125 else if (eap->cmdidx == CMD_echoerr)
9126 {
9127 /* We don't want to abort following commands, restore did_emsg. */
9128 save_did_emsg = did_emsg;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01009129 emsg(ga.ga_data);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009130 if (!force_abort)
9131 did_emsg = save_did_emsg;
9132 }
9133 else if (eap->cmdidx == CMD_execute)
9134 do_cmdline((char_u *)ga.ga_data,
9135 eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE);
9136 }
9137
9138 ga_clear(&ga);
9139
9140 if (eap->skip)
9141 --emsg_skip;
9142
9143 eap->nextcmd = check_nextcmd(arg);
9144}
9145
9146/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009147 * Find window specified by "vp" in tabpage "tp".
9148 */
9149 win_T *
9150find_win_by_nr(
9151 typval_T *vp,
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009152 tabpage_T *tp) /* NULL for current tab page */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009153{
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009154 win_T *wp;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009155 int nr = (int)tv_get_number_chk(vp, NULL);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009156
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009157 if (nr < 0)
9158 return NULL;
9159 if (nr == 0)
9160 return curwin;
9161
Bram Moolenaar29323592016-07-24 22:04:11 +02009162 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
9163 {
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009164 if (nr >= LOWEST_WIN_ID)
9165 {
9166 if (wp->w_id == nr)
9167 return wp;
9168 }
9169 else if (--nr <= 0)
9170 break;
Bram Moolenaar29323592016-07-24 22:04:11 +02009171 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009172 if (nr >= LOWEST_WIN_ID)
Bram Moolenaar4d784b22019-05-25 19:51:39 +02009173 {
9174#ifdef FEAT_TEXT_PROP
Bram Moolenaar9c27b1c2019-05-26 18:48:13 +02009175 // check tab-local popup windows
9176 for (wp = tp->tp_first_popupwin; wp != NULL; wp = wp->w_next)
Bram Moolenaar4d784b22019-05-25 19:51:39 +02009177 if (wp->w_id == nr)
9178 return wp;
Bram Moolenaar9c27b1c2019-05-26 18:48:13 +02009179 // check global popup windows
Bram Moolenaar4d784b22019-05-25 19:51:39 +02009180 for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
9181 if (wp->w_id == nr)
9182 return wp;
9183#endif
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009184 return NULL;
Bram Moolenaar4d784b22019-05-25 19:51:39 +02009185 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009186 return wp;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009187}
9188
9189/*
Bram Moolenaare6e39892018-10-25 12:32:11 +02009190 * Find a window: When using a Window ID in any tab page, when using a number
9191 * in the current tab page.
9192 */
9193 win_T *
9194find_win_by_nr_or_id(typval_T *vp)
9195{
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009196 int nr = (int)tv_get_number_chk(vp, NULL);
Bram Moolenaare6e39892018-10-25 12:32:11 +02009197
9198 if (nr >= LOWEST_WIN_ID)
Bram Moolenaareeb1b9c2019-02-10 22:59:04 +01009199 return win_id2wp(tv_get_number(vp));
Bram Moolenaare6e39892018-10-25 12:32:11 +02009200 return find_win_by_nr(vp, NULL);
9201}
9202
9203/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009204 * Find window specified by "wvp" in tabpage "tvp".
Bram Moolenaar00aa0692019-04-27 20:37:57 +02009205 * Returns the tab page in 'ptp'
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009206 */
9207 win_T *
9208find_tabwin(
Bram Moolenaar00aa0692019-04-27 20:37:57 +02009209 typval_T *wvp, // VAR_UNKNOWN for current window
9210 typval_T *tvp, // VAR_UNKNOWN for current tab page
9211 tabpage_T **ptp)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009212{
9213 win_T *wp = NULL;
9214 tabpage_T *tp = NULL;
9215 long n;
9216
9217 if (wvp->v_type != VAR_UNKNOWN)
9218 {
9219 if (tvp->v_type != VAR_UNKNOWN)
9220 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009221 n = (long)tv_get_number(tvp);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009222 if (n >= 0)
9223 tp = find_tabpage(n);
9224 }
9225 else
9226 tp = curtab;
9227
9228 if (tp != NULL)
Bram Moolenaar00aa0692019-04-27 20:37:57 +02009229 {
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009230 wp = find_win_by_nr(wvp, tp);
Bram Moolenaar00aa0692019-04-27 20:37:57 +02009231 if (wp == NULL && wvp->v_type == VAR_NUMBER
9232 && wvp->vval.v_number != -1)
9233 // A window with the specified number is not found
9234 tp = NULL;
9235 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009236 }
9237 else
Bram Moolenaar00aa0692019-04-27 20:37:57 +02009238 {
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009239 wp = curwin;
Bram Moolenaar00aa0692019-04-27 20:37:57 +02009240 tp = curtab;
9241 }
9242
9243 if (ptp != NULL)
9244 *ptp = tp;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009245
9246 return wp;
9247}
9248
9249/*
9250 * getwinvar() and gettabwinvar()
9251 */
9252 void
9253getwinvar(
9254 typval_T *argvars,
9255 typval_T *rettv,
9256 int off) /* 1 for gettabwinvar() */
9257{
9258 win_T *win;
9259 char_u *varname;
9260 dictitem_T *v;
9261 tabpage_T *tp = NULL;
9262 int done = FALSE;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009263 win_T *oldcurwin;
9264 tabpage_T *oldtabpage;
9265 int need_switch_win;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009266
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009267 if (off == 1)
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009268 tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009269 else
9270 tp = curtab;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009271 win = find_win_by_nr(&argvars[off], tp);
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009272 varname = tv_get_string_chk(&argvars[off + 1]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009273 ++emsg_off;
9274
9275 rettv->v_type = VAR_STRING;
9276 rettv->vval.v_string = NULL;
9277
9278 if (win != NULL && varname != NULL)
9279 {
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009280 /* Set curwin to be our win, temporarily. Also set the tabpage,
9281 * otherwise the window is not valid. Only do this when needed,
9282 * autocommands get blocked. */
9283 need_switch_win = !(tp == curtab && win == curwin);
9284 if (!need_switch_win
9285 || switch_win(&oldcurwin, &oldtabpage, win, tp, TRUE) == OK)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009286 {
Bram Moolenaar30567352016-08-27 21:25:44 +02009287 if (*varname == '&')
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009288 {
Bram Moolenaar30567352016-08-27 21:25:44 +02009289 if (varname[1] == NUL)
9290 {
9291 /* get all window-local options in a dict */
9292 dict_T *opts = get_winbuf_options(FALSE);
9293
9294 if (opts != NULL)
9295 {
Bram Moolenaar45cf6e92017-04-30 20:25:19 +02009296 rettv_dict_set(rettv, opts);
Bram Moolenaar30567352016-08-27 21:25:44 +02009297 done = TRUE;
9298 }
9299 }
9300 else if (get_option_tv(&varname, rettv, 1) == OK)
9301 /* window-local-option */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009302 done = TRUE;
9303 }
9304 else
9305 {
9306 /* Look up the variable. */
9307 /* Let getwinvar({nr}, "") return the "w:" dictionary. */
9308 v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w',
9309 varname, FALSE);
9310 if (v != NULL)
9311 {
9312 copy_tv(&v->di_tv, rettv);
9313 done = TRUE;
9314 }
9315 }
9316 }
9317
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009318 if (need_switch_win)
9319 /* restore previous notion of curwin */
9320 restore_win(oldcurwin, oldtabpage, TRUE);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009321 }
9322
9323 if (!done && argvars[off + 2].v_type != VAR_UNKNOWN)
9324 /* use the default return value */
9325 copy_tv(&argvars[off + 2], rettv);
9326
9327 --emsg_off;
9328}
9329
9330/*
9331 * "setwinvar()" and "settabwinvar()" functions
9332 */
9333 void
9334setwinvar(typval_T *argvars, typval_T *rettv UNUSED, int off)
9335{
9336 win_T *win;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009337 win_T *save_curwin;
9338 tabpage_T *save_curtab;
9339 int need_switch_win;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009340 char_u *varname, *winvarname;
9341 typval_T *varp;
9342 char_u nbuf[NUMBUFLEN];
9343 tabpage_T *tp = NULL;
9344
Bram Moolenaare0fb7d12019-02-12 20:48:10 +01009345 if (check_secure())
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009346 return;
9347
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009348 if (off == 1)
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009349 tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009350 else
9351 tp = curtab;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009352 win = find_win_by_nr(&argvars[off], tp);
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009353 varname = tv_get_string_chk(&argvars[off + 1]);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009354 varp = &argvars[off + 2];
9355
9356 if (win != NULL && varname != NULL && varp != NULL)
9357 {
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009358 need_switch_win = !(tp == curtab && win == curwin);
9359 if (!need_switch_win
9360 || switch_win(&save_curwin, &save_curtab, win, tp, TRUE) == OK)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009361 {
9362 if (*varname == '&')
9363 {
9364 long numval;
9365 char_u *strval;
9366 int error = FALSE;
9367
9368 ++varname;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009369 numval = (long)tv_get_number_chk(varp, &error);
9370 strval = tv_get_string_buf_chk(varp, nbuf);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009371 if (!error && strval != NULL)
9372 set_option_value(varname, numval, strval, OPT_LOCAL);
9373 }
9374 else
9375 {
Bram Moolenaar964b3742019-05-24 18:54:09 +02009376 winvarname = alloc(STRLEN(varname) + 3);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009377 if (winvarname != NULL)
9378 {
9379 STRCPY(winvarname, "w:");
9380 STRCPY(winvarname + 2, varname);
9381 set_var(winvarname, varp, TRUE);
9382 vim_free(winvarname);
9383 }
9384 }
9385 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009386 if (need_switch_win)
9387 restore_win(save_curwin, save_curtab, TRUE);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009388 }
9389}
9390
9391/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009392 * Skip over the name of an option: "&option", "&g:option" or "&l:option".
9393 * "arg" points to the "&" or '+' when called, to "option" when returning.
9394 * Returns NULL when no option name found. Otherwise pointer to the char
9395 * after the option name.
9396 */
9397 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01009398find_option_end(char_u **arg, int *opt_flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009399{
9400 char_u *p = *arg;
9401
9402 ++p;
9403 if (*p == 'g' && p[1] == ':')
9404 {
9405 *opt_flags = OPT_GLOBAL;
9406 p += 2;
9407 }
9408 else if (*p == 'l' && p[1] == ':')
9409 {
9410 *opt_flags = OPT_LOCAL;
9411 p += 2;
9412 }
9413 else
9414 *opt_flags = 0;
9415
9416 if (!ASCII_ISALPHA(*p))
9417 return NULL;
9418 *arg = p;
9419
9420 if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL)
9421 p += 4; /* termcap option */
9422 else
9423 while (ASCII_ISALPHA(*p))
9424 ++p;
9425 return p;
9426}
9427
9428/*
Bram Moolenaara9b579f2016-07-17 18:29:19 +02009429 * Return the autoload script name for a function or variable name.
9430 * Returns NULL when out of memory.
Bram Moolenaar28fc2472019-07-05 22:14:16 +02009431 * Caller must make sure that "name" contains AUTOLOAD_CHAR.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009432 */
Bram Moolenaara1544c02013-05-30 12:35:52 +02009433 char_u *
Bram Moolenaara9b579f2016-07-17 18:29:19 +02009434autoload_name(char_u *name)
Bram Moolenaara1544c02013-05-30 12:35:52 +02009435{
Bram Moolenaar28fc2472019-07-05 22:14:16 +02009436 char_u *p, *q = NULL;
Bram Moolenaara9b579f2016-07-17 18:29:19 +02009437 char_u *scriptname;
Bram Moolenaara1544c02013-05-30 12:35:52 +02009438
Bram Moolenaar28fc2472019-07-05 22:14:16 +02009439 // Get the script file name: replace '#' with '/', append ".vim".
Bram Moolenaar964b3742019-05-24 18:54:09 +02009440 scriptname = alloc(STRLEN(name) + 14);
Bram Moolenaara9b579f2016-07-17 18:29:19 +02009441 if (scriptname == NULL)
Bram Moolenaar1058c9d2019-08-20 21:58:00 +02009442 return NULL;
Bram Moolenaara9b579f2016-07-17 18:29:19 +02009443 STRCPY(scriptname, "autoload/");
9444 STRCAT(scriptname, name);
Bram Moolenaar28fc2472019-07-05 22:14:16 +02009445 for (p = scriptname + 9; (p = vim_strchr(p, AUTOLOAD_CHAR)) != NULL;
9446 q = p, ++p)
Bram Moolenaara9b579f2016-07-17 18:29:19 +02009447 *p = '/';
Bram Moolenaar28fc2472019-07-05 22:14:16 +02009448 STRCPY(q, ".vim");
Bram Moolenaara9b579f2016-07-17 18:29:19 +02009449 return scriptname;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00009450}
9451
9452/*
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00009453 * If "name" has a package name try autoloading the script for it.
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00009454 * Return TRUE if a package was loaded.
9455 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02009456 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01009457script_autoload(
9458 char_u *name,
9459 int reload) /* load script again when already loaded */
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00009460{
9461 char_u *p;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00009462 char_u *scriptname, *tofree;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00009463 int ret = FALSE;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00009464 int i;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00009465
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00009466 /* If there is no '#' after name[0] there is no package name. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00009467 p = vim_strchr(name, AUTOLOAD_CHAR);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00009468 if (p == NULL || p == name)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00009469 return FALSE;
9470
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00009471 tofree = scriptname = autoload_name(name);
Bram Moolenaar1058c9d2019-08-20 21:58:00 +02009472 if (scriptname == NULL)
9473 return FALSE;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00009474
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00009475 /* Find the name in the list of previously loaded package names. Skip
9476 * "autoload/", it's always the same. */
9477 for (i = 0; i < ga_loaded.ga_len; ++i)
9478 if (STRCMP(((char_u **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0)
9479 break;
9480 if (!reload && i < ga_loaded.ga_len)
9481 ret = FALSE; /* was loaded already */
9482 else
9483 {
9484 /* Remember the name if it wasn't loaded already. */
9485 if (i == ga_loaded.ga_len && ga_grow(&ga_loaded, 1) == OK)
9486 {
9487 ((char_u **)ga_loaded.ga_data)[ga_loaded.ga_len++] = scriptname;
9488 tofree = NULL;
9489 }
9490
9491 /* Try loading the package from $VIMRUNTIME/autoload/<name>.vim */
Bram Moolenaar7f8989d2016-03-12 22:11:39 +01009492 if (source_runtime(scriptname, 0) == OK)
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00009493 ret = TRUE;
9494 }
9495
9496 vim_free(tofree);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00009497 return ret;
9498}
9499
Bram Moolenaar661b1822005-07-28 22:36:45 +00009500/*
9501 * Display script name where an item was last set.
9502 * Should only be invoked when 'verbose' is non-zero.
9503 */
9504 void
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02009505last_set_msg(sctx_T script_ctx)
Bram Moolenaar661b1822005-07-28 22:36:45 +00009506{
Bram Moolenaarcafda4f2005-09-06 19:25:11 +00009507 char_u *p;
9508
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02009509 if (script_ctx.sc_sid != 0)
Bram Moolenaar661b1822005-07-28 22:36:45 +00009510 {
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02009511 p = home_replace_save(NULL, get_scriptname(script_ctx.sc_sid));
Bram Moolenaarcafda4f2005-09-06 19:25:11 +00009512 if (p != NULL)
9513 {
9514 verbose_enter();
Bram Moolenaar32526b32019-01-19 17:43:09 +01009515 msg_puts(_("\n\tLast set from "));
9516 msg_puts((char *)p);
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02009517 if (script_ctx.sc_lnum > 0)
9518 {
Bram Moolenaar32526b32019-01-19 17:43:09 +01009519 msg_puts(_(" line "));
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02009520 msg_outnum((long)script_ctx.sc_lnum);
9521 }
Bram Moolenaarcafda4f2005-09-06 19:25:11 +00009522 verbose_leave();
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02009523 vim_free(p);
Bram Moolenaarcafda4f2005-09-06 19:25:11 +00009524 }
Bram Moolenaar661b1822005-07-28 22:36:45 +00009525 }
9526}
9527
Bram Moolenaar61be3762019-03-19 23:04:17 +01009528/*
Bram Moolenaard7c96872019-06-15 17:12:48 +02009529 * reset v:option_new, v:option_old, v:option_oldlocal, v:option_oldglobal,
9530 * v:option_type, and v:option_command.
Bram Moolenaar61be3762019-03-19 23:04:17 +01009531 */
Bram Moolenaar53744302015-07-17 17:38:22 +02009532 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009533reset_v_option_vars(void)
Bram Moolenaar53744302015-07-17 17:38:22 +02009534{
9535 set_vim_var_string(VV_OPTION_NEW, NULL, -1);
9536 set_vim_var_string(VV_OPTION_OLD, NULL, -1);
Bram Moolenaard7c96872019-06-15 17:12:48 +02009537 set_vim_var_string(VV_OPTION_OLDLOCAL, NULL, -1);
9538 set_vim_var_string(VV_OPTION_OLDGLOBAL, NULL, -1);
Bram Moolenaar53744302015-07-17 17:38:22 +02009539 set_vim_var_string(VV_OPTION_TYPE, NULL, -1);
Bram Moolenaard7c96872019-06-15 17:12:48 +02009540 set_vim_var_string(VV_OPTION_COMMAND, NULL, -1);
Bram Moolenaar53744302015-07-17 17:38:22 +02009541}
9542
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009543/*
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02009544 * Add an assert error to v:errors.
9545 */
9546 void
9547assert_error(garray_T *gap)
9548{
9549 struct vimvar *vp = &vimvars[VV_ERRORS];
9550
9551 if (vp->vv_type != VAR_LIST || vimvars[VV_ERRORS].vv_list == NULL)
9552 /* Make sure v:errors is a list. */
9553 set_vim_var_list(VV_ERRORS, list_alloc());
9554 list_append_string(vimvars[VV_ERRORS].vv_list, gap->ga_data, gap->ga_len);
9555}
Bram Moolenaar31988702018-02-13 12:57:42 +01009556/*
9557 * Compare "typ1" and "typ2". Put the result in "typ1".
9558 */
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009559 int
9560typval_compare(
9561 typval_T *typ1, /* first operand */
9562 typval_T *typ2, /* second operand */
9563 exptype_T type, /* operator */
9564 int type_is, /* TRUE for "is" and "isnot" */
Bram Moolenaar31988702018-02-13 12:57:42 +01009565 int ic) /* ignore case */
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009566{
9567 int i;
9568 varnumber_T n1, n2;
9569 char_u *s1, *s2;
9570 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
9571
Bram Moolenaar31988702018-02-13 12:57:42 +01009572 if (type_is && typ1->v_type != typ2->v_type)
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009573 {
Bram Moolenaar31988702018-02-13 12:57:42 +01009574 /* For "is" a different type always means FALSE, for "notis"
9575 * it means TRUE. */
9576 n1 = (type == TYPE_NEQUAL);
9577 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01009578 else if (typ1->v_type == VAR_BLOB || typ2->v_type == VAR_BLOB)
9579 {
9580 if (type_is)
9581 {
9582 n1 = (typ1->v_type == typ2->v_type
9583 && typ1->vval.v_blob == typ2->vval.v_blob);
9584 if (type == TYPE_NEQUAL)
9585 n1 = !n1;
9586 }
9587 else if (typ1->v_type != typ2->v_type
9588 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
9589 {
9590 if (typ1->v_type != typ2->v_type)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01009591 emsg(_("E977: Can only compare Blob with Blob"));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01009592 else
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01009593 emsg(_(e_invalblob));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01009594 clear_tv(typ1);
9595 return FAIL;
9596 }
9597 else
9598 {
9599 // Compare two Blobs for being equal or unequal.
9600 n1 = blob_equal(typ1->vval.v_blob, typ2->vval.v_blob);
9601 if (type == TYPE_NEQUAL)
9602 n1 = !n1;
9603 }
9604 }
Bram Moolenaar31988702018-02-13 12:57:42 +01009605 else if (typ1->v_type == VAR_LIST || typ2->v_type == VAR_LIST)
9606 {
9607 if (type_is)
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009608 {
Bram Moolenaar31988702018-02-13 12:57:42 +01009609 n1 = (typ1->v_type == typ2->v_type
9610 && typ1->vval.v_list == typ2->vval.v_list);
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009611 if (type == TYPE_NEQUAL)
9612 n1 = !n1;
9613 }
Bram Moolenaar31988702018-02-13 12:57:42 +01009614 else if (typ1->v_type != typ2->v_type
9615 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009616 {
Bram Moolenaar31988702018-02-13 12:57:42 +01009617 if (typ1->v_type != typ2->v_type)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01009618 emsg(_("E691: Can only compare List with List"));
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009619 else
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01009620 emsg(_("E692: Invalid operation for List"));
Bram Moolenaar31988702018-02-13 12:57:42 +01009621 clear_tv(typ1);
9622 return FAIL;
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009623 }
9624 else
9625 {
Bram Moolenaar31988702018-02-13 12:57:42 +01009626 /* Compare two Lists for being equal or unequal. */
9627 n1 = list_equal(typ1->vval.v_list, typ2->vval.v_list,
9628 ic, FALSE);
9629 if (type == TYPE_NEQUAL)
9630 n1 = !n1;
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009631 }
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009632 }
Bram Moolenaar31988702018-02-13 12:57:42 +01009633
9634 else if (typ1->v_type == VAR_DICT || typ2->v_type == VAR_DICT)
9635 {
9636 if (type_is)
9637 {
9638 n1 = (typ1->v_type == typ2->v_type
9639 && typ1->vval.v_dict == typ2->vval.v_dict);
9640 if (type == TYPE_NEQUAL)
9641 n1 = !n1;
9642 }
9643 else if (typ1->v_type != typ2->v_type
9644 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
9645 {
9646 if (typ1->v_type != typ2->v_type)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01009647 emsg(_("E735: Can only compare Dictionary with Dictionary"));
Bram Moolenaar31988702018-02-13 12:57:42 +01009648 else
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01009649 emsg(_("E736: Invalid operation for Dictionary"));
Bram Moolenaar31988702018-02-13 12:57:42 +01009650 clear_tv(typ1);
9651 return FAIL;
9652 }
9653 else
9654 {
9655 /* Compare two Dictionaries for being equal or unequal. */
9656 n1 = dict_equal(typ1->vval.v_dict, typ2->vval.v_dict,
9657 ic, FALSE);
9658 if (type == TYPE_NEQUAL)
9659 n1 = !n1;
9660 }
9661 }
9662
9663 else if (typ1->v_type == VAR_FUNC || typ2->v_type == VAR_FUNC
9664 || typ1->v_type == VAR_PARTIAL || typ2->v_type == VAR_PARTIAL)
9665 {
9666 if (type != TYPE_EQUAL && type != TYPE_NEQUAL)
9667 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01009668 emsg(_("E694: Invalid operation for Funcrefs"));
Bram Moolenaar31988702018-02-13 12:57:42 +01009669 clear_tv(typ1);
9670 return FAIL;
9671 }
9672 if ((typ1->v_type == VAR_PARTIAL
9673 && typ1->vval.v_partial == NULL)
9674 || (typ2->v_type == VAR_PARTIAL
9675 && typ2->vval.v_partial == NULL))
9676 /* when a partial is NULL assume not equal */
9677 n1 = FALSE;
9678 else if (type_is)
9679 {
9680 if (typ1->v_type == VAR_FUNC && typ2->v_type == VAR_FUNC)
9681 /* strings are considered the same if their value is
9682 * the same */
9683 n1 = tv_equal(typ1, typ2, ic, FALSE);
9684 else if (typ1->v_type == VAR_PARTIAL
9685 && typ2->v_type == VAR_PARTIAL)
9686 n1 = (typ1->vval.v_partial == typ2->vval.v_partial);
9687 else
9688 n1 = FALSE;
9689 }
9690 else
9691 n1 = tv_equal(typ1, typ2, ic, FALSE);
9692 if (type == TYPE_NEQUAL)
9693 n1 = !n1;
9694 }
9695
9696#ifdef FEAT_FLOAT
9697 /*
9698 * If one of the two variables is a float, compare as a float.
9699 * When using "=~" or "!~", always compare as string.
9700 */
9701 else if ((typ1->v_type == VAR_FLOAT || typ2->v_type == VAR_FLOAT)
9702 && type != TYPE_MATCH && type != TYPE_NOMATCH)
9703 {
9704 float_T f1, f2;
9705
Bram Moolenaar38f08e72019-02-20 22:04:32 +01009706 f1 = tv_get_float(typ1);
9707 f2 = tv_get_float(typ2);
Bram Moolenaar31988702018-02-13 12:57:42 +01009708 n1 = FALSE;
9709 switch (type)
9710 {
9711 case TYPE_EQUAL: n1 = (f1 == f2); break;
9712 case TYPE_NEQUAL: n1 = (f1 != f2); break;
9713 case TYPE_GREATER: n1 = (f1 > f2); break;
9714 case TYPE_GEQUAL: n1 = (f1 >= f2); break;
9715 case TYPE_SMALLER: n1 = (f1 < f2); break;
9716 case TYPE_SEQUAL: n1 = (f1 <= f2); break;
9717 case TYPE_UNKNOWN:
9718 case TYPE_MATCH:
9719 case TYPE_NOMATCH: break; /* avoid gcc warning */
9720 }
9721 }
9722#endif
9723
9724 /*
9725 * If one of the two variables is a number, compare as a number.
9726 * When using "=~" or "!~", always compare as string.
9727 */
9728 else if ((typ1->v_type == VAR_NUMBER || typ2->v_type == VAR_NUMBER)
9729 && type != TYPE_MATCH && type != TYPE_NOMATCH)
9730 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009731 n1 = tv_get_number(typ1);
9732 n2 = tv_get_number(typ2);
Bram Moolenaar31988702018-02-13 12:57:42 +01009733 switch (type)
9734 {
9735 case TYPE_EQUAL: n1 = (n1 == n2); break;
9736 case TYPE_NEQUAL: n1 = (n1 != n2); break;
9737 case TYPE_GREATER: n1 = (n1 > n2); break;
9738 case TYPE_GEQUAL: n1 = (n1 >= n2); break;
9739 case TYPE_SMALLER: n1 = (n1 < n2); break;
9740 case TYPE_SEQUAL: n1 = (n1 <= n2); break;
9741 case TYPE_UNKNOWN:
9742 case TYPE_MATCH:
9743 case TYPE_NOMATCH: break; /* avoid gcc warning */
9744 }
9745 }
9746 else
9747 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +01009748 s1 = tv_get_string_buf(typ1, buf1);
9749 s2 = tv_get_string_buf(typ2, buf2);
Bram Moolenaar31988702018-02-13 12:57:42 +01009750 if (type != TYPE_MATCH && type != TYPE_NOMATCH)
9751 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2);
9752 else
9753 i = 0;
9754 n1 = FALSE;
9755 switch (type)
9756 {
9757 case TYPE_EQUAL: n1 = (i == 0); break;
9758 case TYPE_NEQUAL: n1 = (i != 0); break;
9759 case TYPE_GREATER: n1 = (i > 0); break;
9760 case TYPE_GEQUAL: n1 = (i >= 0); break;
9761 case TYPE_SMALLER: n1 = (i < 0); break;
9762 case TYPE_SEQUAL: n1 = (i <= 0); break;
9763
9764 case TYPE_MATCH:
9765 case TYPE_NOMATCH:
9766 n1 = pattern_match(s2, s1, ic);
9767 if (type == TYPE_NOMATCH)
9768 n1 = !n1;
9769 break;
9770
9771 case TYPE_UNKNOWN: break; /* avoid gcc warning */
9772 }
9773 }
9774 clear_tv(typ1);
9775 typ1->v_type = VAR_NUMBER;
9776 typ1->vval.v_number = n1;
9777
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009778 return OK;
9779}
9780
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009781 char_u *
Bram Moolenaar6f8d2ac2018-07-25 19:49:45 +02009782typval_tostring(typval_T *arg)
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009783{
9784 char_u *tofree;
9785 char_u numbuf[NUMBUFLEN];
9786 char_u *ret = NULL;
9787
9788 if (arg == NULL)
9789 return vim_strsave((char_u *)"(does not exist)");
9790 ret = tv2string(arg, &tofree, numbuf, 0);
9791 /* Make a copy if we have a value but it's not in allocated memory. */
9792 if (ret != NULL && tofree == NULL)
9793 ret = vim_strsave(ret);
9794 return ret;
9795}
9796
9797 int
9798var_exists(char_u *var)
9799{
9800 char_u *name;
9801 char_u *tofree;
9802 typval_T tv;
9803 int len = 0;
9804 int n = FALSE;
9805
9806 /* get_name_len() takes care of expanding curly braces */
9807 name = var;
9808 len = get_name_len(&var, &tofree, TRUE, FALSE);
9809 if (len > 0)
9810 {
9811 if (tofree != NULL)
9812 name = tofree;
9813 n = (get_var_tv(name, len, &tv, NULL, FALSE, TRUE) == OK);
9814 if (n)
9815 {
9816 /* handle d.key, l[idx], f(expr) */
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02009817 n = (handle_subscript(&var, &tv, TRUE, FALSE, name, &name) == OK);
Bram Moolenaarc6f9f732018-02-11 19:06:26 +01009818 if (n)
9819 clear_tv(&tv);
9820 }
9821 }
9822 if (*var != NUL)
9823 n = FALSE;
9824
9825 vim_free(tofree);
9826 return n;
9827}
9828
Bram Moolenaar071d4272004-06-13 20:20:40 +00009829#endif /* FEAT_EVAL */
9830
Bram Moolenaar071d4272004-06-13 20:20:40 +00009831
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009832#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009833
Bram Moolenaar4f974752019-02-17 17:44:42 +01009834#ifdef MSWIN
Bram Moolenaar071d4272004-06-13 20:20:40 +00009835/*
9836 * Functions for ":8" filename modifier: get 8.3 version of a filename.
9837 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009838
9839/*
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009840 * Get the short path (8.3) for the filename in "fnamep".
9841 * Only works for a valid file name.
9842 * When the path gets longer "fnamep" is changed and the allocated buffer
9843 * is put in "bufp".
9844 * *fnamelen is the length of "fnamep" and set to 0 for a nonexistent path.
9845 * Returns OK on success, FAIL on failure.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009846 */
9847 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01009848get_short_pathname(char_u **fnamep, char_u **bufp, int *fnamelen)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009849{
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009850 int l, len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009851 char_u *newbuf;
9852
9853 len = *fnamelen;
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +01009854 l = GetShortPathName((LPSTR)*fnamep, (LPSTR)*fnamep, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009855 if (l > len - 1)
9856 {
9857 /* If that doesn't work (not enough space), then save the string
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009858 * and try again with a new buffer big enough. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009859 newbuf = vim_strnsave(*fnamep, l);
9860 if (newbuf == NULL)
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009861 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009862
9863 vim_free(*bufp);
9864 *fnamep = *bufp = newbuf;
9865
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009866 /* Really should always succeed, as the buffer is big enough. */
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +01009867 l = GetShortPathName((LPSTR)*fnamep, (LPSTR)*fnamep, l+1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009868 }
9869
9870 *fnamelen = l;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009871 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009872}
9873
9874/*
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009875 * Get the short path (8.3) for the filename in "fname". The converted
9876 * path is returned in "bufp".
9877 *
9878 * Some of the directories specified in "fname" may not exist. This function
9879 * will shorten the existing directories at the beginning of the path and then
9880 * append the remaining non-existing path.
9881 *
9882 * fname - Pointer to the filename to shorten. On return, contains the
Bram Moolenaar2c704a72010-06-03 21:17:25 +02009883 * pointer to the shortened pathname
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009884 * bufp - Pointer to an allocated buffer for the filename.
9885 * fnamelen - Length of the filename pointed to by fname
9886 *
9887 * Returns OK on success (or nothing done) and FAIL on failure (out of memory).
Bram Moolenaar071d4272004-06-13 20:20:40 +00009888 */
9889 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01009890shortpath_for_invalid_fname(
9891 char_u **fname,
9892 char_u **bufp,
9893 int *fnamelen)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009894{
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009895 char_u *short_fname, *save_fname, *pbuf_unused;
9896 char_u *endp, *save_endp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009897 char_u ch;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009898 int old_len, len;
9899 int new_len, sfx_len;
9900 int retval = OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009901
9902 /* Make a copy */
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009903 old_len = *fnamelen;
9904 save_fname = vim_strnsave(*fname, old_len);
9905 pbuf_unused = NULL;
9906 short_fname = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009907
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009908 endp = save_fname + old_len - 1; /* Find the end of the copy */
9909 save_endp = endp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009910
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009911 /*
9912 * Try shortening the supplied path till it succeeds by removing one
9913 * directory at a time from the tail of the path.
9914 */
9915 len = 0;
9916 for (;;)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009917 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009918 /* go back one path-separator */
9919 while (endp > save_fname && !after_pathsep(save_fname, endp + 1))
9920 --endp;
9921 if (endp <= save_fname)
9922 break; /* processed the complete path */
9923
9924 /*
9925 * Replace the path separator with a NUL and try to shorten the
9926 * resulting path.
9927 */
9928 ch = *endp;
9929 *endp = 0;
9930 short_fname = save_fname;
Bram Moolenaarc236c162008-07-13 17:41:49 +00009931 len = (int)STRLEN(short_fname) + 1;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009932 if (get_short_pathname(&short_fname, &pbuf_unused, &len) == FAIL)
9933 {
9934 retval = FAIL;
9935 goto theend;
9936 }
9937 *endp = ch; /* preserve the string */
9938
9939 if (len > 0)
9940 break; /* successfully shortened the path */
9941
9942 /* failed to shorten the path. Skip the path separator */
9943 --endp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009944 }
9945
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009946 if (len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009947 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009948 /*
9949 * Succeeded in shortening the path. Now concatenate the shortened
9950 * path with the remaining path at the tail.
9951 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009952
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009953 /* Compute the length of the new path. */
9954 sfx_len = (int)(save_endp - endp) + 1;
9955 new_len = len + sfx_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009956
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009957 *fnamelen = new_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009958 vim_free(*bufp);
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009959 if (new_len > old_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009960 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009961 /* There is not enough space in the currently allocated string,
9962 * copy it to a buffer big enough. */
9963 *fname = *bufp = vim_strnsave(short_fname, new_len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009964 if (*fname == NULL)
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009965 {
9966 retval = FAIL;
9967 goto theend;
9968 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009969 }
9970 else
9971 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009972 /* Transfer short_fname to the main buffer (it's big enough),
9973 * unless get_short_pathname() did its work in-place. */
9974 *fname = *bufp = save_fname;
9975 if (short_fname != save_fname)
9976 vim_strncpy(save_fname, short_fname, len);
9977 save_fname = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009978 }
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009979
9980 /* concat the not-shortened part of the path */
9981 vim_strncpy(*fname + len, endp, sfx_len);
9982 (*fname)[new_len] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009983 }
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009984
9985theend:
9986 vim_free(pbuf_unused);
9987 vim_free(save_fname);
9988
9989 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009990}
9991
9992/*
9993 * Get a pathname for a partial path.
Bram Moolenaarbcebfb62008-05-29 19:47:13 +00009994 * Returns OK for success, FAIL for failure.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009995 */
9996 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01009997shortpath_for_partial(
9998 char_u **fnamep,
9999 char_u **bufp,
10000 int *fnamelen)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010001{
10002 int sepcount, len, tflen;
10003 char_u *p;
10004 char_u *pbuf, *tfname;
10005 int hasTilde;
10006
Bram Moolenaar8c8de832008-06-24 22:58:06 +000010007 /* Count up the path separators from the RHS.. so we know which part
10008 * of the path to return. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010009 sepcount = 0;
Bram Moolenaar91acfff2017-03-12 19:22:36 +010010010 for (p = *fnamep; p < *fnamep + *fnamelen; MB_PTR_ADV(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000010011 if (vim_ispathsep(*p))
10012 ++sepcount;
10013
10014 /* Need full path first (use expand_env() to remove a "~/") */
10015 hasTilde = (**fnamep == '~');
10016 if (hasTilde)
10017 pbuf = tfname = expand_env_save(*fnamep);
10018 else
10019 pbuf = tfname = FullName_save(*fnamep, FALSE);
10020
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000010021 len = tflen = (int)STRLEN(tfname);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010022
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000010023 if (get_short_pathname(&tfname, &pbuf, &len) == FAIL)
10024 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010025
10026 if (len == 0)
10027 {
10028 /* Don't have a valid filename, so shorten the rest of the
10029 * path if we can. This CAN give us invalid 8.3 filenames, but
10030 * there's not a lot of point in guessing what it might be.
10031 */
10032 len = tflen;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000010033 if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == FAIL)
10034 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010035 }
10036
10037 /* Count the paths backward to find the beginning of the desired string. */
10038 for (p = tfname + len - 1; p >= tfname; --p)
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000010039 {
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000010040 if (has_mbyte)
10041 p -= mb_head_off(tfname, p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010042 if (vim_ispathsep(*p))
10043 {
10044 if (sepcount == 0 || (hasTilde && sepcount == 1))
10045 break;
10046 else
10047 sepcount --;
10048 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000010049 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010050 if (hasTilde)
10051 {
10052 --p;
10053 if (p >= tfname)
10054 *p = '~';
10055 else
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000010056 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010057 }
10058 else
10059 ++p;
10060
10061 /* Copy in the string - p indexes into tfname - allocated at pbuf */
10062 vim_free(*bufp);
10063 *fnamelen = (int)STRLEN(p);
10064 *bufp = pbuf;
10065 *fnamep = p;
10066
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000010067 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010068}
Bram Moolenaar4f974752019-02-17 17:44:42 +010010069#endif // MSWIN
Bram Moolenaar071d4272004-06-13 20:20:40 +000010070
10071/*
10072 * Adjust a filename, according to a string of modifiers.
10073 * *fnamep must be NUL terminated when called. When returning, the length is
10074 * determined by *fnamelen.
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000010075 * Returns VALID_ flags or -1 for failure.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010076 * When there is an error, *fnamep is set to NULL.
10077 */
10078 int
Bram Moolenaar7454a062016-01-30 15:14:10 +010010079modify_fname(
Bram Moolenaar00136dc2018-07-25 21:19:13 +020010080 char_u *src, // string with modifiers
10081 int tilde_file, // "~" is a file name, not $HOME
10082 int *usedlen, // characters after src that are used
10083 char_u **fnamep, // file name so far
10084 char_u **bufp, // buffer for allocated file name or NULL
10085 int *fnamelen) // length of fnamep
Bram Moolenaar071d4272004-06-13 20:20:40 +000010086{
10087 int valid = 0;
10088 char_u *tail;
10089 char_u *s, *p, *pbuf;
10090 char_u dirname[MAXPATHL];
10091 int c;
10092 int has_fullname = 0;
Bram Moolenaar4f974752019-02-17 17:44:42 +010010093#ifdef MSWIN
Bram Moolenaardc935552011-08-17 15:23:23 +020010094 char_u *fname_start = *fnamep;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010095 int has_shortname = 0;
10096#endif
10097
10098repeat:
10099 /* ":p" - full path/file_name */
10100 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p')
10101 {
10102 has_fullname = 1;
10103
10104 valid |= VALID_PATH;
10105 *usedlen += 2;
10106
10107 /* Expand "~/path" for all systems and "~user/path" for Unix and VMS */
10108 if ((*fnamep)[0] == '~'
10109#if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME))
10110 && ((*fnamep)[1] == '/'
10111# ifdef BACKSLASH_IN_FILENAME
10112 || (*fnamep)[1] == '\\'
10113# endif
10114 || (*fnamep)[1] == NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010115#endif
Bram Moolenaar00136dc2018-07-25 21:19:13 +020010116 && !(tilde_file && (*fnamep)[1] == NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010117 )
10118 {
10119 *fnamep = expand_env_save(*fnamep);
10120 vim_free(*bufp); /* free any allocated file name */
10121 *bufp = *fnamep;
10122 if (*fnamep == NULL)
10123 return -1;
10124 }
10125
10126 /* When "/." or "/.." is used: force expansion to get rid of it. */
Bram Moolenaar91acfff2017-03-12 19:22:36 +010010127 for (p = *fnamep; *p != NUL; MB_PTR_ADV(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000010128 {
10129 if (vim_ispathsep(*p)
10130 && p[1] == '.'
10131 && (p[2] == NUL
10132 || vim_ispathsep(p[2])
10133 || (p[2] == '.'
10134 && (p[3] == NUL || vim_ispathsep(p[3])))))
10135 break;
10136 }
10137
10138 /* FullName_save() is slow, don't use it when not needed. */
10139 if (*p != NUL || !vim_isAbsName(*fnamep))
10140 {
10141 *fnamep = FullName_save(*fnamep, *p != NUL);
10142 vim_free(*bufp); /* free any allocated file name */
10143 *bufp = *fnamep;
10144 if (*fnamep == NULL)
10145 return -1;
10146 }
10147
Bram Moolenaar4f974752019-02-17 17:44:42 +010010148#ifdef MSWIN
Bram Moolenaar9158f9e2012-06-20 14:02:27 +020010149# if _WIN32_WINNT >= 0x0500
10150 if (vim_strchr(*fnamep, '~') != NULL)
10151 {
Bram Moolenaar2d04a912019-03-30 20:04:08 +010010152 // Expand 8.3 filename to full path. Needed to make sure the same
10153 // file does not have two different names.
10154 // Note: problem does not occur if _WIN32_WINNT < 0x0500.
10155 WCHAR *wfname = enc_to_utf16(*fnamep, NULL);
10156 WCHAR buf[_MAX_PATH];
10157
10158 if (wfname != NULL)
Bram Moolenaar9158f9e2012-06-20 14:02:27 +020010159 {
Bram Moolenaar2d04a912019-03-30 20:04:08 +010010160 if (GetLongPathNameW(wfname, buf, _MAX_PATH))
Bram Moolenaar9158f9e2012-06-20 14:02:27 +020010161 {
Bram Moolenaar2d04a912019-03-30 20:04:08 +010010162 char_u *p = utf16_to_enc(buf, NULL);
10163
10164 if (p != NULL)
10165 {
10166 vim_free(*bufp); // free any allocated file name
10167 *bufp = *fnamep = p;
10168 }
Bram Moolenaar9158f9e2012-06-20 14:02:27 +020010169 }
Bram Moolenaar2d04a912019-03-30 20:04:08 +010010170 vim_free(wfname);
Bram Moolenaar9158f9e2012-06-20 14:02:27 +020010171 }
10172 }
10173# endif
10174#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010175 /* Append a path separator to a directory. */
10176 if (mch_isdir(*fnamep))
10177 {
10178 /* Make room for one or two extra characters. */
10179 *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2);
10180 vim_free(*bufp); /* free any allocated file name */
10181 *bufp = *fnamep;
10182 if (*fnamep == NULL)
10183 return -1;
10184 add_pathsep(*fnamep);
10185 }
10186 }
10187
10188 /* ":." - path relative to the current directory */
10189 /* ":~" - path relative to the home directory */
10190 /* ":8" - shortname path - postponed till after */
10191 while (src[*usedlen] == ':'
10192 && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8'))
10193 {
10194 *usedlen += 2;
10195 if (c == '8')
10196 {
Bram Moolenaar4f974752019-02-17 17:44:42 +010010197#ifdef MSWIN
Bram Moolenaar071d4272004-06-13 20:20:40 +000010198 has_shortname = 1; /* Postpone this. */
10199#endif
10200 continue;
10201 }
10202 pbuf = NULL;
10203 /* Need full path first (use expand_env() to remove a "~/") */
10204 if (!has_fullname)
10205 {
10206 if (c == '.' && **fnamep == '~')
10207 p = pbuf = expand_env_save(*fnamep);
10208 else
10209 p = pbuf = FullName_save(*fnamep, FALSE);
10210 }
10211 else
10212 p = *fnamep;
10213
10214 has_fullname = 0;
10215
10216 if (p != NULL)
10217 {
10218 if (c == '.')
10219 {
10220 mch_dirname(dirname, MAXPATHL);
10221 s = shorten_fname(p, dirname);
10222 if (s != NULL)
10223 {
10224 *fnamep = s;
10225 if (pbuf != NULL)
10226 {
10227 vim_free(*bufp); /* free any allocated file name */
10228 *bufp = pbuf;
10229 pbuf = NULL;
10230 }
10231 }
10232 }
10233 else
10234 {
10235 home_replace(NULL, p, dirname, MAXPATHL, TRUE);
10236 /* Only replace it when it starts with '~' */
10237 if (*dirname == '~')
10238 {
10239 s = vim_strsave(dirname);
10240 if (s != NULL)
10241 {
10242 *fnamep = s;
10243 vim_free(*bufp);
10244 *bufp = s;
10245 }
10246 }
10247 }
10248 vim_free(pbuf);
10249 }
10250 }
10251
10252 tail = gettail(*fnamep);
10253 *fnamelen = (int)STRLEN(*fnamep);
10254
10255 /* ":h" - head, remove "/file_name", can be repeated */
10256 /* Don't remove the first "/" or "c:\" */
10257 while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h')
10258 {
10259 valid |= VALID_HEAD;
10260 *usedlen += 2;
10261 s = get_past_head(*fnamep);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000010262 while (tail > s && after_pathsep(s, tail))
Bram Moolenaar91acfff2017-03-12 19:22:36 +010010263 MB_PTR_BACK(*fnamep, tail);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010264 *fnamelen = (int)(tail - *fnamep);
10265#ifdef VMS
10266 if (*fnamelen > 0)
10267 *fnamelen += 1; /* the path separator is part of the path */
10268#endif
Bram Moolenaar5461cfe2007-09-25 18:40:14 +000010269 if (*fnamelen == 0)
10270 {
10271 /* Result is empty. Turn it into "." to make ":cd %:h" work. */
10272 p = vim_strsave((char_u *)".");
10273 if (p == NULL)
10274 return -1;
10275 vim_free(*bufp);
10276 *bufp = *fnamep = tail = p;
10277 *fnamelen = 1;
10278 }
10279 else
10280 {
10281 while (tail > s && !after_pathsep(s, tail))
Bram Moolenaar91acfff2017-03-12 19:22:36 +010010282 MB_PTR_BACK(*fnamep, tail);
Bram Moolenaar5461cfe2007-09-25 18:40:14 +000010283 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010284 }
10285
10286 /* ":8" - shortname */
10287 if (src[*usedlen] == ':' && src[*usedlen + 1] == '8')
10288 {
10289 *usedlen += 2;
Bram Moolenaar4f974752019-02-17 17:44:42 +010010290#ifdef MSWIN
Bram Moolenaar071d4272004-06-13 20:20:40 +000010291 has_shortname = 1;
10292#endif
10293 }
10294
Bram Moolenaar4f974752019-02-17 17:44:42 +010010295#ifdef MSWIN
Bram Moolenaardc935552011-08-17 15:23:23 +020010296 /*
10297 * Handle ":8" after we have done 'heads' and before we do 'tails'.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010298 */
10299 if (has_shortname)
10300 {
Bram Moolenaardc935552011-08-17 15:23:23 +020010301 /* Copy the string if it is shortened by :h and when it wasn't copied
10302 * yet, because we are going to change it in place. Avoids changing
10303 * the buffer name for "%:8". */
10304 if (*fnamelen < (int)STRLEN(*fnamep) || *fnamep == fname_start)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010305 {
10306 p = vim_strnsave(*fnamep, *fnamelen);
Bram Moolenaardc935552011-08-17 15:23:23 +020010307 if (p == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010308 return -1;
10309 vim_free(*bufp);
10310 *bufp = *fnamep = p;
10311 }
10312
10313 /* Split into two implementations - makes it easier. First is where
Bram Moolenaardc935552011-08-17 15:23:23 +020010314 * there isn't a full name already, second is where there is. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010315 if (!has_fullname && !vim_isAbsName(*fnamep))
10316 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000010317 if (shortpath_for_partial(fnamep, bufp, fnamelen) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010318 return -1;
10319 }
10320 else
10321 {
Bram Moolenaardc935552011-08-17 15:23:23 +020010322 int l = *fnamelen;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010323
Bram Moolenaardc935552011-08-17 15:23:23 +020010324 /* Simple case, already have the full-name.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010325 * Nearly always shorter, so try first time. */
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000010326 if (get_short_pathname(fnamep, bufp, &l) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010327 return -1;
10328
10329 if (l == 0)
10330 {
Bram Moolenaardc935552011-08-17 15:23:23 +020010331 /* Couldn't find the filename, search the paths. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010332 l = *fnamelen;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000010333 if (shortpath_for_invalid_fname(fnamep, bufp, &l) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010334 return -1;
10335 }
10336 *fnamelen = l;
10337 }
10338 }
Bram Moolenaar4f974752019-02-17 17:44:42 +010010339#endif // MSWIN
Bram Moolenaar071d4272004-06-13 20:20:40 +000010340
10341 /* ":t" - tail, just the basename */
10342 if (src[*usedlen] == ':' && src[*usedlen + 1] == 't')
10343 {
10344 *usedlen += 2;
10345 *fnamelen -= (int)(tail - *fnamep);
10346 *fnamep = tail;
10347 }
10348
10349 /* ":e" - extension, can be repeated */
10350 /* ":r" - root, without extension, can be repeated */
10351 while (src[*usedlen] == ':'
10352 && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r'))
10353 {
10354 /* find a '.' in the tail:
10355 * - for second :e: before the current fname
10356 * - otherwise: The last '.'
10357 */
10358 if (src[*usedlen + 1] == 'e' && *fnamep > tail)
10359 s = *fnamep - 2;
10360 else
10361 s = *fnamep + *fnamelen - 1;
10362 for ( ; s > tail; --s)
10363 if (s[0] == '.')
10364 break;
10365 if (src[*usedlen + 1] == 'e') /* :e */
10366 {
10367 if (s > tail)
10368 {
10369 *fnamelen += (int)(*fnamep - (s + 1));
10370 *fnamep = s + 1;
10371#ifdef VMS
10372 /* cut version from the extension */
10373 s = *fnamep + *fnamelen - 1;
10374 for ( ; s > *fnamep; --s)
10375 if (s[0] == ';')
10376 break;
10377 if (s > *fnamep)
10378 *fnamelen = s - *fnamep;
10379#endif
10380 }
10381 else if (*fnamep <= tail)
10382 *fnamelen = 0;
10383 }
10384 else /* :r */
10385 {
10386 if (s > tail) /* remove one extension */
10387 *fnamelen = (int)(s - *fnamep);
10388 }
10389 *usedlen += 2;
10390 }
10391
10392 /* ":s?pat?foo?" - substitute */
10393 /* ":gs?pat?foo?" - global substitute */
10394 if (src[*usedlen] == ':'
10395 && (src[*usedlen + 1] == 's'
10396 || (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's')))
10397 {
10398 char_u *str;
10399 char_u *pat;
10400 char_u *sub;
10401 int sep;
10402 char_u *flags;
10403 int didit = FALSE;
10404
10405 flags = (char_u *)"";
10406 s = src + *usedlen + 2;
10407 if (src[*usedlen + 1] == 'g')
10408 {
10409 flags = (char_u *)"g";
10410 ++s;
10411 }
10412
10413 sep = *s++;
10414 if (sep)
10415 {
10416 /* find end of pattern */
10417 p = vim_strchr(s, sep);
10418 if (p != NULL)
10419 {
10420 pat = vim_strnsave(s, (int)(p - s));
10421 if (pat != NULL)
10422 {
10423 s = p + 1;
10424 /* find end of substitution */
10425 p = vim_strchr(s, sep);
10426 if (p != NULL)
10427 {
10428 sub = vim_strnsave(s, (int)(p - s));
10429 str = vim_strnsave(*fnamep, *fnamelen);
10430 if (sub != NULL && str != NULL)
10431 {
10432 *usedlen = (int)(p + 1 - src);
Bram Moolenaar72ab7292016-07-19 19:10:51 +020010433 s = do_string_sub(str, pat, sub, NULL, flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010434 if (s != NULL)
10435 {
10436 *fnamep = s;
10437 *fnamelen = (int)STRLEN(s);
10438 vim_free(*bufp);
10439 *bufp = s;
10440 didit = TRUE;
10441 }
10442 }
10443 vim_free(sub);
10444 vim_free(str);
10445 }
10446 vim_free(pat);
10447 }
10448 }
10449 /* after using ":s", repeat all the modifiers */
10450 if (didit)
10451 goto repeat;
10452 }
10453 }
10454
Bram Moolenaar26df0922014-02-23 23:39:13 +010010455 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'S')
10456 {
Bram Moolenaar5ca84ce2016-03-23 22:28:25 +010010457 /* vim_strsave_shellescape() needs a NUL terminated string. */
Bram Moolenaard4caf5c2016-03-24 19:14:35 +010010458 c = (*fnamep)[*fnamelen];
Bram Moolenaar52c6eaf2016-03-25 18:42:46 +010010459 if (c != NUL)
10460 (*fnamep)[*fnamelen] = NUL;
Bram Moolenaar26df0922014-02-23 23:39:13 +010010461 p = vim_strsave_shellescape(*fnamep, FALSE, FALSE);
Bram Moolenaar52c6eaf2016-03-25 18:42:46 +010010462 if (c != NUL)
10463 (*fnamep)[*fnamelen] = c;
Bram Moolenaar26df0922014-02-23 23:39:13 +010010464 if (p == NULL)
10465 return -1;
10466 vim_free(*bufp);
10467 *bufp = *fnamep = p;
10468 *fnamelen = (int)STRLEN(p);
10469 *usedlen += 2;
10470 }
10471
Bram Moolenaar071d4272004-06-13 20:20:40 +000010472 return valid;
10473}
10474
10475/*
10476 * Perform a substitution on "str" with pattern "pat" and substitute "sub".
Bram Moolenaar72ab7292016-07-19 19:10:51 +020010477 * When "sub" is NULL "expr" is used, must be a VAR_FUNC or VAR_PARTIAL.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010478 * "flags" can be "g" to do a global substitute.
10479 * Returns an allocated string, NULL for error.
10480 */
10481 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010010482do_string_sub(
10483 char_u *str,
10484 char_u *pat,
10485 char_u *sub,
Bram Moolenaar72ab7292016-07-19 19:10:51 +020010486 typval_T *expr,
Bram Moolenaar7454a062016-01-30 15:14:10 +010010487 char_u *flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010488{
10489 int sublen;
10490 regmatch_T regmatch;
10491 int i;
10492 int do_all;
10493 char_u *tail;
Bram Moolenaare90c8532014-11-05 16:03:44 +010010494 char_u *end;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010495 garray_T ga;
10496 char_u *ret;
10497 char_u *save_cpo;
Bram Moolenaar8af26912014-01-23 20:09:34 +010010498 char_u *zero_width = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010499
10500 /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */
10501 save_cpo = p_cpo;
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +000010502 p_cpo = empty_option;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010503
10504 ga_init2(&ga, 1, 200);
10505
10506 do_all = (flags[0] == 'g');
10507
10508 regmatch.rm_ic = p_ic;
10509 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
10510 if (regmatch.regprog != NULL)
10511 {
10512 tail = str;
Bram Moolenaare90c8532014-11-05 16:03:44 +010010513 end = str + STRLEN(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010514 while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
10515 {
Bram Moolenaar8af26912014-01-23 20:09:34 +010010516 /* Skip empty match except for first match. */
10517 if (regmatch.startp[0] == regmatch.endp[0])
10518 {
10519 if (zero_width == regmatch.startp[0])
10520 {
10521 /* avoid getting stuck on a match with an empty string */
Bram Moolenaar8e7048c2014-06-12 18:39:22 +020010522 i = MB_PTR2LEN(tail);
10523 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail,
10524 (size_t)i);
10525 ga.ga_len += i;
10526 tail += i;
Bram Moolenaar8af26912014-01-23 20:09:34 +010010527 continue;
10528 }
10529 zero_width = regmatch.startp[0];
10530 }
10531
Bram Moolenaar071d4272004-06-13 20:20:40 +000010532 /*
10533 * Get some space for a temporary buffer to do the substitution
10534 * into. It will contain:
10535 * - The text up to where the match is.
10536 * - The substituted text.
10537 * - The text after the match.
10538 */
Bram Moolenaar72ab7292016-07-19 19:10:51 +020010539 sublen = vim_regsub(&regmatch, sub, expr, tail, FALSE, TRUE, FALSE);
Bram Moolenaare90c8532014-11-05 16:03:44 +010010540 if (ga_grow(&ga, (int)((end - tail) + sublen -
Bram Moolenaar071d4272004-06-13 20:20:40 +000010541 (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
10542 {
10543 ga_clear(&ga);
10544 break;
10545 }
10546
10547 /* copy the text up to where the match is */
10548 i = (int)(regmatch.startp[0] - tail);
10549 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
10550 /* add the substituted text */
Bram Moolenaar72ab7292016-07-19 19:10:51 +020010551 (void)vim_regsub(&regmatch, sub, expr, (char_u *)ga.ga_data
Bram Moolenaar071d4272004-06-13 20:20:40 +000010552 + ga.ga_len + i, TRUE, TRUE, FALSE);
10553 ga.ga_len += i + sublen - 1;
Bram Moolenaarceb84af2013-09-29 21:11:05 +020010554 tail = regmatch.endp[0];
10555 if (*tail == NUL)
10556 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010557 if (!do_all)
10558 break;
10559 }
10560
10561 if (ga.ga_data != NULL)
10562 STRCPY((char *)ga.ga_data + ga.ga_len, tail);
10563
Bram Moolenaar473de612013-06-08 18:19:48 +020010564 vim_regfree(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010565 }
10566
10567 ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data);
10568 ga_clear(&ga);
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +000010569 if (p_cpo == empty_option)
10570 p_cpo = save_cpo;
10571 else
Bram Moolenaar72ab7292016-07-19 19:10:51 +020010572 /* Darn, evaluating {sub} expression or {expr} changed the value. */
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +000010573 free_string_option(save_cpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010574
10575 return ret;
10576}
10577
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010578 static int
10579filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)
10580{
10581 typval_T rettv;
10582 typval_T argv[3];
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010583 int retval = FAIL;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010584
10585 copy_tv(tv, &vimvars[VV_VAL].vv_tv);
10586 argv[0] = vimvars[VV_KEY].vv_tv;
10587 argv[1] = vimvars[VV_VAL].vv_tv;
Bram Moolenaar48570482017-10-30 21:48:41 +010010588 if (eval_expr_typval(expr, argv, 2, &rettv) == FAIL)
10589 goto theend;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010590 if (map)
10591 {
10592 /* map(): replace the list item value */
10593 clear_tv(tv);
10594 rettv.v_lock = 0;
10595 *tv = rettv;
10596 }
10597 else
10598 {
10599 int error = FALSE;
10600
10601 /* filter(): when expr is zero remove the item */
Bram Moolenaard155d7a2018-12-21 16:04:21 +010010602 *remp = (tv_get_number_chk(&rettv, &error) == 0);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010603 clear_tv(&rettv);
10604 /* On type error, nothing has been removed; return FAIL to stop the
Bram Moolenaard155d7a2018-12-21 16:04:21 +010010605 * loop. The error message was given by tv_get_number_chk(). */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010606 if (error)
10607 goto theend;
10608 }
10609 retval = OK;
10610theend:
10611 clear_tv(&vimvars[VV_VAL].vv_tv);
10612 return retval;
10613}
10614
10615
10616/*
10617 * Implementation of map() and filter().
10618 */
10619 void
10620filter_map(typval_T *argvars, typval_T *rettv, int map)
10621{
10622 typval_T *expr;
10623 listitem_T *li, *nli;
10624 list_T *l = NULL;
10625 dictitem_T *di;
10626 hashtab_T *ht;
10627 hashitem_T *hi;
10628 dict_T *d = NULL;
10629 typval_T save_val;
10630 typval_T save_key;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +010010631 blob_T *b = NULL;
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010632 int rem;
10633 int todo;
10634 char_u *ermsg = (char_u *)(map ? "map()" : "filter()");
10635 char_u *arg_errmsg = (char_u *)(map ? N_("map() argument")
10636 : N_("filter() argument"));
10637 int save_did_emsg;
10638 int idx = 0;
10639
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +010010640 if (argvars[0].v_type == VAR_BLOB)
10641 {
10642 if ((b = argvars[0].vval.v_blob) == NULL)
10643 return;
10644 }
10645 else if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010646 {
10647 if ((l = argvars[0].vval.v_list) == NULL
Bram Moolenaar05c00c02019-02-11 22:00:11 +010010648 || (!map && var_check_lock(l->lv_lock, arg_errmsg, TRUE)))
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010649 return;
10650 }
10651 else if (argvars[0].v_type == VAR_DICT)
10652 {
10653 if ((d = argvars[0].vval.v_dict) == NULL
Bram Moolenaar05c00c02019-02-11 22:00:11 +010010654 || (!map && var_check_lock(d->dv_lock, arg_errmsg, TRUE)))
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010655 return;
10656 }
10657 else
10658 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +010010659 semsg(_(e_listdictarg), ermsg);
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010660 return;
10661 }
10662
10663 expr = &argvars[1];
10664 /* On type errors, the preceding call has already displayed an error
10665 * message. Avoid a misleading error message for an empty string that
10666 * was not passed as argument. */
10667 if (expr->v_type != VAR_UNKNOWN)
10668 {
10669 prepare_vimvar(VV_VAL, &save_val);
10670
10671 /* We reset "did_emsg" to be able to detect whether an error
10672 * occurred during evaluation of the expression. */
10673 save_did_emsg = did_emsg;
10674 did_emsg = FALSE;
10675
10676 prepare_vimvar(VV_KEY, &save_key);
10677 if (argvars[0].v_type == VAR_DICT)
10678 {
10679 vimvars[VV_KEY].vv_type = VAR_STRING;
10680
10681 ht = &d->dv_hashtab;
10682 hash_lock(ht);
10683 todo = (int)ht->ht_used;
10684 for (hi = ht->ht_array; todo > 0; ++hi)
10685 {
10686 if (!HASHITEM_EMPTY(hi))
10687 {
10688 int r;
10689
10690 --todo;
10691 di = HI2DI(hi);
Bram Moolenaar05c00c02019-02-11 22:00:11 +010010692 if (map && (var_check_lock(di->di_tv.v_lock,
10693 arg_errmsg, TRUE)
10694 || var_check_ro(di->di_flags,
10695 arg_errmsg, TRUE)))
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010696 break;
10697 vimvars[VV_KEY].vv_str = vim_strsave(di->di_key);
10698 r = filter_map_one(&di->di_tv, expr, map, &rem);
10699 clear_tv(&vimvars[VV_KEY].vv_tv);
10700 if (r == FAIL || did_emsg)
10701 break;
10702 if (!map && rem)
10703 {
10704 if (var_check_fixed(di->di_flags, arg_errmsg, TRUE)
10705 || var_check_ro(di->di_flags, arg_errmsg, TRUE))
10706 break;
10707 dictitem_remove(d, di);
10708 }
10709 }
10710 }
10711 hash_unlock(ht);
10712 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +010010713 else if (argvars[0].v_type == VAR_BLOB)
10714 {
10715 int i;
10716 typval_T tv;
10717
10718 vimvars[VV_KEY].vv_type = VAR_NUMBER;
10719 for (i = 0; i < b->bv_ga.ga_len; i++)
10720 {
10721 tv.v_type = VAR_NUMBER;
10722 tv.vval.v_number = blob_get(b, i);
10723 vimvars[VV_KEY].vv_nr = idx;
10724 if (filter_map_one(&tv, expr, map, &rem) == FAIL || did_emsg)
10725 break;
10726 if (tv.v_type != VAR_NUMBER)
10727 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +010010728 emsg(_(e_invalblob));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +010010729 return;
10730 }
10731 tv.v_type = VAR_NUMBER;
10732 blob_set(b, i, tv.vval.v_number);
10733 if (!map && rem)
10734 {
10735 char_u *p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data;
10736
10737 mch_memmove(p + idx, p + i + 1,
10738 (size_t)b->bv_ga.ga_len - i - 1);
10739 --b->bv_ga.ga_len;
10740 --i;
10741 }
10742 }
10743 }
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010744 else
10745 {
Bram Moolenaarce9d50d2019-01-14 22:22:29 +010010746 // argvars[0].v_type == VAR_LIST
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010747 vimvars[VV_KEY].vv_type = VAR_NUMBER;
10748
10749 for (li = l->lv_first; li != NULL; li = nli)
10750 {
Bram Moolenaar05c00c02019-02-11 22:00:11 +010010751 if (map && var_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE))
Bram Moolenaar73dad1e2016-07-17 22:13:49 +020010752 break;
10753 nli = li->li_next;
10754 vimvars[VV_KEY].vv_nr = idx;
10755 if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL
10756 || did_emsg)
10757 break;
10758 if (!map && rem)
10759 listitem_remove(l, li);
10760 ++idx;
10761 }
10762 }
10763
10764 restore_vimvar(VV_KEY, &save_key);
10765 restore_vimvar(VV_VAL, &save_val);
10766
10767 did_emsg |= save_did_emsg;
10768 }
10769
10770 copy_tv(&argvars[0], rettv);
10771}
10772
Bram Moolenaar071d4272004-06-13 20:20:40 +000010773#endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */