blob: e045a67530b55fbf7a51797cd01546fac3f71e07 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* vi:set ts=8 sts=4 sw=4:
2 *
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 Moolenaar071d4272004-06-13 20:20:40 +000019#ifdef AMIGA
20# include <time.h> /* for strftime() */
21#endif
22
Bram Moolenaar314f11d2010-08-09 22:07:08 +020023#ifdef VMS
24# include <float.h>
25#endif
26
Bram Moolenaar071d4272004-06-13 20:20:40 +000027#ifdef MACOS
28# include <time.h> /* for time_t */
29#endif
30
Bram Moolenaar33570922005-01-25 22:26:29 +000031#define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */
Bram Moolenaar071d4272004-06-13 20:20:40 +000032
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000033#define DO_NOT_FREE_CNT 99999 /* refcount for dict or list that should not
34 be freed. */
35
Bram Moolenaar071d4272004-06-13 20:20:40 +000036/*
Bram Moolenaar33570922005-01-25 22:26:29 +000037 * In a hashtab item "hi_key" points to "di_key" in a dictitem.
38 * This avoids adding a pointer to the hashtab item.
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000039 * DI2HIKEY() converts a dictitem pointer to a hashitem key pointer.
40 * HIKEY2DI() converts a hashitem key pointer to a dictitem pointer.
41 * HI2DI() converts a hashitem pointer to a dictitem pointer.
42 */
Bram Moolenaar33570922005-01-25 22:26:29 +000043static dictitem_T dumdi;
Bram Moolenaara7043832005-01-21 11:56:39 +000044#define DI2HIKEY(di) ((di)->di_key)
Bram Moolenaar33570922005-01-25 22:26:29 +000045#define HIKEY2DI(p) ((dictitem_T *)(p - (dumdi.di_key - (char_u *)&dumdi)))
Bram Moolenaara7043832005-01-21 11:56:39 +000046#define HI2DI(hi) HIKEY2DI((hi)->hi_key)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000047
48/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000049 * Structure returned by get_lval() and used by set_var_lval().
50 * For a plain name:
51 * "name" points to the variable name.
52 * "exp_name" is NULL.
53 * "tv" is NULL
54 * For a magic braces name:
55 * "name" points to the expanded variable name.
56 * "exp_name" is non-NULL, to be freed later.
57 * "tv" is NULL
58 * For an index in a list:
59 * "name" points to the (expanded) variable name.
60 * "exp_name" NULL or non-NULL, to be freed later.
61 * "tv" points to the (first) list item value
62 * "li" points to the (first) list item
63 * "range", "n1", "n2" and "empty2" indicate what items are used.
64 * For an existing Dict item:
65 * "name" points to the (expanded) variable name.
66 * "exp_name" NULL or non-NULL, to be freed later.
67 * "tv" points to the dict item value
68 * "newkey" is NULL
69 * For a non-existing Dict item:
70 * "name" points to the (expanded) variable name.
71 * "exp_name" NULL or non-NULL, to be freed later.
Bram Moolenaar33570922005-01-25 22:26:29 +000072 * "tv" points to the Dictionary typval_T
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000073 * "newkey" is the key for the new item.
74 */
75typedef struct lval_S
76{
77 char_u *ll_name; /* start of variable name (can be NULL) */
78 char_u *ll_exp_name; /* NULL or expanded name in allocated memory. */
Bram Moolenaar33570922005-01-25 22:26:29 +000079 typval_T *ll_tv; /* Typeval of item being used. If "newkey"
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000080 isn't NULL it's the Dict to which to add
81 the item. */
Bram Moolenaar33570922005-01-25 22:26:29 +000082 listitem_T *ll_li; /* The list item or NULL. */
83 list_T *ll_list; /* The list or NULL. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000084 int ll_range; /* TRUE when a [i:j] range was used */
85 long ll_n1; /* First index for list */
86 long ll_n2; /* Second index for list range */
87 int ll_empty2; /* Second index is empty: [i:] */
Bram Moolenaar33570922005-01-25 22:26:29 +000088 dict_T *ll_dict; /* The Dictionary or NULL */
89 dictitem_T *ll_di; /* The dictitem or NULL */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000090 char_u *ll_newkey; /* New key for Dict in alloc. mem or NULL. */
Bram Moolenaar33570922005-01-25 22:26:29 +000091} lval_T;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000092
Bram Moolenaarc70646c2005-01-04 21:52:38 +000093static char *e_letunexp = N_("E18: Unexpected characters in :let");
Bram Moolenaare49b69a2005-01-08 16:11:57 +000094static char *e_listidx = N_("E684: list index out of range: %ld");
Bram Moolenaarc70646c2005-01-04 21:52:38 +000095static char *e_undefvar = N_("E121: Undefined variable: %s");
96static char *e_missbrac = N_("E111: Missing ']'");
Bram Moolenaar8c711452005-01-14 21:53:12 +000097static char *e_listarg = N_("E686: Argument of %s must be a List");
Bram Moolenaar13fcaaf2005-04-15 21:13:42 +000098static char *e_listdictarg = N_("E712: Argument of %s must be a List or Dictionary");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000099static char *e_listreq = N_("E714: List required");
100static char *e_dictreq = N_("E715: Dictionary required");
Bram Moolenaar8c711452005-01-14 21:53:12 +0000101static char *e_toomanyarg = N_("E118: Too many arguments for function: %s");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000102static char *e_dictkey = N_("E716: Key not present in Dictionary: %s");
103static char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it");
104static char *e_funcdict = N_("E717: Dictionary entry already exists");
105static char *e_funcref = N_("E718: Funcref required");
106static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary");
107static char *e_letwrong = N_("E734: Wrong variable type for %s=");
Bram Moolenaar05159a02005-02-26 23:04:13 +0000108static char *e_nofunc = N_("E130: Unknown function: %s");
Bram Moolenaar92124a32005-06-17 22:03:40 +0000109static char *e_illvar = N_("E461: Illegal variable name: %s");
Bram Moolenaar8c0e3222013-06-16 17:32:40 +0200110#ifdef FEAT_FLOAT
Bram Moolenaar2a876e42013-06-12 22:08:58 +0200111static char *e_float_as_string = N_("E806: using Float as a String");
Bram Moolenaar8c0e3222013-06-16 17:32:40 +0200112#endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000113
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +0100114#define NAMESPACE_CHAR (char_u *)"abglstvw"
115
Bram Moolenaar230bb3f2013-04-24 14:07:45 +0200116static dictitem_T globvars_var; /* variable used for g: */
Bram Moolenaar33570922005-01-25 22:26:29 +0000117#define globvarht globvardict.dv_hashtab
Bram Moolenaar071d4272004-06-13 20:20:40 +0000118
119/*
Bram Moolenaar532c7802005-01-27 14:44:31 +0000120 * Old Vim variables such as "v:version" are also available without the "v:".
121 * Also in functions. We need a special hashtable for them.
122 */
Bram Moolenaar4debb442005-06-01 21:57:40 +0000123static hashtab_T compat_hashtab;
Bram Moolenaar532c7802005-01-27 14:44:31 +0000124
125/*
Bram Moolenaard9fba312005-06-26 22:34:35 +0000126 * When recursively copying lists and dicts we need to remember which ones we
127 * have done to avoid endless recursiveness. This unique ID is used for that.
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +0000128 * The last bit is used for previous_funccal, ignored when comparing.
Bram Moolenaard9fba312005-06-26 22:34:35 +0000129 */
130static int current_copyID = 0;
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +0000131#define COPYID_INC 2
132#define COPYID_MASK (~0x1)
Bram Moolenaard9fba312005-06-26 22:34:35 +0000133
Bram Moolenaar8502c702014-06-17 12:51:16 +0200134/* Abort conversion to string after a recursion error. */
135static int did_echo_string_emsg = FALSE;
136
Bram Moolenaard9fba312005-06-26 22:34:35 +0000137/*
Bram Moolenaar33570922005-01-25 22:26:29 +0000138 * Array to hold the hashtab with variables local to each sourced script.
139 * Each item holds a variable (nameless) that points to the dict_T.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000140 */
Bram Moolenaar33570922005-01-25 22:26:29 +0000141typedef struct
142{
143 dictitem_T sv_var;
144 dict_T sv_dict;
145} scriptvar_T;
146
Bram Moolenaar9577c3e2010-05-14 12:16:25 +0200147static garray_T ga_scripts = {0, 0, sizeof(scriptvar_T *), 4, NULL};
148#define SCRIPT_SV(id) (((scriptvar_T **)ga_scripts.ga_data)[(id) - 1])
149#define SCRIPT_VARS(id) (SCRIPT_SV(id)->sv_dict.dv_hashtab)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000150
151static int echo_attr = 0; /* attributes used for ":echo" */
152
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000153/* Values for trans_function_name() argument: */
154#define TFN_INT 1 /* internal function name OK */
155#define TFN_QUIET 2 /* no error messages */
Bram Moolenaar6d977d62014-01-14 15:24:39 +0100156#define TFN_NO_AUTOLOAD 4 /* do not use script autoloading */
157
158/* Values for get_lval() flags argument: */
159#define GLV_QUIET TFN_QUIET /* no error messages */
160#define GLV_NO_AUTOLOAD TFN_NO_AUTOLOAD /* do not use script autoloading */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000161
Bram Moolenaar071d4272004-06-13 20:20:40 +0000162/*
163 * Structure to hold info for a user function.
164 */
165typedef struct ufunc ufunc_T;
166
167struct ufunc
168{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000169 int uf_varargs; /* variable nr of arguments */
170 int uf_flags;
171 int uf_calls; /* nr of active calls */
172 garray_T uf_args; /* arguments */
173 garray_T uf_lines; /* function lines */
Bram Moolenaar05159a02005-02-26 23:04:13 +0000174#ifdef FEAT_PROFILE
175 int uf_profiling; /* TRUE when func is being profiled */
176 /* profiling the function as a whole */
177 int uf_tm_count; /* nr of calls */
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000178 proftime_T uf_tm_total; /* time spent in function + children */
179 proftime_T uf_tm_self; /* time spent in function itself */
Bram Moolenaar05159a02005-02-26 23:04:13 +0000180 proftime_T uf_tm_children; /* time spent in children this call */
181 /* profiling the function per line */
182 int *uf_tml_count; /* nr of times line was executed */
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000183 proftime_T *uf_tml_total; /* time spent in a line + children */
184 proftime_T *uf_tml_self; /* time spent in a line itself */
Bram Moolenaar05159a02005-02-26 23:04:13 +0000185 proftime_T uf_tml_start; /* start time for current line */
186 proftime_T uf_tml_children; /* time spent in children for this line */
187 proftime_T uf_tml_wait; /* start wait time for current line */
188 int uf_tml_idx; /* index of line being timed; -1 if none */
189 int uf_tml_execed; /* line being timed was executed */
190#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000191 scid_T uf_script_ID; /* ID of script where function was defined,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000192 used for s: variables */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000193 int uf_refcount; /* for numbered function: reference count */
194 char_u uf_name[1]; /* name of function (actually longer); can
195 start with <SNR>123_ (<SNR> is K_SPECIAL
196 KS_EXTRA KE_SNR) */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000197};
198
199/* function flags */
200#define FC_ABORT 1 /* abort function on error */
201#define FC_RANGE 2 /* function accepts range */
Bram Moolenaare9a41262005-01-15 22:18:47 +0000202#define FC_DICT 4 /* Dict function, uses "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000203
204/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000205 * All user-defined functions are found in this hashtable.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000206 */
Bram Moolenaar4debb442005-06-01 21:57:40 +0000207static hashtab_T func_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000208
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000209/* The names of packages that once were loaded are remembered. */
Bram Moolenaaraa35dd12006-04-29 22:03:41 +0000210static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL};
211
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000212/* list heads for garbage collection */
213static dict_T *first_dict = NULL; /* list of all dicts */
214static list_T *first_list = NULL; /* list of all lists */
215
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000216/* From user function to hashitem and back. */
217static ufunc_T dumuf;
218#define UF2HIKEY(fp) ((fp)->uf_name)
219#define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf)))
220#define HI2UF(hi) HIKEY2UF((hi)->hi_key)
221
222#define FUNCARG(fp, j) ((char_u **)(fp->uf_args.ga_data))[j]
223#define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j]
Bram Moolenaar071d4272004-06-13 20:20:40 +0000224
Bram Moolenaar33570922005-01-25 22:26:29 +0000225#define MAX_FUNC_ARGS 20 /* maximum number of function arguments */
226#define VAR_SHORT_LEN 20 /* short variable name length */
227#define FIXVAR_CNT 12 /* number of fixed variables */
228
Bram Moolenaar071d4272004-06-13 20:20:40 +0000229/* structure to hold info for a function that is currently being executed. */
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000230typedef struct funccall_S funccall_T;
231
232struct funccall_S
Bram Moolenaar071d4272004-06-13 20:20:40 +0000233{
234 ufunc_T *func; /* function being called */
235 int linenr; /* next line to be executed */
236 int returned; /* ":return" used */
Bram Moolenaar33570922005-01-25 22:26:29 +0000237 struct /* fixed variables for arguments */
238 {
239 dictitem_T var; /* variable (without room for name) */
240 char_u room[VAR_SHORT_LEN]; /* room for the name */
241 } fixvar[FIXVAR_CNT];
242 dict_T l_vars; /* l: local function variables */
243 dictitem_T l_vars_var; /* variable for l: scope */
244 dict_T l_avars; /* a: argument variables */
245 dictitem_T l_avars_var; /* variable for a: scope */
246 list_T l_varlist; /* list for a:000 */
247 listitem_T l_listitems[MAX_FUNC_ARGS]; /* listitems for a:000 */
248 typval_T *rettv; /* return value */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000249 linenr_T breakpoint; /* next line with breakpoint or zero */
250 int dbg_tick; /* debug_tick when breakpoint was set */
251 int level; /* top nesting level of executed function */
Bram Moolenaar05159a02005-02-26 23:04:13 +0000252#ifdef FEAT_PROFILE
253 proftime_T prof_child; /* time spent in a child */
254#endif
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000255 funccall_T *caller; /* calling function or NULL */
256};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000257
258/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000259 * Info used by a ":for" loop.
260 */
Bram Moolenaar33570922005-01-25 22:26:29 +0000261typedef struct
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000262{
263 int fi_semicolon; /* TRUE if ending in '; var]' */
264 int fi_varcount; /* nr of variables in the list */
Bram Moolenaar33570922005-01-25 22:26:29 +0000265 listwatch_T fi_lw; /* keep an eye on the item used. */
266 list_T *fi_list; /* list being used */
267} forinfo_T;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000268
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000269/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000270 * Struct used by trans_function_name()
271 */
272typedef struct
273{
Bram Moolenaar33570922005-01-25 22:26:29 +0000274 dict_T *fd_dict; /* Dictionary used */
Bram Moolenaar532c7802005-01-27 14:44:31 +0000275 char_u *fd_newkey; /* new key in "dict" in allocated memory */
Bram Moolenaar33570922005-01-25 22:26:29 +0000276 dictitem_T *fd_di; /* Dictionary item used */
277} funcdict_T;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000278
Bram Moolenaara7043832005-01-21 11:56:39 +0000279
280/*
Bram Moolenaar33570922005-01-25 22:26:29 +0000281 * Array to hold the value of v: variables.
282 * The value is in a dictitem, so that it can also be used in the v: scope.
283 * The reason to use this table anyway is for very quick access to the
284 * variables with the VV_ defines.
285 */
286#include "version.h"
287
288/* values for vv_flags: */
289#define VV_COMPAT 1 /* compatible, also used without "v:" */
290#define VV_RO 2 /* read-only */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000291#define VV_RO_SBX 4 /* read-only in the sandbox */
Bram Moolenaar33570922005-01-25 22:26:29 +0000292
Bram Moolenaarcdb92af2009-06-03 12:26:06 +0000293#define VV_NAME(s, t) s, {{t, 0, {0}}, 0, {0}}, {0}
Bram Moolenaar33570922005-01-25 22:26:29 +0000294
295static struct vimvar
296{
297 char *vv_name; /* name of variable, without v: */
Bram Moolenaar33570922005-01-25 22:26:29 +0000298 dictitem_T vv_di; /* value and name for key */
299 char vv_filler[16]; /* space for LONGEST name below!!! */
300 char vv_flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */
301} vimvars[VV_LEN] =
302{
303 /*
304 * The order here must match the VV_ defines in vim.h!
305 * Initializing a union does not work, leave tv.vval empty to get zero's.
306 */
307 {VV_NAME("count", VAR_NUMBER), VV_COMPAT+VV_RO},
308 {VV_NAME("count1", VAR_NUMBER), VV_RO},
309 {VV_NAME("prevcount", VAR_NUMBER), VV_RO},
310 {VV_NAME("errmsg", VAR_STRING), VV_COMPAT},
311 {VV_NAME("warningmsg", VAR_STRING), 0},
312 {VV_NAME("statusmsg", VAR_STRING), 0},
313 {VV_NAME("shell_error", VAR_NUMBER), VV_COMPAT+VV_RO},
314 {VV_NAME("this_session", VAR_STRING), VV_COMPAT},
315 {VV_NAME("version", VAR_NUMBER), VV_COMPAT+VV_RO},
316 {VV_NAME("lnum", VAR_NUMBER), VV_RO_SBX},
317 {VV_NAME("termresponse", VAR_STRING), VV_RO},
318 {VV_NAME("fname", VAR_STRING), VV_RO},
319 {VV_NAME("lang", VAR_STRING), VV_RO},
320 {VV_NAME("lc_time", VAR_STRING), VV_RO},
321 {VV_NAME("ctype", VAR_STRING), VV_RO},
322 {VV_NAME("charconvert_from", VAR_STRING), VV_RO},
323 {VV_NAME("charconvert_to", VAR_STRING), VV_RO},
324 {VV_NAME("fname_in", VAR_STRING), VV_RO},
325 {VV_NAME("fname_out", VAR_STRING), VV_RO},
326 {VV_NAME("fname_new", VAR_STRING), VV_RO},
327 {VV_NAME("fname_diff", VAR_STRING), VV_RO},
328 {VV_NAME("cmdarg", VAR_STRING), VV_RO},
329 {VV_NAME("foldstart", VAR_NUMBER), VV_RO_SBX},
330 {VV_NAME("foldend", VAR_NUMBER), VV_RO_SBX},
331 {VV_NAME("folddashes", VAR_STRING), VV_RO_SBX},
332 {VV_NAME("foldlevel", VAR_NUMBER), VV_RO_SBX},
333 {VV_NAME("progname", VAR_STRING), VV_RO},
334 {VV_NAME("servername", VAR_STRING), VV_RO},
335 {VV_NAME("dying", VAR_NUMBER), VV_RO},
336 {VV_NAME("exception", VAR_STRING), VV_RO},
337 {VV_NAME("throwpoint", VAR_STRING), VV_RO},
338 {VV_NAME("register", VAR_STRING), VV_RO},
339 {VV_NAME("cmdbang", VAR_NUMBER), VV_RO},
340 {VV_NAME("insertmode", VAR_STRING), VV_RO},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000341 {VV_NAME("val", VAR_UNKNOWN), VV_RO},
342 {VV_NAME("key", VAR_UNKNOWN), VV_RO},
Bram Moolenaar05159a02005-02-26 23:04:13 +0000343 {VV_NAME("profiling", VAR_NUMBER), VV_RO},
Bram Moolenaar19a09a12005-03-04 23:39:37 +0000344 {VV_NAME("fcs_reason", VAR_STRING), VV_RO},
345 {VV_NAME("fcs_choice", VAR_STRING), 0},
Bram Moolenaare2ac10d2005-03-07 23:26:06 +0000346 {VV_NAME("beval_bufnr", VAR_NUMBER), VV_RO},
347 {VV_NAME("beval_winnr", VAR_NUMBER), VV_RO},
348 {VV_NAME("beval_lnum", VAR_NUMBER), VV_RO},
349 {VV_NAME("beval_col", VAR_NUMBER), VV_RO},
350 {VV_NAME("beval_text", VAR_STRING), VV_RO},
Bram Moolenaar761b1132005-10-03 22:05:45 +0000351 {VV_NAME("scrollstart", VAR_STRING), 0},
Bram Moolenaard5bc83f2005-12-07 21:07:59 +0000352 {VV_NAME("swapname", VAR_STRING), VV_RO},
353 {VV_NAME("swapchoice", VAR_STRING), 0},
Bram Moolenaar63a121b2005-12-11 21:36:39 +0000354 {VV_NAME("swapcommand", VAR_STRING), VV_RO},
Bram Moolenaare659c952011-05-19 17:25:41 +0200355 {VV_NAME("char", VAR_STRING), 0},
Bram Moolenaar219b8702006-11-01 14:32:36 +0000356 {VV_NAME("mouse_win", VAR_NUMBER), 0},
357 {VV_NAME("mouse_lnum", VAR_NUMBER), 0},
358 {VV_NAME("mouse_col", VAR_NUMBER), 0},
Bram Moolenaar8af1fbf2008-01-05 12:35:21 +0000359 {VV_NAME("operator", VAR_STRING), VV_RO},
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000360 {VV_NAME("searchforward", VAR_NUMBER), 0},
Bram Moolenaar8050efa2013-11-08 04:30:20 +0100361 {VV_NAME("hlsearch", VAR_NUMBER), 0},
Bram Moolenaard812df62008-11-09 12:46:09 +0000362 {VV_NAME("oldfiles", VAR_LIST), 0},
Bram Moolenaar727c8762010-10-20 19:17:48 +0200363 {VV_NAME("windowid", VAR_NUMBER), VV_RO},
Bram Moolenaara1706c92014-04-01 19:55:49 +0200364 {VV_NAME("progpath", VAR_STRING), VV_RO},
Bram Moolenaar42a45122015-07-10 17:56:23 +0200365 {VV_NAME("completed_item", VAR_DICT), VV_RO},
Bram Moolenaar53744302015-07-17 17:38:22 +0200366 {VV_NAME("option_new", VAR_STRING), VV_RO},
367 {VV_NAME("option_old", VAR_STRING), VV_RO},
368 {VV_NAME("option_type", VAR_STRING), VV_RO},
Bram Moolenaar43345542015-11-29 17:35:35 +0100369 {VV_NAME("errors", VAR_LIST), 0},
Bram Moolenaar520e1e42016-01-23 19:46:28 +0100370 {VV_NAME("false", VAR_SPECIAL), VV_RO},
371 {VV_NAME("true", VAR_SPECIAL), VV_RO},
372 {VV_NAME("null", VAR_SPECIAL), VV_RO},
373 {VV_NAME("none", VAR_SPECIAL), VV_RO},
Bram Moolenaar33570922005-01-25 22:26:29 +0000374};
375
376/* shorthand */
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000377#define vv_type vv_di.di_tv.v_type
378#define vv_nr vv_di.di_tv.vval.v_number
379#define vv_float vv_di.di_tv.vval.v_float
380#define vv_str vv_di.di_tv.vval.v_string
Bram Moolenaard812df62008-11-09 12:46:09 +0000381#define vv_list vv_di.di_tv.vval.v_list
Bram Moolenaar42a45122015-07-10 17:56:23 +0200382#define vv_dict vv_di.di_tv.vval.v_dict
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000383#define vv_tv vv_di.di_tv
Bram Moolenaar33570922005-01-25 22:26:29 +0000384
Bram Moolenaar230bb3f2013-04-24 14:07:45 +0200385static dictitem_T vimvars_var; /* variable used for v: */
Bram Moolenaar33570922005-01-25 22:26:29 +0000386#define vimvarht vimvardict.dv_hashtab
387
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100388static void prepare_vimvar(int idx, typval_T *save_tv);
389static void restore_vimvar(int idx, typval_T *save_tv);
390static int ex_let_vars(char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, char_u *nextchars);
391static char_u *skip_var_list(char_u *arg, int *var_count, int *semicolon);
392static char_u *skip_var_one(char_u *arg);
393static void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *first);
394static void list_glob_vars(int *first);
395static void list_buf_vars(int *first);
396static void list_win_vars(int *first);
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000397#ifdef FEAT_WINDOWS
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100398static void list_tab_vars(int *first);
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000399#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100400static void list_vim_vars(int *first);
401static void list_script_vars(int *first);
402static void list_func_vars(int *first);
403static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first);
404static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, char_u *endchars, char_u *op);
405static int check_changedtick(char_u *arg);
406static char_u *get_lval(char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int flags, int fne_flags);
407static void clear_lval(lval_T *lp);
408static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op);
409static int tv_op(typval_T *tv1, typval_T *tv2, char_u *op);
410static void list_fix_watch(list_T *l, listitem_T *item);
411static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep);
412static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit);
413static int do_lock_var(lval_T *lp, char_u *name_end, int deep, int lock);
414static void item_lock(typval_T *tv, int deep, int lock);
415static int tv_islocked(typval_T *tv);
Bram Moolenaara40058a2005-07-11 22:42:07 +0000416
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100417static int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate);
418static int eval1(char_u **arg, typval_T *rettv, int evaluate);
419static int eval2(char_u **arg, typval_T *rettv, int evaluate);
420static int eval3(char_u **arg, typval_T *rettv, int evaluate);
421static int eval4(char_u **arg, typval_T *rettv, int evaluate);
422static int eval5(char_u **arg, typval_T *rettv, int evaluate);
423static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string);
424static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string);
Bram Moolenaara40058a2005-07-11 22:42:07 +0000425
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100426static int eval_index(char_u **arg, typval_T *rettv, int evaluate, int verbose);
427static int get_option_tv(char_u **arg, typval_T *rettv, int evaluate);
428static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate);
429static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate);
430static int get_list_tv(char_u **arg, typval_T *rettv, int evaluate);
431static long list_len(list_T *l);
432static int list_equal(list_T *l1, list_T *l2, int ic, int recursive);
433static int dict_equal(dict_T *d1, dict_T *d2, int ic, int recursive);
434static int tv_equal(typval_T *tv1, typval_T *tv2, int ic, int recursive);
435static long list_find_nr(list_T *l, long idx, int *errorp);
436static long list_idx_of_item(list_T *l, listitem_T *item);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100437static int list_extend(list_T *l1, list_T *l2, listitem_T *bef);
438static int list_concat(list_T *l1, list_T *l2, typval_T *tv);
439static list_T *list_copy(list_T *orig, int deep, int copyID);
440static char_u *list2string(typval_T *tv, int copyID);
441static int list_join_inner(garray_T *gap, list_T *l, char_u *sep, int echo_style, int copyID, garray_T *join_gap);
442static int list_join(garray_T *gap, list_T *l, char_u *sep, int echo, int copyID);
443static int free_unref_items(int copyID);
444static dictitem_T *dictitem_copy(dictitem_T *org);
445static void dictitem_remove(dict_T *dict, dictitem_T *item);
446static dict_T *dict_copy(dict_T *orig, int deep, int copyID);
447static long dict_len(dict_T *d);
448static char_u *dict2string(typval_T *tv, int copyID);
449static int get_dict_tv(char_u **arg, typval_T *rettv, int evaluate);
450static char_u *echo_string(typval_T *tv, char_u **tofree, char_u *numbuf, int copyID);
451static char_u *tv2string(typval_T *tv, char_u **tofree, char_u *numbuf, int copyID);
452static char_u *string_quote(char_u *str, int function);
453static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate);
454static int find_internal_func(char_u *name);
455static char_u *deref_func_name(char_u *name, int *lenp, int no_autoload);
456static int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100457static void emsg_funcname(char *ermsg, char_u *name);
458static int non_zero_arg(typval_T *argvars);
Bram Moolenaar33570922005-01-25 22:26:29 +0000459
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000460#ifdef FEAT_FLOAT
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100461static void f_abs(typval_T *argvars, typval_T *rettv);
462static void f_acos(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000463#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100464static void f_add(typval_T *argvars, typval_T *rettv);
465static void f_alloc_fail(typval_T *argvars, typval_T *rettv);
466static void f_and(typval_T *argvars, typval_T *rettv);
467static void f_append(typval_T *argvars, typval_T *rettv);
468static void f_argc(typval_T *argvars, typval_T *rettv);
469static void f_argidx(typval_T *argvars, typval_T *rettv);
470static void f_arglistid(typval_T *argvars, typval_T *rettv);
471static void f_argv(typval_T *argvars, typval_T *rettv);
472static void f_assert_equal(typval_T *argvars, typval_T *rettv);
473static void f_assert_exception(typval_T *argvars, typval_T *rettv);
474static void f_assert_fails(typval_T *argvars, typval_T *rettv);
475static void f_assert_false(typval_T *argvars, typval_T *rettv);
476static void f_assert_true(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000477#ifdef FEAT_FLOAT
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100478static void f_asin(typval_T *argvars, typval_T *rettv);
479static void f_atan(typval_T *argvars, typval_T *rettv);
480static void f_atan2(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000481#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100482static void f_browse(typval_T *argvars, typval_T *rettv);
483static void f_browsedir(typval_T *argvars, typval_T *rettv);
484static void f_bufexists(typval_T *argvars, typval_T *rettv);
485static void f_buflisted(typval_T *argvars, typval_T *rettv);
486static void f_bufloaded(typval_T *argvars, typval_T *rettv);
487static void f_bufname(typval_T *argvars, typval_T *rettv);
488static void f_bufnr(typval_T *argvars, typval_T *rettv);
489static void f_bufwinnr(typval_T *argvars, typval_T *rettv);
490static void f_byte2line(typval_T *argvars, typval_T *rettv);
491static void byteidx(typval_T *argvars, typval_T *rettv, int comp);
492static void f_byteidx(typval_T *argvars, typval_T *rettv);
493static void f_byteidxcomp(typval_T *argvars, typval_T *rettv);
494static void f_call(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000495#ifdef FEAT_FLOAT
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100496static void f_ceil(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000497#endif
Bram Moolenaar509ce2a2016-03-11 22:52:15 +0100498#ifdef FEAT_JOB_CHANNEL
Bram Moolenaarf57969a2016-02-02 20:47:49 +0100499static void f_ch_close(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8b1862a2016-02-27 19:21:24 +0100500static void f_ch_evalexpr(typval_T *argvars, typval_T *rettv);
501static void f_ch_evalraw(typval_T *argvars, typval_T *rettv);
Bram Moolenaarc7f0ebc2016-02-27 21:10:09 +0100502static void f_ch_getbufnr(typval_T *argvars, typval_T *rettv);
Bram Moolenaar02e83b42016-02-21 20:10:26 +0100503static void f_ch_getjob(typval_T *argvars, typval_T *rettv);
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100504static void f_ch_log(typval_T *argvars, typval_T *rettv);
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100505static void f_ch_logfile(typval_T *argvars, typval_T *rettv);
506static void f_ch_open(typval_T *argvars, typval_T *rettv);
Bram Moolenaar6f3a5442016-02-20 19:56:13 +0100507static void f_ch_read(typval_T *argvars, typval_T *rettv);
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100508static void f_ch_readraw(typval_T *argvars, typval_T *rettv);
Bram Moolenaarf57969a2016-02-02 20:47:49 +0100509static void f_ch_sendexpr(typval_T *argvars, typval_T *rettv);
510static void f_ch_sendraw(typval_T *argvars, typval_T *rettv);
Bram Moolenaar40ea1da2016-02-19 22:33:35 +0100511static void f_ch_setoptions(typval_T *argvars, typval_T *rettv);
Bram Moolenaar77073442016-02-13 23:23:53 +0100512static void f_ch_status(typval_T *argvars, typval_T *rettv);
Bram Moolenaarf57969a2016-02-02 20:47:49 +0100513#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100514static void f_changenr(typval_T *argvars, typval_T *rettv);
515static void f_char2nr(typval_T *argvars, typval_T *rettv);
516static void f_cindent(typval_T *argvars, typval_T *rettv);
517static void f_clearmatches(typval_T *argvars, typval_T *rettv);
518static void f_col(typval_T *argvars, typval_T *rettv);
Bram Moolenaar572cb562005-08-05 21:35:02 +0000519#if defined(FEAT_INS_EXPAND)
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100520static void f_complete(typval_T *argvars, typval_T *rettv);
521static void f_complete_add(typval_T *argvars, typval_T *rettv);
522static void f_complete_check(typval_T *argvars, typval_T *rettv);
Bram Moolenaar572cb562005-08-05 21:35:02 +0000523#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100524static void f_confirm(typval_T *argvars, typval_T *rettv);
525static void f_copy(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000526#ifdef FEAT_FLOAT
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100527static void f_cos(typval_T *argvars, typval_T *rettv);
528static void f_cosh(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000529#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100530static void f_count(typval_T *argvars, typval_T *rettv);
531static void f_cscope_connection(typval_T *argvars, typval_T *rettv);
532static void f_cursor(typval_T *argsvars, typval_T *rettv);
533static void f_deepcopy(typval_T *argvars, typval_T *rettv);
534static void f_delete(typval_T *argvars, typval_T *rettv);
535static void f_did_filetype(typval_T *argvars, typval_T *rettv);
536static void f_diff_filler(typval_T *argvars, typval_T *rettv);
537static void f_diff_hlID(typval_T *argvars, typval_T *rettv);
Bram Moolenaar2ab375e2016-02-10 22:23:06 +0100538static void f_disable_char_avail_for_testing(typval_T *argvars, typval_T *rettv);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100539static void f_empty(typval_T *argvars, typval_T *rettv);
540static void f_escape(typval_T *argvars, typval_T *rettv);
541static void f_eval(typval_T *argvars, typval_T *rettv);
542static void f_eventhandler(typval_T *argvars, typval_T *rettv);
543static void f_executable(typval_T *argvars, typval_T *rettv);
544static void f_exepath(typval_T *argvars, typval_T *rettv);
545static void f_exists(typval_T *argvars, typval_T *rettv);
Bram Moolenaardb7c6862010-05-21 16:33:48 +0200546#ifdef FEAT_FLOAT
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100547static void f_exp(typval_T *argvars, typval_T *rettv);
Bram Moolenaardb7c6862010-05-21 16:33:48 +0200548#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100549static void f_expand(typval_T *argvars, typval_T *rettv);
550static void f_extend(typval_T *argvars, typval_T *rettv);
551static void f_feedkeys(typval_T *argvars, typval_T *rettv);
552static void f_filereadable(typval_T *argvars, typval_T *rettv);
553static void f_filewritable(typval_T *argvars, typval_T *rettv);
554static void f_filter(typval_T *argvars, typval_T *rettv);
555static void f_finddir(typval_T *argvars, typval_T *rettv);
556static void f_findfile(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000557#ifdef FEAT_FLOAT
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100558static void f_float2nr(typval_T *argvars, typval_T *rettv);
559static void f_floor(typval_T *argvars, typval_T *rettv);
560static void f_fmod(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000561#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100562static void f_fnameescape(typval_T *argvars, typval_T *rettv);
563static void f_fnamemodify(typval_T *argvars, typval_T *rettv);
564static void f_foldclosed(typval_T *argvars, typval_T *rettv);
565static void f_foldclosedend(typval_T *argvars, typval_T *rettv);
566static void f_foldlevel(typval_T *argvars, typval_T *rettv);
567static void f_foldtext(typval_T *argvars, typval_T *rettv);
568static void f_foldtextresult(typval_T *argvars, typval_T *rettv);
569static void f_foreground(typval_T *argvars, typval_T *rettv);
570static void f_function(typval_T *argvars, typval_T *rettv);
571static void f_garbagecollect(typval_T *argvars, typval_T *rettv);
572static void f_get(typval_T *argvars, typval_T *rettv);
573static void f_getbufline(typval_T *argvars, typval_T *rettv);
574static void f_getbufvar(typval_T *argvars, typval_T *rettv);
575static void f_getchar(typval_T *argvars, typval_T *rettv);
576static void f_getcharmod(typval_T *argvars, typval_T *rettv);
577static void f_getcharsearch(typval_T *argvars, typval_T *rettv);
578static void f_getcmdline(typval_T *argvars, typval_T *rettv);
579static void f_getcmdpos(typval_T *argvars, typval_T *rettv);
580static void f_getcmdtype(typval_T *argvars, typval_T *rettv);
581static void f_getcmdwintype(typval_T *argvars, typval_T *rettv);
582static void f_getcwd(typval_T *argvars, typval_T *rettv);
583static void f_getfontname(typval_T *argvars, typval_T *rettv);
584static void f_getfperm(typval_T *argvars, typval_T *rettv);
585static void f_getfsize(typval_T *argvars, typval_T *rettv);
586static void f_getftime(typval_T *argvars, typval_T *rettv);
587static void f_getftype(typval_T *argvars, typval_T *rettv);
588static void f_getline(typval_T *argvars, typval_T *rettv);
589static void f_getmatches(typval_T *argvars, typval_T *rettv);
590static void f_getpid(typval_T *argvars, typval_T *rettv);
591static void f_getcurpos(typval_T *argvars, typval_T *rettv);
592static void f_getpos(typval_T *argvars, typval_T *rettv);
593static void f_getqflist(typval_T *argvars, typval_T *rettv);
594static void f_getreg(typval_T *argvars, typval_T *rettv);
595static void f_getregtype(typval_T *argvars, typval_T *rettv);
596static void f_gettabvar(typval_T *argvars, typval_T *rettv);
597static void f_gettabwinvar(typval_T *argvars, typval_T *rettv);
598static void f_getwinposx(typval_T *argvars, typval_T *rettv);
599static void f_getwinposy(typval_T *argvars, typval_T *rettv);
600static void f_getwinvar(typval_T *argvars, typval_T *rettv);
601static void f_glob(typval_T *argvars, typval_T *rettv);
602static void f_globpath(typval_T *argvars, typval_T *rettv);
603static void f_glob2regpat(typval_T *argvars, typval_T *rettv);
604static void f_has(typval_T *argvars, typval_T *rettv);
605static void f_has_key(typval_T *argvars, typval_T *rettv);
606static void f_haslocaldir(typval_T *argvars, typval_T *rettv);
607static void f_hasmapto(typval_T *argvars, typval_T *rettv);
608static void f_histadd(typval_T *argvars, typval_T *rettv);
609static void f_histdel(typval_T *argvars, typval_T *rettv);
610static void f_histget(typval_T *argvars, typval_T *rettv);
611static void f_histnr(typval_T *argvars, typval_T *rettv);
612static void f_hlID(typval_T *argvars, typval_T *rettv);
613static void f_hlexists(typval_T *argvars, typval_T *rettv);
614static void f_hostname(typval_T *argvars, typval_T *rettv);
615static void f_iconv(typval_T *argvars, typval_T *rettv);
616static void f_indent(typval_T *argvars, typval_T *rettv);
617static void f_index(typval_T *argvars, typval_T *rettv);
618static void f_input(typval_T *argvars, typval_T *rettv);
619static void f_inputdialog(typval_T *argvars, typval_T *rettv);
620static void f_inputlist(typval_T *argvars, typval_T *rettv);
621static void f_inputrestore(typval_T *argvars, typval_T *rettv);
622static void f_inputsave(typval_T *argvars, typval_T *rettv);
623static void f_inputsecret(typval_T *argvars, typval_T *rettv);
624static void f_insert(typval_T *argvars, typval_T *rettv);
625static void f_invert(typval_T *argvars, typval_T *rettv);
626static void f_isdirectory(typval_T *argvars, typval_T *rettv);
627static void f_islocked(typval_T *argvars, typval_T *rettv);
Bram Moolenaarf1b6ac72016-02-23 21:26:43 +0100628#if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
629static void f_isnan(typval_T *argvars, typval_T *rettv);
630#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100631static void f_items(typval_T *argvars, typval_T *rettv);
Bram Moolenaar509ce2a2016-03-11 22:52:15 +0100632#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100633static void f_job_getchannel(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8950a562016-03-12 15:22:55 +0100634static void f_job_info(typval_T *argvars, typval_T *rettv);
Bram Moolenaar65edff82016-02-21 16:40:11 +0100635static void f_job_setoptions(typval_T *argvars, typval_T *rettv);
Bram Moolenaar835dc632016-02-07 14:27:38 +0100636static void f_job_start(typval_T *argvars, typval_T *rettv);
637static void f_job_stop(typval_T *argvars, typval_T *rettv);
638static void f_job_status(typval_T *argvars, typval_T *rettv);
639#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100640static void f_join(typval_T *argvars, typval_T *rettv);
Bram Moolenaar7823a3b2016-02-11 21:08:32 +0100641static void f_js_decode(typval_T *argvars, typval_T *rettv);
642static void f_js_encode(typval_T *argvars, typval_T *rettv);
643static void f_json_decode(typval_T *argvars, typval_T *rettv);
644static void f_json_encode(typval_T *argvars, typval_T *rettv);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100645static void f_keys(typval_T *argvars, typval_T *rettv);
646static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv);
647static void f_len(typval_T *argvars, typval_T *rettv);
648static void f_libcall(typval_T *argvars, typval_T *rettv);
649static void f_libcallnr(typval_T *argvars, typval_T *rettv);
650static void f_line(typval_T *argvars, typval_T *rettv);
651static void f_line2byte(typval_T *argvars, typval_T *rettv);
652static void f_lispindent(typval_T *argvars, typval_T *rettv);
653static void f_localtime(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000654#ifdef FEAT_FLOAT
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100655static void f_log(typval_T *argvars, typval_T *rettv);
656static void f_log10(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000657#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +0200658#ifdef FEAT_LUA
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100659static void f_luaeval(typval_T *argvars, typval_T *rettv);
Bram Moolenaar1dced572012-04-05 16:54:08 +0200660#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100661static void f_map(typval_T *argvars, typval_T *rettv);
662static void f_maparg(typval_T *argvars, typval_T *rettv);
663static void f_mapcheck(typval_T *argvars, typval_T *rettv);
664static void f_match(typval_T *argvars, typval_T *rettv);
665static void f_matchadd(typval_T *argvars, typval_T *rettv);
666static void f_matchaddpos(typval_T *argvars, typval_T *rettv);
667static void f_matcharg(typval_T *argvars, typval_T *rettv);
668static void f_matchdelete(typval_T *argvars, typval_T *rettv);
669static void f_matchend(typval_T *argvars, typval_T *rettv);
670static void f_matchlist(typval_T *argvars, typval_T *rettv);
671static void f_matchstr(typval_T *argvars, typval_T *rettv);
672static void f_max(typval_T *argvars, typval_T *rettv);
673static void f_min(typval_T *argvars, typval_T *rettv);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000674#ifdef vim_mkdir
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100675static void f_mkdir(typval_T *argvars, typval_T *rettv);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000676#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100677static void f_mode(typval_T *argvars, typval_T *rettv);
Bram Moolenaar7e506b62010-01-19 15:55:06 +0100678#ifdef FEAT_MZSCHEME
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100679static void f_mzeval(typval_T *argvars, typval_T *rettv);
Bram Moolenaar7e506b62010-01-19 15:55:06 +0100680#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100681static void f_nextnonblank(typval_T *argvars, typval_T *rettv);
682static void f_nr2char(typval_T *argvars, typval_T *rettv);
683static void f_or(typval_T *argvars, typval_T *rettv);
684static void f_pathshorten(typval_T *argvars, typval_T *rettv);
Bram Moolenaare9b892e2016-01-17 21:15:58 +0100685#ifdef FEAT_PERL
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100686static void f_perleval(typval_T *argvars, typval_T *rettv);
Bram Moolenaare9b892e2016-01-17 21:15:58 +0100687#endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000688#ifdef FEAT_FLOAT
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100689static void f_pow(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000690#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100691static void f_prevnonblank(typval_T *argvars, typval_T *rettv);
692static void f_printf(typval_T *argvars, typval_T *rettv);
693static void f_pumvisible(typval_T *argvars, typval_T *rettv);
Bram Moolenaardb913952012-06-29 12:54:53 +0200694#ifdef FEAT_PYTHON3
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100695static void f_py3eval(typval_T *argvars, typval_T *rettv);
Bram Moolenaardb913952012-06-29 12:54:53 +0200696#endif
697#ifdef FEAT_PYTHON
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100698static void f_pyeval(typval_T *argvars, typval_T *rettv);
Bram Moolenaardb913952012-06-29 12:54:53 +0200699#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100700static void f_range(typval_T *argvars, typval_T *rettv);
701static void f_readfile(typval_T *argvars, typval_T *rettv);
702static void f_reltime(typval_T *argvars, typval_T *rettv);
Bram Moolenaar79c2c882016-02-07 21:19:28 +0100703#ifdef FEAT_FLOAT
704static void f_reltimefloat(typval_T *argvars, typval_T *rettv);
705#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100706static void f_reltimestr(typval_T *argvars, typval_T *rettv);
707static void f_remote_expr(typval_T *argvars, typval_T *rettv);
708static void f_remote_foreground(typval_T *argvars, typval_T *rettv);
709static void f_remote_peek(typval_T *argvars, typval_T *rettv);
710static void f_remote_read(typval_T *argvars, typval_T *rettv);
711static void f_remote_send(typval_T *argvars, typval_T *rettv);
712static void f_remove(typval_T *argvars, typval_T *rettv);
713static void f_rename(typval_T *argvars, typval_T *rettv);
714static void f_repeat(typval_T *argvars, typval_T *rettv);
715static void f_resolve(typval_T *argvars, typval_T *rettv);
716static void f_reverse(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000717#ifdef FEAT_FLOAT
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100718static void f_round(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000719#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100720static void f_screenattr(typval_T *argvars, typval_T *rettv);
721static void f_screenchar(typval_T *argvars, typval_T *rettv);
722static void f_screencol(typval_T *argvars, typval_T *rettv);
723static void f_screenrow(typval_T *argvars, typval_T *rettv);
724static void f_search(typval_T *argvars, typval_T *rettv);
725static void f_searchdecl(typval_T *argvars, typval_T *rettv);
726static void f_searchpair(typval_T *argvars, typval_T *rettv);
727static void f_searchpairpos(typval_T *argvars, typval_T *rettv);
728static void f_searchpos(typval_T *argvars, typval_T *rettv);
729static void f_server2client(typval_T *argvars, typval_T *rettv);
730static void f_serverlist(typval_T *argvars, typval_T *rettv);
731static void f_setbufvar(typval_T *argvars, typval_T *rettv);
732static void f_setcharsearch(typval_T *argvars, typval_T *rettv);
733static void f_setcmdpos(typval_T *argvars, typval_T *rettv);
Bram Moolenaar80492532016-03-08 17:08:53 +0100734static void f_setfperm(typval_T *argvars, typval_T *rettv);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100735static void f_setline(typval_T *argvars, typval_T *rettv);
736static void f_setloclist(typval_T *argvars, typval_T *rettv);
737static void f_setmatches(typval_T *argvars, typval_T *rettv);
738static void f_setpos(typval_T *argvars, typval_T *rettv);
739static void f_setqflist(typval_T *argvars, typval_T *rettv);
740static void f_setreg(typval_T *argvars, typval_T *rettv);
741static void f_settabvar(typval_T *argvars, typval_T *rettv);
742static void f_settabwinvar(typval_T *argvars, typval_T *rettv);
743static void f_setwinvar(typval_T *argvars, typval_T *rettv);
Bram Moolenaaraf9aeb92013-02-13 17:35:04 +0100744#ifdef FEAT_CRYPT
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100745static void f_sha256(typval_T *argvars, typval_T *rettv);
Bram Moolenaaraf9aeb92013-02-13 17:35:04 +0100746#endif /* FEAT_CRYPT */
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100747static void f_shellescape(typval_T *argvars, typval_T *rettv);
748static void f_shiftwidth(typval_T *argvars, typval_T *rettv);
749static void f_simplify(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000750#ifdef FEAT_FLOAT
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100751static void f_sin(typval_T *argvars, typval_T *rettv);
752static void f_sinh(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000753#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100754static void f_sort(typval_T *argvars, typval_T *rettv);
755static void f_soundfold(typval_T *argvars, typval_T *rettv);
756static void f_spellbadword(typval_T *argvars, typval_T *rettv);
757static void f_spellsuggest(typval_T *argvars, typval_T *rettv);
758static void f_split(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000759#ifdef FEAT_FLOAT
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100760static void f_sqrt(typval_T *argvars, typval_T *rettv);
761static void f_str2float(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000762#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100763static void f_str2nr(typval_T *argvars, typval_T *rettv);
764static void f_strchars(typval_T *argvars, typval_T *rettv);
Bram Moolenaar33570922005-01-25 22:26:29 +0000765#ifdef HAVE_STRFTIME
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100766static void f_strftime(typval_T *argvars, typval_T *rettv);
Bram Moolenaar33570922005-01-25 22:26:29 +0000767#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100768static void f_stridx(typval_T *argvars, typval_T *rettv);
769static void f_string(typval_T *argvars, typval_T *rettv);
770static void f_strlen(typval_T *argvars, typval_T *rettv);
771static void f_strpart(typval_T *argvars, typval_T *rettv);
772static void f_strridx(typval_T *argvars, typval_T *rettv);
773static void f_strtrans(typval_T *argvars, typval_T *rettv);
774static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv);
775static void f_strwidth(typval_T *argvars, typval_T *rettv);
776static void f_submatch(typval_T *argvars, typval_T *rettv);
777static void f_substitute(typval_T *argvars, typval_T *rettv);
778static void f_synID(typval_T *argvars, typval_T *rettv);
779static void f_synIDattr(typval_T *argvars, typval_T *rettv);
780static void f_synIDtrans(typval_T *argvars, typval_T *rettv);
781static void f_synstack(typval_T *argvars, typval_T *rettv);
782static void f_synconcealed(typval_T *argvars, typval_T *rettv);
783static void f_system(typval_T *argvars, typval_T *rettv);
784static void f_systemlist(typval_T *argvars, typval_T *rettv);
785static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv);
786static void f_tabpagenr(typval_T *argvars, typval_T *rettv);
787static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv);
788static void f_taglist(typval_T *argvars, typval_T *rettv);
789static void f_tagfiles(typval_T *argvars, typval_T *rettv);
790static void f_tempname(typval_T *argvars, typval_T *rettv);
791static void f_test(typval_T *argvars, typval_T *rettv);
Bram Moolenaardb7c6862010-05-21 16:33:48 +0200792#ifdef FEAT_FLOAT
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100793static void f_tan(typval_T *argvars, typval_T *rettv);
794static void f_tanh(typval_T *argvars, typval_T *rettv);
Bram Moolenaardb7c6862010-05-21 16:33:48 +0200795#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100796static void f_tolower(typval_T *argvars, typval_T *rettv);
797static void f_toupper(typval_T *argvars, typval_T *rettv);
798static void f_tr(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000799#ifdef FEAT_FLOAT
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100800static void f_trunc(typval_T *argvars, typval_T *rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000801#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100802static void f_type(typval_T *argvars, typval_T *rettv);
803static void f_undofile(typval_T *argvars, typval_T *rettv);
804static void f_undotree(typval_T *argvars, typval_T *rettv);
805static void f_uniq(typval_T *argvars, typval_T *rettv);
806static void f_values(typval_T *argvars, typval_T *rettv);
807static void f_virtcol(typval_T *argvars, typval_T *rettv);
808static void f_visualmode(typval_T *argvars, typval_T *rettv);
809static void f_wildmenumode(typval_T *argvars, typval_T *rettv);
Bram Moolenaar9cdf86b2016-03-13 19:04:51 +0100810static void f_win_findbuf(typval_T *argvars, typval_T *rettv);
Bram Moolenaar86edef62016-03-13 18:07:30 +0100811static void f_win_getid(typval_T *argvars, typval_T *rettv);
812static void f_win_gotoid(typval_T *argvars, typval_T *rettv);
813static void f_win_id2tabwin(typval_T *argvars, typval_T *rettv);
814static void f_win_id2win(typval_T *argvars, typval_T *rettv);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100815static void f_winbufnr(typval_T *argvars, typval_T *rettv);
816static void f_wincol(typval_T *argvars, typval_T *rettv);
817static void f_winheight(typval_T *argvars, typval_T *rettv);
818static void f_winline(typval_T *argvars, typval_T *rettv);
819static void f_winnr(typval_T *argvars, typval_T *rettv);
820static void f_winrestcmd(typval_T *argvars, typval_T *rettv);
821static void f_winrestview(typval_T *argvars, typval_T *rettv);
822static void f_winsaveview(typval_T *argvars, typval_T *rettv);
823static void f_winwidth(typval_T *argvars, typval_T *rettv);
824static void f_writefile(typval_T *argvars, typval_T *rettv);
825static void f_wordcount(typval_T *argvars, typval_T *rettv);
826static void f_xor(typval_T *argvars, typval_T *rettv);
Bram Moolenaar33570922005-01-25 22:26:29 +0000827
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100828static int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp);
829static pos_T *var2fpos(typval_T *varp, int dollar_lnum, int *fnum);
830static int get_env_len(char_u **arg);
831static int get_id_len(char_u **arg);
832static int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose);
833static char_u *find_name_end(char_u *arg, char_u **expr_start, char_u **expr_end, int flags);
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000834#define FNE_INCL_BR 1 /* find_name_end(): include [] in name */
835#define FNE_CHECK_START 2 /* find_name_end(): check name starts with
836 valid character */
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100837static char_u * make_expanded_name(char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end);
838static int eval_isnamec(int c);
839static int eval_isnamec1(int c);
840static int get_var_tv(char_u *name, int len, typval_T *rettv, dictitem_T **dip, int verbose, int no_autoload);
841static int handle_subscript(char_u **arg, typval_T *rettv, int evaluate, int verbose);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100842static typval_T *alloc_string_tv(char_u *string);
843static void init_tv(typval_T *varp);
Bram Moolenaarf7edf402016-01-19 23:36:15 +0100844#ifdef FEAT_FLOAT
845static float_T get_tv_float(typval_T *varp);
846#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100847static linenr_T get_tv_lnum(typval_T *argvars);
848static linenr_T get_tv_lnum_buf(typval_T *argvars, buf_T *buf);
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100849static dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload);
850static dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, int no_autoload);
851static hashtab_T *find_var_ht(char_u *name, char_u **varname);
852static funccall_T *get_funccal(void);
853static void vars_clear_ext(hashtab_T *ht, int free_val);
854static void delete_var(hashtab_T *ht, hashitem_T *hi);
855static void list_one_var(dictitem_T *v, char_u *prefix, int *first);
856static void list_one_var_a(char_u *prefix, char_u *name, int type, char_u *string, int *first);
857static void set_var(char_u *name, typval_T *varp, int copy);
858static int var_check_ro(int flags, char_u *name, int use_gettext);
859static int var_check_fixed(int flags, char_u *name, int use_gettext);
860static int var_check_func_name(char_u *name, int new_var);
861static int valid_varname(char_u *varname);
862static int tv_check_lock(int lock, char_u *name, int use_gettext);
863static int item_copy(typval_T *from, typval_T *to, int deep, int copyID);
864static char_u *find_option_end(char_u **arg, int *opt_flags);
865static char_u *trans_function_name(char_u **pp, int skip, int flags, funcdict_T *fd);
866static int eval_fname_script(char_u *p);
867static int eval_fname_sid(char_u *p);
868static void list_func_head(ufunc_T *fp, int indent);
869static ufunc_T *find_func(char_u *name);
870static int function_exists(char_u *name);
871static int builtin_function(char_u *name, int len);
Bram Moolenaar05159a02005-02-26 23:04:13 +0000872#ifdef FEAT_PROFILE
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100873static void func_do_profile(ufunc_T *fp);
874static void prof_sort_list(FILE *fd, ufunc_T **sorttab, int st_len, char *title, int prefer_self);
875static void prof_func_line(FILE *fd, int count, proftime_T *total, proftime_T *self, int prefer_self);
Bram Moolenaar73830342005-02-28 22:48:19 +0000876static int
877# ifdef __BORLANDC__
878 _RTLENTRYF
879# endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100880 prof_total_cmp(const void *s1, const void *s2);
Bram Moolenaar73830342005-02-28 22:48:19 +0000881static int
882# ifdef __BORLANDC__
883 _RTLENTRYF
884# endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100885 prof_self_cmp(const void *s1, const void *s2);
Bram Moolenaar05159a02005-02-26 23:04:13 +0000886#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100887static int script_autoload(char_u *name, int reload);
888static char_u *autoload_name(char_u *name);
889static void cat_func_name(char_u *buf, ufunc_T *fp);
890static void func_free(ufunc_T *fp);
891static void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, linenr_T firstline, linenr_T lastline, dict_T *selfdict);
892static int can_free_funccal(funccall_T *fc, int copyID) ;
893static void free_funccal(funccall_T *fc, int free_val);
894static void add_nr_var(dict_T *dp, dictitem_T *v, char *name, varnumber_T nr);
895static win_T *find_win_by_nr(typval_T *vp, tabpage_T *tp);
896static win_T *find_tabwin(typval_T *wvp, typval_T *tvp);
897static void getwinvar(typval_T *argvars, typval_T *rettv, int off);
898static int searchpair_cmn(typval_T *argvars, pos_T *match_pos);
899static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp);
900static void setwinvar(typval_T *argvars, typval_T *rettv, int off);
901static int write_list(FILE *fd, list_T *list, int binary);
902static void get_cmd_output_as_rettv(typval_T *argvars, typval_T *rettv, int retlist);
Bram Moolenaar33570922005-01-25 22:26:29 +0000903
Bram Moolenaar2c704a72010-06-03 21:17:25 +0200904
905#ifdef EBCDIC
Bram Moolenaar48e697e2016-01-23 22:17:30 +0100906static int compare_func_name(const void *s1, const void *s2);
907static void sortFunctions();
Bram Moolenaar2c704a72010-06-03 21:17:25 +0200908#endif
909
Bram Moolenaar33570922005-01-25 22:26:29 +0000910/*
911 * Initialize the global and v: variables.
Bram Moolenaara7043832005-01-21 11:56:39 +0000912 */
913 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100914eval_init(void)
Bram Moolenaara7043832005-01-21 11:56:39 +0000915{
Bram Moolenaar33570922005-01-25 22:26:29 +0000916 int i;
917 struct vimvar *p;
918
Bram Moolenaarbdb62052012-07-16 17:31:53 +0200919 init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE);
920 init_var_dict(&vimvardict, &vimvars_var, VAR_SCOPE);
Bram Moolenaar32f649e2011-04-11 13:46:13 +0200921 vimvardict.dv_lock = VAR_FIXED;
Bram Moolenaar532c7802005-01-27 14:44:31 +0000922 hash_init(&compat_hashtab);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000923 hash_init(&func_hashtab);
Bram Moolenaar33570922005-01-25 22:26:29 +0000924
925 for (i = 0; i < VV_LEN; ++i)
926 {
927 p = &vimvars[i];
928 STRCPY(p->vv_di.di_key, p->vv_name);
929 if (p->vv_flags & VV_RO)
930 p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
931 else if (p->vv_flags & VV_RO_SBX)
932 p->vv_di.di_flags = DI_FLAGS_RO_SBX | DI_FLAGS_FIX;
933 else
934 p->vv_di.di_flags = DI_FLAGS_FIX;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000935
936 /* add to v: scope dict, unless the value is not always available */
937 if (p->vv_type != VAR_UNKNOWN)
938 hash_add(&vimvarht, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000939 if (p->vv_flags & VV_COMPAT)
Bram Moolenaar532c7802005-01-27 14:44:31 +0000940 /* add to compat scope dict */
941 hash_add(&compat_hashtab, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000942 }
Bram Moolenaara542c682016-01-31 16:28:04 +0100943 vimvars[VV_VERSION].vv_nr = VIM_VERSION_100;
944
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000945 set_vim_var_nr(VV_SEARCHFORWARD, 1L);
Bram Moolenaar8050efa2013-11-08 04:30:20 +0100946 set_vim_var_nr(VV_HLSEARCH, 1L);
Bram Moolenaar42a45122015-07-10 17:56:23 +0200947 set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
Bram Moolenaar4649ded2015-12-03 14:55:55 +0100948 set_vim_var_list(VV_ERRORS, list_alloc());
Bram Moolenaar520e1e42016-01-23 19:46:28 +0100949
950 set_vim_var_nr(VV_FALSE, VVAL_FALSE);
951 set_vim_var_nr(VV_TRUE, VVAL_TRUE);
952 set_vim_var_nr(VV_NONE, VVAL_NONE);
953 set_vim_var_nr(VV_NULL, VVAL_NULL);
954
Bram Moolenaarb429cde2012-04-25 18:24:29 +0200955 set_reg_var(0); /* default for v:register is not 0 but '"' */
Bram Moolenaar2c704a72010-06-03 21:17:25 +0200956
957#ifdef EBCDIC
958 /*
Bram Moolenaar195ea0f2011-11-30 14:57:31 +0100959 * Sort the function table, to enable binary search.
Bram Moolenaar2c704a72010-06-03 21:17:25 +0200960 */
961 sortFunctions();
962#endif
Bram Moolenaara7043832005-01-21 11:56:39 +0000963}
964
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000965#if defined(EXITFREE) || defined(PROTO)
966 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100967eval_clear(void)
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000968{
969 int i;
970 struct vimvar *p;
971
972 for (i = 0; i < VV_LEN; ++i)
973 {
974 p = &vimvars[i];
975 if (p->vv_di.di_tv.v_type == VAR_STRING)
Bram Moolenaard9fba312005-06-26 22:34:35 +0000976 {
Bram Moolenaar12193212008-11-09 16:22:01 +0000977 vim_free(p->vv_str);
978 p->vv_str = NULL;
Bram Moolenaard812df62008-11-09 12:46:09 +0000979 }
980 else if (p->vv_di.di_tv.v_type == VAR_LIST)
981 {
982 list_unref(p->vv_list);
983 p->vv_list = NULL;
Bram Moolenaard9fba312005-06-26 22:34:35 +0000984 }
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000985 }
986 hash_clear(&vimvarht);
Bram Moolenaar0f71c6d2008-11-12 14:29:28 +0000987 hash_init(&vimvarht); /* garbage_collect() will access it */
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000988 hash_clear(&compat_hashtab);
989
Bram Moolenaard9fba312005-06-26 22:34:35 +0000990 free_scriptnames();
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +0100991# if defined(FEAT_CMDL_COMPL)
Bram Moolenaar9b486ca2011-05-19 18:26:40 +0200992 free_locales();
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +0100993# endif
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000994
995 /* global variables */
996 vars_clear(&globvarht);
Bram Moolenaard9fba312005-06-26 22:34:35 +0000997
Bram Moolenaaraa35dd12006-04-29 22:03:41 +0000998 /* autoloaded script names */
999 ga_clear_strings(&ga_loaded);
1000
Bram Moolenaarcca74132013-09-25 21:00:28 +02001001 /* Script-local variables. First clear all the variables and in a second
1002 * loop free the scriptvar_T, because a variable in one script might hold
1003 * a reference to the whole scope of another script. */
Bram Moolenaar9577c3e2010-05-14 12:16:25 +02001004 for (i = 1; i <= ga_scripts.ga_len; ++i)
Bram Moolenaar9577c3e2010-05-14 12:16:25 +02001005 vars_clear(&SCRIPT_VARS(i));
Bram Moolenaarcca74132013-09-25 21:00:28 +02001006 for (i = 1; i <= ga_scripts.ga_len; ++i)
Bram Moolenaar9577c3e2010-05-14 12:16:25 +02001007 vim_free(SCRIPT_SV(i));
Bram Moolenaar9577c3e2010-05-14 12:16:25 +02001008 ga_clear(&ga_scripts);
1009
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00001010 /* unreferenced lists and dicts */
1011 (void)garbage_collect();
Bram Moolenaar8c8de832008-06-24 22:58:06 +00001012
1013 /* functions */
1014 free_all_functions();
1015 hash_clear(&func_hashtab);
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +00001016}
1017#endif
1018
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001019/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00001020 * Return the name of the executed function.
1021 */
1022 char_u *
Bram Moolenaarb7604cc2016-01-15 21:23:22 +01001023func_name(void *cookie)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001024{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001025 return ((funccall_T *)cookie)->func->uf_name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001026}
1027
1028/*
1029 * Return the address holding the next breakpoint line for a funccall cookie.
1030 */
1031 linenr_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001032func_breakpoint(void *cookie)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001033{
Bram Moolenaar33570922005-01-25 22:26:29 +00001034 return &((funccall_T *)cookie)->breakpoint;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001035}
1036
1037/*
1038 * Return the address holding the debug tick for a funccall cookie.
1039 */
1040 int *
Bram Moolenaarb7604cc2016-01-15 21:23:22 +01001041func_dbg_tick(void *cookie)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001042{
Bram Moolenaar33570922005-01-25 22:26:29 +00001043 return &((funccall_T *)cookie)->dbg_tick;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001044}
1045
1046/*
1047 * Return the nesting level for a funccall cookie.
1048 */
1049 int
Bram Moolenaarb7604cc2016-01-15 21:23:22 +01001050func_level(void *cookie)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001051{
Bram Moolenaar33570922005-01-25 22:26:29 +00001052 return ((funccall_T *)cookie)->level;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001053}
1054
1055/* pointer to funccal for currently active function */
Bram Moolenaar33570922005-01-25 22:26:29 +00001056funccall_T *current_funccal = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001057
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +00001058/* pointer to list of previously used funccal, still around because some
1059 * item in it is still being used. */
1060funccall_T *previous_funccal = NULL;
1061
Bram Moolenaar071d4272004-06-13 20:20:40 +00001062/*
1063 * Return TRUE when a function was ended by a ":return" command.
1064 */
1065 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001066current_func_returned(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001067{
1068 return current_funccal->returned;
1069}
1070
1071
1072/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00001073 * Set an internal variable to a string value. Creates the variable if it does
1074 * not already exist.
1075 */
1076 void
Bram Moolenaarb7604cc2016-01-15 21:23:22 +01001077set_internal_string_var(char_u *name, char_u *value)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001078{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001079 char_u *val;
Bram Moolenaar33570922005-01-25 22:26:29 +00001080 typval_T *tvp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001081
1082 val = vim_strsave(value);
1083 if (val != NULL)
1084 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001085 tvp = alloc_string_tv(val);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001086 if (tvp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001087 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001088 set_var(name, tvp, FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001089 free_tv(tvp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001090 }
1091 }
1092}
1093
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001094static lval_T *redir_lval = NULL;
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001095static garray_T redir_ga; /* only valid when redir_lval is not NULL */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001096static char_u *redir_endp = NULL;
1097static char_u *redir_varname = NULL;
1098
1099/*
1100 * Start recording command output to a variable
Bram Moolenaarb7604cc2016-01-15 21:23:22 +01001101 * When "append" is TRUE append to an existing variable.
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001102 * Returns OK if successfully completed the setup. FAIL otherwise.
1103 */
1104 int
Bram Moolenaarb7604cc2016-01-15 21:23:22 +01001105var_redir_start(char_u *name, int append)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001106{
1107 int save_emsg;
1108 int err;
1109 typval_T tv;
1110
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +00001111 /* Catch a bad name early. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001112 if (!eval_isnamec1(*name))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001113 {
1114 EMSG(_(e_invarg));
1115 return FAIL;
1116 }
1117
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +00001118 /* Make a copy of the name, it is used in redir_lval until redir ends. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001119 redir_varname = vim_strsave(name);
1120 if (redir_varname == NULL)
1121 return FAIL;
1122
1123 redir_lval = (lval_T *)alloc_clear((unsigned)sizeof(lval_T));
1124 if (redir_lval == NULL)
1125 {
1126 var_redir_stop();
1127 return FAIL;
1128 }
1129
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001130 /* The output is stored in growarray "redir_ga" until redirection ends. */
1131 ga_init2(&redir_ga, (int)sizeof(char), 500);
1132
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001133 /* Parse the variable name (can be a dict or list entry). */
Bram Moolenaar6d977d62014-01-14 15:24:39 +01001134 redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, 0,
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001135 FNE_CHECK_START);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001136 if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != NUL)
1137 {
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +02001138 clear_lval(redir_lval);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001139 if (redir_endp != NULL && *redir_endp != NUL)
1140 /* Trailing characters are present after the variable name */
1141 EMSG(_(e_trailing));
1142 else
1143 EMSG(_(e_invarg));
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +00001144 redir_endp = NULL; /* don't store a value, only cleanup */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001145 var_redir_stop();
1146 return FAIL;
1147 }
1148
1149 /* check if we can write to the variable: set it to or append an empty
1150 * string */
1151 save_emsg = did_emsg;
1152 did_emsg = FALSE;
1153 tv.v_type = VAR_STRING;
1154 tv.vval.v_string = (char_u *)"";
1155 if (append)
1156 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)".");
1157 else
1158 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)"=");
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +02001159 clear_lval(redir_lval);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001160 err = did_emsg;
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00001161 did_emsg |= save_emsg;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001162 if (err)
1163 {
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +00001164 redir_endp = NULL; /* don't store a value, only cleanup */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001165 var_redir_stop();
1166 return FAIL;
1167 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001168
1169 return OK;
1170}
1171
1172/*
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001173 * Append "value[value_len]" to the variable set by var_redir_start().
1174 * The actual appending is postponed until redirection ends, because the value
1175 * appended may in fact be the string we write to, changing it may cause freed
1176 * memory to be used:
1177 * :redir => foo
1178 * :let foo
1179 * :redir END
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001180 */
1181 void
Bram Moolenaarb7604cc2016-01-15 21:23:22 +01001182var_redir_str(char_u *value, int value_len)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001183{
Bram Moolenaar5fdec472007-07-24 08:45:13 +00001184 int len;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001185
1186 if (redir_lval == NULL)
1187 return;
1188
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001189 if (value_len == -1)
Bram Moolenaar5fdec472007-07-24 08:45:13 +00001190 len = (int)STRLEN(value); /* Append the entire string */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001191 else
Bram Moolenaar5fdec472007-07-24 08:45:13 +00001192 len = value_len; /* Append only "value_len" characters */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001193
Bram Moolenaar5fdec472007-07-24 08:45:13 +00001194 if (ga_grow(&redir_ga, len) == OK)
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001195 {
1196 mch_memmove((char *)redir_ga.ga_data + redir_ga.ga_len, value, len);
Bram Moolenaar5fdec472007-07-24 08:45:13 +00001197 redir_ga.ga_len += len;
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001198 }
1199 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001200 var_redir_stop();
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001201}
1202
1203/*
1204 * Stop redirecting command output to a variable.
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +00001205 * Frees the allocated memory.
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001206 */
1207 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001208var_redir_stop(void)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001209{
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001210 typval_T tv;
1211
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001212 if (redir_lval != NULL)
1213 {
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +00001214 /* If there was no error: assign the text to the variable. */
1215 if (redir_endp != NULL)
1216 {
1217 ga_append(&redir_ga, NUL); /* Append the trailing NUL. */
1218 tv.v_type = VAR_STRING;
1219 tv.vval.v_string = redir_ga.ga_data;
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +02001220 /* Call get_lval() again, if it's inside a Dict or List it may
1221 * have changed. */
1222 redir_endp = get_lval(redir_varname, NULL, redir_lval,
Bram Moolenaar6d977d62014-01-14 15:24:39 +01001223 FALSE, FALSE, 0, FNE_CHECK_START);
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +02001224 if (redir_endp != NULL && redir_lval->ll_name != NULL)
1225 set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)".");
1226 clear_lval(redir_lval);
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +00001227 }
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001228
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +00001229 /* free the collected output */
1230 vim_free(redir_ga.ga_data);
1231 redir_ga.ga_data = NULL;
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001232
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001233 vim_free(redir_lval);
1234 redir_lval = NULL;
1235 }
1236 vim_free(redir_varname);
1237 redir_varname = NULL;
1238}
1239
Bram Moolenaar071d4272004-06-13 20:20:40 +00001240# if defined(FEAT_MBYTE) || defined(PROTO)
1241 int
Bram Moolenaarb7604cc2016-01-15 21:23:22 +01001242eval_charconvert(
1243 char_u *enc_from,
1244 char_u *enc_to,
1245 char_u *fname_from,
1246 char_u *fname_to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001247{
1248 int err = FALSE;
1249
1250 set_vim_var_string(VV_CC_FROM, enc_from, -1);
1251 set_vim_var_string(VV_CC_TO, enc_to, -1);
1252 set_vim_var_string(VV_FNAME_IN, fname_from, -1);
1253 set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
1254 if (eval_to_bool(p_ccv, &err, NULL, FALSE))
1255 err = TRUE;
1256 set_vim_var_string(VV_CC_FROM, NULL, -1);
1257 set_vim_var_string(VV_CC_TO, NULL, -1);
1258 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1259 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
1260
1261 if (err)
1262 return FAIL;
1263 return OK;
1264}
1265# endif
1266
1267# if defined(FEAT_POSTSCRIPT) || defined(PROTO)
1268 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001269eval_printexpr(char_u *fname, char_u *args)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001270{
1271 int err = FALSE;
1272
1273 set_vim_var_string(VV_FNAME_IN, fname, -1);
1274 set_vim_var_string(VV_CMDARG, args, -1);
1275 if (eval_to_bool(p_pexpr, &err, NULL, FALSE))
1276 err = TRUE;
1277 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1278 set_vim_var_string(VV_CMDARG, NULL, -1);
1279
1280 if (err)
1281 {
1282 mch_remove(fname);
1283 return FAIL;
1284 }
1285 return OK;
1286}
1287# endif
1288
1289# if defined(FEAT_DIFF) || defined(PROTO)
1290 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001291eval_diff(
1292 char_u *origfile,
1293 char_u *newfile,
1294 char_u *outfile)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001295{
1296 int err = FALSE;
1297
1298 set_vim_var_string(VV_FNAME_IN, origfile, -1);
1299 set_vim_var_string(VV_FNAME_NEW, newfile, -1);
1300 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
1301 (void)eval_to_bool(p_dex, &err, NULL, FALSE);
1302 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1303 set_vim_var_string(VV_FNAME_NEW, NULL, -1);
1304 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
1305}
1306
1307 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001308eval_patch(
1309 char_u *origfile,
1310 char_u *difffile,
1311 char_u *outfile)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001312{
1313 int err;
1314
1315 set_vim_var_string(VV_FNAME_IN, origfile, -1);
1316 set_vim_var_string(VV_FNAME_DIFF, difffile, -1);
1317 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
1318 (void)eval_to_bool(p_pex, &err, NULL, FALSE);
1319 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1320 set_vim_var_string(VV_FNAME_DIFF, NULL, -1);
1321 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
1322}
1323# endif
1324
1325/*
1326 * Top level evaluation function, returning a boolean.
1327 * Sets "error" to TRUE if there was an error.
1328 * Return TRUE or FALSE.
1329 */
1330 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001331eval_to_bool(
1332 char_u *arg,
1333 int *error,
1334 char_u **nextcmd,
1335 int skip) /* only parse, don't execute */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001336{
Bram Moolenaar33570922005-01-25 22:26:29 +00001337 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001338 int retval = FALSE;
1339
1340 if (skip)
1341 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001342 if (eval0(arg, &tv, nextcmd, !skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001343 *error = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001344 else
1345 {
1346 *error = FALSE;
1347 if (!skip)
1348 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001349 retval = (get_tv_number_chk(&tv, error) != 0);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001350 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001351 }
1352 }
1353 if (skip)
1354 --emsg_skip;
1355
1356 return retval;
1357}
1358
1359/*
1360 * Top level evaluation function, returning a string. If "skip" is TRUE,
1361 * only parsing to "nextcmd" is done, without reporting errors. Return
1362 * pointer to allocated memory, or NULL for failure or when "skip" is TRUE.
1363 */
1364 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001365eval_to_string_skip(
1366 char_u *arg,
1367 char_u **nextcmd,
1368 int skip) /* only parse, don't execute */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001369{
Bram Moolenaar33570922005-01-25 22:26:29 +00001370 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001371 char_u *retval;
1372
1373 if (skip)
1374 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001375 if (eval0(arg, &tv, nextcmd, !skip) == FAIL || skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001376 retval = NULL;
1377 else
1378 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001379 retval = vim_strsave(get_tv_string(&tv));
1380 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001381 }
1382 if (skip)
1383 --emsg_skip;
1384
1385 return retval;
1386}
1387
1388/*
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001389 * Skip over an expression at "*pp".
1390 * Return FAIL for an error, OK otherwise.
1391 */
1392 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001393skip_expr(char_u **pp)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001394{
Bram Moolenaar33570922005-01-25 22:26:29 +00001395 typval_T rettv;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001396
1397 *pp = skipwhite(*pp);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001398 return eval1(pp, &rettv, FALSE);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001399}
1400
1401/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00001402 * Top level evaluation function, returning a string.
Bram Moolenaara85fb752008-09-07 11:55:43 +00001403 * When "convert" is TRUE convert a List into a sequence of lines and convert
1404 * a Float to a String.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001405 * Return pointer to allocated memory, or NULL for failure.
1406 */
1407 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001408eval_to_string(
1409 char_u *arg,
1410 char_u **nextcmd,
1411 int convert)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001412{
Bram Moolenaar33570922005-01-25 22:26:29 +00001413 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001414 char_u *retval;
Bram Moolenaar362e1a32006-03-06 23:29:24 +00001415 garray_T ga;
Bram Moolenaar798b30b2009-04-22 10:56:16 +00001416#ifdef FEAT_FLOAT
Bram Moolenaara85fb752008-09-07 11:55:43 +00001417 char_u numbuf[NUMBUFLEN];
Bram Moolenaar798b30b2009-04-22 10:56:16 +00001418#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001419
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001420 if (eval0(arg, &tv, nextcmd, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001421 retval = NULL;
1422 else
1423 {
Bram Moolenaara85fb752008-09-07 11:55:43 +00001424 if (convert && tv.v_type == VAR_LIST)
Bram Moolenaar362e1a32006-03-06 23:29:24 +00001425 {
1426 ga_init2(&ga, (int)sizeof(char), 80);
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00001427 if (tv.vval.v_list != NULL)
Bram Moolenaar213b10a2011-08-10 12:38:08 +02001428 {
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00001429 list_join(&ga, tv.vval.v_list, (char_u *)"\n", TRUE, 0);
Bram Moolenaar213b10a2011-08-10 12:38:08 +02001430 if (tv.vval.v_list->lv_len > 0)
1431 ga_append(&ga, NL);
1432 }
Bram Moolenaar362e1a32006-03-06 23:29:24 +00001433 ga_append(&ga, NUL);
1434 retval = (char_u *)ga.ga_data;
1435 }
Bram Moolenaara85fb752008-09-07 11:55:43 +00001436#ifdef FEAT_FLOAT
1437 else if (convert && tv.v_type == VAR_FLOAT)
1438 {
1439 vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv.vval.v_float);
1440 retval = vim_strsave(numbuf);
1441 }
1442#endif
Bram Moolenaar362e1a32006-03-06 23:29:24 +00001443 else
1444 retval = vim_strsave(get_tv_string(&tv));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001445 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001446 }
1447
1448 return retval;
1449}
1450
1451/*
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001452 * Call eval_to_string() without using current local variables and using
1453 * textlock. When "use_sandbox" is TRUE use the sandbox.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001454 */
1455 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001456eval_to_string_safe(
1457 char_u *arg,
1458 char_u **nextcmd,
1459 int use_sandbox)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001460{
1461 char_u *retval;
1462 void *save_funccalp;
1463
1464 save_funccalp = save_funccal();
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001465 if (use_sandbox)
1466 ++sandbox;
1467 ++textlock;
Bram Moolenaar362e1a32006-03-06 23:29:24 +00001468 retval = eval_to_string(arg, nextcmd, FALSE);
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001469 if (use_sandbox)
1470 --sandbox;
1471 --textlock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001472 restore_funccal(save_funccalp);
1473 return retval;
1474}
1475
Bram Moolenaar071d4272004-06-13 20:20:40 +00001476/*
1477 * Top level evaluation function, returning a number.
1478 * Evaluates "expr" silently.
1479 * Returns -1 for an error.
1480 */
1481 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001482eval_to_number(char_u *expr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001483{
Bram Moolenaar33570922005-01-25 22:26:29 +00001484 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001485 int retval;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00001486 char_u *p = skipwhite(expr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001487
1488 ++emsg_off;
1489
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001490 if (eval1(&p, &rettv, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001491 retval = -1;
1492 else
1493 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001494 retval = get_tv_number_chk(&rettv, NULL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001495 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001496 }
1497 --emsg_off;
1498
1499 return retval;
1500}
1501
Bram Moolenaara40058a2005-07-11 22:42:07 +00001502/*
1503 * Prepare v: variable "idx" to be used.
1504 * Save the current typeval in "save_tv".
1505 * When not used yet add the variable to the v: hashtable.
1506 */
1507 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001508prepare_vimvar(int idx, typval_T *save_tv)
Bram Moolenaara40058a2005-07-11 22:42:07 +00001509{
1510 *save_tv = vimvars[idx].vv_tv;
1511 if (vimvars[idx].vv_type == VAR_UNKNOWN)
1512 hash_add(&vimvarht, vimvars[idx].vv_di.di_key);
1513}
1514
1515/*
1516 * Restore v: variable "idx" to typeval "save_tv".
1517 * When no longer defined, remove the variable from the v: hashtable.
1518 */
1519 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001520restore_vimvar(int idx, typval_T *save_tv)
Bram Moolenaara40058a2005-07-11 22:42:07 +00001521{
1522 hashitem_T *hi;
1523
Bram Moolenaara40058a2005-07-11 22:42:07 +00001524 vimvars[idx].vv_tv = *save_tv;
1525 if (vimvars[idx].vv_type == VAR_UNKNOWN)
1526 {
1527 hi = hash_find(&vimvarht, vimvars[idx].vv_di.di_key);
1528 if (HASHITEM_EMPTY(hi))
1529 EMSG2(_(e_intern2), "restore_vimvar()");
1530 else
1531 hash_remove(&vimvarht, hi);
1532 }
1533}
1534
Bram Moolenaar3c56a962006-03-12 22:19:04 +00001535#if defined(FEAT_SPELL) || defined(PROTO)
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001536/*
1537 * Evaluate an expression to a list with suggestions.
1538 * For the "expr:" part of 'spellsuggest'.
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00001539 * Returns NULL when there is an error.
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001540 */
1541 list_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001542eval_spell_expr(char_u *badword, char_u *expr)
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001543{
1544 typval_T save_val;
1545 typval_T rettv;
1546 list_T *list = NULL;
1547 char_u *p = skipwhite(expr);
1548
1549 /* Set "v:val" to the bad word. */
1550 prepare_vimvar(VV_VAL, &save_val);
1551 vimvars[VV_VAL].vv_type = VAR_STRING;
1552 vimvars[VV_VAL].vv_str = badword;
1553 if (p_verbose == 0)
1554 ++emsg_off;
1555
1556 if (eval1(&p, &rettv, TRUE) == OK)
1557 {
1558 if (rettv.v_type != VAR_LIST)
1559 clear_tv(&rettv);
1560 else
1561 list = rettv.vval.v_list;
1562 }
1563
1564 if (p_verbose == 0)
1565 --emsg_off;
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001566 restore_vimvar(VV_VAL, &save_val);
1567
1568 return list;
1569}
1570
1571/*
1572 * "list" is supposed to contain two items: a word and a number. Return the
1573 * word in "pp" and the number as the return value.
1574 * Return -1 if anything isn't right.
1575 * Used to get the good word and score from the eval_spell_expr() result.
1576 */
1577 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001578get_spellword(list_T *list, char_u **pp)
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001579{
1580 listitem_T *li;
1581
1582 li = list->lv_first;
1583 if (li == NULL)
1584 return -1;
1585 *pp = get_tv_string(&li->li_tv);
1586
1587 li = li->li_next;
1588 if (li == NULL)
1589 return -1;
1590 return get_tv_number(&li->li_tv);
1591}
1592#endif
1593
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001594/*
Bram Moolenaar4770d092006-01-12 23:22:24 +00001595 * Top level evaluation function.
1596 * Returns an allocated typval_T with the result.
1597 * Returns NULL when there is an error.
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001598 */
1599 typval_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001600eval_expr(char_u *arg, char_u **nextcmd)
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001601{
1602 typval_T *tv;
1603
1604 tv = (typval_T *)alloc(sizeof(typval_T));
Bram Moolenaar4770d092006-01-12 23:22:24 +00001605 if (tv != NULL && eval0(arg, tv, nextcmd, TRUE) == FAIL)
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001606 {
1607 vim_free(tv);
Bram Moolenaar4770d092006-01-12 23:22:24 +00001608 tv = NULL;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001609 }
1610
1611 return tv;
1612}
1613
1614
Bram Moolenaar071d4272004-06-13 20:20:40 +00001615/*
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001616 * Call some vimL function and return the result in "*rettv".
Bram Moolenaar8c8de832008-06-24 22:58:06 +00001617 * Uses argv[argc] for the function arguments. Only Number and String
1618 * arguments are currently supported.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001619 * Returns OK or FAIL.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001620 */
Bram Moolenaar82139082011-09-14 16:52:09 +02001621 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001622call_vim_function(
1623 char_u *func,
1624 int argc,
1625 char_u **argv,
1626 int safe, /* use the sandbox */
1627 int str_arg_only, /* all arguments are strings */
1628 typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001629{
Bram Moolenaar33570922005-01-25 22:26:29 +00001630 typval_T *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001631 long n;
1632 int len;
1633 int i;
1634 int doesrange;
1635 void *save_funccalp = NULL;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001636 int ret;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001637
Bram Moolenaareb3593b2006-04-22 22:33:57 +00001638 argvars = (typval_T *)alloc((unsigned)((argc + 1) * sizeof(typval_T)));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001639 if (argvars == NULL)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001640 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001641
1642 for (i = 0; i < argc; i++)
1643 {
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00001644 /* Pass a NULL or empty argument as an empty string */
1645 if (argv[i] == NULL || *argv[i] == NUL)
1646 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001647 argvars[i].v_type = VAR_STRING;
1648 argvars[i].vval.v_string = (char_u *)"";
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00001649 continue;
1650 }
1651
Bram Moolenaar0cbba942012-07-25 16:47:03 +02001652 if (str_arg_only)
1653 len = 0;
1654 else
1655 /* Recognize a number argument, the others must be strings. */
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001656 vim_str2nr(argv[i], NULL, &len, STR2NR_ALL, &n, NULL, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001657 if (len != 0 && len == (int)STRLEN(argv[i]))
1658 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001659 argvars[i].v_type = VAR_NUMBER;
1660 argvars[i].vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001661 }
1662 else
1663 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001664 argvars[i].v_type = VAR_STRING;
1665 argvars[i].vval.v_string = argv[i];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001666 }
1667 }
1668
1669 if (safe)
1670 {
1671 save_funccalp = save_funccal();
1672 ++sandbox;
1673 }
1674
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001675 rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */
1676 ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001677 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001678 &doesrange, TRUE, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001679 if (safe)
1680 {
1681 --sandbox;
1682 restore_funccal(save_funccalp);
1683 }
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001684 vim_free(argvars);
1685
1686 if (ret == FAIL)
1687 clear_tv(rettv);
1688
1689 return ret;
1690}
1691
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001692/*
1693 * Call vimL function "func" and return the result as a number.
1694 * Returns -1 when calling the function fails.
1695 * Uses argv[argc] for the function arguments.
1696 */
1697 long
Bram Moolenaar7454a062016-01-30 15:14:10 +01001698call_func_retnr(
1699 char_u *func,
1700 int argc,
1701 char_u **argv,
1702 int safe) /* use the sandbox */
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001703{
1704 typval_T rettv;
1705 long retval;
1706
1707 /* All arguments are passed as strings, no conversion to number. */
1708 if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL)
1709 return -1;
1710
1711 retval = get_tv_number_chk(&rettv, NULL);
1712 clear_tv(&rettv);
1713 return retval;
1714}
1715
1716#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) \
1717 || defined(FEAT_COMPL_FUNC) || defined(PROTO)
1718
Bram Moolenaar4f688582007-07-24 12:34:30 +00001719# if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001720/*
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001721 * Call vimL function "func" and return the result as a string.
1722 * Returns NULL when calling the function fails.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001723 * Uses argv[argc] for the function arguments.
1724 */
1725 void *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001726call_func_retstr(
1727 char_u *func,
1728 int argc,
1729 char_u **argv,
1730 int safe) /* use the sandbox */
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001731{
1732 typval_T rettv;
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001733 char_u *retval;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001734
Bram Moolenaar0cbba942012-07-25 16:47:03 +02001735 /* All arguments are passed as strings, no conversion to number. */
1736 if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001737 return NULL;
1738
1739 retval = vim_strsave(get_tv_string(&rettv));
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001740 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001741 return retval;
1742}
Bram Moolenaar4f688582007-07-24 12:34:30 +00001743# endif
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001744
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001745/*
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00001746 * Call vimL function "func" and return the result as a List.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001747 * Uses argv[argc] for the function arguments.
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00001748 * Returns NULL when there is something wrong.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001749 */
1750 void *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001751call_func_retlist(
1752 char_u *func,
1753 int argc,
1754 char_u **argv,
1755 int safe) /* use the sandbox */
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001756{
1757 typval_T rettv;
1758
Bram Moolenaar0cbba942012-07-25 16:47:03 +02001759 /* All arguments are passed as strings, no conversion to number. */
1760 if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001761 return NULL;
1762
1763 if (rettv.v_type != VAR_LIST)
1764 {
1765 clear_tv(&rettv);
1766 return NULL;
1767 }
1768
1769 return rettv.vval.v_list;
1770}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001771#endif
1772
1773/*
1774 * Save the current function call pointer, and set it to NULL.
1775 * Used when executing autocommands and for ":source".
1776 */
1777 void *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001778save_funccal(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001779{
Bram Moolenaar05159a02005-02-26 23:04:13 +00001780 funccall_T *fc = current_funccal;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001781
Bram Moolenaar071d4272004-06-13 20:20:40 +00001782 current_funccal = NULL;
1783 return (void *)fc;
1784}
1785
1786 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001787restore_funccal(void *vfc)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001788{
Bram Moolenaar05159a02005-02-26 23:04:13 +00001789 funccall_T *fc = (funccall_T *)vfc;
1790
1791 current_funccal = fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001792}
1793
Bram Moolenaar05159a02005-02-26 23:04:13 +00001794#if defined(FEAT_PROFILE) || defined(PROTO)
1795/*
1796 * Prepare profiling for entering a child or something else that is not
1797 * counted for the script/function itself.
1798 * Should always be called in pair with prof_child_exit().
1799 */
1800 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001801prof_child_enter(
1802 proftime_T *tm) /* place to store waittime */
Bram Moolenaar05159a02005-02-26 23:04:13 +00001803{
1804 funccall_T *fc = current_funccal;
1805
1806 if (fc != NULL && fc->func->uf_profiling)
1807 profile_start(&fc->prof_child);
1808 script_prof_save(tm);
1809}
1810
1811/*
1812 * Take care of time spent in a child.
1813 * Should always be called after prof_child_enter().
1814 */
1815 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001816prof_child_exit(
1817 proftime_T *tm) /* where waittime was stored */
Bram Moolenaar05159a02005-02-26 23:04:13 +00001818{
1819 funccall_T *fc = current_funccal;
1820
1821 if (fc != NULL && fc->func->uf_profiling)
1822 {
1823 profile_end(&fc->prof_child);
1824 profile_sub_wait(tm, &fc->prof_child); /* don't count waiting time */
1825 profile_add(&fc->func->uf_tm_children, &fc->prof_child);
1826 profile_add(&fc->func->uf_tml_children, &fc->prof_child);
1827 }
1828 script_prof_restore(tm);
1829}
1830#endif
1831
1832
Bram Moolenaar071d4272004-06-13 20:20:40 +00001833#ifdef FEAT_FOLDING
1834/*
1835 * Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding
1836 * it in "*cp". Doesn't give error messages.
1837 */
1838 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001839eval_foldexpr(char_u *arg, int *cp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001840{
Bram Moolenaar33570922005-01-25 22:26:29 +00001841 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001842 int retval;
1843 char_u *s;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00001844 int use_sandbox = was_set_insecurely((char_u *)"foldexpr",
1845 OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001846
1847 ++emsg_off;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001848 if (use_sandbox)
1849 ++sandbox;
1850 ++textlock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001851 *cp = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001852 if (eval0(arg, &tv, NULL, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001853 retval = 0;
1854 else
1855 {
1856 /* If the result is a number, just return the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001857 if (tv.v_type == VAR_NUMBER)
1858 retval = tv.vval.v_number;
Bram Moolenaar758711c2005-02-02 23:11:38 +00001859 else if (tv.v_type != VAR_STRING || tv.vval.v_string == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001860 retval = 0;
1861 else
1862 {
1863 /* If the result is a string, check if there is a non-digit before
1864 * the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001865 s = tv.vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001866 if (!VIM_ISDIGIT(*s) && *s != '-')
1867 *cp = *s++;
1868 retval = atol((char *)s);
1869 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001870 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001871 }
1872 --emsg_off;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001873 if (use_sandbox)
1874 --sandbox;
1875 --textlock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001876
1877 return retval;
1878}
1879#endif
1880
Bram Moolenaar071d4272004-06-13 20:20:40 +00001881/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001882 * ":let" list all variable values
1883 * ":let var1 var2" list variable values
1884 * ":let var = expr" assignment command.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001885 * ":let var += expr" assignment command.
1886 * ":let var -= expr" assignment command.
1887 * ":let var .= expr" assignment command.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001888 * ":let [var1, var2] = expr" unpack list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001889 */
1890 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001891ex_let(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001892{
1893 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001894 char_u *expr = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00001895 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001896 int i;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001897 int var_count = 0;
1898 int semicolon = 0;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001899 char_u op[2];
Bram Moolenaardb552d602006-03-23 22:59:57 +00001900 char_u *argend;
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001901 int first = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001902
Bram Moolenaardb552d602006-03-23 22:59:57 +00001903 argend = skip_var_list(arg, &var_count, &semicolon);
1904 if (argend == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001905 return;
Bram Moolenaar76b92b22006-03-24 22:46:53 +00001906 if (argend > arg && argend[-1] == '.') /* for var.='str' */
1907 --argend;
Bram Moolenaara3920382014-03-30 16:49:09 +02001908 expr = skipwhite(argend);
1909 if (*expr != '=' && !(vim_strchr((char_u *)"+-.", *expr) != NULL
1910 && expr[1] == '='))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001911 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001912 /*
1913 * ":let" without "=": list variables
1914 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001915 if (*arg == '[')
1916 EMSG(_(e_invarg));
1917 else if (!ends_excmd(*arg))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001918 /* ":let var1 var2" */
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001919 arg = list_arg_vars(eap, arg, &first);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001920 else if (!eap->skip)
Bram Moolenaara7043832005-01-21 11:56:39 +00001921 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001922 /* ":let" */
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001923 list_glob_vars(&first);
1924 list_buf_vars(&first);
1925 list_win_vars(&first);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001926#ifdef FEAT_WINDOWS
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001927 list_tab_vars(&first);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001928#endif
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001929 list_script_vars(&first);
1930 list_func_vars(&first);
1931 list_vim_vars(&first);
Bram Moolenaara7043832005-01-21 11:56:39 +00001932 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001933 eap->nextcmd = check_nextcmd(arg);
1934 }
1935 else
1936 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001937 op[0] = '=';
1938 op[1] = NUL;
Bram Moolenaara3920382014-03-30 16:49:09 +02001939 if (*expr != '=')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001940 {
Bram Moolenaara3920382014-03-30 16:49:09 +02001941 if (vim_strchr((char_u *)"+-.", *expr) != NULL)
1942 op[0] = *expr; /* +=, -= or .= */
1943 expr = skipwhite(expr + 2);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001944 }
Bram Moolenaara3920382014-03-30 16:49:09 +02001945 else
1946 expr = skipwhite(expr + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001947
Bram Moolenaar071d4272004-06-13 20:20:40 +00001948 if (eap->skip)
1949 ++emsg_skip;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001950 i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001951 if (eap->skip)
1952 {
1953 if (i != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001954 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001955 --emsg_skip;
1956 }
1957 else if (i != FAIL)
1958 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001959 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001960 op);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001961 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001962 }
1963 }
1964}
1965
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001966/*
1967 * Assign the typevalue "tv" to the variable or variables at "arg_start".
1968 * Handles both "var" with any type and "[var, var; var]" with a list type.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001969 * When "nextchars" is not NULL it points to a string with characters that
1970 * must appear after the variable(s). Use "+", "-" or "." for add, subtract
1971 * or concatenate.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001972 * Returns OK or FAIL;
1973 */
1974 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001975ex_let_vars(
1976 char_u *arg_start,
1977 typval_T *tv,
1978 int copy, /* copy values from "tv", don't move */
1979 int semicolon, /* from skip_var_list() */
1980 int var_count, /* from skip_var_list() */
1981 char_u *nextchars)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001982{
1983 char_u *arg = arg_start;
Bram Moolenaar33570922005-01-25 22:26:29 +00001984 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001985 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00001986 listitem_T *item;
1987 typval_T ltv;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001988
1989 if (*arg != '[')
1990 {
1991 /*
1992 * ":let var = expr" or ":for var in list"
1993 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001994 if (ex_let_one(arg, tv, copy, nextchars, nextchars) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001995 return FAIL;
1996 return OK;
1997 }
1998
1999 /*
2000 * ":let [v1, v2] = list" or ":for [v1, v2] in listlist"
2001 */
Bram Moolenaar758711c2005-02-02 23:11:38 +00002002 if (tv->v_type != VAR_LIST || (l = tv->vval.v_list) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002003 {
2004 EMSG(_(e_listreq));
2005 return FAIL;
2006 }
2007
2008 i = list_len(l);
2009 if (semicolon == 0 && var_count < i)
2010 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00002011 EMSG(_("E687: Less targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002012 return FAIL;
2013 }
2014 if (var_count - semicolon > i)
2015 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00002016 EMSG(_("E688: More targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002017 return FAIL;
2018 }
2019
2020 item = l->lv_first;
2021 while (*arg != ']')
2022 {
2023 arg = skipwhite(arg + 1);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002024 arg = ex_let_one(arg, &item->li_tv, TRUE, (char_u *)",;]", nextchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002025 item = item->li_next;
2026 if (arg == NULL)
2027 return FAIL;
2028
2029 arg = skipwhite(arg);
2030 if (*arg == ';')
2031 {
2032 /* Put the rest of the list (may be empty) in the var after ';'.
2033 * Create a new list for this. */
2034 l = list_alloc();
2035 if (l == NULL)
2036 return FAIL;
2037 while (item != NULL)
2038 {
2039 list_append_tv(l, &item->li_tv);
2040 item = item->li_next;
2041 }
2042
2043 ltv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002044 ltv.v_lock = 0;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002045 ltv.vval.v_list = l;
2046 l->lv_refcount = 1;
2047
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002048 arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE,
2049 (char_u *)"]", nextchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002050 clear_tv(&ltv);
2051 if (arg == NULL)
2052 return FAIL;
2053 break;
2054 }
2055 else if (*arg != ',' && *arg != ']')
2056 {
2057 EMSG2(_(e_intern2), "ex_let_vars()");
2058 return FAIL;
2059 }
2060 }
2061
2062 return OK;
2063}
2064
2065/*
2066 * Skip over assignable variable "var" or list of variables "[var, var]".
2067 * Used for ":let varvar = expr" and ":for varvar in expr".
2068 * For "[var, var]" increment "*var_count" for each variable.
2069 * for "[var, var; var]" set "semicolon".
2070 * Return NULL for an error.
2071 */
2072 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01002073skip_var_list(
2074 char_u *arg,
2075 int *var_count,
2076 int *semicolon)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002077{
2078 char_u *p, *s;
2079
2080 if (*arg == '[')
2081 {
2082 /* "[var, var]": find the matching ']'. */
2083 p = arg;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00002084 for (;;)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002085 {
2086 p = skipwhite(p + 1); /* skip whites after '[', ';' or ',' */
2087 s = skip_var_one(p);
2088 if (s == p)
2089 {
2090 EMSG2(_(e_invarg2), p);
2091 return NULL;
2092 }
2093 ++*var_count;
2094
2095 p = skipwhite(s);
2096 if (*p == ']')
2097 break;
2098 else if (*p == ';')
2099 {
2100 if (*semicolon == 1)
2101 {
2102 EMSG(_("Double ; in list of variables"));
2103 return NULL;
2104 }
2105 *semicolon = 1;
2106 }
2107 else if (*p != ',')
2108 {
2109 EMSG2(_(e_invarg2), p);
2110 return NULL;
2111 }
2112 }
2113 return p + 1;
2114 }
2115 else
2116 return skip_var_one(arg);
2117}
2118
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002119/*
Bram Moolenaarbae0c162007-05-10 19:30:25 +00002120 * Skip one (assignable) variable name, including @r, $VAR, &option, d.key,
Bram Moolenaar92124a32005-06-17 22:03:40 +00002121 * l[idx].
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002122 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002123 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01002124skip_var_one(char_u *arg)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002125{
Bram Moolenaar92124a32005-06-17 22:03:40 +00002126 if (*arg == '@' && arg[1] != NUL)
2127 return arg + 2;
2128 return find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg,
2129 NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002130}
2131
Bram Moolenaara7043832005-01-21 11:56:39 +00002132/*
Bram Moolenaar33570922005-01-25 22:26:29 +00002133 * List variables for hashtab "ht" with prefix "prefix".
2134 * If "empty" is TRUE also list NULL strings as empty strings.
Bram Moolenaara7043832005-01-21 11:56:39 +00002135 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002136 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002137list_hashtable_vars(
2138 hashtab_T *ht,
2139 char_u *prefix,
2140 int empty,
2141 int *first)
Bram Moolenaara7043832005-01-21 11:56:39 +00002142{
Bram Moolenaar33570922005-01-25 22:26:29 +00002143 hashitem_T *hi;
2144 dictitem_T *di;
Bram Moolenaara7043832005-01-21 11:56:39 +00002145 int todo;
2146
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00002147 todo = (int)ht->ht_used;
Bram Moolenaara7043832005-01-21 11:56:39 +00002148 for (hi = ht->ht_array; todo > 0 && !got_int; ++hi)
2149 {
2150 if (!HASHITEM_EMPTY(hi))
2151 {
2152 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00002153 di = HI2DI(hi);
2154 if (empty || di->di_tv.v_type != VAR_STRING
2155 || di->di_tv.vval.v_string != NULL)
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002156 list_one_var(di, prefix, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00002157 }
2158 }
2159}
2160
2161/*
2162 * List global variables.
2163 */
2164 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002165list_glob_vars(int *first)
Bram Moolenaara7043832005-01-21 11:56:39 +00002166{
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002167 list_hashtable_vars(&globvarht, (char_u *)"", TRUE, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00002168}
2169
2170/*
2171 * List buffer variables.
2172 */
2173 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002174list_buf_vars(int *first)
Bram Moolenaara7043832005-01-21 11:56:39 +00002175{
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002176 char_u numbuf[NUMBUFLEN];
2177
Bram Moolenaar429fa852013-04-15 12:27:36 +02002178 list_hashtable_vars(&curbuf->b_vars->dv_hashtab, (char_u *)"b:",
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002179 TRUE, first);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002180
2181 sprintf((char *)numbuf, "%ld", (long)curbuf->b_changedtick);
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002182 list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER,
2183 numbuf, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00002184}
2185
2186/*
2187 * List window variables.
2188 */
2189 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002190list_win_vars(int *first)
Bram Moolenaara7043832005-01-21 11:56:39 +00002191{
Bram Moolenaar429fa852013-04-15 12:27:36 +02002192 list_hashtable_vars(&curwin->w_vars->dv_hashtab,
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002193 (char_u *)"w:", TRUE, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00002194}
2195
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002196#ifdef FEAT_WINDOWS
2197/*
2198 * List tab page variables.
2199 */
2200 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002201list_tab_vars(int *first)
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002202{
Bram Moolenaar429fa852013-04-15 12:27:36 +02002203 list_hashtable_vars(&curtab->tp_vars->dv_hashtab,
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002204 (char_u *)"t:", TRUE, first);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002205}
2206#endif
2207
Bram Moolenaara7043832005-01-21 11:56:39 +00002208/*
2209 * List Vim variables.
2210 */
2211 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002212list_vim_vars(int *first)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002213{
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002214 list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE, first);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002215}
2216
2217/*
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00002218 * List script-local variables, if there is a script.
2219 */
2220 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002221list_script_vars(int *first)
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00002222{
2223 if (current_SID > 0 && current_SID <= ga_scripts.ga_len)
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002224 list_hashtable_vars(&SCRIPT_VARS(current_SID),
2225 (char_u *)"s:", FALSE, first);
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00002226}
2227
2228/*
2229 * List function variables, if there is a function.
2230 */
2231 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002232list_func_vars(int *first)
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00002233{
2234 if (current_funccal != NULL)
2235 list_hashtable_vars(&current_funccal->l_vars.dv_hashtab,
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002236 (char_u *)"l:", FALSE, first);
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00002237}
2238
2239/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002240 * List variables in "arg".
2241 */
2242 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01002243list_arg_vars(exarg_T *eap, char_u *arg, int *first)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002244{
2245 int error = FALSE;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002246 int len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002247 char_u *name;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002248 char_u *name_start;
2249 char_u *arg_subsc;
2250 char_u *tofree;
2251 typval_T tv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002252
2253 while (!ends_excmd(*arg) && !got_int)
2254 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002255 if (error || eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002256 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002257 arg = find_name_end(arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002258 if (!vim_iswhite(*arg) && !ends_excmd(*arg))
2259 {
2260 emsg_severe = TRUE;
2261 EMSG(_(e_trailing));
2262 break;
2263 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002264 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002265 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002266 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002267 /* get_name_len() takes care of expanding curly braces */
2268 name_start = name = arg;
2269 len = get_name_len(&arg, &tofree, TRUE, TRUE);
2270 if (len <= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002271 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002272 /* This is mainly to keep test 49 working: when expanding
2273 * curly braces fails overrule the exception error message. */
2274 if (len < 0 && !aborting())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002275 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002276 emsg_severe = TRUE;
2277 EMSG2(_(e_invarg2), arg);
2278 break;
2279 }
2280 error = TRUE;
2281 }
2282 else
2283 {
2284 if (tofree != NULL)
2285 name = tofree;
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02002286 if (get_var_tv(name, len, &tv, NULL, TRUE, FALSE) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002287 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002288 else
2289 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002290 /* handle d.key, l[idx], f(expr) */
2291 arg_subsc = arg;
2292 if (handle_subscript(&arg, &tv, TRUE, TRUE) == FAIL)
Bram Moolenaara7043832005-01-21 11:56:39 +00002293 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002294 else
Bram Moolenaara7043832005-01-21 11:56:39 +00002295 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002296 if (arg == arg_subsc && len == 2 && name[1] == ':')
Bram Moolenaara7043832005-01-21 11:56:39 +00002297 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002298 switch (*name)
Bram Moolenaara7043832005-01-21 11:56:39 +00002299 {
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002300 case 'g': list_glob_vars(first); break;
2301 case 'b': list_buf_vars(first); break;
2302 case 'w': list_win_vars(first); break;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002303#ifdef FEAT_WINDOWS
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002304 case 't': list_tab_vars(first); break;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002305#endif
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002306 case 'v': list_vim_vars(first); break;
2307 case 's': list_script_vars(first); break;
2308 case 'l': list_func_vars(first); break;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002309 default:
2310 EMSG2(_("E738: Can't list variables for %s"), name);
Bram Moolenaara7043832005-01-21 11:56:39 +00002311 }
Bram Moolenaara7043832005-01-21 11:56:39 +00002312 }
2313 else
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002314 {
2315 char_u numbuf[NUMBUFLEN];
2316 char_u *tf;
2317 int c;
2318 char_u *s;
2319
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002320 s = echo_string(&tv, &tf, numbuf, 0);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002321 c = *arg;
2322 *arg = NUL;
2323 list_one_var_a((char_u *)"",
2324 arg == arg_subsc ? name : name_start,
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002325 tv.v_type,
2326 s == NULL ? (char_u *)"" : s,
2327 first);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002328 *arg = c;
2329 vim_free(tf);
2330 }
2331 clear_tv(&tv);
Bram Moolenaara7043832005-01-21 11:56:39 +00002332 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002333 }
2334 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002335
2336 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002337 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002338
2339 arg = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002340 }
2341
2342 return arg;
2343}
2344
2345/*
2346 * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value.
2347 * Returns a pointer to the char just after the var name.
2348 * Returns NULL if there is an error.
2349 */
2350 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01002351ex_let_one(
2352 char_u *arg, /* points to variable name */
2353 typval_T *tv, /* value to assign to variable */
2354 int copy, /* copy value from "tv" */
2355 char_u *endchars, /* valid chars after variable name or NULL */
2356 char_u *op) /* "+", "-", "." or NULL*/
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002357{
2358 int c1;
2359 char_u *name;
2360 char_u *p;
2361 char_u *arg_end = NULL;
2362 int len;
2363 int opt_flags;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002364 char_u *tofree = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002365
2366 /*
2367 * ":let $VAR = expr": Set environment variable.
2368 */
2369 if (*arg == '$')
2370 {
2371 /* Find the end of the name. */
2372 ++arg;
2373 name = arg;
2374 len = get_env_len(&arg);
2375 if (len == 0)
2376 EMSG2(_(e_invarg2), name - 1);
2377 else
2378 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002379 if (op != NULL && (*op == '+' || *op == '-'))
2380 EMSG2(_(e_letwrong), op);
2381 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002382 && vim_strchr(endchars, *skipwhite(arg)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002383 EMSG(_(e_letunexp));
Bram Moolenaard4ddfaf2010-12-02 14:48:14 +01002384 else if (!check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002385 {
2386 c1 = name[len];
2387 name[len] = NUL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002388 p = get_tv_string_chk(tv);
2389 if (p != NULL && op != NULL && *op == '.')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002390 {
2391 int mustfree = FALSE;
2392 char_u *s = vim_getenv(name, &mustfree);
2393
2394 if (s != NULL)
2395 {
2396 p = tofree = concat_str(s, p);
2397 if (mustfree)
2398 vim_free(s);
2399 }
2400 }
2401 if (p != NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002402 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002403 vim_setenv(name, p);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002404 if (STRICMP(name, "HOME") == 0)
2405 init_homedir();
2406 else if (didset_vim && STRICMP(name, "VIM") == 0)
2407 didset_vim = FALSE;
2408 else if (didset_vimruntime
2409 && STRICMP(name, "VIMRUNTIME") == 0)
2410 didset_vimruntime = FALSE;
2411 arg_end = arg;
2412 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002413 name[len] = c1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002414 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002415 }
2416 }
2417 }
2418
2419 /*
2420 * ":let &option = expr": Set option value.
2421 * ":let &l:option = expr": Set local option value.
2422 * ":let &g:option = expr": Set global option value.
2423 */
2424 else if (*arg == '&')
2425 {
2426 /* Find the end of the name. */
2427 p = find_option_end(&arg, &opt_flags);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002428 if (p == NULL || (endchars != NULL
2429 && vim_strchr(endchars, *skipwhite(p)) == NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002430 EMSG(_(e_letunexp));
2431 else
2432 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002433 long n;
2434 int opt_type;
2435 long numval;
2436 char_u *stringval = NULL;
2437 char_u *s;
2438
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002439 c1 = *p;
2440 *p = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002441
2442 n = get_tv_number(tv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002443 s = get_tv_string_chk(tv); /* != NULL if number or string */
2444 if (s != NULL && op != NULL && *op != '=')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002445 {
2446 opt_type = get_option_value(arg, &numval,
2447 &stringval, opt_flags);
2448 if ((opt_type == 1 && *op == '.')
2449 || (opt_type == 0 && *op != '.'))
2450 EMSG2(_(e_letwrong), op);
2451 else
2452 {
2453 if (opt_type == 1) /* number */
2454 {
2455 if (*op == '+')
2456 n = numval + n;
2457 else
2458 n = numval - n;
2459 }
2460 else if (opt_type == 0 && stringval != NULL) /* string */
2461 {
2462 s = concat_str(stringval, s);
2463 vim_free(stringval);
2464 stringval = s;
2465 }
2466 }
2467 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002468 if (s != NULL)
2469 {
2470 set_option_value(arg, n, s, opt_flags);
2471 arg_end = p;
2472 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002473 *p = c1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002474 vim_free(stringval);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002475 }
2476 }
2477
2478 /*
2479 * ":let @r = expr": Set register contents.
2480 */
2481 else if (*arg == '@')
2482 {
2483 ++arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002484 if (op != NULL && (*op == '+' || *op == '-'))
2485 EMSG2(_(e_letwrong), op);
2486 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002487 && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002488 EMSG(_(e_letunexp));
2489 else
2490 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00002491 char_u *ptofree = NULL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002492 char_u *s;
2493
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002494 p = get_tv_string_chk(tv);
2495 if (p != NULL && op != NULL && *op == '.')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002496 {
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +02002497 s = get_reg_contents(*arg == '@' ? '"' : *arg, GREG_EXPR_SRC);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002498 if (s != NULL)
2499 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00002500 p = ptofree = concat_str(s, p);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002501 vim_free(s);
2502 }
2503 }
2504 if (p != NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002505 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002506 write_reg_contents(*arg == '@' ? '"' : *arg, p, -1, FALSE);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002507 arg_end = arg + 1;
2508 }
Bram Moolenaar89d40322006-08-29 15:30:07 +00002509 vim_free(ptofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002510 }
2511 }
2512
2513 /*
2514 * ":let var = expr": Set internal variable.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002515 * ":let {expr} = expr": Idem, name made with curly braces
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002516 */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002517 else if (eval_isnamec1(*arg) || *arg == '{')
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002518 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002519 lval_T lv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002520
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002521 p = get_lval(arg, tv, &lv, FALSE, FALSE, 0, FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002522 if (p != NULL && lv.ll_name != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002523 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002524 if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL)
2525 EMSG(_(e_letunexp));
2526 else
2527 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002528 set_var_lval(&lv, p, tv, copy, op);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002529 arg_end = p;
2530 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002531 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002532 clear_lval(&lv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002533 }
2534
2535 else
2536 EMSG2(_(e_invarg2), arg);
2537
2538 return arg_end;
2539}
2540
2541/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00002542 * If "arg" is equal to "b:changedtick" give an error and return TRUE.
2543 */
2544 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01002545check_changedtick(char_u *arg)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002546{
2547 if (STRNCMP(arg, "b:changedtick", 13) == 0 && !eval_isnamec(arg[13]))
2548 {
2549 EMSG2(_(e_readonlyvar), arg);
2550 return TRUE;
2551 }
2552 return FALSE;
2553}
2554
2555/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002556 * Get an lval: variable, Dict item or List item that can be assigned a value
2557 * to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]",
2558 * "name.key", "name.key[expr]" etc.
2559 * Indexing only works if "name" is an existing List or Dictionary.
2560 * "name" points to the start of the name.
2561 * If "rettv" is not NULL it points to the value to be assigned.
2562 * "unlet" is TRUE for ":unlet": slightly different behavior when something is
2563 * wrong; must end in space or cmd separator.
2564 *
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002565 * flags:
2566 * GLV_QUIET: do not give error messages
2567 * GLV_NO_AUTOLOAD: do not use script autoloading
2568 *
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002569 * Returns a pointer to just after the name, including indexes.
Bram Moolenaara7043832005-01-21 11:56:39 +00002570 * When an evaluation error occurs "lp->ll_name" is NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002571 * Returns NULL for a parsing error. Still need to free items in "lp"!
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002572 */
2573 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01002574get_lval(
2575 char_u *name,
2576 typval_T *rettv,
2577 lval_T *lp,
2578 int unlet,
2579 int skip,
2580 int flags, /* GLV_ values */
2581 int fne_flags) /* flags for find_name_end() */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002582{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002583 char_u *p;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002584 char_u *expr_start, *expr_end;
2585 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00002586 dictitem_T *v;
2587 typval_T var1;
2588 typval_T var2;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002589 int empty1 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00002590 listitem_T *ni;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002591 char_u *key = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002592 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +00002593 hashtab_T *ht;
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002594 int quiet = flags & GLV_QUIET;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002595
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002596 /* Clear everything in "lp". */
Bram Moolenaar33570922005-01-25 22:26:29 +00002597 vim_memset(lp, 0, sizeof(lval_T));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002598
2599 if (skip)
2600 {
2601 /* When skipping just find the end of the name. */
2602 lp->ll_name = name;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002603 return find_name_end(name, NULL, NULL, FNE_INCL_BR | fne_flags);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002604 }
2605
2606 /* Find the end of the name. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002607 p = find_name_end(name, &expr_start, &expr_end, fne_flags);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002608 if (expr_start != NULL)
2609 {
2610 /* Don't expand the name when we already know there is an error. */
2611 if (unlet && !vim_iswhite(*p) && !ends_excmd(*p)
2612 && *p != '[' && *p != '.')
2613 {
2614 EMSG(_(e_trailing));
2615 return NULL;
2616 }
2617
2618 lp->ll_exp_name = make_expanded_name(name, expr_start, expr_end, p);
2619 if (lp->ll_exp_name == NULL)
2620 {
2621 /* Report an invalid expression in braces, unless the
2622 * expression evaluation has been cancelled due to an
2623 * aborting error, an interrupt, or an exception. */
2624 if (!aborting() && !quiet)
2625 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002626 emsg_severe = TRUE;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002627 EMSG2(_(e_invarg2), name);
2628 return NULL;
2629 }
2630 }
2631 lp->ll_name = lp->ll_exp_name;
2632 }
2633 else
2634 lp->ll_name = name;
2635
2636 /* Without [idx] or .key we are done. */
2637 if ((*p != '[' && *p != '.') || lp->ll_name == NULL)
2638 return p;
2639
2640 cc = *p;
2641 *p = NUL;
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002642 v = find_var(lp->ll_name, &ht, flags & GLV_NO_AUTOLOAD);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002643 if (v == NULL && !quiet)
2644 EMSG2(_(e_undefvar), lp->ll_name);
2645 *p = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002646 if (v == NULL)
2647 return NULL;
2648
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002649 /*
2650 * Loop until no more [idx] or .key is following.
2651 */
Bram Moolenaar33570922005-01-25 22:26:29 +00002652 lp->ll_tv = &v->di_tv;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002653 while (*p == '[' || (*p == '.' && lp->ll_tv->v_type == VAR_DICT))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002654 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002655 if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL)
2656 && !(lp->ll_tv->v_type == VAR_DICT
2657 && lp->ll_tv->vval.v_dict != NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002658 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002659 if (!quiet)
2660 EMSG(_("E689: Can only index a List or Dictionary"));
2661 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002662 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002663 if (lp->ll_range)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002664 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002665 if (!quiet)
2666 EMSG(_("E708: [:] must come last"));
2667 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002668 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002669
Bram Moolenaar8c711452005-01-14 21:53:12 +00002670 len = -1;
2671 if (*p == '.')
2672 {
2673 key = p + 1;
2674 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
2675 ;
2676 if (len == 0)
2677 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002678 if (!quiet)
2679 EMSG(_(e_emptykey));
2680 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002681 }
2682 p = key + len;
2683 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002684 else
2685 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002686 /* Get the index [expr] or the first index [expr: ]. */
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002687 p = skipwhite(p + 1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002688 if (*p == ':')
2689 empty1 = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002690 else
2691 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002692 empty1 = FALSE;
2693 if (eval1(&p, &var1, TRUE) == FAIL) /* recursive! */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002694 return NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002695 if (get_tv_string_chk(&var1) == NULL)
2696 {
2697 /* not a number or string */
2698 clear_tv(&var1);
2699 return NULL;
2700 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002701 }
2702
2703 /* Optionally get the second index [ :expr]. */
2704 if (*p == ':')
2705 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002706 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002707 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002708 if (!quiet)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002709 EMSG(_(e_dictrange));
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002710 if (!empty1)
2711 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002712 return NULL;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002713 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002714 if (rettv != NULL && (rettv->v_type != VAR_LIST
2715 || rettv->vval.v_list == NULL))
Bram Moolenaar8c711452005-01-14 21:53:12 +00002716 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002717 if (!quiet)
2718 EMSG(_("E709: [:] requires a List value"));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002719 if (!empty1)
2720 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002721 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002722 }
2723 p = skipwhite(p + 1);
2724 if (*p == ']')
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002725 lp->ll_empty2 = TRUE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002726 else
2727 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002728 lp->ll_empty2 = FALSE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002729 if (eval1(&p, &var2, TRUE) == FAIL) /* recursive! */
2730 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002731 if (!empty1)
2732 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002733 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002734 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002735 if (get_tv_string_chk(&var2) == NULL)
2736 {
2737 /* not a number or string */
2738 if (!empty1)
2739 clear_tv(&var1);
2740 clear_tv(&var2);
2741 return NULL;
2742 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002743 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002744 lp->ll_range = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002745 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002746 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002747 lp->ll_range = FALSE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002748
Bram Moolenaar8c711452005-01-14 21:53:12 +00002749 if (*p != ']')
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002750 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002751 if (!quiet)
2752 EMSG(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002753 if (!empty1)
2754 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002755 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002756 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002757 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002758 }
2759
2760 /* Skip to past ']'. */
2761 ++p;
2762 }
2763
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002764 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002765 {
2766 if (len == -1)
2767 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002768 /* "[key]": get key from "var1" */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002769 key = get_tv_string(&var1); /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002770 if (*key == NUL)
2771 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002772 if (!quiet)
2773 EMSG(_(e_emptykey));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002774 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002775 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002776 }
2777 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002778 lp->ll_list = NULL;
2779 lp->ll_dict = lp->ll_tv->vval.v_dict;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002780 lp->ll_di = dict_find(lp->ll_dict, key, len);
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002781
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002782 /* When assigning to a scope dictionary check that a function and
2783 * variable name is valid (only variable name unless it is l: or
2784 * g: dictionary). Disallow overwriting a builtin function. */
2785 if (rettv != NULL && lp->ll_dict->dv_scope != 0)
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002786 {
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002787 int prevval;
2788 int wrong;
2789
2790 if (len != -1)
2791 {
2792 prevval = key[len];
2793 key[len] = NUL;
2794 }
Bram Moolenaar4380d1e2013-06-09 20:51:00 +02002795 else
2796 prevval = 0; /* avoid compiler warning */
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002797 wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE
2798 && rettv->v_type == VAR_FUNC
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002799 && var_check_func_name(key, lp->ll_di == NULL))
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002800 || !valid_varname(key);
2801 if (len != -1)
2802 key[len] = prevval;
2803 if (wrong)
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002804 return NULL;
2805 }
2806
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002807 if (lp->ll_di == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002808 {
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002809 /* Can't add "v:" variable. */
2810 if (lp->ll_dict == &vimvardict)
2811 {
2812 EMSG2(_(e_illvar), name);
2813 return NULL;
2814 }
2815
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002816 /* Key does not exist in dict: may need to add it. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002817 if (*p == '[' || *p == '.' || unlet)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002818 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002819 if (!quiet)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002820 EMSG2(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002821 if (len == -1)
2822 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002823 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002824 }
2825 if (len == -1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002826 lp->ll_newkey = vim_strsave(key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002827 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002828 lp->ll_newkey = vim_strnsave(key, len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002829 if (len == -1)
2830 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002831 if (lp->ll_newkey == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002832 p = NULL;
2833 break;
2834 }
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002835 /* existing variable, need to check if it can be changed */
Bram Moolenaar77354e72015-04-21 16:49:05 +02002836 else if (var_check_ro(lp->ll_di->di_flags, name, FALSE))
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002837 return NULL;
2838
Bram Moolenaar8c711452005-01-14 21:53:12 +00002839 if (len == -1)
2840 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002841 lp->ll_tv = &lp->ll_di->di_tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002842 }
2843 else
2844 {
2845 /*
2846 * Get the number and item for the only or first index of the List.
2847 */
2848 if (empty1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002849 lp->ll_n1 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002850 else
2851 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002852 lp->ll_n1 = get_tv_number(&var1); /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002853 clear_tv(&var1);
2854 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002855 lp->ll_dict = NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002856 lp->ll_list = lp->ll_tv->vval.v_list;
2857 lp->ll_li = list_find(lp->ll_list, lp->ll_n1);
2858 if (lp->ll_li == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002859 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00002860 if (lp->ll_n1 < 0)
2861 {
2862 lp->ll_n1 = 0;
2863 lp->ll_li = list_find(lp->ll_list, lp->ll_n1);
2864 }
2865 }
2866 if (lp->ll_li == NULL)
2867 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002868 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002869 clear_tv(&var2);
Bram Moolenaare9623882011-04-21 14:27:28 +02002870 if (!quiet)
2871 EMSGN(_(e_listidx), lp->ll_n1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002872 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002873 }
2874
2875 /*
2876 * May need to find the item or absolute index for the second
2877 * index of a range.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002878 * When no index given: "lp->ll_empty2" is TRUE.
2879 * Otherwise "lp->ll_n2" is set to the second index.
Bram Moolenaar8c711452005-01-14 21:53:12 +00002880 */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002881 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002882 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002883 lp->ll_n2 = get_tv_number(&var2); /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002884 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002885 if (lp->ll_n2 < 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002886 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002887 ni = list_find(lp->ll_list, lp->ll_n2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002888 if (ni == NULL)
Bram Moolenaare9623882011-04-21 14:27:28 +02002889 {
2890 if (!quiet)
2891 EMSGN(_(e_listidx), lp->ll_n2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002892 return NULL;
Bram Moolenaare9623882011-04-21 14:27:28 +02002893 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002894 lp->ll_n2 = list_idx_of_item(lp->ll_list, ni);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002895 }
2896
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002897 /* Check that lp->ll_n2 isn't before lp->ll_n1. */
2898 if (lp->ll_n1 < 0)
2899 lp->ll_n1 = list_idx_of_item(lp->ll_list, lp->ll_li);
2900 if (lp->ll_n2 < lp->ll_n1)
Bram Moolenaare9623882011-04-21 14:27:28 +02002901 {
2902 if (!quiet)
2903 EMSGN(_(e_listidx), lp->ll_n2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002904 return NULL;
Bram Moolenaare9623882011-04-21 14:27:28 +02002905 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002906 }
2907
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002908 lp->ll_tv = &lp->ll_li->li_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002909 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002910 }
2911
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002912 return p;
2913}
2914
2915/*
Bram Moolenaar33570922005-01-25 22:26:29 +00002916 * Clear lval "lp" that was filled by get_lval().
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002917 */
2918 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002919clear_lval(lval_T *lp)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002920{
2921 vim_free(lp->ll_exp_name);
2922 vim_free(lp->ll_newkey);
2923}
2924
2925/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002926 * Set a variable that was parsed by get_lval() to "rettv".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002927 * "endp" points to just after the parsed name.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002928 * "op" is NULL, "+" for "+=", "-" for "-=", "." for ".=" or "=" for "=".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002929 */
2930 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002931set_var_lval(
2932 lval_T *lp,
2933 char_u *endp,
2934 typval_T *rettv,
2935 int copy,
2936 char_u *op)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002937{
2938 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00002939 listitem_T *ri;
2940 dictitem_T *di;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002941
2942 if (lp->ll_tv == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002943 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002944 if (!check_changedtick(lp->ll_name))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002945 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002946 cc = *endp;
2947 *endp = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002948 if (op != NULL && *op != '=')
2949 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002950 typval_T tv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002951
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002952 /* handle +=, -= and .= */
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02002953 di = NULL;
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00002954 if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02002955 &tv, &di, TRUE, FALSE) == OK)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002956 {
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02002957 if ((di == NULL
2958 || (!var_check_ro(di->di_flags, lp->ll_name, FALSE)
2959 && !tv_check_lock(di->di_tv.v_lock, lp->ll_name,
2960 FALSE)))
2961 && tv_op(&tv, rettv, op) == OK)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002962 set_var(lp->ll_name, &tv, FALSE);
2963 clear_tv(&tv);
2964 }
2965 }
2966 else
2967 set_var(lp->ll_name, rettv, copy);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002968 *endp = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002969 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002970 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002971 else if (tv_check_lock(lp->ll_newkey == NULL
2972 ? lp->ll_tv->v_lock
Bram Moolenaar77354e72015-04-21 16:49:05 +02002973 : lp->ll_tv->vval.v_dict->dv_lock, lp->ll_name, FALSE))
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002974 ;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002975 else if (lp->ll_range)
2976 {
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02002977 listitem_T *ll_li = lp->ll_li;
2978 int ll_n1 = lp->ll_n1;
2979
2980 /*
2981 * Check whether any of the list items is locked
2982 */
Bram Moolenaarb2a851f2014-12-07 00:18:33 +01002983 for (ri = rettv->vval.v_list->lv_first; ri != NULL && ll_li != NULL; )
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02002984 {
Bram Moolenaar77354e72015-04-21 16:49:05 +02002985 if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name, FALSE))
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02002986 return;
2987 ri = ri->li_next;
2988 if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == ll_n1))
2989 break;
2990 ll_li = ll_li->li_next;
2991 ++ll_n1;
2992 }
2993
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002994 /*
2995 * Assign the List values to the list items.
2996 */
2997 for (ri = rettv->vval.v_list->lv_first; ri != NULL; )
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002998 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002999 if (op != NULL && *op != '=')
3000 tv_op(&lp->ll_li->li_tv, &ri->li_tv, op);
3001 else
3002 {
3003 clear_tv(&lp->ll_li->li_tv);
3004 copy_tv(&ri->li_tv, &lp->ll_li->li_tv);
3005 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003006 ri = ri->li_next;
3007 if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == lp->ll_n1))
3008 break;
3009 if (lp->ll_li->li_next == NULL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00003010 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003011 /* Need to add an empty item. */
Bram Moolenaar4463f292005-09-25 22:20:24 +00003012 if (list_append_number(lp->ll_list, 0) == FAIL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00003013 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003014 ri = NULL;
3015 break;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00003016 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00003017 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003018 lp->ll_li = lp->ll_li->li_next;
3019 ++lp->ll_n1;
3020 }
3021 if (ri != NULL)
3022 EMSG(_("E710: List value has more items than target"));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003023 else if (lp->ll_empty2
3024 ? (lp->ll_li != NULL && lp->ll_li->li_next != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003025 : lp->ll_n1 != lp->ll_n2)
3026 EMSG(_("E711: List value has not enough items"));
3027 }
3028 else
3029 {
3030 /*
3031 * Assign to a List or Dictionary item.
3032 */
3033 if (lp->ll_newkey != NULL)
3034 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003035 if (op != NULL && *op != '=')
3036 {
3037 EMSG2(_(e_letwrong), op);
3038 return;
3039 }
3040
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003041 /* Need to add an item to the Dictionary. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003042 di = dictitem_alloc(lp->ll_newkey);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003043 if (di == NULL)
3044 return;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003045 if (dict_add(lp->ll_tv->vval.v_dict, di) == FAIL)
3046 {
3047 vim_free(di);
3048 return;
3049 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003050 lp->ll_tv = &di->di_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00003051 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003052 else if (op != NULL && *op != '=')
3053 {
3054 tv_op(lp->ll_tv, rettv, op);
3055 return;
3056 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003057 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003058 clear_tv(lp->ll_tv);
Bram Moolenaar8c711452005-01-14 21:53:12 +00003059
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003060 /*
3061 * Assign the value to the variable or list item.
3062 */
3063 if (copy)
3064 copy_tv(rettv, lp->ll_tv);
3065 else
3066 {
3067 *lp->ll_tv = *rettv;
Bram Moolenaar758711c2005-02-02 23:11:38 +00003068 lp->ll_tv->v_lock = 0;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003069 init_tv(rettv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003070 }
3071 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003072}
3073
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003074/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003075 * Handle "tv1 += tv2", "tv1 -= tv2" and "tv1 .= tv2"
3076 * Returns OK or FAIL.
3077 */
3078 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003079tv_op(typval_T *tv1, typval_T *tv2, char_u *op)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003080{
3081 long n;
3082 char_u numbuf[NUMBUFLEN];
3083 char_u *s;
3084
Bram Moolenaar520e1e42016-01-23 19:46:28 +01003085 /* Can't do anything with a Funcref, Dict, v:true on the right. */
3086 if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT
3087 && tv2->v_type != VAR_SPECIAL)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003088 {
3089 switch (tv1->v_type)
3090 {
Bram Moolenaar835dc632016-02-07 14:27:38 +01003091 case VAR_UNKNOWN:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003092 case VAR_DICT:
3093 case VAR_FUNC:
Bram Moolenaar520e1e42016-01-23 19:46:28 +01003094 case VAR_SPECIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01003095 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01003096 case VAR_CHANNEL:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003097 break;
3098
3099 case VAR_LIST:
3100 if (*op != '+' || tv2->v_type != VAR_LIST)
3101 break;
3102 /* List += List */
3103 if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL)
3104 list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL);
3105 return OK;
3106
3107 case VAR_NUMBER:
3108 case VAR_STRING:
3109 if (tv2->v_type == VAR_LIST)
3110 break;
3111 if (*op == '+' || *op == '-')
3112 {
3113 /* nr += nr or nr -= nr*/
3114 n = get_tv_number(tv1);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003115#ifdef FEAT_FLOAT
3116 if (tv2->v_type == VAR_FLOAT)
3117 {
3118 float_T f = n;
3119
3120 if (*op == '+')
3121 f += tv2->vval.v_float;
3122 else
3123 f -= tv2->vval.v_float;
3124 clear_tv(tv1);
3125 tv1->v_type = VAR_FLOAT;
3126 tv1->vval.v_float = f;
3127 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003128 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003129#endif
3130 {
3131 if (*op == '+')
3132 n += get_tv_number(tv2);
3133 else
3134 n -= get_tv_number(tv2);
3135 clear_tv(tv1);
3136 tv1->v_type = VAR_NUMBER;
3137 tv1->vval.v_number = n;
3138 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003139 }
3140 else
3141 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003142 if (tv2->v_type == VAR_FLOAT)
3143 break;
3144
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003145 /* str .= str */
3146 s = get_tv_string(tv1);
3147 s = concat_str(s, get_tv_string_buf(tv2, numbuf));
3148 clear_tv(tv1);
3149 tv1->v_type = VAR_STRING;
3150 tv1->vval.v_string = s;
3151 }
3152 return OK;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003153
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003154 case VAR_FLOAT:
Bram Moolenaar5fac4672016-03-02 22:16:32 +01003155#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003156 {
3157 float_T f;
3158
3159 if (*op == '.' || (tv2->v_type != VAR_FLOAT
3160 && tv2->v_type != VAR_NUMBER
3161 && tv2->v_type != VAR_STRING))
3162 break;
3163 if (tv2->v_type == VAR_FLOAT)
3164 f = tv2->vval.v_float;
3165 else
3166 f = get_tv_number(tv2);
3167 if (*op == '+')
3168 tv1->vval.v_float += f;
3169 else
3170 tv1->vval.v_float -= f;
3171 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003172#endif
Bram Moolenaar5fac4672016-03-02 22:16:32 +01003173 return OK;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003174 }
3175 }
3176
3177 EMSG2(_(e_letwrong), op);
3178 return FAIL;
3179}
3180
3181/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003182 * Add a watcher to a list.
3183 */
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003184 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003185list_add_watch(list_T *l, listwatch_T *lw)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003186{
3187 lw->lw_next = l->lv_watch;
3188 l->lv_watch = lw;
3189}
3190
3191/*
Bram Moolenaar758711c2005-02-02 23:11:38 +00003192 * Remove a watcher from a list.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003193 * No warning when it isn't found...
3194 */
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003195 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003196list_rem_watch(list_T *l, listwatch_T *lwrem)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003197{
Bram Moolenaar33570922005-01-25 22:26:29 +00003198 listwatch_T *lw, **lwp;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003199
3200 lwp = &l->lv_watch;
3201 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
3202 {
3203 if (lw == lwrem)
3204 {
3205 *lwp = lw->lw_next;
3206 break;
3207 }
3208 lwp = &lw->lw_next;
3209 }
3210}
3211
3212/*
3213 * Just before removing an item from a list: advance watchers to the next
3214 * item.
3215 */
3216 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003217list_fix_watch(list_T *l, listitem_T *item)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003218{
Bram Moolenaar33570922005-01-25 22:26:29 +00003219 listwatch_T *lw;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003220
3221 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
3222 if (lw->lw_item == item)
3223 lw->lw_item = item->li_next;
3224}
3225
3226/*
3227 * Evaluate the expression used in a ":for var in expr" command.
3228 * "arg" points to "var".
3229 * Set "*errp" to TRUE for an error, FALSE otherwise;
3230 * Return a pointer that holds the info. Null when there is an error.
3231 */
3232 void *
Bram Moolenaar7454a062016-01-30 15:14:10 +01003233eval_for_line(
3234 char_u *arg,
3235 int *errp,
3236 char_u **nextcmdp,
3237 int skip)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003238{
Bram Moolenaar33570922005-01-25 22:26:29 +00003239 forinfo_T *fi;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003240 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +00003241 typval_T tv;
3242 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003243
3244 *errp = TRUE; /* default: there is an error */
3245
Bram Moolenaar33570922005-01-25 22:26:29 +00003246 fi = (forinfo_T *)alloc_clear(sizeof(forinfo_T));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003247 if (fi == NULL)
3248 return NULL;
3249
3250 expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
3251 if (expr == NULL)
3252 return fi;
3253
3254 expr = skipwhite(expr);
3255 if (expr[0] != 'i' || expr[1] != 'n' || !vim_iswhite(expr[2]))
3256 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003257 EMSG(_("E690: Missing \"in\" after :for"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003258 return fi;
3259 }
3260
3261 if (skip)
3262 ++emsg_skip;
3263 if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK)
3264 {
3265 *errp = FALSE;
3266 if (!skip)
3267 {
3268 l = tv.vval.v_list;
3269 if (tv.v_type != VAR_LIST || l == NULL)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00003270 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003271 EMSG(_(e_listreq));
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00003272 clear_tv(&tv);
3273 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003274 else
3275 {
Bram Moolenaar7bb4c6e2005-09-07 21:22:27 +00003276 /* No need to increment the refcount, it's already set for the
3277 * list being used in "tv". */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003278 fi->fi_list = l;
3279 list_add_watch(l, &fi->fi_lw);
3280 fi->fi_lw.lw_item = l->lv_first;
3281 }
3282 }
3283 }
3284 if (skip)
3285 --emsg_skip;
3286
3287 return fi;
3288}
3289
3290/*
3291 * Use the first item in a ":for" list. Advance to the next.
3292 * Assign the values to the variable (list). "arg" points to the first one.
3293 * Return TRUE when a valid item was found, FALSE when at end of list or
3294 * something wrong.
3295 */
3296 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003297next_for_item(void *fi_void, char_u *arg)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003298{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003299 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003300 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00003301 listitem_T *item;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003302
3303 item = fi->fi_lw.lw_item;
3304 if (item == NULL)
3305 result = FALSE;
3306 else
3307 {
3308 fi->fi_lw.lw_item = item->li_next;
3309 result = (ex_let_vars(arg, &item->li_tv, TRUE,
3310 fi->fi_semicolon, fi->fi_varcount, NULL) == OK);
3311 }
3312 return result;
3313}
3314
3315/*
3316 * Free the structure used to store info used by ":for".
3317 */
3318 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003319free_for_info(void *fi_void)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003320{
Bram Moolenaar33570922005-01-25 22:26:29 +00003321 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003322
Bram Moolenaarab7013c2005-01-09 21:23:56 +00003323 if (fi != NULL && fi->fi_list != NULL)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00003324 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003325 list_rem_watch(fi->fi_list, &fi->fi_lw);
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00003326 list_unref(fi->fi_list);
3327 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003328 vim_free(fi);
3329}
3330
Bram Moolenaar071d4272004-06-13 20:20:40 +00003331#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
3332
3333 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003334set_context_for_expression(
3335 expand_T *xp,
3336 char_u *arg,
3337 cmdidx_T cmdidx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003338{
3339 int got_eq = FALSE;
3340 int c;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003341 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003342
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003343 if (cmdidx == CMD_let)
3344 {
3345 xp->xp_context = EXPAND_USER_VARS;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00003346 if (vim_strpbrk(arg, (char_u *)"\"'+-*/%.=!?~|&$([<>,#") == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003347 {
3348 /* ":let var1 var2 ...": find last space. */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00003349 for (p = arg + STRLEN(arg); p >= arg; )
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003350 {
3351 xp->xp_pattern = p;
Bram Moolenaar33570922005-01-25 22:26:29 +00003352 mb_ptr_back(arg, p);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003353 if (vim_iswhite(*p))
3354 break;
3355 }
3356 return;
3357 }
3358 }
3359 else
3360 xp->xp_context = cmdidx == CMD_call ? EXPAND_FUNCTIONS
3361 : EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003362 while ((xp->xp_pattern = vim_strpbrk(arg,
3363 (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL)
3364 {
3365 c = *xp->xp_pattern;
3366 if (c == '&')
3367 {
3368 c = xp->xp_pattern[1];
3369 if (c == '&')
3370 {
3371 ++xp->xp_pattern;
3372 xp->xp_context = cmdidx != CMD_let || got_eq
3373 ? EXPAND_EXPRESSION : EXPAND_NOTHING;
3374 }
3375 else if (c != ' ')
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00003376 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00003377 xp->xp_context = EXPAND_SETTINGS;
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00003378 if ((c == 'l' || c == 'g') && xp->xp_pattern[2] == ':')
3379 xp->xp_pattern += 2;
3380
3381 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003382 }
3383 else if (c == '$')
3384 {
3385 /* environment variable */
3386 xp->xp_context = EXPAND_ENV_VARS;
3387 }
3388 else if (c == '=')
3389 {
3390 got_eq = TRUE;
3391 xp->xp_context = EXPAND_EXPRESSION;
3392 }
Bram Moolenaar8a349ff2014-11-12 20:09:06 +01003393 else if ((c == '<' || c == '#')
Bram Moolenaar071d4272004-06-13 20:20:40 +00003394 && xp->xp_context == EXPAND_FUNCTIONS
3395 && vim_strchr(xp->xp_pattern, '(') == NULL)
3396 {
Bram Moolenaar8a349ff2014-11-12 20:09:06 +01003397 /* Function name can start with "<SNR>" and contain '#'. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003398 break;
3399 }
3400 else if (cmdidx != CMD_let || got_eq)
3401 {
3402 if (c == '"') /* string */
3403 {
3404 while ((c = *++xp->xp_pattern) != NUL && c != '"')
3405 if (c == '\\' && xp->xp_pattern[1] != NUL)
3406 ++xp->xp_pattern;
3407 xp->xp_context = EXPAND_NOTHING;
3408 }
3409 else if (c == '\'') /* literal string */
3410 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00003411 /* Trick: '' is like stopping and starting a literal string. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003412 while ((c = *++xp->xp_pattern) != NUL && c != '\'')
3413 /* skip */ ;
3414 xp->xp_context = EXPAND_NOTHING;
3415 }
3416 else if (c == '|')
3417 {
3418 if (xp->xp_pattern[1] == '|')
3419 {
3420 ++xp->xp_pattern;
3421 xp->xp_context = EXPAND_EXPRESSION;
3422 }
3423 else
3424 xp->xp_context = EXPAND_COMMANDS;
3425 }
3426 else
3427 xp->xp_context = EXPAND_EXPRESSION;
3428 }
3429 else
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003430 /* Doesn't look like something valid, expand as an expression
3431 * anyway. */
3432 xp->xp_context = EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003433 arg = xp->xp_pattern;
3434 if (*arg != NUL)
3435 while ((c = *++arg) != NUL && (c == ' ' || c == '\t'))
3436 /* skip */ ;
3437 }
3438 xp->xp_pattern = arg;
3439}
3440
3441#endif /* FEAT_CMDL_COMPL */
3442
3443/*
3444 * ":1,25call func(arg1, arg2)" function call.
3445 */
3446 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003447ex_call(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003448{
3449 char_u *arg = eap->arg;
3450 char_u *startarg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003451 char_u *name;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003452 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003453 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +00003454 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003455 linenr_T lnum;
3456 int doesrange;
3457 int failed = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00003458 funcdict_T fudi;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003459
Bram Moolenaar6d0efda2011-01-04 19:03:27 +01003460 if (eap->skip)
3461 {
3462 /* trans_function_name() doesn't work well when skipping, use eval0()
3463 * instead to skip to any following command, e.g. for:
3464 * :if 0 | call dict.foo().bar() | endif */
Bram Moolenaar25091292011-09-30 18:35:57 +02003465 ++emsg_skip;
3466 if (eval0(eap->arg, &rettv, &eap->nextcmd, FALSE) != FAIL)
3467 clear_tv(&rettv);
3468 --emsg_skip;
Bram Moolenaar6d0efda2011-01-04 19:03:27 +01003469 return;
3470 }
3471
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003472 tofree = trans_function_name(&arg, eap->skip, TFN_INT, &fudi);
Bram Moolenaara2a31752006-10-24 11:49:25 +00003473 if (fudi.fd_newkey != NULL)
3474 {
3475 /* Still need to give an error message for missing key. */
3476 EMSG2(_(e_dictkey), fudi.fd_newkey);
3477 vim_free(fudi.fd_newkey);
3478 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003479 if (tofree == NULL)
3480 return;
3481
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003482 /* Increase refcount on dictionary, it could get deleted when evaluating
3483 * the arguments. */
3484 if (fudi.fd_dict != NULL)
3485 ++fudi.fd_dict->dv_refcount;
3486
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003487 /* If it is the name of a variable of type VAR_FUNC use its contents. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003488 len = (int)STRLEN(tofree);
Bram Moolenaar8822a9c2014-01-14 19:44:34 +01003489 name = deref_func_name(tofree, &len, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003490
Bram Moolenaar532c7802005-01-27 14:44:31 +00003491 /* Skip white space to allow ":call func ()". Not good, but required for
3492 * backward compatibility. */
3493 startarg = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003494 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003495
3496 if (*startarg != '(')
3497 {
Bram Moolenaar8dd9ac52008-11-06 10:05:42 +00003498 EMSG2(_("E107: Missing parentheses: %s"), eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003499 goto end;
3500 }
3501
3502 /*
3503 * When skipping, evaluate the function once, to find the end of the
3504 * arguments.
3505 * When the function takes a range, this is discovered after the first
3506 * call, and the loop is broken.
3507 */
3508 if (eap->skip)
3509 {
3510 ++emsg_skip;
3511 lnum = eap->line2; /* do it once, also with an invalid range */
3512 }
3513 else
3514 lnum = eap->line1;
3515 for ( ; lnum <= eap->line2; ++lnum)
3516 {
3517 if (!eap->skip && eap->addr_count > 0)
3518 {
3519 curwin->w_cursor.lnum = lnum;
3520 curwin->w_cursor.col = 0;
Bram Moolenaar0acc5612011-07-15 21:24:11 +02003521#ifdef FEAT_VIRTUALEDIT
3522 curwin->w_cursor.coladd = 0;
3523#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003524 }
3525 arg = startarg;
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003526 if (get_func_tv(name, (int)STRLEN(name), &rettv, &arg,
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003527 eap->line1, eap->line2, &doesrange,
3528 !eap->skip, fudi.fd_dict) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003529 {
3530 failed = TRUE;
3531 break;
3532 }
Bram Moolenaarf2789872006-11-28 19:54:04 +00003533
3534 /* Handle a function returning a Funcref, Dictionary or List. */
3535 if (handle_subscript(&arg, &rettv, !eap->skip, TRUE) == FAIL)
3536 {
3537 failed = TRUE;
3538 break;
3539 }
3540
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003541 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003542 if (doesrange || eap->skip)
3543 break;
Bram Moolenaarf2789872006-11-28 19:54:04 +00003544
Bram Moolenaar071d4272004-06-13 20:20:40 +00003545 /* Stop when immediately aborting on error, or when an interrupt
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003546 * occurred or an exception was thrown but not caught.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003547 * get_func_tv() returned OK, so that the check for trailing
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003548 * characters below is executed. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003549 if (aborting())
3550 break;
3551 }
3552 if (eap->skip)
3553 --emsg_skip;
3554
3555 if (!failed)
3556 {
3557 /* Check for trailing illegal characters and a following command. */
3558 if (!ends_excmd(*arg))
3559 {
3560 emsg_severe = TRUE;
3561 EMSG(_(e_trailing));
3562 }
3563 else
3564 eap->nextcmd = check_nextcmd(arg);
3565 }
3566
3567end:
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003568 dict_unref(fudi.fd_dict);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003569 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003570}
3571
3572/*
3573 * ":unlet[!] var1 ... " command.
3574 */
3575 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003576ex_unlet(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003577{
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003578 ex_unletlock(eap, eap->arg, 0);
3579}
3580
3581/*
3582 * ":lockvar" and ":unlockvar" commands
3583 */
3584 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003585ex_lockvar(exarg_T *eap)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003586{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003587 char_u *arg = eap->arg;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003588 int deep = 2;
3589
3590 if (eap->forceit)
3591 deep = -1;
3592 else if (vim_isdigit(*arg))
3593 {
3594 deep = getdigits(&arg);
3595 arg = skipwhite(arg);
3596 }
3597
3598 ex_unletlock(eap, arg, deep);
3599}
3600
3601/*
3602 * ":unlet", ":lockvar" and ":unlockvar" are quite similar.
3603 */
3604 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003605ex_unletlock(
3606 exarg_T *eap,
3607 char_u *argstart,
3608 int deep)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003609{
3610 char_u *arg = argstart;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003611 char_u *name_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003612 int error = FALSE;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003613 lval_T lv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003614
3615 do
3616 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003617 /* Parse the name and find the end. */
Bram Moolenaar6d977d62014-01-14 15:24:39 +01003618 name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error, 0,
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00003619 FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003620 if (lv.ll_name == NULL)
3621 error = TRUE; /* error but continue parsing */
3622 if (name_end == NULL || (!vim_iswhite(*name_end)
3623 && !ends_excmd(*name_end)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003624 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003625 if (name_end != NULL)
3626 {
3627 emsg_severe = TRUE;
3628 EMSG(_(e_trailing));
3629 }
3630 if (!(eap->skip || error))
3631 clear_lval(&lv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003632 break;
3633 }
3634
3635 if (!error && !eap->skip)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003636 {
3637 if (eap->cmdidx == CMD_unlet)
3638 {
3639 if (do_unlet_var(&lv, name_end, eap->forceit) == FAIL)
3640 error = TRUE;
3641 }
3642 else
3643 {
3644 if (do_lock_var(&lv, name_end, deep,
3645 eap->cmdidx == CMD_lockvar) == FAIL)
3646 error = TRUE;
3647 }
3648 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003649
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003650 if (!eap->skip)
3651 clear_lval(&lv);
3652
Bram Moolenaar071d4272004-06-13 20:20:40 +00003653 arg = skipwhite(name_end);
3654 } while (!ends_excmd(*arg));
3655
3656 eap->nextcmd = check_nextcmd(arg);
3657}
3658
Bram Moolenaar8c711452005-01-14 21:53:12 +00003659 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003660do_unlet_var(
3661 lval_T *lp,
3662 char_u *name_end,
3663 int forceit)
Bram Moolenaar8c711452005-01-14 21:53:12 +00003664{
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003665 int ret = OK;
3666 int cc;
3667
3668 if (lp->ll_tv == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00003669 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003670 cc = *name_end;
3671 *name_end = NUL;
3672
3673 /* Normal name or expanded name. */
3674 if (check_changedtick(lp->ll_name))
3675 ret = FAIL;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003676 else if (do_unlet(lp->ll_name, forceit) == FAIL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003677 ret = FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003678 *name_end = cc;
Bram Moolenaar8c711452005-01-14 21:53:12 +00003679 }
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02003680 else if ((lp->ll_list != NULL
Bram Moolenaar77354e72015-04-21 16:49:05 +02003681 && tv_check_lock(lp->ll_list->lv_lock, lp->ll_name, FALSE))
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02003682 || (lp->ll_dict != NULL
Bram Moolenaar77354e72015-04-21 16:49:05 +02003683 && tv_check_lock(lp->ll_dict->dv_lock, lp->ll_name, FALSE)))
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003684 return FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003685 else if (lp->ll_range)
3686 {
Bram Moolenaar33570922005-01-25 22:26:29 +00003687 listitem_T *li;
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02003688 listitem_T *ll_li = lp->ll_li;
Bram Moolenaarc9703302016-01-17 21:49:33 +01003689 int ll_n1 = lp->ll_n1;
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02003690
3691 while (ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= ll_n1))
3692 {
3693 li = ll_li->li_next;
Bram Moolenaar77354e72015-04-21 16:49:05 +02003694 if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name, FALSE))
Bram Moolenaarf2d912e2014-08-29 09:46:10 +02003695 return FAIL;
3696 ll_li = li;
3697 ++ll_n1;
3698 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003699
3700 /* Delete a range of List items. */
3701 while (lp->ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
3702 {
3703 li = lp->ll_li->li_next;
3704 listitem_remove(lp->ll_list, lp->ll_li);
3705 lp->ll_li = li;
3706 ++lp->ll_n1;
3707 }
3708 }
3709 else
3710 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003711 if (lp->ll_list != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003712 /* unlet a List item. */
3713 listitem_remove(lp->ll_list, lp->ll_li);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003714 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003715 /* unlet a Dictionary item. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003716 dictitem_remove(lp->ll_dict, lp->ll_di);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003717 }
3718
3719 return ret;
Bram Moolenaar8c711452005-01-14 21:53:12 +00003720}
3721
Bram Moolenaar071d4272004-06-13 20:20:40 +00003722/*
3723 * "unlet" a variable. Return OK if it existed, FAIL if not.
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003724 * When "forceit" is TRUE don't complain if the variable doesn't exist.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003725 */
3726 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003727do_unlet(char_u *name, int forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003728{
Bram Moolenaar33570922005-01-25 22:26:29 +00003729 hashtab_T *ht;
3730 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003731 char_u *varname;
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02003732 dict_T *d;
Bram Moolenaarafbdeb82008-01-05 21:16:31 +00003733 dictitem_T *di;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003734
Bram Moolenaar33570922005-01-25 22:26:29 +00003735 ht = find_var_ht(name, &varname);
3736 if (ht != NULL && *varname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003737 {
Bram Moolenaar71bcfdf2016-01-09 18:20:46 +01003738 if (ht == &globvarht)
3739 d = &globvardict;
3740 else if (current_funccal != NULL
3741 && ht == &current_funccal->l_vars.dv_hashtab)
3742 d = &current_funccal->l_vars;
3743 else if (ht == &compat_hashtab)
3744 d = &vimvardict;
3745 else
3746 {
3747 di = find_var_in_ht(ht, *name, (char_u *)"", FALSE);
3748 d = di == NULL ? NULL : di->di_tv.vval.v_dict;
3749 }
3750 if (d == NULL)
3751 {
3752 EMSG2(_(e_intern2), "do_unlet()");
3753 return FAIL;
3754 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003755 hi = hash_find(ht, varname);
3756 if (!HASHITEM_EMPTY(hi))
Bram Moolenaara7043832005-01-21 11:56:39 +00003757 {
Bram Moolenaarafbdeb82008-01-05 21:16:31 +00003758 di = HI2DI(hi);
Bram Moolenaar77354e72015-04-21 16:49:05 +02003759 if (var_check_fixed(di->di_flags, name, FALSE)
Bram Moolenaar71bcfdf2016-01-09 18:20:46 +01003760 || var_check_ro(di->di_flags, name, FALSE)
3761 || tv_check_lock(d->dv_lock, name, FALSE))
Bram Moolenaaraf8af8b2016-01-04 22:05:24 +01003762 return FAIL;
3763
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003764 delete_var(ht, hi);
3765 return OK;
Bram Moolenaara7043832005-01-21 11:56:39 +00003766 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003767 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003768 if (forceit)
3769 return OK;
3770 EMSG2(_("E108: No such variable: \"%s\""), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003771 return FAIL;
3772}
3773
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003774/*
3775 * Lock or unlock variable indicated by "lp".
3776 * "deep" is the levels to go (-1 for unlimited);
3777 * "lock" is TRUE for ":lockvar", FALSE for ":unlockvar".
3778 */
3779 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003780do_lock_var(
3781 lval_T *lp,
3782 char_u *name_end,
3783 int deep,
3784 int lock)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003785{
3786 int ret = OK;
3787 int cc;
3788 dictitem_T *di;
3789
3790 if (deep == 0) /* nothing to do */
3791 return OK;
3792
3793 if (lp->ll_tv == NULL)
3794 {
3795 cc = *name_end;
3796 *name_end = NUL;
3797
3798 /* Normal name or expanded name. */
3799 if (check_changedtick(lp->ll_name))
3800 ret = FAIL;
3801 else
3802 {
Bram Moolenaar6d977d62014-01-14 15:24:39 +01003803 di = find_var(lp->ll_name, NULL, TRUE);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003804 if (di == NULL)
3805 ret = FAIL;
3806 else
3807 {
3808 if (lock)
3809 di->di_flags |= DI_FLAGS_LOCK;
3810 else
3811 di->di_flags &= ~DI_FLAGS_LOCK;
3812 item_lock(&di->di_tv, deep, lock);
3813 }
3814 }
3815 *name_end = cc;
3816 }
3817 else if (lp->ll_range)
3818 {
3819 listitem_T *li = lp->ll_li;
3820
3821 /* (un)lock a range of List items. */
3822 while (li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
3823 {
3824 item_lock(&li->li_tv, deep, lock);
3825 li = li->li_next;
3826 ++lp->ll_n1;
3827 }
3828 }
3829 else if (lp->ll_list != NULL)
3830 /* (un)lock a List item. */
3831 item_lock(&lp->ll_li->li_tv, deep, lock);
3832 else
Bram Moolenaar641e48c2015-06-25 16:09:26 +02003833 /* (un)lock a Dictionary item. */
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003834 item_lock(&lp->ll_di->di_tv, deep, lock);
3835
3836 return ret;
3837}
3838
3839/*
3840 * Lock or unlock an item. "deep" is nr of levels to go.
3841 */
3842 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003843item_lock(typval_T *tv, int deep, int lock)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003844{
3845 static int recurse = 0;
3846 list_T *l;
3847 listitem_T *li;
3848 dict_T *d;
3849 hashitem_T *hi;
3850 int todo;
3851
3852 if (recurse >= DICT_MAXNEST)
3853 {
3854 EMSG(_("E743: variable nested too deep for (un)lock"));
3855 return;
3856 }
3857 if (deep == 0)
3858 return;
3859 ++recurse;
3860
3861 /* lock/unlock the item itself */
3862 if (lock)
3863 tv->v_lock |= VAR_LOCKED;
3864 else
3865 tv->v_lock &= ~VAR_LOCKED;
3866
3867 switch (tv->v_type)
3868 {
Bram Moolenaara03f2332016-02-06 18:09:59 +01003869 case VAR_UNKNOWN:
3870 case VAR_NUMBER:
3871 case VAR_STRING:
3872 case VAR_FUNC:
3873 case VAR_FLOAT:
3874 case VAR_SPECIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01003875 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01003876 case VAR_CHANNEL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01003877 break;
3878
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003879 case VAR_LIST:
3880 if ((l = tv->vval.v_list) != NULL)
3881 {
3882 if (lock)
3883 l->lv_lock |= VAR_LOCKED;
3884 else
3885 l->lv_lock &= ~VAR_LOCKED;
3886 if (deep < 0 || deep > 1)
3887 /* recursive: lock/unlock the items the List contains */
3888 for (li = l->lv_first; li != NULL; li = li->li_next)
3889 item_lock(&li->li_tv, deep - 1, lock);
3890 }
3891 break;
3892 case VAR_DICT:
3893 if ((d = tv->vval.v_dict) != NULL)
3894 {
3895 if (lock)
3896 d->dv_lock |= VAR_LOCKED;
3897 else
3898 d->dv_lock &= ~VAR_LOCKED;
3899 if (deep < 0 || deep > 1)
3900 {
3901 /* recursive: lock/unlock the items the List contains */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003902 todo = (int)d->dv_hashtab.ht_used;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003903 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
3904 {
3905 if (!HASHITEM_EMPTY(hi))
3906 {
3907 --todo;
3908 item_lock(&HI2DI(hi)->di_tv, deep - 1, lock);
3909 }
3910 }
3911 }
3912 }
3913 }
3914 --recurse;
3915}
3916
Bram Moolenaara40058a2005-07-11 22:42:07 +00003917/*
Bram Moolenaar61c4e2c2008-08-25 02:49:18 +00003918 * Return TRUE if typeval "tv" is locked: Either that value is locked itself
3919 * or it refers to a List or Dictionary that is locked.
Bram Moolenaara40058a2005-07-11 22:42:07 +00003920 */
3921 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003922tv_islocked(typval_T *tv)
Bram Moolenaara40058a2005-07-11 22:42:07 +00003923{
3924 return (tv->v_lock & VAR_LOCKED)
3925 || (tv->v_type == VAR_LIST
3926 && tv->vval.v_list != NULL
3927 && (tv->vval.v_list->lv_lock & VAR_LOCKED))
3928 || (tv->v_type == VAR_DICT
3929 && tv->vval.v_dict != NULL
3930 && (tv->vval.v_dict->dv_lock & VAR_LOCKED));
3931}
3932
Bram Moolenaar071d4272004-06-13 20:20:40 +00003933#if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO)
3934/*
3935 * Delete all "menutrans_" variables.
3936 */
3937 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01003938del_menutrans_vars(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003939{
Bram Moolenaar33570922005-01-25 22:26:29 +00003940 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003941 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003942
Bram Moolenaar33570922005-01-25 22:26:29 +00003943 hash_lock(&globvarht);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003944 todo = (int)globvarht.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00003945 for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaara7043832005-01-21 11:56:39 +00003946 {
3947 if (!HASHITEM_EMPTY(hi))
3948 {
3949 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00003950 if (STRNCMP(HI2DI(hi)->di_key, "menutrans_", 10) == 0)
3951 delete_var(&globvarht, hi);
Bram Moolenaara7043832005-01-21 11:56:39 +00003952 }
3953 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003954 hash_unlock(&globvarht);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003955}
3956#endif
3957
3958#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
3959
3960/*
3961 * Local string buffer for the next two functions to store a variable name
3962 * with its prefix. Allocated in cat_prefix_varname(), freed later in
3963 * get_user_var_name().
3964 */
3965
Bram Moolenaar48e697e2016-01-23 22:17:30 +01003966static char_u *cat_prefix_varname(int prefix, char_u *name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003967
3968static char_u *varnamebuf = NULL;
3969static int varnamebuflen = 0;
3970
3971/*
3972 * Function to concatenate a prefix and a variable name.
3973 */
3974 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01003975cat_prefix_varname(int prefix, char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003976{
3977 int len;
3978
3979 len = (int)STRLEN(name) + 3;
3980 if (len > varnamebuflen)
3981 {
3982 vim_free(varnamebuf);
3983 len += 10; /* some additional space */
3984 varnamebuf = alloc(len);
3985 if (varnamebuf == NULL)
3986 {
3987 varnamebuflen = 0;
3988 return NULL;
3989 }
3990 varnamebuflen = len;
3991 }
3992 *varnamebuf = prefix;
3993 varnamebuf[1] = ':';
3994 STRCPY(varnamebuf + 2, name);
3995 return varnamebuf;
3996}
3997
3998/*
3999 * Function given to ExpandGeneric() to obtain the list of user defined
4000 * (global/buffer/window/built-in) variable names.
4001 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004002 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01004003get_user_var_name(expand_T *xp, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004004{
Bram Moolenaar532c7802005-01-27 14:44:31 +00004005 static long_u gdone;
4006 static long_u bdone;
4007 static long_u wdone;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00004008#ifdef FEAT_WINDOWS
4009 static long_u tdone;
4010#endif
Bram Moolenaar532c7802005-01-27 14:44:31 +00004011 static int vidx;
4012 static hashitem_T *hi;
4013 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004014
4015 if (idx == 0)
Bram Moolenaar910f66f2006-04-05 20:41:53 +00004016 {
Bram Moolenaara7043832005-01-21 11:56:39 +00004017 gdone = bdone = wdone = vidx = 0;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00004018#ifdef FEAT_WINDOWS
4019 tdone = 0;
4020#endif
4021 }
Bram Moolenaar33570922005-01-25 22:26:29 +00004022
4023 /* Global variables */
4024 if (gdone < globvarht.ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004025 {
Bram Moolenaara7043832005-01-21 11:56:39 +00004026 if (gdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00004027 hi = globvarht.ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00004028 else
4029 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00004030 while (HASHITEM_EMPTY(hi))
4031 ++hi;
4032 if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
4033 return cat_prefix_varname('g', hi->hi_key);
4034 return hi->hi_key;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004035 }
Bram Moolenaar33570922005-01-25 22:26:29 +00004036
4037 /* b: variables */
Bram Moolenaar429fa852013-04-15 12:27:36 +02004038 ht = &curbuf->b_vars->dv_hashtab;
Bram Moolenaar33570922005-01-25 22:26:29 +00004039 if (bdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004040 {
Bram Moolenaara7043832005-01-21 11:56:39 +00004041 if (bdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00004042 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00004043 else
4044 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00004045 while (HASHITEM_EMPTY(hi))
4046 ++hi;
4047 return cat_prefix_varname('b', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004048 }
Bram Moolenaar33570922005-01-25 22:26:29 +00004049 if (bdone == ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004050 {
Bram Moolenaara7043832005-01-21 11:56:39 +00004051 ++bdone;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004052 return (char_u *)"b:changedtick";
4053 }
Bram Moolenaar33570922005-01-25 22:26:29 +00004054
4055 /* w: variables */
Bram Moolenaar429fa852013-04-15 12:27:36 +02004056 ht = &curwin->w_vars->dv_hashtab;
Bram Moolenaar33570922005-01-25 22:26:29 +00004057 if (wdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004058 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00004059 if (wdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00004060 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00004061 else
4062 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00004063 while (HASHITEM_EMPTY(hi))
4064 ++hi;
4065 return cat_prefix_varname('w', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004066 }
Bram Moolenaar33570922005-01-25 22:26:29 +00004067
Bram Moolenaar910f66f2006-04-05 20:41:53 +00004068#ifdef FEAT_WINDOWS
4069 /* t: variables */
Bram Moolenaar429fa852013-04-15 12:27:36 +02004070 ht = &curtab->tp_vars->dv_hashtab;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00004071 if (tdone < ht->ht_used)
4072 {
4073 if (tdone++ == 0)
4074 hi = ht->ht_array;
4075 else
4076 ++hi;
4077 while (HASHITEM_EMPTY(hi))
4078 ++hi;
4079 return cat_prefix_varname('t', hi->hi_key);
4080 }
4081#endif
4082
Bram Moolenaar33570922005-01-25 22:26:29 +00004083 /* v: variables */
4084 if (vidx < VV_LEN)
4085 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].vv_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004086
4087 vim_free(varnamebuf);
4088 varnamebuf = NULL;
4089 varnamebuflen = 0;
4090 return NULL;
4091}
4092
4093#endif /* FEAT_CMDL_COMPL */
4094
4095/*
4096 * types for expressions.
4097 */
4098typedef enum
4099{
4100 TYPE_UNKNOWN = 0
4101 , TYPE_EQUAL /* == */
4102 , TYPE_NEQUAL /* != */
4103 , TYPE_GREATER /* > */
4104 , TYPE_GEQUAL /* >= */
4105 , TYPE_SMALLER /* < */
4106 , TYPE_SEQUAL /* <= */
4107 , TYPE_MATCH /* =~ */
4108 , TYPE_NOMATCH /* !~ */
4109} exptype_T;
4110
4111/*
4112 * The "evaluate" argument: When FALSE, the argument is only parsed but not
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004113 * executed. The function may return OK, but the rettv will be of type
Bram Moolenaar071d4272004-06-13 20:20:40 +00004114 * VAR_UNKNOWN. The function still returns FAIL for a syntax error.
4115 */
4116
4117/*
4118 * Handle zero level expression.
4119 * This calls eval1() and handles error message and nextcmd.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004120 * Put the result in "rettv" when returning OK and "evaluate" is TRUE.
Bram Moolenaar4463f292005-09-25 22:20:24 +00004121 * Note: "rettv.v_lock" is not set.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004122 * Return OK or FAIL.
4123 */
4124 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004125eval0(
4126 char_u *arg,
4127 typval_T *rettv,
4128 char_u **nextcmd,
4129 int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004130{
4131 int ret;
4132 char_u *p;
4133
4134 p = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004135 ret = eval1(&p, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004136 if (ret == FAIL || !ends_excmd(*p))
4137 {
4138 if (ret != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004139 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004140 /*
4141 * Report the invalid expression unless the expression evaluation has
4142 * been cancelled due to an aborting error, an interrupt, or an
4143 * exception.
4144 */
4145 if (!aborting())
4146 EMSG2(_(e_invexpr2), arg);
4147 ret = FAIL;
4148 }
4149 if (nextcmd != NULL)
4150 *nextcmd = check_nextcmd(p);
4151
4152 return ret;
4153}
4154
4155/*
4156 * Handle top level expression:
Bram Moolenaarb67cc162009-02-04 15:27:06 +00004157 * expr2 ? expr1 : expr1
Bram Moolenaar071d4272004-06-13 20:20:40 +00004158 *
4159 * "arg" must point to the first non-white of the expression.
4160 * "arg" is advanced to the next non-white after the recognized expression.
4161 *
Bram Moolenaar4463f292005-09-25 22:20:24 +00004162 * Note: "rettv.v_lock" is not set.
4163 *
Bram Moolenaar071d4272004-06-13 20:20:40 +00004164 * Return OK or FAIL.
4165 */
4166 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004167eval1(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004168{
4169 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00004170 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004171
4172 /*
4173 * Get the first variable.
4174 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004175 if (eval2(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004176 return FAIL;
4177
4178 if ((*arg)[0] == '?')
4179 {
4180 result = FALSE;
4181 if (evaluate)
4182 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004183 int error = FALSE;
4184
4185 if (get_tv_number_chk(rettv, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004186 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004187 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004188 if (error)
4189 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004190 }
4191
4192 /*
4193 * Get the second variable.
4194 */
4195 *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004196 if (eval1(arg, rettv, evaluate && result) == FAIL) /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004197 return FAIL;
4198
4199 /*
4200 * Check for the ":".
4201 */
4202 if ((*arg)[0] != ':')
4203 {
4204 EMSG(_("E109: Missing ':' after '?'"));
4205 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004206 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004207 return FAIL;
4208 }
4209
4210 /*
4211 * Get the third variable.
4212 */
4213 *arg = skipwhite(*arg + 1);
4214 if (eval1(arg, &var2, evaluate && !result) == FAIL) /* recursive! */
4215 {
4216 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004217 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004218 return FAIL;
4219 }
4220 if (evaluate && !result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004221 *rettv = var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004222 }
4223
4224 return OK;
4225}
4226
4227/*
4228 * Handle first level expression:
4229 * expr2 || expr2 || expr2 logical OR
4230 *
4231 * "arg" must point to the first non-white of the expression.
4232 * "arg" is advanced to the next non-white after the recognized expression.
4233 *
4234 * Return OK or FAIL.
4235 */
4236 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004237eval2(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004238{
Bram Moolenaar33570922005-01-25 22:26:29 +00004239 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004240 long result;
4241 int first;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004242 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004243
4244 /*
4245 * Get the first variable.
4246 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004247 if (eval3(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004248 return FAIL;
4249
4250 /*
4251 * Repeat until there is no following "||".
4252 */
4253 first = TRUE;
4254 result = FALSE;
4255 while ((*arg)[0] == '|' && (*arg)[1] == '|')
4256 {
4257 if (evaluate && first)
4258 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004259 if (get_tv_number_chk(rettv, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004260 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004261 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004262 if (error)
4263 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004264 first = FALSE;
4265 }
4266
4267 /*
4268 * Get the second variable.
4269 */
4270 *arg = skipwhite(*arg + 2);
4271 if (eval3(arg, &var2, evaluate && !result) == FAIL)
4272 return FAIL;
4273
4274 /*
4275 * Compute the result.
4276 */
4277 if (evaluate && !result)
4278 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004279 if (get_tv_number_chk(&var2, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004280 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004281 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004282 if (error)
4283 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004284 }
4285 if (evaluate)
4286 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004287 rettv->v_type = VAR_NUMBER;
4288 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004289 }
4290 }
4291
4292 return OK;
4293}
4294
4295/*
4296 * Handle second level expression:
4297 * expr3 && expr3 && expr3 logical AND
4298 *
4299 * "arg" must point to the first non-white of the expression.
4300 * "arg" is advanced to the next non-white after the recognized expression.
4301 *
4302 * Return OK or FAIL.
4303 */
4304 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004305eval3(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004306{
Bram Moolenaar33570922005-01-25 22:26:29 +00004307 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004308 long result;
4309 int first;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004310 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004311
4312 /*
4313 * Get the first variable.
4314 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004315 if (eval4(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004316 return FAIL;
4317
4318 /*
4319 * Repeat until there is no following "&&".
4320 */
4321 first = TRUE;
4322 result = TRUE;
4323 while ((*arg)[0] == '&' && (*arg)[1] == '&')
4324 {
4325 if (evaluate && first)
4326 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004327 if (get_tv_number_chk(rettv, &error) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004328 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004329 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004330 if (error)
4331 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004332 first = FALSE;
4333 }
4334
4335 /*
4336 * Get the second variable.
4337 */
4338 *arg = skipwhite(*arg + 2);
4339 if (eval4(arg, &var2, evaluate && result) == FAIL)
4340 return FAIL;
4341
4342 /*
4343 * Compute the result.
4344 */
4345 if (evaluate && result)
4346 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004347 if (get_tv_number_chk(&var2, &error) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004348 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004349 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004350 if (error)
4351 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004352 }
4353 if (evaluate)
4354 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004355 rettv->v_type = VAR_NUMBER;
4356 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004357 }
4358 }
4359
4360 return OK;
4361}
4362
4363/*
4364 * Handle third level expression:
4365 * var1 == var2
4366 * var1 =~ var2
4367 * var1 != var2
4368 * var1 !~ var2
4369 * var1 > var2
4370 * var1 >= var2
4371 * var1 < var2
4372 * var1 <= var2
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004373 * var1 is var2
4374 * var1 isnot var2
Bram Moolenaar071d4272004-06-13 20:20:40 +00004375 *
4376 * "arg" must point to the first non-white of the expression.
4377 * "arg" is advanced to the next non-white after the recognized expression.
4378 *
4379 * Return OK or FAIL.
4380 */
4381 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004382eval4(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004383{
Bram Moolenaar33570922005-01-25 22:26:29 +00004384 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004385 char_u *p;
4386 int i;
4387 exptype_T type = TYPE_UNKNOWN;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004388 int type_is = FALSE; /* TRUE for "is" and "isnot" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004389 int len = 2;
4390 long n1, n2;
4391 char_u *s1, *s2;
4392 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4393 regmatch_T regmatch;
4394 int ic;
4395 char_u *save_cpo;
4396
4397 /*
4398 * Get the first variable.
4399 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004400 if (eval5(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004401 return FAIL;
4402
4403 p = *arg;
4404 switch (p[0])
4405 {
4406 case '=': if (p[1] == '=')
4407 type = TYPE_EQUAL;
4408 else if (p[1] == '~')
4409 type = TYPE_MATCH;
4410 break;
4411 case '!': if (p[1] == '=')
4412 type = TYPE_NEQUAL;
4413 else if (p[1] == '~')
4414 type = TYPE_NOMATCH;
4415 break;
4416 case '>': if (p[1] != '=')
4417 {
4418 type = TYPE_GREATER;
4419 len = 1;
4420 }
4421 else
4422 type = TYPE_GEQUAL;
4423 break;
4424 case '<': if (p[1] != '=')
4425 {
4426 type = TYPE_SMALLER;
4427 len = 1;
4428 }
4429 else
4430 type = TYPE_SEQUAL;
4431 break;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004432 case 'i': if (p[1] == 's')
4433 {
4434 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
4435 len = 5;
Bram Moolenaar37a8de12015-09-01 16:05:00 +02004436 i = p[len];
4437 if (!isalnum(i) && i != '_')
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004438 {
4439 type = len == 2 ? TYPE_EQUAL : TYPE_NEQUAL;
4440 type_is = TRUE;
4441 }
4442 }
4443 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004444 }
4445
4446 /*
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004447 * If there is a comparative operator, use it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004448 */
4449 if (type != TYPE_UNKNOWN)
4450 {
4451 /* extra question mark appended: ignore case */
4452 if (p[len] == '?')
4453 {
4454 ic = TRUE;
4455 ++len;
4456 }
4457 /* extra '#' appended: match case */
4458 else if (p[len] == '#')
4459 {
4460 ic = FALSE;
4461 ++len;
4462 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004463 /* nothing appended: use 'ignorecase' */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004464 else
4465 ic = p_ic;
4466
4467 /*
4468 * Get the second variable.
4469 */
4470 *arg = skipwhite(p + len);
4471 if (eval5(arg, &var2, evaluate) == FAIL)
4472 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004473 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004474 return FAIL;
4475 }
4476
4477 if (evaluate)
4478 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004479 if (type_is && rettv->v_type != var2.v_type)
4480 {
4481 /* For "is" a different type always means FALSE, for "notis"
4482 * it means TRUE. */
4483 n1 = (type == TYPE_NEQUAL);
4484 }
4485 else if (rettv->v_type == VAR_LIST || var2.v_type == VAR_LIST)
4486 {
4487 if (type_is)
4488 {
4489 n1 = (rettv->v_type == var2.v_type
4490 && rettv->vval.v_list == var2.vval.v_list);
4491 if (type == TYPE_NEQUAL)
4492 n1 = !n1;
4493 }
4494 else if (rettv->v_type != var2.v_type
4495 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
4496 {
4497 if (rettv->v_type != var2.v_type)
Bram Moolenaare49b69a2005-01-08 16:11:57 +00004498 EMSG(_("E691: Can only compare List with List"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004499 else
Bram Moolenaar59838522014-05-13 13:46:33 +02004500 EMSG(_("E692: Invalid operation for List"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004501 clear_tv(rettv);
4502 clear_tv(&var2);
4503 return FAIL;
4504 }
4505 else
4506 {
4507 /* Compare two Lists for being equal or unequal. */
Bram Moolenaar67b3f992010-11-10 20:41:57 +01004508 n1 = list_equal(rettv->vval.v_list, var2.vval.v_list,
4509 ic, FALSE);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004510 if (type == TYPE_NEQUAL)
4511 n1 = !n1;
4512 }
4513 }
4514
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004515 else if (rettv->v_type == VAR_DICT || var2.v_type == VAR_DICT)
4516 {
4517 if (type_is)
4518 {
4519 n1 = (rettv->v_type == var2.v_type
4520 && rettv->vval.v_dict == var2.vval.v_dict);
4521 if (type == TYPE_NEQUAL)
4522 n1 = !n1;
4523 }
4524 else if (rettv->v_type != var2.v_type
4525 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
4526 {
4527 if (rettv->v_type != var2.v_type)
4528 EMSG(_("E735: Can only compare Dictionary with Dictionary"));
4529 else
4530 EMSG(_("E736: Invalid operation for Dictionary"));
4531 clear_tv(rettv);
4532 clear_tv(&var2);
4533 return FAIL;
4534 }
4535 else
4536 {
4537 /* Compare two Dictionaries for being equal or unequal. */
Bram Moolenaar67b3f992010-11-10 20:41:57 +01004538 n1 = dict_equal(rettv->vval.v_dict, var2.vval.v_dict,
4539 ic, FALSE);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004540 if (type == TYPE_NEQUAL)
4541 n1 = !n1;
4542 }
4543 }
4544
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004545 else if (rettv->v_type == VAR_FUNC || var2.v_type == VAR_FUNC)
4546 {
4547 if (rettv->v_type != var2.v_type
4548 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
4549 {
4550 if (rettv->v_type != var2.v_type)
Bram Moolenaare49b69a2005-01-08 16:11:57 +00004551 EMSG(_("E693: Can only compare Funcref with Funcref"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004552 else
Bram Moolenaare49b69a2005-01-08 16:11:57 +00004553 EMSG(_("E694: Invalid operation for Funcrefs"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004554 clear_tv(rettv);
4555 clear_tv(&var2);
4556 return FAIL;
4557 }
4558 else
4559 {
4560 /* Compare two Funcrefs for being equal or unequal. */
4561 if (rettv->vval.v_string == NULL
4562 || var2.vval.v_string == NULL)
4563 n1 = FALSE;
4564 else
4565 n1 = STRCMP(rettv->vval.v_string,
4566 var2.vval.v_string) == 0;
4567 if (type == TYPE_NEQUAL)
4568 n1 = !n1;
4569 }
4570 }
4571
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004572#ifdef FEAT_FLOAT
4573 /*
4574 * If one of the two variables is a float, compare as a float.
4575 * When using "=~" or "!~", always compare as string.
4576 */
4577 else if ((rettv->v_type == VAR_FLOAT || var2.v_type == VAR_FLOAT)
4578 && type != TYPE_MATCH && type != TYPE_NOMATCH)
4579 {
4580 float_T f1, f2;
4581
4582 if (rettv->v_type == VAR_FLOAT)
4583 f1 = rettv->vval.v_float;
4584 else
4585 f1 = get_tv_number(rettv);
4586 if (var2.v_type == VAR_FLOAT)
4587 f2 = var2.vval.v_float;
4588 else
4589 f2 = get_tv_number(&var2);
4590 n1 = FALSE;
4591 switch (type)
4592 {
4593 case TYPE_EQUAL: n1 = (f1 == f2); break;
4594 case TYPE_NEQUAL: n1 = (f1 != f2); break;
4595 case TYPE_GREATER: n1 = (f1 > f2); break;
4596 case TYPE_GEQUAL: n1 = (f1 >= f2); break;
4597 case TYPE_SMALLER: n1 = (f1 < f2); break;
4598 case TYPE_SEQUAL: n1 = (f1 <= f2); break;
4599 case TYPE_UNKNOWN:
4600 case TYPE_MATCH:
4601 case TYPE_NOMATCH: break; /* avoid gcc warning */
4602 }
4603 }
4604#endif
4605
Bram Moolenaar071d4272004-06-13 20:20:40 +00004606 /*
4607 * If one of the two variables is a number, compare as a number.
4608 * When using "=~" or "!~", always compare as string.
4609 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004610 else if ((rettv->v_type == VAR_NUMBER || var2.v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004611 && type != TYPE_MATCH && type != TYPE_NOMATCH)
4612 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004613 n1 = get_tv_number(rettv);
4614 n2 = get_tv_number(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004615 switch (type)
4616 {
4617 case TYPE_EQUAL: n1 = (n1 == n2); break;
4618 case TYPE_NEQUAL: n1 = (n1 != n2); break;
4619 case TYPE_GREATER: n1 = (n1 > n2); break;
4620 case TYPE_GEQUAL: n1 = (n1 >= n2); break;
4621 case TYPE_SMALLER: n1 = (n1 < n2); break;
4622 case TYPE_SEQUAL: n1 = (n1 <= n2); break;
4623 case TYPE_UNKNOWN:
4624 case TYPE_MATCH:
4625 case TYPE_NOMATCH: break; /* avoid gcc warning */
4626 }
4627 }
4628 else
4629 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004630 s1 = get_tv_string_buf(rettv, buf1);
4631 s2 = get_tv_string_buf(&var2, buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004632 if (type != TYPE_MATCH && type != TYPE_NOMATCH)
4633 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2);
4634 else
4635 i = 0;
4636 n1 = FALSE;
4637 switch (type)
4638 {
4639 case TYPE_EQUAL: n1 = (i == 0); break;
4640 case TYPE_NEQUAL: n1 = (i != 0); break;
4641 case TYPE_GREATER: n1 = (i > 0); break;
4642 case TYPE_GEQUAL: n1 = (i >= 0); break;
4643 case TYPE_SMALLER: n1 = (i < 0); break;
4644 case TYPE_SEQUAL: n1 = (i <= 0); break;
4645
4646 case TYPE_MATCH:
4647 case TYPE_NOMATCH:
4648 /* avoid 'l' flag in 'cpoptions' */
4649 save_cpo = p_cpo;
4650 p_cpo = (char_u *)"";
4651 regmatch.regprog = vim_regcomp(s2,
4652 RE_MAGIC + RE_STRING);
4653 regmatch.rm_ic = ic;
4654 if (regmatch.regprog != NULL)
4655 {
4656 n1 = vim_regexec_nl(&regmatch, s1, (colnr_T)0);
Bram Moolenaar473de612013-06-08 18:19:48 +02004657 vim_regfree(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004658 if (type == TYPE_NOMATCH)
4659 n1 = !n1;
4660 }
4661 p_cpo = save_cpo;
4662 break;
4663
4664 case TYPE_UNKNOWN: break; /* avoid gcc warning */
4665 }
4666 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004667 clear_tv(rettv);
4668 clear_tv(&var2);
4669 rettv->v_type = VAR_NUMBER;
4670 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004671 }
4672 }
4673
4674 return OK;
4675}
4676
4677/*
4678 * Handle fourth level expression:
4679 * + number addition
4680 * - number subtraction
4681 * . string concatenation
4682 *
4683 * "arg" must point to the first non-white of the expression.
4684 * "arg" is advanced to the next non-white after the recognized expression.
4685 *
4686 * Return OK or FAIL.
4687 */
4688 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004689eval5(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004690{
Bram Moolenaar33570922005-01-25 22:26:29 +00004691 typval_T var2;
4692 typval_T var3;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004693 int op;
4694 long n1, n2;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004695#ifdef FEAT_FLOAT
4696 float_T f1 = 0, f2 = 0;
4697#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004698 char_u *s1, *s2;
4699 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4700 char_u *p;
4701
4702 /*
4703 * Get the first variable.
4704 */
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004705 if (eval6(arg, rettv, evaluate, FALSE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004706 return FAIL;
4707
4708 /*
4709 * Repeat computing, until no '+', '-' or '.' is following.
4710 */
4711 for (;;)
4712 {
4713 op = **arg;
4714 if (op != '+' && op != '-' && op != '.')
4715 break;
4716
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004717 if ((op != '+' || rettv->v_type != VAR_LIST)
4718#ifdef FEAT_FLOAT
4719 && (op == '.' || rettv->v_type != VAR_FLOAT)
4720#endif
4721 )
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004722 {
4723 /* For "list + ...", an illegal use of the first operand as
4724 * a number cannot be determined before evaluating the 2nd
4725 * operand: if this is also a list, all is ok.
4726 * For "something . ...", "something - ..." or "non-list + ...",
4727 * we know that the first operand needs to be a string or number
4728 * without evaluating the 2nd operand. So check before to avoid
4729 * side effects after an error. */
4730 if (evaluate && get_tv_string_chk(rettv) == NULL)
4731 {
4732 clear_tv(rettv);
4733 return FAIL;
4734 }
4735 }
4736
Bram Moolenaar071d4272004-06-13 20:20:40 +00004737 /*
4738 * Get the second variable.
4739 */
4740 *arg = skipwhite(*arg + 1);
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004741 if (eval6(arg, &var2, evaluate, op == '.') == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004742 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004743 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004744 return FAIL;
4745 }
4746
4747 if (evaluate)
4748 {
4749 /*
4750 * Compute the result.
4751 */
4752 if (op == '.')
4753 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004754 s1 = get_tv_string_buf(rettv, buf1); /* already checked */
4755 s2 = get_tv_string_buf_chk(&var2, buf2);
4756 if (s2 == NULL) /* type error ? */
4757 {
4758 clear_tv(rettv);
4759 clear_tv(&var2);
4760 return FAIL;
4761 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004762 p = concat_str(s1, s2);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004763 clear_tv(rettv);
4764 rettv->v_type = VAR_STRING;
4765 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004766 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00004767 else if (op == '+' && rettv->v_type == VAR_LIST
4768 && var2.v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004769 {
4770 /* concatenate Lists */
4771 if (list_concat(rettv->vval.v_list, var2.vval.v_list,
4772 &var3) == FAIL)
4773 {
4774 clear_tv(rettv);
4775 clear_tv(&var2);
4776 return FAIL;
4777 }
4778 clear_tv(rettv);
4779 *rettv = var3;
4780 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004781 else
4782 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004783 int error = FALSE;
4784
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004785#ifdef FEAT_FLOAT
4786 if (rettv->v_type == VAR_FLOAT)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004787 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004788 f1 = rettv->vval.v_float;
4789 n1 = 0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004790 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004791 else
4792#endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004793 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004794 n1 = get_tv_number_chk(rettv, &error);
4795 if (error)
4796 {
4797 /* This can only happen for "list + non-list". For
4798 * "non-list + ..." or "something - ...", we returned
4799 * before evaluating the 2nd operand. */
4800 clear_tv(rettv);
4801 return FAIL;
4802 }
4803#ifdef FEAT_FLOAT
4804 if (var2.v_type == VAR_FLOAT)
4805 f1 = n1;
4806#endif
4807 }
4808#ifdef FEAT_FLOAT
4809 if (var2.v_type == VAR_FLOAT)
4810 {
4811 f2 = var2.vval.v_float;
4812 n2 = 0;
4813 }
4814 else
4815#endif
4816 {
4817 n2 = get_tv_number_chk(&var2, &error);
4818 if (error)
4819 {
4820 clear_tv(rettv);
4821 clear_tv(&var2);
4822 return FAIL;
4823 }
4824#ifdef FEAT_FLOAT
4825 if (rettv->v_type == VAR_FLOAT)
4826 f2 = n2;
4827#endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004828 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004829 clear_tv(rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004830
4831#ifdef FEAT_FLOAT
4832 /* If there is a float on either side the result is a float. */
4833 if (rettv->v_type == VAR_FLOAT || var2.v_type == VAR_FLOAT)
4834 {
4835 if (op == '+')
4836 f1 = f1 + f2;
4837 else
4838 f1 = f1 - f2;
4839 rettv->v_type = VAR_FLOAT;
4840 rettv->vval.v_float = f1;
4841 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004842 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004843#endif
4844 {
4845 if (op == '+')
4846 n1 = n1 + n2;
4847 else
4848 n1 = n1 - n2;
4849 rettv->v_type = VAR_NUMBER;
4850 rettv->vval.v_number = n1;
4851 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004852 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004853 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004854 }
4855 }
4856 return OK;
4857}
4858
4859/*
4860 * Handle fifth level expression:
4861 * * number multiplication
4862 * / number division
4863 * % number modulo
4864 *
4865 * "arg" must point to the first non-white of the expression.
4866 * "arg" is advanced to the next non-white after the recognized expression.
4867 *
4868 * Return OK or FAIL.
4869 */
4870 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01004871eval6(
4872 char_u **arg,
4873 typval_T *rettv,
4874 int evaluate,
4875 int want_string) /* after "." operator */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004876{
Bram Moolenaar33570922005-01-25 22:26:29 +00004877 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004878 int op;
4879 long n1, n2;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004880#ifdef FEAT_FLOAT
4881 int use_float = FALSE;
4882 float_T f1 = 0, f2;
4883#endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004884 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004885
4886 /*
4887 * Get the first variable.
4888 */
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004889 if (eval7(arg, rettv, evaluate, want_string) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004890 return FAIL;
4891
4892 /*
4893 * Repeat computing, until no '*', '/' or '%' is following.
4894 */
4895 for (;;)
4896 {
4897 op = **arg;
4898 if (op != '*' && op != '/' && op != '%')
4899 break;
4900
4901 if (evaluate)
4902 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004903#ifdef FEAT_FLOAT
4904 if (rettv->v_type == VAR_FLOAT)
4905 {
4906 f1 = rettv->vval.v_float;
4907 use_float = TRUE;
4908 n1 = 0;
4909 }
4910 else
4911#endif
4912 n1 = get_tv_number_chk(rettv, &error);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004913 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004914 if (error)
4915 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004916 }
4917 else
4918 n1 = 0;
4919
4920 /*
4921 * Get the second variable.
4922 */
4923 *arg = skipwhite(*arg + 1);
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004924 if (eval7(arg, &var2, evaluate, FALSE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004925 return FAIL;
4926
4927 if (evaluate)
4928 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004929#ifdef FEAT_FLOAT
4930 if (var2.v_type == VAR_FLOAT)
4931 {
4932 if (!use_float)
4933 {
4934 f1 = n1;
4935 use_float = TRUE;
4936 }
4937 f2 = var2.vval.v_float;
4938 n2 = 0;
4939 }
4940 else
4941#endif
4942 {
4943 n2 = get_tv_number_chk(&var2, &error);
4944 clear_tv(&var2);
4945 if (error)
4946 return FAIL;
4947#ifdef FEAT_FLOAT
4948 if (use_float)
4949 f2 = n2;
4950#endif
4951 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004952
4953 /*
4954 * Compute the result.
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004955 * When either side is a float the result is a float.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004956 */
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004957#ifdef FEAT_FLOAT
4958 if (use_float)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004959 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004960 if (op == '*')
4961 f1 = f1 * f2;
4962 else if (op == '/')
4963 {
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004964# ifdef VMS
4965 /* VMS crashes on divide by zero, work around it */
4966 if (f2 == 0.0)
4967 {
4968 if (f1 == 0)
Bram Moolenaar314f11d2010-08-09 22:07:08 +02004969 f1 = -1 * __F_FLT_MAX - 1L; /* similar to NaN */
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004970 else if (f1 < 0)
Bram Moolenaar314f11d2010-08-09 22:07:08 +02004971 f1 = -1 * __F_FLT_MAX;
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004972 else
Bram Moolenaar314f11d2010-08-09 22:07:08 +02004973 f1 = __F_FLT_MAX;
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004974 }
4975 else
4976 f1 = f1 / f2;
4977# else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004978 /* We rely on the floating point library to handle divide
4979 * by zero to result in "inf" and not a crash. */
4980 f1 = f1 / f2;
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004981# endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004982 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004983 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004984 {
Bram Moolenaar1378fca2008-07-04 16:51:55 +00004985 EMSG(_("E804: Cannot use '%' with Float"));
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004986 return FAIL;
4987 }
4988 rettv->v_type = VAR_FLOAT;
4989 rettv->vval.v_float = f1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004990 }
4991 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004992#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004993 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004994 if (op == '*')
4995 n1 = n1 * n2;
4996 else if (op == '/')
4997 {
4998 if (n2 == 0) /* give an error message? */
4999 {
5000 if (n1 == 0)
5001 n1 = -0x7fffffffL - 1L; /* similar to NaN */
5002 else if (n1 < 0)
5003 n1 = -0x7fffffffL;
5004 else
5005 n1 = 0x7fffffffL;
5006 }
5007 else
5008 n1 = n1 / n2;
5009 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005010 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005011 {
5012 if (n2 == 0) /* give an error message? */
5013 n1 = 0;
5014 else
5015 n1 = n1 % n2;
5016 }
5017 rettv->v_type = VAR_NUMBER;
5018 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005019 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005020 }
5021 }
5022
5023 return OK;
5024}
5025
5026/*
5027 * Handle sixth level expression:
5028 * number number constant
Bram Moolenaarbae0c162007-05-10 19:30:25 +00005029 * "string" string constant
5030 * 'string' literal string constant
Bram Moolenaar071d4272004-06-13 20:20:40 +00005031 * &option-name option value
5032 * @r register contents
5033 * identifier variable value
5034 * function() function call
5035 * $VAR environment variable
5036 * (expression) nested expression
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005037 * [expr, expr] List
5038 * {key: val, key: val} Dictionary
Bram Moolenaar071d4272004-06-13 20:20:40 +00005039 *
5040 * Also handle:
5041 * ! in front logical NOT
5042 * - in front unary minus
5043 * + in front unary plus (ignored)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005044 * trailing [] subscript in String or List
5045 * trailing .name entry in Dictionary
Bram Moolenaar071d4272004-06-13 20:20:40 +00005046 *
5047 * "arg" must point to the first non-white of the expression.
5048 * "arg" is advanced to the next non-white after the recognized expression.
5049 *
5050 * Return OK or FAIL.
5051 */
5052 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005053eval7(
5054 char_u **arg,
5055 typval_T *rettv,
5056 int evaluate,
5057 int want_string UNUSED) /* after "." operator */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005058{
Bram Moolenaar071d4272004-06-13 20:20:40 +00005059 long n;
5060 int len;
5061 char_u *s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005062 char_u *start_leader, *end_leader;
5063 int ret = OK;
5064 char_u *alias;
5065
5066 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005067 * Initialise variable so that clear_tv() can't mistake this for a
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005068 * string and free a string that isn't there.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005069 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005070 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005071
5072 /*
5073 * Skip '!' and '-' characters. They are handled later.
5074 */
5075 start_leader = *arg;
5076 while (**arg == '!' || **arg == '-' || **arg == '+')
5077 *arg = skipwhite(*arg + 1);
5078 end_leader = *arg;
5079
5080 switch (**arg)
5081 {
5082 /*
5083 * Number constant.
5084 */
5085 case '0':
5086 case '1':
5087 case '2':
5088 case '3':
5089 case '4':
5090 case '5':
5091 case '6':
5092 case '7':
5093 case '8':
5094 case '9':
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005095 {
5096#ifdef FEAT_FLOAT
5097 char_u *p = skipdigits(*arg + 1);
5098 int get_float = FALSE;
5099
5100 /* We accept a float when the format matches
5101 * "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00005102 * strict to avoid backwards compatibility problems.
5103 * Don't look for a float after the "." operator, so that
5104 * ":let vers = 1.2.3" doesn't fail. */
5105 if (!want_string && p[0] == '.' && vim_isdigit(p[1]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005106 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005107 get_float = TRUE;
5108 p = skipdigits(p + 2);
5109 if (*p == 'e' || *p == 'E')
5110 {
5111 ++p;
5112 if (*p == '-' || *p == '+')
5113 ++p;
5114 if (!vim_isdigit(*p))
5115 get_float = FALSE;
5116 else
5117 p = skipdigits(p + 1);
5118 }
5119 if (ASCII_ISALPHA(*p) || *p == '.')
5120 get_float = FALSE;
5121 }
5122 if (get_float)
5123 {
5124 float_T f;
5125
5126 *arg += string2float(*arg, &f);
5127 if (evaluate)
5128 {
5129 rettv->v_type = VAR_FLOAT;
5130 rettv->vval.v_float = f;
5131 }
5132 }
5133 else
5134#endif
5135 {
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01005136 vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005137 *arg += len;
5138 if (evaluate)
5139 {
5140 rettv->v_type = VAR_NUMBER;
5141 rettv->vval.v_number = n;
5142 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005143 }
5144 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005145 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005146
5147 /*
5148 * String constant: "string".
5149 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005150 case '"': ret = get_string_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005151 break;
5152
5153 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005154 * Literal string constant: 'str''ing'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005155 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005156 case '\'': ret = get_lit_string_tv(arg, rettv, evaluate);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005157 break;
5158
5159 /*
5160 * List: [expr, expr]
5161 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005162 case '[': ret = get_list_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005163 break;
5164
5165 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005166 * Dictionary: {key: val, key: val}
5167 */
5168 case '{': ret = get_dict_tv(arg, rettv, evaluate);
5169 break;
5170
5171 /*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005172 * Option value: &name
Bram Moolenaar071d4272004-06-13 20:20:40 +00005173 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00005174 case '&': ret = get_option_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005175 break;
5176
5177 /*
5178 * Environment variable: $VAR.
5179 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005180 case '$': ret = get_env_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005181 break;
5182
5183 /*
5184 * Register contents: @r.
5185 */
5186 case '@': ++*arg;
5187 if (evaluate)
5188 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005189 rettv->v_type = VAR_STRING;
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +02005190 rettv->vval.v_string = get_reg_contents(**arg,
5191 GREG_EXPR_SRC);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005192 }
5193 if (**arg != NUL)
5194 ++*arg;
5195 break;
5196
5197 /*
5198 * nested expression: (expression).
5199 */
5200 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005201 ret = eval1(arg, rettv, evaluate); /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005202 if (**arg == ')')
5203 ++*arg;
5204 else if (ret == OK)
5205 {
5206 EMSG(_("E110: Missing ')'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005207 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005208 ret = FAIL;
5209 }
5210 break;
5211
Bram Moolenaar8c711452005-01-14 21:53:12 +00005212 default: ret = NOTDONE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005213 break;
5214 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005215
5216 if (ret == NOTDONE)
5217 {
5218 /*
5219 * Must be a variable or function name.
5220 * Can also be a curly-braces kind of name: {expr}.
5221 */
5222 s = *arg;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005223 len = get_name_len(arg, &alias, evaluate, TRUE);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005224 if (alias != NULL)
5225 s = alias;
5226
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005227 if (len <= 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005228 ret = FAIL;
5229 else
5230 {
5231 if (**arg == '(') /* recursive! */
5232 {
5233 /* If "s" is the name of a variable of type VAR_FUNC
5234 * use its contents. */
Bram Moolenaarf31ecce2014-02-05 22:13:05 +01005235 s = deref_func_name(s, &len, !evaluate);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005236
5237 /* Invoke the function. */
5238 ret = get_func_tv(s, len, rettv, arg,
5239 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
Bram Moolenaare9a41262005-01-15 22:18:47 +00005240 &len, evaluate, NULL);
Bram Moolenaare17c2602013-02-26 19:36:15 +01005241
5242 /* If evaluate is FALSE rettv->v_type was not set in
5243 * get_func_tv, but it's needed in handle_subscript() to parse
5244 * what follows. So set it here. */
5245 if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(')
5246 {
Bram Moolenaar988232f2013-02-26 21:43:32 +01005247 rettv->vval.v_string = vim_strsave((char_u *)"");
Bram Moolenaare17c2602013-02-26 19:36:15 +01005248 rettv->v_type = VAR_FUNC;
5249 }
5250
Bram Moolenaar8c711452005-01-14 21:53:12 +00005251 /* Stop the expression evaluation when immediately
5252 * aborting on error, or when an interrupt occurred or
5253 * an exception was thrown but not caught. */
5254 if (aborting())
5255 {
5256 if (ret == OK)
5257 clear_tv(rettv);
5258 ret = FAIL;
5259 }
5260 }
5261 else if (evaluate)
Bram Moolenaar1cd5e612015-05-04 11:10:27 +02005262 ret = get_var_tv(s, len, rettv, NULL, TRUE, FALSE);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005263 else
5264 ret = OK;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005265 }
Bram Moolenaar3c2d6532011-02-01 13:48:53 +01005266 vim_free(alias);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005267 }
5268
Bram Moolenaar071d4272004-06-13 20:20:40 +00005269 *arg = skipwhite(*arg);
5270
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005271 /* Handle following '[', '(' and '.' for expr[expr], expr.name,
5272 * expr(expr). */
5273 if (ret == OK)
5274 ret = handle_subscript(arg, rettv, evaluate, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005275
5276 /*
5277 * Apply logical NOT and unary '-', from right to left, ignore '+'.
5278 */
5279 if (ret == OK && evaluate && end_leader > start_leader)
5280 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005281 int error = FALSE;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005282 int val = 0;
5283#ifdef FEAT_FLOAT
5284 float_T f = 0.0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005285
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005286 if (rettv->v_type == VAR_FLOAT)
5287 f = rettv->vval.v_float;
5288 else
5289#endif
5290 val = get_tv_number_chk(rettv, &error);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005291 if (error)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005292 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005293 clear_tv(rettv);
5294 ret = FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005295 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005296 else
5297 {
5298 while (end_leader > start_leader)
5299 {
5300 --end_leader;
5301 if (*end_leader == '!')
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005302 {
5303#ifdef FEAT_FLOAT
5304 if (rettv->v_type == VAR_FLOAT)
5305 f = !f;
5306 else
5307#endif
5308 val = !val;
5309 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005310 else if (*end_leader == '-')
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005311 {
5312#ifdef FEAT_FLOAT
5313 if (rettv->v_type == VAR_FLOAT)
5314 f = -f;
5315 else
5316#endif
5317 val = -val;
5318 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005319 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005320#ifdef FEAT_FLOAT
5321 if (rettv->v_type == VAR_FLOAT)
5322 {
5323 clear_tv(rettv);
5324 rettv->vval.v_float = f;
5325 }
5326 else
5327#endif
5328 {
5329 clear_tv(rettv);
5330 rettv->v_type = VAR_NUMBER;
5331 rettv->vval.v_number = val;
5332 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005333 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005334 }
5335
5336 return ret;
5337}
5338
5339/*
Bram Moolenaar9e54a0e2006-04-14 20:42:25 +00005340 * Evaluate an "[expr]" or "[expr:expr]" index. Also "dict.key".
5341 * "*arg" points to the '[' or '.'.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005342 * Returns FAIL or OK. "*arg" is advanced to after the ']'.
5343 */
5344 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005345eval_index(
5346 char_u **arg,
5347 typval_T *rettv,
5348 int evaluate,
5349 int verbose) /* give error messages */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005350{
5351 int empty1 = FALSE, empty2 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00005352 typval_T var1, var2;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005353 long n1, n2 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005354 long len = -1;
5355 int range = FALSE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005356 char_u *s;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005357 char_u *key = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005358
Bram Moolenaara03f2332016-02-06 18:09:59 +01005359 switch (rettv->v_type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005360 {
Bram Moolenaara03f2332016-02-06 18:09:59 +01005361 case VAR_FUNC:
5362 if (verbose)
5363 EMSG(_("E695: Cannot index a Funcref"));
5364 return FAIL;
5365 case VAR_FLOAT:
Bram Moolenaar2a876e42013-06-12 22:08:58 +02005366#ifdef FEAT_FLOAT
Bram Moolenaara03f2332016-02-06 18:09:59 +01005367 if (verbose)
5368 EMSG(_(e_float_as_string));
5369 return FAIL;
Bram Moolenaar2a876e42013-06-12 22:08:58 +02005370#endif
Bram Moolenaara03f2332016-02-06 18:09:59 +01005371 case VAR_SPECIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01005372 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01005373 case VAR_CHANNEL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01005374 if (verbose)
5375 EMSG(_("E909: Cannot index a special variable"));
5376 return FAIL;
5377 case VAR_UNKNOWN:
5378 if (evaluate)
5379 return FAIL;
5380 /* FALLTHROUGH */
5381
5382 case VAR_STRING:
5383 case VAR_NUMBER:
5384 case VAR_LIST:
5385 case VAR_DICT:
5386 break;
Bram Moolenaar520e1e42016-01-23 19:46:28 +01005387 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005388
Bram Moolenaar0a38dd22015-08-25 16:49:01 +02005389 init_tv(&var1);
5390 init_tv(&var2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005391 if (**arg == '.')
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005392 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005393 /*
5394 * dict.name
5395 */
5396 key = *arg + 1;
5397 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
5398 ;
5399 if (len == 0)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005400 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005401 *arg = skipwhite(key + len);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005402 }
5403 else
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005404 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005405 /*
5406 * something[idx]
5407 *
5408 * Get the (first) variable from inside the [].
5409 */
5410 *arg = skipwhite(*arg + 1);
5411 if (**arg == ':')
5412 empty1 = TRUE;
5413 else if (eval1(arg, &var1, evaluate) == FAIL) /* recursive! */
5414 return FAIL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005415 else if (evaluate && get_tv_string_chk(&var1) == NULL)
5416 {
5417 /* not a number or string */
5418 clear_tv(&var1);
5419 return FAIL;
5420 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005421
5422 /*
5423 * Get the second variable from inside the [:].
5424 */
5425 if (**arg == ':')
5426 {
5427 range = TRUE;
5428 *arg = skipwhite(*arg + 1);
5429 if (**arg == ']')
5430 empty2 = TRUE;
5431 else if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */
5432 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005433 if (!empty1)
5434 clear_tv(&var1);
5435 return FAIL;
5436 }
5437 else if (evaluate && get_tv_string_chk(&var2) == NULL)
5438 {
5439 /* not a number or string */
5440 if (!empty1)
5441 clear_tv(&var1);
5442 clear_tv(&var2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005443 return FAIL;
5444 }
5445 }
5446
5447 /* Check for the ']'. */
5448 if (**arg != ']')
5449 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005450 if (verbose)
5451 EMSG(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00005452 clear_tv(&var1);
5453 if (range)
5454 clear_tv(&var2);
5455 return FAIL;
5456 }
5457 *arg = skipwhite(*arg + 1); /* skip the ']' */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005458 }
5459
5460 if (evaluate)
5461 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005462 n1 = 0;
5463 if (!empty1 && rettv->v_type != VAR_DICT)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005464 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005465 n1 = get_tv_number(&var1);
5466 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005467 }
5468 if (range)
5469 {
5470 if (empty2)
5471 n2 = -1;
5472 else
5473 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005474 n2 = get_tv_number(&var2);
5475 clear_tv(&var2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005476 }
5477 }
5478
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005479 switch (rettv->v_type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005480 {
Bram Moolenaar835dc632016-02-07 14:27:38 +01005481 case VAR_UNKNOWN:
Bram Moolenaara03f2332016-02-06 18:09:59 +01005482 case VAR_FUNC:
5483 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01005484 case VAR_SPECIAL:
5485 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01005486 case VAR_CHANNEL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01005487 break; /* not evaluating, skipping over subscript */
5488
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005489 case VAR_NUMBER:
5490 case VAR_STRING:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005491 s = get_tv_string(rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005492 len = (long)STRLEN(s);
5493 if (range)
5494 {
5495 /* The resulting variable is a substring. If the indexes
5496 * are out of range the result is empty. */
5497 if (n1 < 0)
5498 {
5499 n1 = len + n1;
5500 if (n1 < 0)
5501 n1 = 0;
5502 }
5503 if (n2 < 0)
5504 n2 = len + n2;
5505 else if (n2 >= len)
5506 n2 = len;
5507 if (n1 >= len || n2 < 0 || n1 > n2)
5508 s = NULL;
5509 else
5510 s = vim_strnsave(s + n1, (int)(n2 - n1 + 1));
5511 }
5512 else
5513 {
5514 /* The resulting variable is a string of a single
5515 * character. If the index is too big or negative the
5516 * result is empty. */
5517 if (n1 >= len || n1 < 0)
5518 s = NULL;
5519 else
5520 s = vim_strnsave(s + n1, 1);
5521 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005522 clear_tv(rettv);
5523 rettv->v_type = VAR_STRING;
5524 rettv->vval.v_string = s;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005525 break;
5526
5527 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005528 len = list_len(rettv->vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005529 if (n1 < 0)
5530 n1 = len + n1;
5531 if (!empty1 && (n1 < 0 || n1 >= len))
5532 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00005533 /* For a range we allow invalid values and return an empty
5534 * list. A list index out of range is an error. */
5535 if (!range)
5536 {
5537 if (verbose)
5538 EMSGN(_(e_listidx), n1);
5539 return FAIL;
5540 }
5541 n1 = len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005542 }
5543 if (range)
5544 {
Bram Moolenaar33570922005-01-25 22:26:29 +00005545 list_T *l;
5546 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005547
5548 if (n2 < 0)
5549 n2 = len + n2;
Bram Moolenaar9e54a0e2006-04-14 20:42:25 +00005550 else if (n2 >= len)
5551 n2 = len - 1;
5552 if (!empty2 && (n2 < 0 || n2 + 1 < n1))
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00005553 n2 = -1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005554 l = list_alloc();
5555 if (l == NULL)
5556 return FAIL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005557 for (item = list_find(rettv->vval.v_list, n1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005558 n1 <= n2; ++n1)
5559 {
5560 if (list_append_tv(l, &item->li_tv) == FAIL)
5561 {
Bram Moolenaar685295c2006-10-15 20:37:38 +00005562 list_free(l, TRUE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005563 return FAIL;
5564 }
5565 item = item->li_next;
5566 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005567 clear_tv(rettv);
5568 rettv->v_type = VAR_LIST;
5569 rettv->vval.v_list = l;
Bram Moolenaar0d660222005-01-07 21:51:51 +00005570 ++l->lv_refcount;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005571 }
5572 else
5573 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00005574 copy_tv(&list_find(rettv->vval.v_list, n1)->li_tv, &var1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005575 clear_tv(rettv);
5576 *rettv = var1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005577 }
5578 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005579
5580 case VAR_DICT:
5581 if (range)
5582 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005583 if (verbose)
5584 EMSG(_(e_dictrange));
Bram Moolenaar8c711452005-01-14 21:53:12 +00005585 if (len == -1)
5586 clear_tv(&var1);
5587 return FAIL;
5588 }
5589 {
Bram Moolenaar33570922005-01-25 22:26:29 +00005590 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005591
5592 if (len == -1)
5593 {
5594 key = get_tv_string(&var1);
5595 if (*key == NUL)
5596 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005597 if (verbose)
5598 EMSG(_(e_emptykey));
Bram Moolenaar8c711452005-01-14 21:53:12 +00005599 clear_tv(&var1);
5600 return FAIL;
5601 }
5602 }
5603
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005604 item = dict_find(rettv->vval.v_dict, key, (int)len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005605
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005606 if (item == NULL && verbose)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005607 EMSG2(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005608 if (len == -1)
5609 clear_tv(&var1);
5610 if (item == NULL)
5611 return FAIL;
5612
5613 copy_tv(&item->di_tv, &var1);
5614 clear_tv(rettv);
5615 *rettv = var1;
5616 }
5617 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005618 }
5619 }
5620
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005621 return OK;
5622}
5623
5624/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005625 * Get an option value.
5626 * "arg" points to the '&' or '+' before the option name.
5627 * "arg" is advanced to character after the option name.
5628 * Return OK or FAIL.
5629 */
5630 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005631get_option_tv(
5632 char_u **arg,
5633 typval_T *rettv, /* when NULL, only check if option exists */
5634 int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005635{
5636 char_u *option_end;
5637 long numval;
5638 char_u *stringval;
5639 int opt_type;
5640 int c;
5641 int working = (**arg == '+'); /* has("+option") */
5642 int ret = OK;
5643 int opt_flags;
5644
5645 /*
5646 * Isolate the option name and find its value.
5647 */
5648 option_end = find_option_end(arg, &opt_flags);
5649 if (option_end == NULL)
5650 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005651 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005652 EMSG2(_("E112: Option name missing: %s"), *arg);
5653 return FAIL;
5654 }
5655
5656 if (!evaluate)
5657 {
5658 *arg = option_end;
5659 return OK;
5660 }
5661
5662 c = *option_end;
5663 *option_end = NUL;
5664 opt_type = get_option_value(*arg, &numval,
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005665 rettv == NULL ? NULL : &stringval, opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005666
5667 if (opt_type == -3) /* invalid name */
5668 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005669 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005670 EMSG2(_("E113: Unknown option: %s"), *arg);
5671 ret = FAIL;
5672 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005673 else if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005674 {
5675 if (opt_type == -2) /* hidden string option */
5676 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005677 rettv->v_type = VAR_STRING;
5678 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005679 }
5680 else if (opt_type == -1) /* hidden number option */
5681 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005682 rettv->v_type = VAR_NUMBER;
5683 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005684 }
5685 else if (opt_type == 1) /* number option */
5686 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005687 rettv->v_type = VAR_NUMBER;
5688 rettv->vval.v_number = numval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005689 }
5690 else /* string option */
5691 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005692 rettv->v_type = VAR_STRING;
5693 rettv->vval.v_string = stringval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005694 }
5695 }
5696 else if (working && (opt_type == -2 || opt_type == -1))
5697 ret = FAIL;
5698
5699 *option_end = c; /* put back for error messages */
5700 *arg = option_end;
5701
5702 return ret;
5703}
5704
5705/*
5706 * Allocate a variable for a string constant.
5707 * Return OK or FAIL.
5708 */
5709 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005710get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005711{
5712 char_u *p;
5713 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005714 int extra = 0;
5715
5716 /*
5717 * Find the end of the string, skipping backslashed characters.
5718 */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005719 for (p = *arg + 1; *p != NUL && *p != '"'; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005720 {
5721 if (*p == '\\' && p[1] != NUL)
5722 {
5723 ++p;
5724 /* A "\<x>" form occupies at least 4 characters, and produces up
5725 * to 6 characters: reserve space for 2 extra */
5726 if (*p == '<')
5727 extra += 2;
5728 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005729 }
5730
5731 if (*p != '"')
5732 {
5733 EMSG2(_("E114: Missing quote: %s"), *arg);
5734 return FAIL;
5735 }
5736
5737 /* If only parsing, set *arg and return here */
5738 if (!evaluate)
5739 {
5740 *arg = p + 1;
5741 return OK;
5742 }
5743
5744 /*
5745 * Copy the string into allocated memory, handling backslashed
5746 * characters.
5747 */
5748 name = alloc((unsigned)(p - *arg + extra));
5749 if (name == NULL)
5750 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005751 rettv->v_type = VAR_STRING;
5752 rettv->vval.v_string = name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005753
Bram Moolenaar8c711452005-01-14 21:53:12 +00005754 for (p = *arg + 1; *p != NUL && *p != '"'; )
Bram Moolenaar071d4272004-06-13 20:20:40 +00005755 {
5756 if (*p == '\\')
5757 {
5758 switch (*++p)
5759 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005760 case 'b': *name++ = BS; ++p; break;
5761 case 'e': *name++ = ESC; ++p; break;
5762 case 'f': *name++ = FF; ++p; break;
5763 case 'n': *name++ = NL; ++p; break;
5764 case 'r': *name++ = CAR; ++p; break;
5765 case 't': *name++ = TAB; ++p; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005766
5767 case 'X': /* hex: "\x1", "\x12" */
5768 case 'x':
5769 case 'u': /* Unicode: "\u0023" */
5770 case 'U':
5771 if (vim_isxdigit(p[1]))
5772 {
5773 int n, nr;
5774 int c = toupper(*p);
5775
5776 if (c == 'X')
5777 n = 2;
Bram Moolenaaracc39882015-06-19 12:08:13 +02005778 else if (*p == 'u')
Bram Moolenaar071d4272004-06-13 20:20:40 +00005779 n = 4;
Bram Moolenaaracc39882015-06-19 12:08:13 +02005780 else
5781 n = 8;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005782 nr = 0;
5783 while (--n >= 0 && vim_isxdigit(p[1]))
5784 {
5785 ++p;
5786 nr = (nr << 4) + hex2nr(*p);
5787 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005788 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005789#ifdef FEAT_MBYTE
5790 /* For "\u" store the number according to
5791 * 'encoding'. */
5792 if (c != 'X')
Bram Moolenaar8c711452005-01-14 21:53:12 +00005793 name += (*mb_char2bytes)(nr, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005794 else
5795#endif
Bram Moolenaar8c711452005-01-14 21:53:12 +00005796 *name++ = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005797 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005798 break;
5799
5800 /* octal: "\1", "\12", "\123" */
5801 case '0':
5802 case '1':
5803 case '2':
5804 case '3':
5805 case '4':
5806 case '5':
5807 case '6':
Bram Moolenaar8c711452005-01-14 21:53:12 +00005808 case '7': *name = *p++ - '0';
5809 if (*p >= '0' && *p <= '7')
Bram Moolenaar071d4272004-06-13 20:20:40 +00005810 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005811 *name = (*name << 3) + *p++ - '0';
5812 if (*p >= '0' && *p <= '7')
5813 *name = (*name << 3) + *p++ - '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +00005814 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005815 ++name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005816 break;
5817
5818 /* Special key, e.g.: "\<C-W>" */
Bram Moolenaar8c711452005-01-14 21:53:12 +00005819 case '<': extra = trans_special(&p, name, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005820 if (extra != 0)
5821 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005822 name += extra;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005823 break;
5824 }
5825 /* FALLTHROUGH */
5826
Bram Moolenaar8c711452005-01-14 21:53:12 +00005827 default: MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005828 break;
5829 }
5830 }
5831 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00005832 MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005833
Bram Moolenaar071d4272004-06-13 20:20:40 +00005834 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005835 *name = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005836 *arg = p + 1;
5837
Bram Moolenaar071d4272004-06-13 20:20:40 +00005838 return OK;
5839}
5840
5841/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005842 * Allocate a variable for a 'str''ing' constant.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005843 * Return OK or FAIL.
5844 */
5845 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005846get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005847{
5848 char_u *p;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005849 char_u *str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005850 int reduce = 0;
5851
5852 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005853 * Find the end of the string, skipping ''.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005854 */
5855 for (p = *arg + 1; *p != NUL; mb_ptr_adv(p))
5856 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005857 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005858 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005859 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005860 break;
5861 ++reduce;
5862 ++p;
5863 }
5864 }
5865
Bram Moolenaar8c711452005-01-14 21:53:12 +00005866 if (*p != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005867 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005868 EMSG2(_("E115: Missing quote: %s"), *arg);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005869 return FAIL;
5870 }
5871
Bram Moolenaar8c711452005-01-14 21:53:12 +00005872 /* If only parsing return after setting "*arg" */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005873 if (!evaluate)
5874 {
5875 *arg = p + 1;
5876 return OK;
5877 }
5878
5879 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005880 * Copy the string into allocated memory, handling '' to ' reduction.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005881 */
5882 str = alloc((unsigned)((p - *arg) - reduce));
5883 if (str == NULL)
5884 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005885 rettv->v_type = VAR_STRING;
5886 rettv->vval.v_string = str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005887
Bram Moolenaar8c711452005-01-14 21:53:12 +00005888 for (p = *arg + 1; *p != NUL; )
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005889 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005890 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005891 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005892 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005893 break;
5894 ++p;
5895 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005896 MB_COPY_CHAR(p, str);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005897 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005898 *str = NUL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005899 *arg = p + 1;
5900
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005901 return OK;
5902}
5903
5904/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005905 * Allocate a variable for a List and fill it from "*arg".
5906 * Return OK or FAIL.
5907 */
5908 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005909get_list_tv(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005910{
Bram Moolenaar33570922005-01-25 22:26:29 +00005911 list_T *l = NULL;
5912 typval_T tv;
5913 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005914
5915 if (evaluate)
5916 {
5917 l = list_alloc();
5918 if (l == NULL)
5919 return FAIL;
5920 }
5921
5922 *arg = skipwhite(*arg + 1);
5923 while (**arg != ']' && **arg != NUL)
5924 {
5925 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
5926 goto failret;
5927 if (evaluate)
5928 {
5929 item = listitem_alloc();
5930 if (item != NULL)
5931 {
5932 item->li_tv = tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005933 item->li_tv.v_lock = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005934 list_append(l, item);
5935 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005936 else
5937 clear_tv(&tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005938 }
5939
5940 if (**arg == ']')
5941 break;
5942 if (**arg != ',')
5943 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005944 EMSG2(_("E696: Missing comma in List: %s"), *arg);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005945 goto failret;
5946 }
5947 *arg = skipwhite(*arg + 1);
5948 }
5949
5950 if (**arg != ']')
5951 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005952 EMSG2(_("E697: Missing end of List ']': %s"), *arg);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005953failret:
5954 if (evaluate)
Bram Moolenaar685295c2006-10-15 20:37:38 +00005955 list_free(l, TRUE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005956 return FAIL;
5957 }
5958
5959 *arg = skipwhite(*arg + 1);
5960 if (evaluate)
5961 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005962 rettv->v_type = VAR_LIST;
5963 rettv->vval.v_list = l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005964 ++l->lv_refcount;
5965 }
5966
5967 return OK;
5968}
5969
5970/*
5971 * Allocate an empty header for a list.
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00005972 * Caller should take care of the reference count.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005973 */
Bram Moolenaar1ef15e32006-02-01 21:56:25 +00005974 list_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01005975list_alloc(void)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005976{
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005977 list_T *l;
5978
5979 l = (list_T *)alloc_clear(sizeof(list_T));
5980 if (l != NULL)
5981 {
5982 /* Prepend the list to the list of lists for garbage collection. */
5983 if (first_list != NULL)
5984 first_list->lv_used_prev = l;
5985 l->lv_used_prev = NULL;
5986 l->lv_used_next = first_list;
5987 first_list = l;
5988 }
5989 return l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005990}
5991
5992/*
Bram Moolenaareddf53b2006-02-27 00:11:10 +00005993 * Allocate an empty list for a return value.
5994 * Returns OK or FAIL.
5995 */
Bram Moolenaar520e1e42016-01-23 19:46:28 +01005996 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005997rettv_list_alloc(typval_T *rettv)
Bram Moolenaareddf53b2006-02-27 00:11:10 +00005998{
5999 list_T *l = list_alloc();
6000
6001 if (l == NULL)
6002 return FAIL;
6003
6004 rettv->vval.v_list = l;
6005 rettv->v_type = VAR_LIST;
6006 ++l->lv_refcount;
6007 return OK;
6008}
6009
6010/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006011 * Unreference a list: decrement the reference count and free it when it
6012 * becomes zero.
6013 */
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00006014 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01006015list_unref(list_T *l)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006016{
Bram Moolenaar685295c2006-10-15 20:37:38 +00006017 if (l != NULL && --l->lv_refcount <= 0)
6018 list_free(l, TRUE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006019}
6020
6021/*
Bram Moolenaare71eea82015-02-03 17:10:06 +01006022 * Free a list, including all non-container items it points to.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006023 * Ignores the reference count.
6024 */
Bram Moolenaar1ef15e32006-02-01 21:56:25 +00006025 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01006026list_free(
6027 list_T *l,
6028 int recurse) /* Free Lists and Dictionaries recursively. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006029{
Bram Moolenaar33570922005-01-25 22:26:29 +00006030 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006031
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006032 /* Remove the list from the list of lists for garbage collection. */
6033 if (l->lv_used_prev == NULL)
6034 first_list = l->lv_used_next;
6035 else
6036 l->lv_used_prev->lv_used_next = l->lv_used_next;
6037 if (l->lv_used_next != NULL)
6038 l->lv_used_next->lv_used_prev = l->lv_used_prev;
6039
Bram Moolenaard9fba312005-06-26 22:34:35 +00006040 for (item = l->lv_first; item != NULL; item = l->lv_first)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006041 {
Bram Moolenaard9fba312005-06-26 22:34:35 +00006042 /* Remove the item before deleting it. */
6043 l->lv_first = item->li_next;
Bram Moolenaar685295c2006-10-15 20:37:38 +00006044 if (recurse || (item->li_tv.v_type != VAR_LIST
6045 && item->li_tv.v_type != VAR_DICT))
6046 clear_tv(&item->li_tv);
6047 vim_free(item);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006048 }
6049 vim_free(l);
6050}
6051
6052/*
6053 * Allocate a list item.
Bram Moolenaar9a492d42015-01-27 13:49:31 +01006054 * It is not initialized, don't forget to set v_lock.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006055 */
Bram Moolenaardb913952012-06-29 12:54:53 +02006056 listitem_T *
Bram Moolenaard14e00e2016-01-31 17:30:51 +01006057listitem_alloc(void)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006058{
Bram Moolenaar33570922005-01-25 22:26:29 +00006059 return (listitem_T *)alloc(sizeof(listitem_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006060}
6061
6062/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00006063 * Free a list item. Also clears the value. Does not notify watchers.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006064 */
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006065 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01006066listitem_free(listitem_T *item)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006067{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006068 clear_tv(&item->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006069 vim_free(item);
6070}
6071
6072/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00006073 * Remove a list item from a List and free it. Also clears the value.
6074 */
Bram Moolenaardb913952012-06-29 12:54:53 +02006075 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01006076listitem_remove(list_T *l, listitem_T *item)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00006077{
Bram Moolenaar3ec7f4e2014-05-07 17:31:37 +02006078 vimlist_remove(l, item, item);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00006079 listitem_free(item);
6080}
6081
6082/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006083 * Get the number of items in a list.
6084 */
6085 static long
Bram Moolenaar7454a062016-01-30 15:14:10 +01006086list_len(list_T *l)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006087{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006088 if (l == NULL)
6089 return 0L;
Bram Moolenaar758711c2005-02-02 23:11:38 +00006090 return l->lv_len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006091}
6092
6093/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006094 * Return TRUE when two lists have exactly the same values.
6095 */
6096 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006097list_equal(
6098 list_T *l1,
6099 list_T *l2,
6100 int ic, /* ignore case for strings */
6101 int recursive) /* TRUE when used recursively */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006102{
Bram Moolenaar33570922005-01-25 22:26:29 +00006103 listitem_T *item1, *item2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006104
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00006105 if (l1 == NULL || l2 == NULL)
6106 return FALSE;
Bram Moolenaar8b402a02006-10-17 13:16:39 +00006107 if (l1 == l2)
6108 return TRUE;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006109 if (list_len(l1) != list_len(l2))
6110 return FALSE;
6111
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006112 for (item1 = l1->lv_first, item2 = l2->lv_first;
6113 item1 != NULL && item2 != NULL;
6114 item1 = item1->li_next, item2 = item2->li_next)
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006115 if (!tv_equal(&item1->li_tv, &item2->li_tv, ic, recursive))
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006116 return FALSE;
6117 return item1 == NULL && item2 == NULL;
6118}
6119
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006120/*
6121 * Return the dictitem that an entry in a hashtable points to.
6122 */
6123 dictitem_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006124dict_lookup(hashitem_T *hi)
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006125{
6126 return HI2DI(hi);
6127}
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006128
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006129/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006130 * Return TRUE when two dictionaries have exactly the same key/values.
6131 */
6132 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006133dict_equal(
6134 dict_T *d1,
6135 dict_T *d2,
6136 int ic, /* ignore case for strings */
6137 int recursive) /* TRUE when used recursively */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006138{
Bram Moolenaar33570922005-01-25 22:26:29 +00006139 hashitem_T *hi;
6140 dictitem_T *item2;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006141 int todo;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006142
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00006143 if (d1 == NULL || d2 == NULL)
6144 return FALSE;
Bram Moolenaar8b402a02006-10-17 13:16:39 +00006145 if (d1 == d2)
6146 return TRUE;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006147 if (dict_len(d1) != dict_len(d2))
6148 return FALSE;
6149
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00006150 todo = (int)d1->dv_hashtab.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00006151 for (hi = d1->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006152 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006153 if (!HASHITEM_EMPTY(hi))
6154 {
6155 item2 = dict_find(d2, hi->hi_key, -1);
6156 if (item2 == NULL)
6157 return FALSE;
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006158 if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic, recursive))
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006159 return FALSE;
6160 --todo;
6161 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006162 }
6163 return TRUE;
6164}
6165
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006166static int tv_equal_recurse_limit;
6167
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006168/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006169 * Return TRUE if "tv1" and "tv2" have the same value.
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00006170 * Compares the items just like "==" would compare them, but strings and
Bram Moolenaar8c8de832008-06-24 22:58:06 +00006171 * numbers are different. Floats and numbers are also different.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006172 */
6173 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006174tv_equal(
6175 typval_T *tv1,
6176 typval_T *tv2,
6177 int ic, /* ignore case */
6178 int recursive) /* TRUE when used recursively */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006179{
6180 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006181 char_u *s1, *s2;
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006182 static int recursive_cnt = 0; /* catch recursive loops */
Bram Moolenaarb47a2402006-10-15 13:09:12 +00006183 int r;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006184
Bram Moolenaar8b402a02006-10-17 13:16:39 +00006185 if (tv1->v_type != tv2->v_type)
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00006186 return FALSE;
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006187
Bram Moolenaar8b402a02006-10-17 13:16:39 +00006188 /* Catch lists and dicts that have an endless loop by limiting
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006189 * recursiveness to a limit. We guess they are equal then.
6190 * A fixed limit has the problem of still taking an awful long time.
6191 * Reduce the limit every time running into it. That should work fine for
6192 * deeply linked structures that are not recursively linked and catch
6193 * recursiveness quickly. */
6194 if (!recursive)
6195 tv_equal_recurse_limit = 1000;
6196 if (recursive_cnt >= tv_equal_recurse_limit)
6197 {
6198 --tv_equal_recurse_limit;
Bram Moolenaar8b402a02006-10-17 13:16:39 +00006199 return TRUE;
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006200 }
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00006201
6202 switch (tv1->v_type)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006203 {
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00006204 case VAR_LIST:
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006205 ++recursive_cnt;
6206 r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic, TRUE);
6207 --recursive_cnt;
Bram Moolenaarb47a2402006-10-15 13:09:12 +00006208 return r;
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00006209
6210 case VAR_DICT:
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006211 ++recursive_cnt;
6212 r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, TRUE);
6213 --recursive_cnt;
Bram Moolenaarb47a2402006-10-15 13:09:12 +00006214 return r;
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00006215
6216 case VAR_FUNC:
6217 return (tv1->vval.v_string != NULL
6218 && tv2->vval.v_string != NULL
6219 && STRCMP(tv1->vval.v_string, tv2->vval.v_string) == 0);
6220
6221 case VAR_NUMBER:
6222 return tv1->vval.v_number == tv2->vval.v_number;
6223
6224 case VAR_STRING:
6225 s1 = get_tv_string_buf(tv1, buf1);
6226 s2 = get_tv_string_buf(tv2, buf2);
6227 return ((ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2)) == 0);
Bram Moolenaar520e1e42016-01-23 19:46:28 +01006228
6229 case VAR_SPECIAL:
6230 return tv1->vval.v_number == tv2->vval.v_number;
Bram Moolenaar835dc632016-02-07 14:27:38 +01006231
6232 case VAR_FLOAT:
6233#ifdef FEAT_FLOAT
6234 return tv1->vval.v_float == tv2->vval.v_float;
6235#endif
6236 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01006237#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +01006238 return tv1->vval.v_job == tv2->vval.v_job;
6239#endif
Bram Moolenaar77073442016-02-13 23:23:53 +01006240 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01006241#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +01006242 return tv1->vval.v_channel == tv2->vval.v_channel;
6243#endif
Bram Moolenaar835dc632016-02-07 14:27:38 +01006244 case VAR_UNKNOWN:
6245 break;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006246 }
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00006247
Bram Moolenaara03f2332016-02-06 18:09:59 +01006248 /* VAR_UNKNOWN can be the result of a invalid expression, let's say it
6249 * does not equal anything, not even itself. */
6250 return FALSE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006251}
6252
6253/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006254 * Locate item with index "n" in list "l" and return it.
6255 * A negative index is counted from the end; -1 is the last item.
6256 * Returns NULL when "n" is out of range.
6257 */
Bram Moolenaardb913952012-06-29 12:54:53 +02006258 listitem_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006259list_find(list_T *l, long n)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006260{
Bram Moolenaar33570922005-01-25 22:26:29 +00006261 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006262 long idx;
6263
6264 if (l == NULL)
6265 return NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +00006266
6267 /* Negative index is relative to the end. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006268 if (n < 0)
Bram Moolenaar758711c2005-02-02 23:11:38 +00006269 n = l->lv_len + n;
6270
6271 /* Check for index out of range. */
6272 if (n < 0 || n >= l->lv_len)
6273 return NULL;
6274
6275 /* When there is a cached index may start search from there. */
6276 if (l->lv_idx_item != NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006277 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00006278 if (n < l->lv_idx / 2)
6279 {
6280 /* closest to the start of the list */
6281 item = l->lv_first;
6282 idx = 0;
6283 }
6284 else if (n > (l->lv_idx + l->lv_len) / 2)
6285 {
6286 /* closest to the end of the list */
6287 item = l->lv_last;
6288 idx = l->lv_len - 1;
6289 }
6290 else
6291 {
6292 /* closest to the cached index */
6293 item = l->lv_idx_item;
6294 idx = l->lv_idx;
6295 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006296 }
6297 else
6298 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00006299 if (n < l->lv_len / 2)
6300 {
6301 /* closest to the start of the list */
6302 item = l->lv_first;
6303 idx = 0;
6304 }
6305 else
6306 {
6307 /* closest to the end of the list */
6308 item = l->lv_last;
6309 idx = l->lv_len - 1;
6310 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006311 }
Bram Moolenaar758711c2005-02-02 23:11:38 +00006312
6313 while (n > idx)
6314 {
6315 /* search forward */
6316 item = item->li_next;
6317 ++idx;
6318 }
6319 while (n < idx)
6320 {
6321 /* search backward */
6322 item = item->li_prev;
6323 --idx;
6324 }
6325
6326 /* cache the used index */
6327 l->lv_idx = idx;
6328 l->lv_idx_item = item;
6329
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006330 return item;
6331}
6332
6333/*
Bram Moolenaara5525202006-03-02 22:52:09 +00006334 * Get list item "l[idx]" as a number.
6335 */
6336 static long
Bram Moolenaar7454a062016-01-30 15:14:10 +01006337list_find_nr(
6338 list_T *l,
6339 long idx,
6340 int *errorp) /* set to TRUE when something wrong */
Bram Moolenaara5525202006-03-02 22:52:09 +00006341{
6342 listitem_T *li;
6343
6344 li = list_find(l, idx);
6345 if (li == NULL)
6346 {
6347 if (errorp != NULL)
6348 *errorp = TRUE;
6349 return -1L;
6350 }
6351 return get_tv_number_chk(&li->li_tv, errorp);
6352}
6353
6354/*
Bram Moolenaard812df62008-11-09 12:46:09 +00006355 * Get list item "l[idx - 1]" as a string. Returns NULL for failure.
6356 */
6357 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006358list_find_str(list_T *l, long idx)
Bram Moolenaard812df62008-11-09 12:46:09 +00006359{
6360 listitem_T *li;
6361
6362 li = list_find(l, idx - 1);
6363 if (li == NULL)
6364 {
6365 EMSGN(_(e_listidx), idx);
6366 return NULL;
6367 }
6368 return get_tv_string(&li->li_tv);
6369}
6370
6371/*
Bram Moolenaar6cc16192005-01-08 21:49:45 +00006372 * Locate "item" list "l" and return its index.
6373 * Returns -1 when "item" is not in the list.
6374 */
6375 static long
Bram Moolenaar7454a062016-01-30 15:14:10 +01006376list_idx_of_item(list_T *l, listitem_T *item)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00006377{
6378 long idx = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00006379 listitem_T *li;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00006380
6381 if (l == NULL)
6382 return -1;
6383 idx = 0;
6384 for (li = l->lv_first; li != NULL && li != item; li = li->li_next)
6385 ++idx;
6386 if (li == NULL)
6387 return -1;
Bram Moolenaar75c50c42005-06-04 22:06:24 +00006388 return idx;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00006389}
6390
6391/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006392 * Append item "item" to the end of list "l".
6393 */
Bram Moolenaardb913952012-06-29 12:54:53 +02006394 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01006395list_append(list_T *l, listitem_T *item)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006396{
6397 if (l->lv_last == NULL)
6398 {
6399 /* empty list */
6400 l->lv_first = item;
6401 l->lv_last = item;
6402 item->li_prev = NULL;
6403 }
6404 else
6405 {
6406 l->lv_last->li_next = item;
6407 item->li_prev = l->lv_last;
6408 l->lv_last = item;
6409 }
Bram Moolenaar758711c2005-02-02 23:11:38 +00006410 ++l->lv_len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006411 item->li_next = NULL;
6412}
6413
6414/*
Bram Moolenaar33570922005-01-25 22:26:29 +00006415 * Append typval_T "tv" to the end of list "l".
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006416 * Return FAIL when out of memory.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006417 */
Bram Moolenaar7e506b62010-01-19 15:55:06 +01006418 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006419list_append_tv(list_T *l, typval_T *tv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006420{
Bram Moolenaar05159a02005-02-26 23:04:13 +00006421 listitem_T *li = listitem_alloc();
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006422
Bram Moolenaar05159a02005-02-26 23:04:13 +00006423 if (li == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006424 return FAIL;
Bram Moolenaar05159a02005-02-26 23:04:13 +00006425 copy_tv(tv, &li->li_tv);
6426 list_append(l, li);
6427 return OK;
6428}
6429
6430/*
Bram Moolenaar2641f772005-03-25 21:58:17 +00006431 * Add a dictionary to a list. Used by getqflist().
Bram Moolenaar05159a02005-02-26 23:04:13 +00006432 * Return FAIL when out of memory.
6433 */
6434 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006435list_append_dict(list_T *list, dict_T *dict)
Bram Moolenaar05159a02005-02-26 23:04:13 +00006436{
6437 listitem_T *li = listitem_alloc();
6438
6439 if (li == NULL)
6440 return FAIL;
6441 li->li_tv.v_type = VAR_DICT;
6442 li->li_tv.v_lock = 0;
6443 li->li_tv.vval.v_dict = dict;
6444 list_append(list, li);
6445 ++dict->dv_refcount;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006446 return OK;
6447}
6448
6449/*
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00006450 * Make a copy of "str" and append it as an item to list "l".
Bram Moolenaar4463f292005-09-25 22:20:24 +00006451 * When "len" >= 0 use "str[len]".
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00006452 * Returns FAIL when out of memory.
6453 */
Bram Moolenaard812df62008-11-09 12:46:09 +00006454 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006455list_append_string(list_T *l, char_u *str, int len)
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00006456{
6457 listitem_T *li = listitem_alloc();
6458
6459 if (li == NULL)
6460 return FAIL;
6461 list_append(l, li);
6462 li->li_tv.v_type = VAR_STRING;
6463 li->li_tv.v_lock = 0;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00006464 if (str == NULL)
6465 li->li_tv.vval.v_string = NULL;
6466 else if ((li->li_tv.vval.v_string = (len >= 0 ? vim_strnsave(str, len)
Bram Moolenaar482aaeb2005-09-29 18:26:07 +00006467 : vim_strsave(str))) == NULL)
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00006468 return FAIL;
6469 return OK;
6470}
6471
6472/*
Bram Moolenaar4463f292005-09-25 22:20:24 +00006473 * Append "n" to list "l".
6474 * Returns FAIL when out of memory.
6475 */
Bram Moolenaar86edef62016-03-13 18:07:30 +01006476 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006477list_append_number(list_T *l, varnumber_T n)
Bram Moolenaar4463f292005-09-25 22:20:24 +00006478{
6479 listitem_T *li;
6480
6481 li = listitem_alloc();
6482 if (li == NULL)
6483 return FAIL;
6484 li->li_tv.v_type = VAR_NUMBER;
6485 li->li_tv.v_lock = 0;
6486 li->li_tv.vval.v_number = n;
6487 list_append(l, li);
6488 return OK;
6489}
6490
6491/*
Bram Moolenaar33570922005-01-25 22:26:29 +00006492 * Insert typval_T "tv" in list "l" before "item".
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006493 * If "item" is NULL append at the end.
6494 * Return FAIL when out of memory.
6495 */
Bram Moolenaardb913952012-06-29 12:54:53 +02006496 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006497list_insert_tv(list_T *l, typval_T *tv, listitem_T *item)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006498{
Bram Moolenaar33570922005-01-25 22:26:29 +00006499 listitem_T *ni = listitem_alloc();
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006500
6501 if (ni == NULL)
6502 return FAIL;
6503 copy_tv(tv, &ni->li_tv);
Bram Moolenaar063a46b2014-01-14 16:36:51 +01006504 list_insert(l, ni, item);
6505 return OK;
6506}
6507
6508 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01006509list_insert(list_T *l, listitem_T *ni, listitem_T *item)
Bram Moolenaar063a46b2014-01-14 16:36:51 +01006510{
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006511 if (item == NULL)
6512 /* Append new item at end of list. */
6513 list_append(l, ni);
6514 else
6515 {
6516 /* Insert new item before existing item. */
6517 ni->li_prev = item->li_prev;
6518 ni->li_next = item;
6519 if (item->li_prev == NULL)
Bram Moolenaar758711c2005-02-02 23:11:38 +00006520 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006521 l->lv_first = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00006522 ++l->lv_idx;
6523 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006524 else
Bram Moolenaar758711c2005-02-02 23:11:38 +00006525 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006526 item->li_prev->li_next = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00006527 l->lv_idx_item = NULL;
6528 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006529 item->li_prev = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00006530 ++l->lv_len;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006531 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006532}
6533
6534/*
6535 * Extend "l1" with "l2".
6536 * If "bef" is NULL append at the end, otherwise insert before this item.
6537 * Returns FAIL when out of memory.
6538 */
6539 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006540list_extend(list_T *l1, list_T *l2, listitem_T *bef)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006541{
Bram Moolenaar33570922005-01-25 22:26:29 +00006542 listitem_T *item;
Bram Moolenaardc9cf9c2008-08-08 10:36:31 +00006543 int todo = l2->lv_len;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006544
Bram Moolenaardc9cf9c2008-08-08 10:36:31 +00006545 /* We also quit the loop when we have inserted the original item count of
6546 * the list, avoid a hang when we extend a list with itself. */
6547 for (item = l2->lv_first; item != NULL && --todo >= 0; item = item->li_next)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006548 if (list_insert_tv(l1, &item->li_tv, bef) == FAIL)
6549 return FAIL;
6550 return OK;
6551}
6552
6553/*
6554 * Concatenate lists "l1" and "l2" into a new list, stored in "tv".
6555 * Return FAIL when out of memory.
6556 */
6557 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006558list_concat(list_T *l1, list_T *l2, typval_T *tv)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006559{
Bram Moolenaar33570922005-01-25 22:26:29 +00006560 list_T *l;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006561
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00006562 if (l1 == NULL || l2 == NULL)
6563 return FAIL;
6564
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006565 /* make a copy of the first list. */
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006566 l = list_copy(l1, FALSE, 0);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006567 if (l == NULL)
6568 return FAIL;
6569 tv->v_type = VAR_LIST;
6570 tv->vval.v_list = l;
6571
6572 /* append all items from the second list */
6573 return list_extend(l, l2, NULL);
6574}
6575
6576/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00006577 * Make a copy of list "orig". Shallow if "deep" is FALSE.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006578 * The refcount of the new list is set to 1.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006579 * See item_copy() for "copyID".
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006580 * Returns NULL when out of memory.
6581 */
Bram Moolenaar33570922005-01-25 22:26:29 +00006582 static list_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006583list_copy(list_T *orig, int deep, int copyID)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006584{
Bram Moolenaar33570922005-01-25 22:26:29 +00006585 list_T *copy;
6586 listitem_T *item;
6587 listitem_T *ni;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006588
6589 if (orig == NULL)
6590 return NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006591
6592 copy = list_alloc();
6593 if (copy != NULL)
6594 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006595 if (copyID != 0)
6596 {
6597 /* Do this before adding the items, because one of the items may
6598 * refer back to this list. */
6599 orig->lv_copyID = copyID;
6600 orig->lv_copylist = copy;
6601 }
6602 for (item = orig->lv_first; item != NULL && !got_int;
6603 item = item->li_next)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006604 {
6605 ni = listitem_alloc();
6606 if (ni == NULL)
6607 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006608 if (deep)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006609 {
6610 if (item_copy(&item->li_tv, &ni->li_tv, deep, copyID) == FAIL)
6611 {
6612 vim_free(ni);
6613 break;
6614 }
6615 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006616 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006617 copy_tv(&item->li_tv, &ni->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006618 list_append(copy, ni);
6619 }
6620 ++copy->lv_refcount;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006621 if (item != NULL)
6622 {
6623 list_unref(copy);
6624 copy = NULL;
6625 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006626 }
6627
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006628 return copy;
6629}
6630
6631/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006632 * Remove items "item" to "item2" from list "l".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00006633 * Does not free the listitem or the value!
Bram Moolenaar3ec7f4e2014-05-07 17:31:37 +02006634 * This used to be called list_remove, but that conflicts with a Sun header
6635 * file.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006636 */
Bram Moolenaardb913952012-06-29 12:54:53 +02006637 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01006638vimlist_remove(list_T *l, listitem_T *item, listitem_T *item2)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006639{
Bram Moolenaar33570922005-01-25 22:26:29 +00006640 listitem_T *ip;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006641
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006642 /* notify watchers */
6643 for (ip = item; ip != NULL; ip = ip->li_next)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006644 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00006645 --l->lv_len;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006646 list_fix_watch(l, ip);
6647 if (ip == item2)
6648 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006649 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006650
6651 if (item2->li_next == NULL)
6652 l->lv_last = item->li_prev;
6653 else
6654 item2->li_next->li_prev = item->li_prev;
6655 if (item->li_prev == NULL)
6656 l->lv_first = item2->li_next;
6657 else
6658 item->li_prev->li_next = item2->li_next;
Bram Moolenaar758711c2005-02-02 23:11:38 +00006659 l->lv_idx_item = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006660}
6661
6662/*
6663 * Return an allocated string with the string representation of a list.
6664 * May return NULL.
6665 */
6666 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006667list2string(typval_T *tv, int copyID)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006668{
6669 garray_T ga;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006670
6671 if (tv->vval.v_list == NULL)
6672 return NULL;
6673 ga_init2(&ga, (int)sizeof(char), 80);
6674 ga_append(&ga, '[');
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006675 if (list_join(&ga, tv->vval.v_list, (char_u *)", ", FALSE, copyID) == FAIL)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006676 {
6677 vim_free(ga.ga_data);
6678 return NULL;
6679 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006680 ga_append(&ga, ']');
6681 ga_append(&ga, NUL);
6682 return (char_u *)ga.ga_data;
6683}
6684
Bram Moolenaar3fe37d62012-02-06 00:13:22 +01006685typedef struct join_S {
6686 char_u *s;
6687 char_u *tofree;
6688} join_T;
6689
6690 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006691list_join_inner(
6692 garray_T *gap, /* to store the result in */
6693 list_T *l,
6694 char_u *sep,
6695 int echo_style,
6696 int copyID,
6697 garray_T *join_gap) /* to keep each list item string */
Bram Moolenaar3fe37d62012-02-06 00:13:22 +01006698{
6699 int i;
6700 join_T *p;
6701 int len;
6702 int sumlen = 0;
6703 int first = TRUE;
6704 char_u *tofree;
6705 char_u numbuf[NUMBUFLEN];
6706 listitem_T *item;
6707 char_u *s;
6708
6709 /* Stringify each item in the list. */
6710 for (item = l->lv_first; item != NULL && !got_int; item = item->li_next)
6711 {
6712 if (echo_style)
6713 s = echo_string(&item->li_tv, &tofree, numbuf, copyID);
6714 else
6715 s = tv2string(&item->li_tv, &tofree, numbuf, copyID);
6716 if (s == NULL)
6717 return FAIL;
6718
6719 len = (int)STRLEN(s);
6720 sumlen += len;
6721
Bram Moolenaarcde88542015-08-11 19:14:00 +02006722 (void)ga_grow(join_gap, 1);
Bram Moolenaar3fe37d62012-02-06 00:13:22 +01006723 p = ((join_T *)join_gap->ga_data) + (join_gap->ga_len++);
6724 if (tofree != NULL || s != numbuf)
6725 {
6726 p->s = s;
6727 p->tofree = tofree;
6728 }
6729 else
6730 {
6731 p->s = vim_strnsave(s, len);
6732 p->tofree = p->s;
6733 }
6734
6735 line_breakcheck();
Bram Moolenaar8502c702014-06-17 12:51:16 +02006736 if (did_echo_string_emsg) /* recursion error, bail out */
6737 break;
Bram Moolenaar3fe37d62012-02-06 00:13:22 +01006738 }
6739
6740 /* Allocate result buffer with its total size, avoid re-allocation and
6741 * multiple copy operations. Add 2 for a tailing ']' and NUL. */
6742 if (join_gap->ga_len >= 2)
6743 sumlen += (int)STRLEN(sep) * (join_gap->ga_len - 1);
6744 if (ga_grow(gap, sumlen + 2) == FAIL)
6745 return FAIL;
6746
6747 for (i = 0; i < join_gap->ga_len && !got_int; ++i)
6748 {
6749 if (first)
6750 first = FALSE;
6751 else
6752 ga_concat(gap, sep);
6753 p = ((join_T *)join_gap->ga_data) + i;
6754
6755 if (p->s != NULL)
6756 ga_concat(gap, p->s);
6757 line_breakcheck();
6758 }
6759
6760 return OK;
6761}
6762
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006763/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006764 * Join list "l" into a string in "*gap", using separator "sep".
Bram Moolenaar70b2a562012-01-10 22:26:17 +01006765 * When "echo_style" is TRUE use String as echoed, otherwise as inside a List.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006766 * Return FAIL or OK.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006767 */
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006768 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006769list_join(
6770 garray_T *gap,
6771 list_T *l,
6772 char_u *sep,
6773 int echo_style,
6774 int copyID)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006775{
Bram Moolenaar3fe37d62012-02-06 00:13:22 +01006776 garray_T join_ga;
6777 int retval;
6778 join_T *p;
6779 int i;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006780
Bram Moolenaard39a7512015-04-16 22:51:22 +02006781 if (l->lv_len < 1)
6782 return OK; /* nothing to do */
Bram Moolenaar3fe37d62012-02-06 00:13:22 +01006783 ga_init2(&join_ga, (int)sizeof(join_T), l->lv_len);
6784 retval = list_join_inner(gap, l, sep, echo_style, copyID, &join_ga);
6785
6786 /* Dispose each item in join_ga. */
6787 if (join_ga.ga_data != NULL)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006788 {
Bram Moolenaar3fe37d62012-02-06 00:13:22 +01006789 p = (join_T *)join_ga.ga_data;
6790 for (i = 0; i < join_ga.ga_len; ++i)
6791 {
6792 vim_free(p->tofree);
6793 ++p;
6794 }
6795 ga_clear(&join_ga);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006796 }
Bram Moolenaar3fe37d62012-02-06 00:13:22 +01006797
6798 return retval;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006799}
6800
6801/*
Bram Moolenaar520e1e42016-01-23 19:46:28 +01006802 * Return the next (unique) copy ID.
6803 * Used for serializing nested structures.
6804 */
6805 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006806get_copyID(void)
Bram Moolenaar520e1e42016-01-23 19:46:28 +01006807{
6808 current_copyID += COPYID_INC;
6809 return current_copyID;
6810}
6811
6812/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006813 * Garbage collection for lists and dictionaries.
6814 *
6815 * We use reference counts to be able to free most items right away when they
6816 * are no longer used. But for composite items it's possible that it becomes
6817 * unused while the reference count is > 0: When there is a recursive
6818 * reference. Example:
6819 * :let l = [1, 2, 3]
6820 * :let d = {9: l}
6821 * :let l[1] = d
6822 *
6823 * Since this is quite unusual we handle this with garbage collection: every
6824 * once in a while find out which lists and dicts are not referenced from any
6825 * variable.
6826 *
6827 * Here is a good reference text about garbage collection (refers to Python
6828 * but it applies to all reference-counting mechanisms):
6829 * http://python.ca/nas/python/gc/
Bram Moolenaard9fba312005-06-26 22:34:35 +00006830 */
Bram Moolenaard9fba312005-06-26 22:34:35 +00006831
6832/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006833 * Do garbage collection for lists and dicts.
6834 * Return TRUE if some memory was freed.
Bram Moolenaard9fba312005-06-26 22:34:35 +00006835 */
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006836 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006837garbage_collect(void)
Bram Moolenaard9fba312005-06-26 22:34:35 +00006838{
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006839 int copyID;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006840 int abort = FALSE;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006841 buf_T *buf;
6842 win_T *wp;
6843 int i;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +00006844 funccall_T *fc, **pfc;
Bram Moolenaar934b1362015-02-04 23:06:45 +01006845 int did_free = FALSE;
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006846 int did_free_funccal = FALSE;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00006847#ifdef FEAT_WINDOWS
6848 tabpage_T *tp;
6849#endif
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006850
Bram Moolenaar9fecb462006-09-05 10:59:47 +00006851 /* Only do this once. */
6852 want_garbage_collect = FALSE;
6853 may_garbage_collect = FALSE;
Bram Moolenaar9d2c8c12007-09-25 16:00:00 +00006854 garbage_collect_at_exit = FALSE;
Bram Moolenaar9fecb462006-09-05 10:59:47 +00006855
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006856 /* We advance by two because we add one for items referenced through
6857 * previous_funccal. */
Bram Moolenaar520e1e42016-01-23 19:46:28 +01006858 copyID = get_copyID();
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006859
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006860 /*
6861 * 1. Go through all accessible variables and mark all lists and dicts
6862 * with copyID.
6863 */
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006864
6865 /* Don't free variables in the previous_funccal list unless they are only
6866 * referenced through previous_funccal. This must be first, because if
Bram Moolenaar2c2398c2009-06-03 11:22:45 +00006867 * the item is referenced elsewhere the funccal must not be freed. */
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006868 for (fc = previous_funccal; fc != NULL; fc = fc->caller)
6869 {
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006870 abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1,
6871 NULL);
6872 abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1,
6873 NULL);
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006874 }
6875
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006876 /* script-local variables */
6877 for (i = 1; i <= ga_scripts.ga_len; ++i)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006878 abort = abort || set_ref_in_ht(&SCRIPT_VARS(i), copyID, NULL);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006879
6880 /* buffer-local variables */
6881 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006882 abort = abort || set_ref_in_item(&buf->b_bufvar.di_tv, copyID,
6883 NULL, NULL);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006884
6885 /* window-local variables */
Bram Moolenaar910f66f2006-04-05 20:41:53 +00006886 FOR_ALL_TAB_WINDOWS(tp, wp)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006887 abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
6888 NULL, NULL);
Bram Moolenaar3bb28552013-04-15 18:25:59 +02006889#ifdef FEAT_AUTOCMD
6890 if (aucmd_win != NULL)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006891 abort = abort || set_ref_in_item(&aucmd_win->w_winvar.di_tv, copyID,
6892 NULL, NULL);
Bram Moolenaar3bb28552013-04-15 18:25:59 +02006893#endif
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006894
Bram Moolenaar910f66f2006-04-05 20:41:53 +00006895#ifdef FEAT_WINDOWS
6896 /* tabpage-local variables */
6897 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006898 abort = abort || set_ref_in_item(&tp->tp_winvar.di_tv, copyID,
6899 NULL, NULL);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00006900#endif
6901
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006902 /* global variables */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006903 abort = abort || set_ref_in_ht(&globvarht, copyID, NULL);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006904
6905 /* function-local variables */
6906 for (fc = current_funccal; fc != NULL; fc = fc->caller)
6907 {
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006908 abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL);
6909 abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006910 }
6911
Bram Moolenaard812df62008-11-09 12:46:09 +00006912 /* v: vars */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006913 abort = abort || set_ref_in_ht(&vimvarht, copyID, NULL);
Bram Moolenaard812df62008-11-09 12:46:09 +00006914
Bram Moolenaar1dced572012-04-05 16:54:08 +02006915#ifdef FEAT_LUA
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006916 abort = abort || set_ref_in_lua(copyID);
Bram Moolenaar1dced572012-04-05 16:54:08 +02006917#endif
6918
Bram Moolenaardb913952012-06-29 12:54:53 +02006919#ifdef FEAT_PYTHON
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006920 abort = abort || set_ref_in_python(copyID);
Bram Moolenaardb913952012-06-29 12:54:53 +02006921#endif
6922
6923#ifdef FEAT_PYTHON3
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006924 abort = abort || set_ref_in_python3(copyID);
Bram Moolenaardb913952012-06-29 12:54:53 +02006925#endif
6926
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01006927#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar4b6a6dc2016-02-04 22:49:49 +01006928 abort = abort || set_ref_in_channel(copyID);
6929#endif
6930
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006931 if (!abort)
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006932 {
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006933 /*
6934 * 2. Free lists and dictionaries that are not referenced.
6935 */
6936 did_free = free_unref_items(copyID);
6937
6938 /*
6939 * 3. Check if any funccal can be freed now.
6940 */
6941 for (pfc = &previous_funccal; *pfc != NULL; )
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006942 {
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006943 if (can_free_funccal(*pfc, copyID))
6944 {
6945 fc = *pfc;
6946 *pfc = fc->caller;
6947 free_funccal(fc, TRUE);
6948 did_free = TRUE;
6949 did_free_funccal = TRUE;
6950 }
6951 else
6952 pfc = &(*pfc)->caller;
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006953 }
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006954 if (did_free_funccal)
6955 /* When a funccal was freed some more items might be garbage
6956 * collected, so run again. */
6957 (void)garbage_collect();
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006958 }
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006959 else if (p_verbose > 0)
6960 {
6961 verb_msg((char_u *)_("Not enough memory to set references, garbage collection aborted!"));
6962 }
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006963
6964 return did_free;
6965}
6966
6967/*
Bram Moolenaar835dc632016-02-07 14:27:38 +01006968 * Free lists, dictionaries and jobs that are no longer referenced.
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006969 */
6970 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006971free_unref_items(int copyID)
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006972{
Bram Moolenaare71eea82015-02-03 17:10:06 +01006973 dict_T *dd, *dd_next;
6974 list_T *ll, *ll_next;
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006975 int did_free = FALSE;
6976
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006977 /*
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006978 * Go through the list of dicts and free items without the copyID.
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006979 */
6980 for (dd = first_dict; dd != NULL; )
Bram Moolenaare71eea82015-02-03 17:10:06 +01006981 {
6982 dd_next = dd->dv_used_next;
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006983 if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK))
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006984 {
Bram Moolenaar685295c2006-10-15 20:37:38 +00006985 /* Free the Dictionary and ordinary items it contains, but don't
6986 * recurse into Lists and Dictionaries, they will be in the list
6987 * of dicts or list of lists. */
6988 dict_free(dd, FALSE);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006989 did_free = TRUE;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006990 }
Bram Moolenaare71eea82015-02-03 17:10:06 +01006991 dd = dd_next;
6992 }
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006993
6994 /*
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006995 * Go through the list of lists and free items without the copyID.
6996 * But don't free a list that has a watcher (used in a for loop), these
6997 * are not referenced anywhere.
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006998 */
6999 for (ll = first_list; ll != NULL; )
Bram Moolenaare71eea82015-02-03 17:10:06 +01007000 {
7001 ll_next = ll->lv_used_next;
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00007002 if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)
7003 && ll->lv_watch == NULL)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007004 {
Bram Moolenaar685295c2006-10-15 20:37:38 +00007005 /* Free the List and ordinary items it contains, but don't recurse
7006 * into Lists and Dictionaries, they will be in the list of dicts
7007 * or list of lists. */
7008 list_free(ll, FALSE);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007009 did_free = TRUE;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007010 }
Bram Moolenaare71eea82015-02-03 17:10:06 +01007011 ll = ll_next;
7012 }
Bram Moolenaar835dc632016-02-07 14:27:38 +01007013
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007014 return did_free;
7015}
7016
7017/*
7018 * Mark all lists and dicts referenced through hashtab "ht" with "copyID".
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01007019 * "list_stack" is used to add lists to be marked. Can be NULL.
7020 *
7021 * Returns TRUE if setting references failed somehow.
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007022 */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01007023 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007024set_ref_in_ht(hashtab_T *ht, int copyID, list_stack_T **list_stack)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007025{
7026 int todo;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01007027 int abort = FALSE;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007028 hashitem_T *hi;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01007029 hashtab_T *cur_ht;
7030 ht_stack_T *ht_stack = NULL;
7031 ht_stack_T *tempitem;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007032
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01007033 cur_ht = ht;
7034 for (;;)
7035 {
7036 if (!abort)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007037 {
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01007038 /* Mark each item in the hashtab. If the item contains a hashtab
7039 * it is added to ht_stack, if it contains a list it is added to
7040 * list_stack. */
7041 todo = (int)cur_ht->ht_used;
7042 for (hi = cur_ht->ht_array; todo > 0; ++hi)
7043 if (!HASHITEM_EMPTY(hi))
7044 {
7045 --todo;
7046 abort = abort || set_ref_in_item(&HI2DI(hi)->di_tv, copyID,
7047 &ht_stack, list_stack);
7048 }
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007049 }
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01007050
7051 if (ht_stack == NULL)
7052 break;
7053
7054 /* take an item from the stack */
7055 cur_ht = ht_stack->ht;
7056 tempitem = ht_stack;
7057 ht_stack = ht_stack->prev;
7058 free(tempitem);
7059 }
7060
7061 return abort;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007062}
7063
7064/*
7065 * Mark all lists and dicts referenced through list "l" with "copyID".
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01007066 * "ht_stack" is used to add hashtabs to be marked. Can be NULL.
7067 *
7068 * Returns TRUE if setting references failed somehow.
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007069 */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01007070 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007071set_ref_in_list(list_T *l, int copyID, ht_stack_T **ht_stack)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007072{
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01007073 listitem_T *li;
7074 int abort = FALSE;
7075 list_T *cur_l;
7076 list_stack_T *list_stack = NULL;
7077 list_stack_T *tempitem;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007078
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01007079 cur_l = l;
7080 for (;;)
7081 {
7082 if (!abort)
7083 /* Mark each item in the list. If the item contains a hashtab
7084 * it is added to ht_stack, if it contains a list it is added to
7085 * list_stack. */
7086 for (li = cur_l->lv_first; !abort && li != NULL; li = li->li_next)
7087 abort = abort || set_ref_in_item(&li->li_tv, copyID,
7088 ht_stack, &list_stack);
7089 if (list_stack == NULL)
7090 break;
7091
7092 /* take an item from the stack */
7093 cur_l = list_stack->list;
7094 tempitem = list_stack;
7095 list_stack = list_stack->prev;
7096 free(tempitem);
7097 }
7098
7099 return abort;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007100}
7101
7102/*
7103 * Mark all lists and dicts referenced through typval "tv" with "copyID".
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01007104 * "list_stack" is used to add lists to be marked. Can be NULL.
7105 * "ht_stack" is used to add hashtabs to be marked. Can be NULL.
7106 *
7107 * Returns TRUE if setting references failed somehow.
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007108 */
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01007109 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007110set_ref_in_item(
7111 typval_T *tv,
7112 int copyID,
7113 ht_stack_T **ht_stack,
7114 list_stack_T **list_stack)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007115{
7116 dict_T *dd;
7117 list_T *ll;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01007118 int abort = FALSE;
Bram Moolenaard9fba312005-06-26 22:34:35 +00007119
Bram Moolenaara03f2332016-02-06 18:09:59 +01007120 if (tv->v_type == VAR_DICT)
Bram Moolenaard9fba312005-06-26 22:34:35 +00007121 {
Bram Moolenaara03f2332016-02-06 18:09:59 +01007122 dd = tv->vval.v_dict;
7123 if (dd != NULL && dd->dv_copyID != copyID)
7124 {
7125 /* Didn't see this dict yet. */
7126 dd->dv_copyID = copyID;
7127 if (ht_stack == NULL)
Bram Moolenaard9fba312005-06-26 22:34:35 +00007128 {
Bram Moolenaara03f2332016-02-06 18:09:59 +01007129 abort = set_ref_in_ht(&dd->dv_hashtab, copyID, list_stack);
7130 }
7131 else
7132 {
7133 ht_stack_T *newitem = (ht_stack_T*)malloc(sizeof(ht_stack_T));
7134 if (newitem == NULL)
7135 abort = TRUE;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01007136 else
7137 {
Bram Moolenaara03f2332016-02-06 18:09:59 +01007138 newitem->ht = &dd->dv_hashtab;
7139 newitem->prev = *ht_stack;
7140 *ht_stack = newitem;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01007141 }
Bram Moolenaard9fba312005-06-26 22:34:35 +00007142 }
Bram Moolenaara03f2332016-02-06 18:09:59 +01007143 }
7144 }
7145 else if (tv->v_type == VAR_LIST)
7146 {
7147 ll = tv->vval.v_list;
7148 if (ll != NULL && ll->lv_copyID != copyID)
7149 {
7150 /* Didn't see this list yet. */
7151 ll->lv_copyID = copyID;
7152 if (list_stack == NULL)
Bram Moolenaard9fba312005-06-26 22:34:35 +00007153 {
Bram Moolenaara03f2332016-02-06 18:09:59 +01007154 abort = set_ref_in_list(ll, copyID, ht_stack);
7155 }
7156 else
7157 {
7158 list_stack_T *newitem = (list_stack_T*)malloc(
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01007159 sizeof(list_stack_T));
Bram Moolenaara03f2332016-02-06 18:09:59 +01007160 if (newitem == NULL)
7161 abort = TRUE;
7162 else
7163 {
7164 newitem->list = ll;
7165 newitem->prev = *list_stack;
7166 *list_stack = newitem;
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01007167 }
Bram Moolenaard9fba312005-06-26 22:34:35 +00007168 }
Bram Moolenaara03f2332016-02-06 18:09:59 +01007169 }
Bram Moolenaard9fba312005-06-26 22:34:35 +00007170 }
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01007171 return abort;
Bram Moolenaard9fba312005-06-26 22:34:35 +00007172}
7173
7174/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00007175 * Allocate an empty header for a dictionary.
7176 */
Bram Moolenaar05159a02005-02-26 23:04:13 +00007177 dict_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007178dict_alloc(void)
Bram Moolenaar8c711452005-01-14 21:53:12 +00007179{
Bram Moolenaar33570922005-01-25 22:26:29 +00007180 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007181
Bram Moolenaar33570922005-01-25 22:26:29 +00007182 d = (dict_T *)alloc(sizeof(dict_T));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007183 if (d != NULL)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007184 {
Bram Moolenaarbdb62052012-07-16 17:31:53 +02007185 /* Add the dict to the list of dicts for garbage collection. */
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007186 if (first_dict != NULL)
7187 first_dict->dv_used_prev = d;
7188 d->dv_used_next = first_dict;
7189 d->dv_used_prev = NULL;
Bram Moolenaar685295c2006-10-15 20:37:38 +00007190 first_dict = d;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007191
Bram Moolenaar33570922005-01-25 22:26:29 +00007192 hash_init(&d->dv_hashtab);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007193 d->dv_lock = 0;
Bram Moolenaarbdb62052012-07-16 17:31:53 +02007194 d->dv_scope = 0;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007195 d->dv_refcount = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007196 d->dv_copyID = 0;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007197 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007198 return d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007199}
7200
7201/*
Bram Moolenaara800b422010-06-27 01:15:55 +02007202 * Allocate an empty dict for a return value.
7203 * Returns OK or FAIL.
7204 */
Bram Moolenaar520e1e42016-01-23 19:46:28 +01007205 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007206rettv_dict_alloc(typval_T *rettv)
Bram Moolenaara800b422010-06-27 01:15:55 +02007207{
7208 dict_T *d = dict_alloc();
7209
7210 if (d == NULL)
7211 return FAIL;
7212
7213 rettv->vval.v_dict = d;
7214 rettv->v_type = VAR_DICT;
7215 ++d->dv_refcount;
7216 return OK;
7217}
7218
7219
7220/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00007221 * Unreference a Dictionary: decrement the reference count and free it when it
7222 * becomes zero.
7223 */
Bram Moolenaar82139082011-09-14 16:52:09 +02007224 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007225dict_unref(dict_T *d)
Bram Moolenaar8c711452005-01-14 21:53:12 +00007226{
Bram Moolenaar685295c2006-10-15 20:37:38 +00007227 if (d != NULL && --d->dv_refcount <= 0)
7228 dict_free(d, TRUE);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007229}
7230
7231/*
Bram Moolenaare71eea82015-02-03 17:10:06 +01007232 * Free a Dictionary, including all non-container items it contains.
Bram Moolenaar8c711452005-01-14 21:53:12 +00007233 * Ignores the reference count.
7234 */
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02007235 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007236dict_free(
7237 dict_T *d,
7238 int recurse) /* Free Lists and Dictionaries recursively. */
Bram Moolenaar8c711452005-01-14 21:53:12 +00007239{
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007240 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00007241 hashitem_T *hi;
Bram Moolenaard9fba312005-06-26 22:34:35 +00007242 dictitem_T *di;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007243
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007244 /* Remove the dict from the list of dicts for garbage collection. */
7245 if (d->dv_used_prev == NULL)
7246 first_dict = d->dv_used_next;
7247 else
7248 d->dv_used_prev->dv_used_next = d->dv_used_next;
7249 if (d->dv_used_next != NULL)
7250 d->dv_used_next->dv_used_prev = d->dv_used_prev;
7251
7252 /* Lock the hashtab, we don't want it to resize while freeing items. */
Bram Moolenaard9fba312005-06-26 22:34:35 +00007253 hash_lock(&d->dv_hashtab);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007254 todo = (int)d->dv_hashtab.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00007255 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +00007256 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007257 if (!HASHITEM_EMPTY(hi))
7258 {
Bram Moolenaard9fba312005-06-26 22:34:35 +00007259 /* Remove the item before deleting it, just in case there is
7260 * something recursive causing trouble. */
7261 di = HI2DI(hi);
7262 hash_remove(&d->dv_hashtab, hi);
Bram Moolenaar685295c2006-10-15 20:37:38 +00007263 if (recurse || (di->di_tv.v_type != VAR_LIST
7264 && di->di_tv.v_type != VAR_DICT))
7265 clear_tv(&di->di_tv);
7266 vim_free(di);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007267 --todo;
7268 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00007269 }
Bram Moolenaar33570922005-01-25 22:26:29 +00007270 hash_clear(&d->dv_hashtab);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007271 vim_free(d);
7272}
7273
7274/*
7275 * Allocate a Dictionary item.
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007276 * The "key" is copied to the new item.
7277 * Note that the value of the item "di_tv" still needs to be initialized!
7278 * Returns NULL when out of memory.
Bram Moolenaar8c711452005-01-14 21:53:12 +00007279 */
Bram Moolenaar7e506b62010-01-19 15:55:06 +01007280 dictitem_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007281dictitem_alloc(char_u *key)
Bram Moolenaar8c711452005-01-14 21:53:12 +00007282{
Bram Moolenaar33570922005-01-25 22:26:29 +00007283 dictitem_T *di;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007284
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007285 di = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T) + STRLEN(key)));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007286 if (di != NULL)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007287 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007288 STRCPY(di->di_key, key);
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02007289 di->di_flags = DI_FLAGS_ALLOC;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007290 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007291 return di;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007292}
7293
7294/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00007295 * Make a copy of a Dictionary item.
7296 */
Bram Moolenaar33570922005-01-25 22:26:29 +00007297 static dictitem_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007298dictitem_copy(dictitem_T *org)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007299{
Bram Moolenaar33570922005-01-25 22:26:29 +00007300 dictitem_T *di;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007301
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007302 di = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
7303 + STRLEN(org->di_key)));
Bram Moolenaare9a41262005-01-15 22:18:47 +00007304 if (di != NULL)
7305 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007306 STRCPY(di->di_key, org->di_key);
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02007307 di->di_flags = DI_FLAGS_ALLOC;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007308 copy_tv(&org->di_tv, &di->di_tv);
7309 }
7310 return di;
7311}
7312
7313/*
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007314 * Remove item "item" from Dictionary "dict" and free it.
7315 */
7316 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007317dictitem_remove(dict_T *dict, dictitem_T *item)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007318{
Bram Moolenaar33570922005-01-25 22:26:29 +00007319 hashitem_T *hi;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007320
Bram Moolenaar33570922005-01-25 22:26:29 +00007321 hi = hash_find(&dict->dv_hashtab, item->di_key);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007322 if (HASHITEM_EMPTY(hi))
7323 EMSG2(_(e_intern2), "dictitem_remove()");
7324 else
Bram Moolenaar33570922005-01-25 22:26:29 +00007325 hash_remove(&dict->dv_hashtab, hi);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007326 dictitem_free(item);
7327}
7328
7329/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00007330 * Free a dict item. Also clears the value.
7331 */
Bram Moolenaar7e506b62010-01-19 15:55:06 +01007332 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007333dictitem_free(dictitem_T *item)
Bram Moolenaar8c711452005-01-14 21:53:12 +00007334{
Bram Moolenaar8c711452005-01-14 21:53:12 +00007335 clear_tv(&item->di_tv);
Bram Moolenaar9bc174b2015-04-13 16:16:38 +02007336 if (item->di_flags & DI_FLAGS_ALLOC)
7337 vim_free(item);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007338}
7339
7340/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00007341 * Make a copy of dict "d". Shallow if "deep" is FALSE.
7342 * The refcount of the new dict is set to 1.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007343 * See item_copy() for "copyID".
Bram Moolenaare9a41262005-01-15 22:18:47 +00007344 * Returns NULL when out of memory.
7345 */
Bram Moolenaar33570922005-01-25 22:26:29 +00007346 static dict_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007347dict_copy(dict_T *orig, int deep, int copyID)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007348{
Bram Moolenaar33570922005-01-25 22:26:29 +00007349 dict_T *copy;
7350 dictitem_T *di;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007351 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00007352 hashitem_T *hi;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007353
7354 if (orig == NULL)
7355 return NULL;
7356
7357 copy = dict_alloc();
7358 if (copy != NULL)
7359 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007360 if (copyID != 0)
7361 {
7362 orig->dv_copyID = copyID;
7363 orig->dv_copydict = copy;
7364 }
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007365 todo = (int)orig->dv_hashtab.ht_used;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007366 for (hi = orig->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007367 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007368 if (!HASHITEM_EMPTY(hi))
Bram Moolenaare9a41262005-01-15 22:18:47 +00007369 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007370 --todo;
7371
7372 di = dictitem_alloc(hi->hi_key);
7373 if (di == NULL)
7374 break;
7375 if (deep)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007376 {
7377 if (item_copy(&HI2DI(hi)->di_tv, &di->di_tv, deep,
7378 copyID) == FAIL)
7379 {
7380 vim_free(di);
7381 break;
7382 }
7383 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007384 else
7385 copy_tv(&HI2DI(hi)->di_tv, &di->di_tv);
7386 if (dict_add(copy, di) == FAIL)
7387 {
7388 dictitem_free(di);
7389 break;
7390 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007391 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007392 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007393
Bram Moolenaare9a41262005-01-15 22:18:47 +00007394 ++copy->dv_refcount;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007395 if (todo > 0)
7396 {
7397 dict_unref(copy);
7398 copy = NULL;
7399 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007400 }
7401
7402 return copy;
7403}
7404
7405/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00007406 * Add item "item" to Dictionary "d".
Bram Moolenaara800b422010-06-27 01:15:55 +02007407 * Returns FAIL when out of memory and when key already exists.
Bram Moolenaar8c711452005-01-14 21:53:12 +00007408 */
Bram Moolenaar7e506b62010-01-19 15:55:06 +01007409 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007410dict_add(dict_T *d, dictitem_T *item)
Bram Moolenaar8c711452005-01-14 21:53:12 +00007411{
Bram Moolenaar33570922005-01-25 22:26:29 +00007412 return hash_add(&d->dv_hashtab, item->di_key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007413}
7414
Bram Moolenaar8c711452005-01-14 21:53:12 +00007415/*
Bram Moolenaar05159a02005-02-26 23:04:13 +00007416 * Add a number or string entry to dictionary "d".
7417 * When "str" is NULL use number "nr", otherwise use "str".
7418 * Returns FAIL when out of memory and when key already exists.
7419 */
7420 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007421dict_add_nr_str(
7422 dict_T *d,
7423 char *key,
7424 long nr,
7425 char_u *str)
Bram Moolenaar05159a02005-02-26 23:04:13 +00007426{
7427 dictitem_T *item;
7428
7429 item = dictitem_alloc((char_u *)key);
7430 if (item == NULL)
7431 return FAIL;
7432 item->di_tv.v_lock = 0;
7433 if (str == NULL)
7434 {
7435 item->di_tv.v_type = VAR_NUMBER;
7436 item->di_tv.vval.v_number = nr;
7437 }
7438 else
7439 {
7440 item->di_tv.v_type = VAR_STRING;
7441 item->di_tv.vval.v_string = vim_strsave(str);
7442 }
7443 if (dict_add(d, item) == FAIL)
7444 {
7445 dictitem_free(item);
7446 return FAIL;
7447 }
7448 return OK;
7449}
7450
7451/*
Bram Moolenaar217d2852010-09-14 12:47:37 +02007452 * Add a list entry to dictionary "d".
Bram Moolenaara800b422010-06-27 01:15:55 +02007453 * Returns FAIL when out of memory and when key already exists.
7454 */
7455 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007456dict_add_list(dict_T *d, char *key, list_T *list)
Bram Moolenaara800b422010-06-27 01:15:55 +02007457{
7458 dictitem_T *item;
7459
7460 item = dictitem_alloc((char_u *)key);
7461 if (item == NULL)
7462 return FAIL;
7463 item->di_tv.v_lock = 0;
7464 item->di_tv.v_type = VAR_LIST;
7465 item->di_tv.vval.v_list = list;
7466 if (dict_add(d, item) == FAIL)
7467 {
7468 dictitem_free(item);
7469 return FAIL;
7470 }
Bram Moolenaar217d2852010-09-14 12:47:37 +02007471 ++list->lv_refcount;
Bram Moolenaara800b422010-06-27 01:15:55 +02007472 return OK;
7473}
7474
7475/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00007476 * Get the number of items in a Dictionary.
7477 */
7478 static long
Bram Moolenaar7454a062016-01-30 15:14:10 +01007479dict_len(dict_T *d)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007480{
Bram Moolenaare9a41262005-01-15 22:18:47 +00007481 if (d == NULL)
7482 return 0L;
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007483 return (long)d->dv_hashtab.ht_used;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007484}
7485
7486/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00007487 * Find item "key[len]" in Dictionary "d".
7488 * If "len" is negative use strlen(key).
7489 * Returns NULL when not found.
7490 */
Bram Moolenaar8bcf9652010-06-12 20:12:02 +02007491 dictitem_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007492dict_find(dict_T *d, char_u *key, int len)
Bram Moolenaar8c711452005-01-14 21:53:12 +00007493{
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007494#define AKEYLEN 200
7495 char_u buf[AKEYLEN];
7496 char_u *akey;
7497 char_u *tofree = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00007498 hashitem_T *hi;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007499
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007500 if (len < 0)
7501 akey = key;
7502 else if (len >= AKEYLEN)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00007503 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007504 tofree = akey = vim_strnsave(key, len);
7505 if (akey == NULL)
7506 return NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00007507 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007508 else
7509 {
7510 /* Avoid a malloc/free by using buf[]. */
Bram Moolenaarce0842a2005-07-18 21:58:11 +00007511 vim_strncpy(buf, key, len);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007512 akey = buf;
7513 }
7514
Bram Moolenaar33570922005-01-25 22:26:29 +00007515 hi = hash_find(&d->dv_hashtab, akey);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007516 vim_free(tofree);
7517 if (HASHITEM_EMPTY(hi))
7518 return NULL;
7519 return HI2DI(hi);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007520}
7521
7522/*
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00007523 * Get a string item from a dictionary.
7524 * When "save" is TRUE allocate memory for it.
Bram Moolenaar2641f772005-03-25 21:58:17 +00007525 * Returns NULL if the entry doesn't exist or out of memory.
7526 */
7527 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007528get_dict_string(dict_T *d, char_u *key, int save)
Bram Moolenaar2641f772005-03-25 21:58:17 +00007529{
7530 dictitem_T *di;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00007531 char_u *s;
Bram Moolenaar2641f772005-03-25 21:58:17 +00007532
7533 di = dict_find(d, key, -1);
7534 if (di == NULL)
7535 return NULL;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00007536 s = get_tv_string(&di->di_tv);
7537 if (save && s != NULL)
7538 s = vim_strsave(s);
7539 return s;
Bram Moolenaar2641f772005-03-25 21:58:17 +00007540}
7541
7542/*
7543 * Get a number item from a dictionary.
Bram Moolenaarba093bc2016-02-16 19:37:29 +01007544 * Returns 0 if the entry doesn't exist.
Bram Moolenaar2641f772005-03-25 21:58:17 +00007545 */
7546 long
Bram Moolenaar7454a062016-01-30 15:14:10 +01007547get_dict_number(dict_T *d, char_u *key)
Bram Moolenaar2641f772005-03-25 21:58:17 +00007548{
7549 dictitem_T *di;
7550
7551 di = dict_find(d, key, -1);
7552 if (di == NULL)
7553 return 0;
7554 return get_tv_number(&di->di_tv);
7555}
7556
7557/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00007558 * Return an allocated string with the string representation of a Dictionary.
7559 * May return NULL.
7560 */
7561 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007562dict2string(typval_T *tv, int copyID)
Bram Moolenaar8c711452005-01-14 21:53:12 +00007563{
7564 garray_T ga;
7565 int first = TRUE;
7566 char_u *tofree;
7567 char_u numbuf[NUMBUFLEN];
Bram Moolenaar33570922005-01-25 22:26:29 +00007568 hashitem_T *hi;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007569 char_u *s;
Bram Moolenaar33570922005-01-25 22:26:29 +00007570 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007571 int todo;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007572
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007573 if ((d = tv->vval.v_dict) == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00007574 return NULL;
7575 ga_init2(&ga, (int)sizeof(char), 80);
7576 ga_append(&ga, '{');
7577
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007578 todo = (int)d->dv_hashtab.ht_used;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007579 for (hi = d->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +00007580 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007581 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar8c711452005-01-14 21:53:12 +00007582 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007583 --todo;
7584
7585 if (first)
7586 first = FALSE;
7587 else
7588 ga_concat(&ga, (char_u *)", ");
7589
7590 tofree = string_quote(hi->hi_key, FALSE);
7591 if (tofree != NULL)
7592 {
7593 ga_concat(&ga, tofree);
7594 vim_free(tofree);
7595 }
7596 ga_concat(&ga, (char_u *)": ");
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007597 s = tv2string(&HI2DI(hi)->di_tv, &tofree, numbuf, copyID);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007598 if (s != NULL)
7599 ga_concat(&ga, s);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007600 vim_free(tofree);
Bram Moolenaar8502c702014-06-17 12:51:16 +02007601 if (s == NULL || did_echo_string_emsg)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007602 break;
Bram Moolenaar8502c702014-06-17 12:51:16 +02007603 line_breakcheck();
7604
Bram Moolenaar8c711452005-01-14 21:53:12 +00007605 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00007606 }
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007607 if (todo > 0)
7608 {
7609 vim_free(ga.ga_data);
7610 return NULL;
7611 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00007612
7613 ga_append(&ga, '}');
7614 ga_append(&ga, NUL);
7615 return (char_u *)ga.ga_data;
7616}
7617
7618/*
7619 * Allocate a variable for a Dictionary and fill it from "*arg".
7620 * Return OK or FAIL. Returns NOTDONE for {expr}.
7621 */
7622 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007623get_dict_tv(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar8c711452005-01-14 21:53:12 +00007624{
Bram Moolenaar33570922005-01-25 22:26:29 +00007625 dict_T *d = NULL;
7626 typval_T tvkey;
7627 typval_T tv;
Bram Moolenaarad6c2272007-09-17 20:21:33 +00007628 char_u *key = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00007629 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007630 char_u *start = skipwhite(*arg + 1);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007631 char_u buf[NUMBUFLEN];
Bram Moolenaar8c711452005-01-14 21:53:12 +00007632
7633 /*
7634 * First check if it's not a curly-braces thing: {expr}.
7635 * Must do this without evaluating, otherwise a function may be called
7636 * twice. Unfortunately this means we need to call eval1() twice for the
7637 * first item.
Bram Moolenaare9a41262005-01-15 22:18:47 +00007638 * But {} is an empty Dictionary.
Bram Moolenaar8c711452005-01-14 21:53:12 +00007639 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00007640 if (*start != '}')
7641 {
7642 if (eval1(&start, &tv, FALSE) == FAIL) /* recursive! */
7643 return FAIL;
7644 if (*start == '}')
7645 return NOTDONE;
7646 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00007647
7648 if (evaluate)
7649 {
7650 d = dict_alloc();
7651 if (d == NULL)
7652 return FAIL;
7653 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007654 tvkey.v_type = VAR_UNKNOWN;
7655 tv.v_type = VAR_UNKNOWN;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007656
7657 *arg = skipwhite(*arg + 1);
7658 while (**arg != '}' && **arg != NUL)
7659 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007660 if (eval1(arg, &tvkey, evaluate) == FAIL) /* recursive! */
Bram Moolenaar8c711452005-01-14 21:53:12 +00007661 goto failret;
7662 if (**arg != ':')
7663 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007664 EMSG2(_("E720: Missing colon in Dictionary: %s"), *arg);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007665 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007666 goto failret;
7667 }
Bram Moolenaar037cc642007-09-13 18:40:54 +00007668 if (evaluate)
Bram Moolenaar8c711452005-01-14 21:53:12 +00007669 {
Bram Moolenaar037cc642007-09-13 18:40:54 +00007670 key = get_tv_string_buf_chk(&tvkey, buf);
7671 if (key == NULL || *key == NUL)
7672 {
7673 /* "key" is NULL when get_tv_string_buf_chk() gave an errmsg */
7674 if (key != NULL)
7675 EMSG(_(e_emptykey));
7676 clear_tv(&tvkey);
7677 goto failret;
7678 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00007679 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00007680
7681 *arg = skipwhite(*arg + 1);
7682 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
7683 {
Bram Moolenaar037cc642007-09-13 18:40:54 +00007684 if (evaluate)
7685 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007686 goto failret;
7687 }
7688 if (evaluate)
7689 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007690 item = dict_find(d, key, -1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007691 if (item != NULL)
7692 {
Bram Moolenaarb982ca52005-03-28 21:02:15 +00007693 EMSG2(_("E721: Duplicate key in Dictionary: \"%s\""), key);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007694 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007695 clear_tv(&tv);
7696 goto failret;
7697 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007698 item = dictitem_alloc(key);
7699 clear_tv(&tvkey);
7700 if (item != NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00007701 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00007702 item->di_tv = tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007703 item->di_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007704 if (dict_add(d, item) == FAIL)
7705 dictitem_free(item);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007706 }
7707 }
7708
7709 if (**arg == '}')
7710 break;
7711 if (**arg != ',')
7712 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007713 EMSG2(_("E722: Missing comma in Dictionary: %s"), *arg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007714 goto failret;
7715 }
7716 *arg = skipwhite(*arg + 1);
7717 }
7718
7719 if (**arg != '}')
7720 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007721 EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007722failret:
7723 if (evaluate)
Bram Moolenaar685295c2006-10-15 20:37:38 +00007724 dict_free(d, TRUE);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007725 return FAIL;
7726 }
7727
7728 *arg = skipwhite(*arg + 1);
7729 if (evaluate)
7730 {
7731 rettv->v_type = VAR_DICT;
7732 rettv->vval.v_dict = d;
7733 ++d->dv_refcount;
7734 }
7735
7736 return OK;
7737}
7738
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01007739#if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
Bram Moolenaar835dc632016-02-07 14:27:38 +01007740#endif
7741
Bram Moolenaar17a13432016-01-24 14:22:10 +01007742 static char *
7743get_var_special_name(int nr)
7744{
7745 switch (nr)
7746 {
Bram Moolenaarf48aa162016-01-24 17:54:24 +01007747 case VVAL_FALSE: return "v:false";
Bram Moolenaar65edff82016-02-21 16:40:11 +01007748 case VVAL_TRUE: return "v:true";
7749 case VVAL_NONE: return "v:none";
7750 case VVAL_NULL: return "v:null";
Bram Moolenaar17a13432016-01-24 14:22:10 +01007751 }
7752 EMSG2(_(e_intern2), "get_var_special_name()");
7753 return "42";
7754}
7755
Bram Moolenaar8c711452005-01-14 21:53:12 +00007756/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007757 * Return a string with the string representation of a variable.
7758 * If the memory is allocated "tofree" is set to it, otherwise NULL.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007759 * "numbuf" is used for a number.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007760 * Does not put quotes around strings, as ":echo" displays values.
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007761 * When "copyID" is not NULL replace recursive lists and dicts with "...".
Bram Moolenaar92c5aba2007-08-14 20:29:31 +00007762 * May return NULL.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007763 */
7764 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007765echo_string(
7766 typval_T *tv,
7767 char_u **tofree,
7768 char_u *numbuf,
7769 int copyID)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007770{
Bram Moolenaare9a41262005-01-15 22:18:47 +00007771 static int recurse = 0;
7772 char_u *r = NULL;
7773
Bram Moolenaar33570922005-01-25 22:26:29 +00007774 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007775 {
Bram Moolenaar8502c702014-06-17 12:51:16 +02007776 if (!did_echo_string_emsg)
7777 {
7778 /* Only give this message once for a recursive call to avoid
7779 * flooding the user with errors. And stop iterating over lists
7780 * and dicts. */
7781 did_echo_string_emsg = TRUE;
7782 EMSG(_("E724: variable nested too deep for displaying"));
7783 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007784 *tofree = NULL;
Bram Moolenaar8502c702014-06-17 12:51:16 +02007785 return (char_u *)"{E724}";
Bram Moolenaare9a41262005-01-15 22:18:47 +00007786 }
7787 ++recurse;
7788
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007789 switch (tv->v_type)
7790 {
7791 case VAR_FUNC:
7792 *tofree = NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007793 r = tv->vval.v_string;
7794 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007795
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007796 case VAR_LIST:
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007797 if (tv->vval.v_list == NULL)
7798 {
7799 *tofree = NULL;
7800 r = NULL;
7801 }
7802 else if (copyID != 0 && tv->vval.v_list->lv_copyID == copyID)
7803 {
7804 *tofree = NULL;
7805 r = (char_u *)"[...]";
7806 }
7807 else
7808 {
7809 tv->vval.v_list->lv_copyID = copyID;
7810 *tofree = list2string(tv, copyID);
7811 r = *tofree;
7812 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007813 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007814
Bram Moolenaar8c711452005-01-14 21:53:12 +00007815 case VAR_DICT:
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007816 if (tv->vval.v_dict == NULL)
7817 {
7818 *tofree = NULL;
7819 r = NULL;
7820 }
7821 else if (copyID != 0 && tv->vval.v_dict->dv_copyID == copyID)
7822 {
7823 *tofree = NULL;
7824 r = (char_u *)"{...}";
7825 }
7826 else
7827 {
7828 tv->vval.v_dict->dv_copyID = copyID;
7829 *tofree = dict2string(tv, copyID);
7830 r = *tofree;
7831 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007832 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007833
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007834 case VAR_STRING:
7835 case VAR_NUMBER:
Bram Moolenaara03f2332016-02-06 18:09:59 +01007836 case VAR_UNKNOWN:
Bram Moolenaar835dc632016-02-07 14:27:38 +01007837 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01007838 case VAR_CHANNEL:
Bram Moolenaare9a41262005-01-15 22:18:47 +00007839 *tofree = NULL;
7840 r = get_tv_string_buf(tv, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007841 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007842
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007843 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +01007844#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007845 *tofree = NULL;
7846 vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv->vval.v_float);
7847 r = numbuf;
7848 break;
7849#endif
7850
Bram Moolenaar520e1e42016-01-23 19:46:28 +01007851 case VAR_SPECIAL:
7852 *tofree = NULL;
Bram Moolenaar17a13432016-01-24 14:22:10 +01007853 r = (char_u *)get_var_special_name(tv->vval.v_number);
Bram Moolenaar520e1e42016-01-23 19:46:28 +01007854 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007855 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007856
Bram Moolenaar8502c702014-06-17 12:51:16 +02007857 if (--recurse == 0)
7858 did_echo_string_emsg = FALSE;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007859 return r;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007860}
7861
7862/*
7863 * Return a string with the string representation of a variable.
7864 * If the memory is allocated "tofree" is set to it, otherwise NULL.
7865 * "numbuf" is used for a number.
7866 * Puts quotes around strings, so that they can be parsed back by eval().
Bram Moolenaar92c5aba2007-08-14 20:29:31 +00007867 * May return NULL.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007868 */
7869 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007870tv2string(
7871 typval_T *tv,
7872 char_u **tofree,
7873 char_u *numbuf,
7874 int copyID)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007875{
7876 switch (tv->v_type)
7877 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007878 case VAR_FUNC:
7879 *tofree = string_quote(tv->vval.v_string, TRUE);
7880 return *tofree;
7881 case VAR_STRING:
7882 *tofree = string_quote(tv->vval.v_string, FALSE);
7883 return *tofree;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007884 case VAR_FLOAT:
Bram Moolenaar5fac4672016-03-02 22:16:32 +01007885#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007886 *tofree = NULL;
7887 vim_snprintf((char *)numbuf, NUMBUFLEN - 1, "%g", tv->vval.v_float);
7888 return numbuf;
7889#endif
Bram Moolenaare9a41262005-01-15 22:18:47 +00007890 case VAR_NUMBER:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007891 case VAR_LIST:
Bram Moolenaar8c711452005-01-14 21:53:12 +00007892 case VAR_DICT:
Bram Moolenaar520e1e42016-01-23 19:46:28 +01007893 case VAR_SPECIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01007894 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01007895 case VAR_CHANNEL:
Bram Moolenaara03f2332016-02-06 18:09:59 +01007896 case VAR_UNKNOWN:
Bram Moolenaare9a41262005-01-15 22:18:47 +00007897 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007898 }
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007899 return echo_string(tv, tofree, numbuf, copyID);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007900}
7901
7902/*
Bram Moolenaar33570922005-01-25 22:26:29 +00007903 * Return string "str" in ' quotes, doubling ' characters.
7904 * If "str" is NULL an empty string is assumed.
Bram Moolenaar8c711452005-01-14 21:53:12 +00007905 * If "function" is TRUE make it function('string').
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007906 */
7907 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007908string_quote(char_u *str, int function)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007909{
Bram Moolenaar33570922005-01-25 22:26:29 +00007910 unsigned len;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007911 char_u *p, *r, *s;
7912
Bram Moolenaar33570922005-01-25 22:26:29 +00007913 len = (function ? 13 : 3);
7914 if (str != NULL)
7915 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007916 len += (unsigned)STRLEN(str);
Bram Moolenaar33570922005-01-25 22:26:29 +00007917 for (p = str; *p != NUL; mb_ptr_adv(p))
7918 if (*p == '\'')
7919 ++len;
7920 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007921 s = r = alloc(len);
7922 if (r != NULL)
7923 {
7924 if (function)
7925 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00007926 STRCPY(r, "function('");
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007927 r += 10;
7928 }
7929 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00007930 *r++ = '\'';
Bram Moolenaar33570922005-01-25 22:26:29 +00007931 if (str != NULL)
7932 for (p = str; *p != NUL; )
7933 {
7934 if (*p == '\'')
7935 *r++ = '\'';
7936 MB_COPY_CHAR(p, r);
7937 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00007938 *r++ = '\'';
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007939 if (function)
7940 *r++ = ')';
7941 *r++ = NUL;
7942 }
7943 return s;
7944}
7945
Bram Moolenaar520e1e42016-01-23 19:46:28 +01007946#if defined(FEAT_FLOAT) || defined(PROTO)
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007947/*
7948 * Convert the string "text" to a floating point number.
7949 * This uses strtod(). setlocale(LC_NUMERIC, "C") has been used to make sure
7950 * this always uses a decimal point.
7951 * Returns the length of the text that was consumed.
7952 */
Bram Moolenaar520e1e42016-01-23 19:46:28 +01007953 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007954string2float(
7955 char_u *text,
7956 float_T *value) /* result stored here */
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007957{
7958 char *s = (char *)text;
7959 float_T f;
7960
7961 f = strtod(s, &s);
7962 *value = f;
7963 return (int)((char_u *)s - text);
7964}
7965#endif
7966
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007967/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007968 * Get the value of an environment variable.
7969 * "arg" is pointing to the '$'. It is advanced to after the name.
7970 * If the environment variable was not set, silently assume it is empty.
Bram Moolenaare512c8c2014-04-29 17:41:22 +02007971 * Return FAIL if the name is invalid.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007972 */
7973 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007974get_env_tv(char_u **arg, typval_T *rettv, int evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007975{
7976 char_u *string = NULL;
7977 int len;
7978 int cc;
7979 char_u *name;
Bram Moolenaar05159a02005-02-26 23:04:13 +00007980 int mustfree = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007981
7982 ++*arg;
7983 name = *arg;
7984 len = get_env_len(arg);
7985 if (evaluate)
7986 {
Bram Moolenaare512c8c2014-04-29 17:41:22 +02007987 if (len == 0)
Bram Moolenaar615b9972015-01-14 17:15:05 +01007988 return FAIL; /* invalid empty name */
Bram Moolenaar05159a02005-02-26 23:04:13 +00007989
Bram Moolenaare512c8c2014-04-29 17:41:22 +02007990 cc = name[len];
7991 name[len] = NUL;
7992 /* first try vim_getenv(), fast for normal environment vars */
7993 string = vim_getenv(name, &mustfree);
7994 if (string != NULL && *string != NUL)
7995 {
7996 if (!mustfree)
7997 string = vim_strsave(string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007998 }
Bram Moolenaare512c8c2014-04-29 17:41:22 +02007999 else
8000 {
8001 if (mustfree)
8002 vim_free(string);
8003
8004 /* next try expanding things like $VIM and ${HOME} */
8005 string = expand_env_save(name - 1);
8006 if (string != NULL && *string == '$')
8007 {
8008 vim_free(string);
8009 string = NULL;
8010 }
8011 }
8012 name[len] = cc;
8013
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008014 rettv->v_type = VAR_STRING;
8015 rettv->vval.v_string = string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008016 }
8017
8018 return OK;
8019}
8020
8021/*
8022 * Array with names and number of arguments of all internal functions
8023 * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH!
8024 */
8025static struct fst
8026{
8027 char *f_name; /* function name */
8028 char f_min_argc; /* minimal number of arguments */
8029 char f_max_argc; /* maximal number of arguments */
Bram Moolenaar48e697e2016-01-23 22:17:30 +01008030 void (*f_func)(typval_T *args, typval_T *rvar);
Bram Moolenaarbae0c162007-05-10 19:30:25 +00008031 /* implementation of function */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008032} functions[] =
8033{
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008034#ifdef FEAT_FLOAT
8035 {"abs", 1, 1, f_abs},
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008036 {"acos", 1, 1, f_acos}, /* WJMc */
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008037#endif
Bram Moolenaar0d660222005-01-07 21:51:51 +00008038 {"add", 2, 2, f_add},
Bram Moolenaar75bdf6a2016-01-07 21:25:08 +01008039 {"alloc_fail", 3, 3, f_alloc_fail},
Bram Moolenaard6e256c2011-12-14 15:32:50 +01008040 {"and", 2, 2, f_and},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008041 {"append", 2, 2, f_append},
8042 {"argc", 0, 0, f_argc},
8043 {"argidx", 0, 0, f_argidx},
Bram Moolenaar2d1fe052014-05-28 18:22:57 +02008044 {"arglistid", 0, 2, f_arglistid},
Bram Moolenaare2f98b92006-03-29 21:18:24 +00008045 {"argv", 0, 1, f_argv},
Bram Moolenaar099fdde2015-12-13 14:45:21 +01008046#ifdef FEAT_FLOAT
8047 {"asin", 1, 1, f_asin}, /* WJMc */
8048#endif
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01008049 {"assert_equal", 2, 3, f_assert_equal},
Bram Moolenaara803c7f2016-01-15 15:31:39 +01008050 {"assert_exception", 1, 2, f_assert_exception},
Bram Moolenaara260b872016-01-15 20:48:22 +01008051 {"assert_fails", 1, 2, f_assert_fails},
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01008052 {"assert_false", 1, 2, f_assert_false},
8053 {"assert_true", 1, 2, f_assert_true},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008054#ifdef FEAT_FLOAT
8055 {"atan", 1, 1, f_atan},
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008056 {"atan2", 2, 2, f_atan2},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008057#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008058 {"browse", 4, 4, f_browse},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008059 {"browsedir", 2, 2, f_browsedir},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008060 {"bufexists", 1, 1, f_bufexists},
8061 {"buffer_exists", 1, 1, f_bufexists}, /* obsolete */
8062 {"buffer_name", 1, 1, f_bufname}, /* obsolete */
8063 {"buffer_number", 1, 1, f_bufnr}, /* obsolete */
8064 {"buflisted", 1, 1, f_buflisted},
8065 {"bufloaded", 1, 1, f_bufloaded},
8066 {"bufname", 1, 1, f_bufname},
Bram Moolenaar0e34f622006-03-03 23:00:03 +00008067 {"bufnr", 1, 2, f_bufnr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008068 {"bufwinnr", 1, 1, f_bufwinnr},
8069 {"byte2line", 1, 1, f_byte2line},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00008070 {"byteidx", 2, 2, f_byteidx},
Bram Moolenaar0ffbbf92013-11-02 23:29:26 +01008071 {"byteidxcomp", 2, 2, f_byteidxcomp},
Bram Moolenaare9a41262005-01-15 22:18:47 +00008072 {"call", 2, 3, f_call},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008073#ifdef FEAT_FLOAT
8074 {"ceil", 1, 1, f_ceil},
8075#endif
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01008076#ifdef FEAT_JOB_CHANNEL
Bram Moolenaarf57969a2016-02-02 20:47:49 +01008077 {"ch_close", 1, 1, f_ch_close},
Bram Moolenaar8b1862a2016-02-27 19:21:24 +01008078 {"ch_evalexpr", 2, 3, f_ch_evalexpr},
8079 {"ch_evalraw", 2, 3, f_ch_evalraw},
Bram Moolenaarc7f0ebc2016-02-27 21:10:09 +01008080 {"ch_getbufnr", 2, 2, f_ch_getbufnr},
Bram Moolenaar02e83b42016-02-21 20:10:26 +01008081 {"ch_getjob", 1, 1, f_ch_getjob},
Bram Moolenaar81661fb2016-02-18 22:23:34 +01008082 {"ch_log", 1, 2, f_ch_log},
Bram Moolenaar6463ca22016-02-13 17:04:46 +01008083 {"ch_logfile", 1, 2, f_ch_logfile},
Bram Moolenaar4d919d72016-02-05 22:36:41 +01008084 {"ch_open", 1, 2, f_ch_open},
Bram Moolenaar6f3a5442016-02-20 19:56:13 +01008085 {"ch_read", 1, 2, f_ch_read},
Bram Moolenaar6463ca22016-02-13 17:04:46 +01008086 {"ch_readraw", 1, 2, f_ch_readraw},
Bram Moolenaarf57969a2016-02-02 20:47:49 +01008087 {"ch_sendexpr", 2, 3, f_ch_sendexpr},
8088 {"ch_sendraw", 2, 3, f_ch_sendraw},
Bram Moolenaar40ea1da2016-02-19 22:33:35 +01008089 {"ch_setoptions", 2, 2, f_ch_setoptions},
Bram Moolenaar77073442016-02-13 23:23:53 +01008090 {"ch_status", 1, 1, f_ch_status},
Bram Moolenaarf57969a2016-02-02 20:47:49 +01008091#endif
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00008092 {"changenr", 0, 0, f_changenr},
Bram Moolenaard35d7842013-01-23 17:17:10 +01008093 {"char2nr", 1, 2, f_char2nr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008094 {"cindent", 1, 1, f_cindent},
Bram Moolenaar6ee10162007-07-26 20:58:42 +00008095 {"clearmatches", 0, 0, f_clearmatches},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008096 {"col", 1, 1, f_col},
Bram Moolenaar572cb562005-08-05 21:35:02 +00008097#if defined(FEAT_INS_EXPAND)
Bram Moolenaarade00832006-03-10 21:46:58 +00008098 {"complete", 2, 2, f_complete},
Bram Moolenaar572cb562005-08-05 21:35:02 +00008099 {"complete_add", 1, 1, f_complete_add},
8100 {"complete_check", 0, 0, f_complete_check},
8101#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008102 {"confirm", 1, 4, f_confirm},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008103 {"copy", 1, 1, f_copy},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008104#ifdef FEAT_FLOAT
8105 {"cos", 1, 1, f_cos},
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008106 {"cosh", 1, 1, f_cosh},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008107#endif
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008108 {"count", 2, 4, f_count},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008109 {"cscope_connection",0,3, f_cscope_connection},
Bram Moolenaara5525202006-03-02 22:52:09 +00008110 {"cursor", 1, 3, f_cursor},
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008111 {"deepcopy", 1, 2, f_deepcopy},
Bram Moolenaarda440d22016-01-16 21:27:23 +01008112 {"delete", 1, 2, f_delete},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008113 {"did_filetype", 0, 0, f_did_filetype},
Bram Moolenaar47136d72004-10-12 20:02:24 +00008114 {"diff_filler", 1, 1, f_diff_filler},
8115 {"diff_hlID", 2, 2, f_diff_hlID},
Bram Moolenaar2ab375e2016-02-10 22:23:06 +01008116 {"disable_char_avail_for_testing", 1, 1, f_disable_char_avail_for_testing},
Bram Moolenaare49b69a2005-01-08 16:11:57 +00008117 {"empty", 1, 1, f_empty},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008118 {"escape", 2, 2, f_escape},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008119 {"eval", 1, 1, f_eval},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008120 {"eventhandler", 0, 0, f_eventhandler},
8121 {"executable", 1, 1, f_executable},
Bram Moolenaarc7f02552014-04-01 21:00:59 +02008122 {"exepath", 1, 1, f_exepath},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008123 {"exists", 1, 1, f_exists},
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008124#ifdef FEAT_FLOAT
8125 {"exp", 1, 1, f_exp},
8126#endif
Bram Moolenaar146e9c32012-03-07 19:18:23 +01008127 {"expand", 1, 3, f_expand},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008128 {"extend", 2, 3, f_extend},
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00008129 {"feedkeys", 1, 2, f_feedkeys},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008130 {"file_readable", 1, 1, f_filereadable}, /* obsolete */
8131 {"filereadable", 1, 1, f_filereadable},
8132 {"filewritable", 1, 1, f_filewritable},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008133 {"filter", 2, 2, f_filter},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008134 {"finddir", 1, 3, f_finddir},
8135 {"findfile", 1, 3, f_findfile},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008136#ifdef FEAT_FLOAT
8137 {"float2nr", 1, 1, f_float2nr},
8138 {"floor", 1, 1, f_floor},
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008139 {"fmod", 2, 2, f_fmod},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008140#endif
Bram Moolenaaraebaf892008-05-28 14:49:58 +00008141 {"fnameescape", 1, 1, f_fnameescape},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008142 {"fnamemodify", 2, 2, f_fnamemodify},
8143 {"foldclosed", 1, 1, f_foldclosed},
8144 {"foldclosedend", 1, 1, f_foldclosedend},
8145 {"foldlevel", 1, 1, f_foldlevel},
8146 {"foldtext", 0, 0, f_foldtext},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008147 {"foldtextresult", 1, 1, f_foldtextresult},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008148 {"foreground", 0, 0, f_foreground},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008149 {"function", 1, 1, f_function},
Bram Moolenaar9d2c8c12007-09-25 16:00:00 +00008150 {"garbagecollect", 0, 1, f_garbagecollect},
Bram Moolenaar0d660222005-01-07 21:51:51 +00008151 {"get", 2, 3, f_get},
Bram Moolenaar80fc0432005-07-20 22:06:07 +00008152 {"getbufline", 2, 3, f_getbufline},
Bram Moolenaar63dbda12013-02-20 21:12:10 +01008153 {"getbufvar", 2, 3, f_getbufvar},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008154 {"getchar", 0, 1, f_getchar},
8155 {"getcharmod", 0, 0, f_getcharmod},
Bram Moolenaardbd24b52015-08-11 14:26:19 +02008156 {"getcharsearch", 0, 0, f_getcharsearch},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008157 {"getcmdline", 0, 0, f_getcmdline},
8158 {"getcmdpos", 0, 0, f_getcmdpos},
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +00008159 {"getcmdtype", 0, 0, f_getcmdtype},
Bram Moolenaar8c1329c2014-08-06 13:36:59 +02008160 {"getcmdwintype", 0, 0, f_getcmdwintype},
Bram Moolenaar6f6c0f82014-05-28 20:31:42 +02008161 {"getcurpos", 0, 0, f_getcurpos},
Bram Moolenaarc9703302016-01-17 21:49:33 +01008162 {"getcwd", 0, 2, f_getcwd},
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008163 {"getfontname", 0, 1, f_getfontname},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008164 {"getfperm", 1, 1, f_getfperm},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008165 {"getfsize", 1, 1, f_getfsize},
8166 {"getftime", 1, 1, f_getftime},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008167 {"getftype", 1, 1, f_getftype},
Bram Moolenaar0d660222005-01-07 21:51:51 +00008168 {"getline", 1, 2, f_getline},
Bram Moolenaar280f1262006-01-30 00:14:18 +00008169 {"getloclist", 1, 1, f_getqflist},
Bram Moolenaar2240aeb2007-07-27 19:33:14 +00008170 {"getmatches", 0, 0, f_getmatches},
Bram Moolenaar18081e32008-02-20 19:11:07 +00008171 {"getpid", 0, 0, f_getpid},
Bram Moolenaara5525202006-03-02 22:52:09 +00008172 {"getpos", 1, 1, f_getpos},
Bram Moolenaar2641f772005-03-25 21:58:17 +00008173 {"getqflist", 0, 0, f_getqflist},
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +02008174 {"getreg", 0, 3, f_getreg},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008175 {"getregtype", 0, 1, f_getregtype},
Bram Moolenaar63dbda12013-02-20 21:12:10 +01008176 {"gettabvar", 2, 3, f_gettabvar},
8177 {"gettabwinvar", 3, 4, f_gettabwinvar},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008178 {"getwinposx", 0, 0, f_getwinposx},
8179 {"getwinposy", 0, 0, f_getwinposy},
Bram Moolenaar63dbda12013-02-20 21:12:10 +01008180 {"getwinvar", 2, 3, f_getwinvar},
Bram Moolenaara245bc72015-03-05 19:35:25 +01008181 {"glob", 1, 4, f_glob},
Bram Moolenaar825e7ab2015-03-20 17:36:42 +01008182 {"glob2regpat", 1, 1, f_glob2regpat},
Bram Moolenaara245bc72015-03-05 19:35:25 +01008183 {"globpath", 2, 5, f_globpath},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008184 {"has", 1, 1, f_has},
Bram Moolenaare9a41262005-01-15 22:18:47 +00008185 {"has_key", 2, 2, f_has_key},
Bram Moolenaarc9703302016-01-17 21:49:33 +01008186 {"haslocaldir", 0, 2, f_haslocaldir},
Bram Moolenaar2c932302006-03-18 21:42:09 +00008187 {"hasmapto", 1, 3, f_hasmapto},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008188 {"highlightID", 1, 1, f_hlID}, /* obsolete */
8189 {"highlight_exists",1, 1, f_hlexists}, /* obsolete */
8190 {"histadd", 2, 2, f_histadd},
8191 {"histdel", 1, 2, f_histdel},
8192 {"histget", 1, 2, f_histget},
8193 {"histnr", 1, 1, f_histnr},
8194 {"hlID", 1, 1, f_hlID},
8195 {"hlexists", 1, 1, f_hlexists},
8196 {"hostname", 0, 0, f_hostname},
8197 {"iconv", 3, 3, f_iconv},
8198 {"indent", 1, 1, f_indent},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008199 {"index", 2, 4, f_index},
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +00008200 {"input", 1, 3, f_input},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008201 {"inputdialog", 1, 3, f_inputdialog},
Bram Moolenaar6efa2b32005-09-10 19:26:26 +00008202 {"inputlist", 1, 1, f_inputlist},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008203 {"inputrestore", 0, 0, f_inputrestore},
8204 {"inputsave", 0, 0, f_inputsave},
8205 {"inputsecret", 1, 2, f_inputsecret},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008206 {"insert", 2, 3, f_insert},
Bram Moolenaard6e256c2011-12-14 15:32:50 +01008207 {"invert", 1, 1, f_invert},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008208 {"isdirectory", 1, 1, f_isdirectory},
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008209 {"islocked", 1, 1, f_islocked},
Bram Moolenaarf1b6ac72016-02-23 21:26:43 +01008210#if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
8211 {"isnan", 1, 1, f_isnan},
8212#endif
Bram Moolenaar8c711452005-01-14 21:53:12 +00008213 {"items", 1, 1, f_items},
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01008214#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar6463ca22016-02-13 17:04:46 +01008215 {"job_getchannel", 1, 1, f_job_getchannel},
Bram Moolenaar8950a562016-03-12 15:22:55 +01008216 {"job_info", 1, 1, f_job_info},
Bram Moolenaar65edff82016-02-21 16:40:11 +01008217 {"job_setoptions", 2, 2, f_job_setoptions},
Bram Moolenaar835dc632016-02-07 14:27:38 +01008218 {"job_start", 1, 2, f_job_start},
8219 {"job_status", 1, 1, f_job_status},
Bram Moolenaar942d6b22016-02-07 19:57:16 +01008220 {"job_stop", 1, 2, f_job_stop},
Bram Moolenaar835dc632016-02-07 14:27:38 +01008221#endif
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008222 {"join", 1, 2, f_join},
Bram Moolenaar7823a3b2016-02-11 21:08:32 +01008223 {"js_decode", 1, 1, f_js_decode},
8224 {"js_encode", 1, 1, f_js_encode},
8225 {"json_decode", 1, 1, f_json_decode},
8226 {"json_encode", 1, 1, f_json_encode},
Bram Moolenaar8c711452005-01-14 21:53:12 +00008227 {"keys", 1, 1, f_keys},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008228 {"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008229 {"len", 1, 1, f_len},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008230 {"libcall", 3, 3, f_libcall},
8231 {"libcallnr", 3, 3, f_libcallnr},
8232 {"line", 1, 1, f_line},
8233 {"line2byte", 1, 1, f_line2byte},
8234 {"lispindent", 1, 1, f_lispindent},
8235 {"localtime", 0, 0, f_localtime},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008236#ifdef FEAT_FLOAT
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008237 {"log", 1, 1, f_log},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008238 {"log10", 1, 1, f_log10},
8239#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +02008240#ifdef FEAT_LUA
Bram Moolenaar9feaf622014-02-22 22:18:47 +01008241 {"luaeval", 1, 2, f_luaeval},
Bram Moolenaar1dced572012-04-05 16:54:08 +02008242#endif
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008243 {"map", 2, 2, f_map},
Bram Moolenaarbd743252010-10-20 21:23:33 +02008244 {"maparg", 1, 4, f_maparg},
Bram Moolenaar2c932302006-03-18 21:42:09 +00008245 {"mapcheck", 1, 3, f_mapcheck},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008246 {"match", 2, 4, f_match},
Bram Moolenaar6561d522015-07-21 15:48:27 +02008247 {"matchadd", 2, 5, f_matchadd},
8248 {"matchaddpos", 2, 5, f_matchaddpos},
Bram Moolenaar910f66f2006-04-05 20:41:53 +00008249 {"matcharg", 1, 1, f_matcharg},
Bram Moolenaar6ee10162007-07-26 20:58:42 +00008250 {"matchdelete", 1, 1, f_matchdelete},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008251 {"matchend", 2, 4, f_matchend},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008252 {"matchlist", 2, 4, f_matchlist},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008253 {"matchstr", 2, 4, f_matchstr},
Bram Moolenaar6cc16192005-01-08 21:49:45 +00008254 {"max", 1, 1, f_max},
8255 {"min", 1, 1, f_min},
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008256#ifdef vim_mkdir
8257 {"mkdir", 1, 3, f_mkdir},
8258#endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008259 {"mode", 0, 1, f_mode},
Bram Moolenaar7e506b62010-01-19 15:55:06 +01008260#ifdef FEAT_MZSCHEME
8261 {"mzeval", 1, 1, f_mzeval},
8262#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008263 {"nextnonblank", 1, 1, f_nextnonblank},
Bram Moolenaard35d7842013-01-23 17:17:10 +01008264 {"nr2char", 1, 2, f_nr2char},
Bram Moolenaard6e256c2011-12-14 15:32:50 +01008265 {"or", 2, 2, f_or},
Bram Moolenaar910f66f2006-04-05 20:41:53 +00008266 {"pathshorten", 1, 1, f_pathshorten},
Bram Moolenaare9b892e2016-01-17 21:15:58 +01008267#ifdef FEAT_PERL
8268 {"perleval", 1, 1, f_perleval},
8269#endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008270#ifdef FEAT_FLOAT
8271 {"pow", 2, 2, f_pow},
8272#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008273 {"prevnonblank", 1, 1, f_prevnonblank},
Bram Moolenaar4be06f92005-07-29 22:36:03 +00008274 {"printf", 2, 19, f_printf},
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00008275 {"pumvisible", 0, 0, f_pumvisible},
Bram Moolenaardb913952012-06-29 12:54:53 +02008276#ifdef FEAT_PYTHON3
8277 {"py3eval", 1, 1, f_py3eval},
8278#endif
8279#ifdef FEAT_PYTHON
8280 {"pyeval", 1, 1, f_pyeval},
8281#endif
Bram Moolenaar8c711452005-01-14 21:53:12 +00008282 {"range", 1, 3, f_range},
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008283 {"readfile", 1, 3, f_readfile},
Bram Moolenaare580b0c2006-03-21 21:33:03 +00008284 {"reltime", 0, 2, f_reltime},
Bram Moolenaar10b369f2016-02-29 23:12:49 +01008285#ifdef FEAT_FLOAT
Bram Moolenaar79c2c882016-02-07 21:19:28 +01008286 {"reltimefloat", 1, 1, f_reltimefloat},
Bram Moolenaar10b369f2016-02-29 23:12:49 +01008287#endif
Bram Moolenaare580b0c2006-03-21 21:33:03 +00008288 {"reltimestr", 1, 1, f_reltimestr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008289 {"remote_expr", 2, 3, f_remote_expr},
8290 {"remote_foreground", 1, 1, f_remote_foreground},
8291 {"remote_peek", 1, 2, f_remote_peek},
8292 {"remote_read", 1, 1, f_remote_read},
8293 {"remote_send", 2, 3, f_remote_send},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008294 {"remove", 2, 3, f_remove},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008295 {"rename", 2, 2, f_rename},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00008296 {"repeat", 2, 2, f_repeat},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008297 {"resolve", 1, 1, f_resolve},
Bram Moolenaar0d660222005-01-07 21:51:51 +00008298 {"reverse", 1, 1, f_reverse},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008299#ifdef FEAT_FLOAT
8300 {"round", 1, 1, f_round},
8301#endif
Bram Moolenaar9a773482013-06-11 18:40:13 +02008302 {"screenattr", 2, 2, f_screenattr},
8303 {"screenchar", 2, 2, f_screenchar},
Bram Moolenaar9750bb12012-12-05 16:10:42 +01008304 {"screencol", 0, 0, f_screencol},
8305 {"screenrow", 0, 0, f_screenrow},
Bram Moolenaar76929292008-01-06 19:07:36 +00008306 {"search", 1, 4, f_search},
Bram Moolenaare6facf92005-09-13 21:22:27 +00008307 {"searchdecl", 1, 3, f_searchdecl},
Bram Moolenaar76929292008-01-06 19:07:36 +00008308 {"searchpair", 3, 7, f_searchpair},
8309 {"searchpairpos", 3, 7, f_searchpairpos},
8310 {"searchpos", 1, 4, f_searchpos},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008311 {"server2client", 2, 2, f_server2client},
8312 {"serverlist", 0, 0, f_serverlist},
8313 {"setbufvar", 3, 3, f_setbufvar},
Bram Moolenaardbd24b52015-08-11 14:26:19 +02008314 {"setcharsearch", 1, 1, f_setcharsearch},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008315 {"setcmdpos", 1, 1, f_setcmdpos},
Bram Moolenaar80492532016-03-08 17:08:53 +01008316 {"setfperm", 2, 2, f_setfperm},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008317 {"setline", 2, 2, f_setline},
Bram Moolenaar17c7c012006-01-26 22:25:15 +00008318 {"setloclist", 2, 3, f_setloclist},
Bram Moolenaar6ee10162007-07-26 20:58:42 +00008319 {"setmatches", 1, 1, f_setmatches},
Bram Moolenaar0e34f622006-03-03 23:00:03 +00008320 {"setpos", 2, 2, f_setpos},
Bram Moolenaarf4630b62005-05-20 21:31:17 +00008321 {"setqflist", 1, 2, f_setqflist},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008322 {"setreg", 2, 3, f_setreg},
Bram Moolenaar06b5d512010-05-22 15:37:44 +02008323 {"settabvar", 3, 3, f_settabvar},
Bram Moolenaar99ebf042006-04-15 20:28:54 +00008324 {"settabwinvar", 4, 4, f_settabwinvar},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008325 {"setwinvar", 3, 3, f_setwinvar},
Bram Moolenaaraf9aeb92013-02-13 17:35:04 +01008326#ifdef FEAT_CRYPT
8327 {"sha256", 1, 1, f_sha256},
8328#endif
Bram Moolenaar05bb9532008-07-04 09:44:11 +00008329 {"shellescape", 1, 2, f_shellescape},
Bram Moolenaar2d17fa32012-10-21 00:45:18 +02008330 {"shiftwidth", 0, 0, f_shiftwidth},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008331 {"simplify", 1, 1, f_simplify},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008332#ifdef FEAT_FLOAT
8333 {"sin", 1, 1, f_sin},
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008334 {"sinh", 1, 1, f_sinh},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008335#endif
Bram Moolenaar5f894962011-06-19 02:55:37 +02008336 {"sort", 1, 3, f_sort},
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00008337 {"soundfold", 1, 1, f_soundfold},
Bram Moolenaar4463f292005-09-25 22:20:24 +00008338 {"spellbadword", 0, 1, f_spellbadword},
Bram Moolenaar69e0ff92005-09-30 21:23:56 +00008339 {"spellsuggest", 1, 3, f_spellsuggest},
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00008340 {"split", 1, 3, f_split},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008341#ifdef FEAT_FLOAT
8342 {"sqrt", 1, 1, f_sqrt},
8343 {"str2float", 1, 1, f_str2float},
8344#endif
Bram Moolenaar2c932302006-03-18 21:42:09 +00008345 {"str2nr", 1, 2, f_str2nr},
Bram Moolenaar641e48c2015-06-25 16:09:26 +02008346 {"strchars", 1, 2, f_strchars},
Bram Moolenaardc536092010-07-18 15:45:49 +02008347 {"strdisplaywidth", 1, 2, f_strdisplaywidth},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008348#ifdef HAVE_STRFTIME
8349 {"strftime", 1, 2, f_strftime},
8350#endif
Bram Moolenaar33570922005-01-25 22:26:29 +00008351 {"stridx", 2, 3, f_stridx},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008352 {"string", 1, 1, f_string},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008353 {"strlen", 1, 1, f_strlen},
8354 {"strpart", 2, 3, f_strpart},
Bram Moolenaar532c7802005-01-27 14:44:31 +00008355 {"strridx", 2, 3, f_strridx},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008356 {"strtrans", 1, 1, f_strtrans},
Bram Moolenaar72597a52010-07-18 15:31:08 +02008357 {"strwidth", 1, 1, f_strwidth},
Bram Moolenaar41571762014-04-02 19:00:58 +02008358 {"submatch", 1, 2, f_submatch},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008359 {"substitute", 4, 4, f_substitute},
8360 {"synID", 3, 3, f_synID},
8361 {"synIDattr", 2, 3, f_synIDattr},
8362 {"synIDtrans", 1, 1, f_synIDtrans},
Bram Moolenaar7510fe72010-07-25 12:46:44 +02008363 {"synconcealed", 2, 2, f_synconcealed},
Bram Moolenaar9d188ab2008-01-10 21:24:39 +00008364 {"synstack", 2, 2, f_synstack},
Bram Moolenaarc0197e22004-09-13 20:26:32 +00008365 {"system", 1, 2, f_system},
Bram Moolenaar39c29ed2014-04-05 19:44:40 +02008366 {"systemlist", 1, 2, f_systemlist},
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00008367 {"tabpagebuflist", 0, 1, f_tabpagebuflist},
Bram Moolenaar7e8fd632006-02-18 22:14:51 +00008368 {"tabpagenr", 0, 1, f_tabpagenr},
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00008369 {"tabpagewinnr", 1, 2, f_tabpagewinnr},
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00008370 {"tagfiles", 0, 0, f_tagfiles},
Bram Moolenaar19a09a12005-03-04 23:39:37 +00008371 {"taglist", 1, 1, f_taglist},
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008372#ifdef FEAT_FLOAT
8373 {"tan", 1, 1, f_tan},
8374 {"tanh", 1, 1, f_tanh},
8375#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008376 {"tempname", 0, 0, f_tempname},
Bram Moolenaard52d9742005-08-21 22:20:28 +00008377 {"test", 1, 1, f_test},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008378 {"tolower", 1, 1, f_tolower},
8379 {"toupper", 1, 1, f_toupper},
Bram Moolenaar8299df92004-07-10 09:47:34 +00008380 {"tr", 3, 3, f_tr},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008381#ifdef FEAT_FLOAT
8382 {"trunc", 1, 1, f_trunc},
8383#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008384 {"type", 1, 1, f_type},
Bram Moolenaara17d4c12010-05-30 18:30:36 +02008385 {"undofile", 1, 1, f_undofile},
Bram Moolenaara800b422010-06-27 01:15:55 +02008386 {"undotree", 0, 0, f_undotree},
Bram Moolenaar327aa022014-03-25 18:24:23 +01008387 {"uniq", 1, 3, f_uniq},
Bram Moolenaar8c711452005-01-14 21:53:12 +00008388 {"values", 1, 1, f_values},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008389 {"virtcol", 1, 1, f_virtcol},
8390 {"visualmode", 0, 1, f_visualmode},
Bram Moolenaar8738fc12013-02-20 17:59:11 +01008391 {"wildmenumode", 0, 0, f_wildmenumode},
Bram Moolenaar9cdf86b2016-03-13 19:04:51 +01008392 {"win_findbuf", 1, 1, f_win_findbuf},
Bram Moolenaar86edef62016-03-13 18:07:30 +01008393 {"win_getid", 0, 2, f_win_getid},
8394 {"win_gotoid", 1, 1, f_win_gotoid},
8395 {"win_id2tabwin", 1, 1, f_win_id2tabwin},
8396 {"win_id2win", 1, 1, f_win_id2win},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008397 {"winbufnr", 1, 1, f_winbufnr},
8398 {"wincol", 0, 0, f_wincol},
8399 {"winheight", 1, 1, f_winheight},
8400 {"winline", 0, 0, f_winline},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008401 {"winnr", 0, 1, f_winnr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008402 {"winrestcmd", 0, 0, f_winrestcmd},
Bram Moolenaar768b8c42006-03-04 21:58:33 +00008403 {"winrestview", 1, 1, f_winrestview},
8404 {"winsaveview", 0, 0, f_winsaveview},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008405 {"winwidth", 1, 1, f_winwidth},
Bram Moolenaared767a22016-01-03 22:49:16 +01008406 {"wordcount", 0, 0, f_wordcount},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008407 {"writefile", 2, 3, f_writefile},
Bram Moolenaard6e256c2011-12-14 15:32:50 +01008408 {"xor", 2, 2, f_xor},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008409};
8410
8411#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
8412
8413/*
8414 * Function given to ExpandGeneric() to obtain the list of internal
8415 * or user defined function names.
8416 */
8417 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01008418get_function_name(expand_T *xp, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008419{
8420 static int intidx = -1;
8421 char_u *name;
8422
8423 if (idx == 0)
8424 intidx = -1;
8425 if (intidx < 0)
8426 {
8427 name = get_user_func_name(xp, idx);
8428 if (name != NULL)
8429 return name;
8430 }
8431 if (++intidx < (int)(sizeof(functions) / sizeof(struct fst)))
8432 {
8433 STRCPY(IObuff, functions[intidx].f_name);
8434 STRCAT(IObuff, "(");
8435 if (functions[intidx].f_max_argc == 0)
8436 STRCAT(IObuff, ")");
8437 return IObuff;
8438 }
8439
8440 return NULL;
8441}
8442
8443/*
8444 * Function given to ExpandGeneric() to obtain the list of internal or
8445 * user defined variable or function names.
8446 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008447 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01008448get_expr_name(expand_T *xp, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008449{
8450 static int intidx = -1;
8451 char_u *name;
8452
8453 if (idx == 0)
8454 intidx = -1;
8455 if (intidx < 0)
8456 {
8457 name = get_function_name(xp, idx);
8458 if (name != NULL)
8459 return name;
8460 }
8461 return get_user_var_name(xp, ++intidx);
8462}
8463
8464#endif /* FEAT_CMDL_COMPL */
8465
Bram Moolenaar2c704a72010-06-03 21:17:25 +02008466#if defined(EBCDIC) || defined(PROTO)
8467/*
8468 * Compare struct fst by function name.
8469 */
8470 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01008471compare_func_name(const void *s1, const void *s2)
Bram Moolenaar2c704a72010-06-03 21:17:25 +02008472{
8473 struct fst *p1 = (struct fst *)s1;
8474 struct fst *p2 = (struct fst *)s2;
8475
8476 return STRCMP(p1->f_name, p2->f_name);
8477}
8478
8479/*
8480 * Sort the function table by function name.
8481 * The sorting of the table above is ASCII dependant.
8482 * On machines using EBCDIC we have to sort it.
8483 */
8484 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008485sortFunctions(void)
Bram Moolenaar2c704a72010-06-03 21:17:25 +02008486{
8487 int funcCnt = (int)(sizeof(functions) / sizeof(struct fst)) - 1;
8488
8489 qsort(functions, (size_t)funcCnt, sizeof(struct fst), compare_func_name);
8490}
8491#endif
8492
8493
Bram Moolenaar071d4272004-06-13 20:20:40 +00008494/*
8495 * Find internal function in table above.
8496 * Return index, or -1 if not found
8497 */
8498 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01008499find_internal_func(
8500 char_u *name) /* name of the function */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008501{
8502 int first = 0;
8503 int last = (int)(sizeof(functions) / sizeof(struct fst)) - 1;
8504 int cmp;
8505 int x;
8506
8507 /*
8508 * Find the function name in the table. Binary search.
8509 */
8510 while (first <= last)
8511 {
8512 x = first + ((unsigned)(last - first) >> 1);
8513 cmp = STRCMP(name, functions[x].f_name);
8514 if (cmp < 0)
8515 last = x - 1;
8516 else if (cmp > 0)
8517 first = x + 1;
8518 else
8519 return x;
8520 }
8521 return -1;
8522}
8523
8524/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008525 * Check if "name" is a variable of type VAR_FUNC. If so, return the function
8526 * name it contains, otherwise return "name".
8527 */
8528 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01008529deref_func_name(char_u *name, int *lenp, int no_autoload)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008530{
Bram Moolenaar33570922005-01-25 22:26:29 +00008531 dictitem_T *v;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008532 int cc;
8533
8534 cc = name[*lenp];
8535 name[*lenp] = NUL;
Bram Moolenaar8822a9c2014-01-14 19:44:34 +01008536 v = find_var(name, NULL, no_autoload);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008537 name[*lenp] = cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00008538 if (v != NULL && v->di_tv.v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008539 {
Bram Moolenaar33570922005-01-25 22:26:29 +00008540 if (v->di_tv.vval.v_string == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008541 {
8542 *lenp = 0;
8543 return (char_u *)""; /* just in case */
8544 }
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008545 *lenp = (int)STRLEN(v->di_tv.vval.v_string);
Bram Moolenaar33570922005-01-25 22:26:29 +00008546 return v->di_tv.vval.v_string;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008547 }
8548
8549 return name;
8550}
8551
8552/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008553 * Allocate a variable for the result of a function.
8554 * Return OK or FAIL.
8555 */
8556 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01008557get_func_tv(
8558 char_u *name, /* name of the function */
8559 int len, /* length of "name" */
8560 typval_T *rettv,
8561 char_u **arg, /* argument, pointing to the '(' */
8562 linenr_T firstline, /* first line of range */
8563 linenr_T lastline, /* last line of range */
8564 int *doesrange, /* return: function handled range */
8565 int evaluate,
8566 dict_T *selfdict) /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008567{
8568 char_u *argp;
8569 int ret = OK;
Bram Moolenaareb3593b2006-04-22 22:33:57 +00008570 typval_T argvars[MAX_FUNC_ARGS + 1]; /* vars for arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008571 int argcount = 0; /* number of arguments found */
8572
8573 /*
8574 * Get the arguments.
8575 */
8576 argp = *arg;
8577 while (argcount < MAX_FUNC_ARGS)
8578 {
8579 argp = skipwhite(argp + 1); /* skip the '(' or ',' */
8580 if (*argp == ')' || *argp == ',' || *argp == NUL)
8581 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008582 if (eval1(&argp, &argvars[argcount], evaluate) == FAIL)
8583 {
8584 ret = FAIL;
8585 break;
8586 }
8587 ++argcount;
8588 if (*argp != ',')
8589 break;
8590 }
8591 if (*argp == ')')
8592 ++argp;
8593 else
8594 ret = FAIL;
8595
8596 if (ret == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008597 ret = call_func(name, len, rettv, argcount, argvars,
Bram Moolenaare9a41262005-01-15 22:18:47 +00008598 firstline, lastline, doesrange, evaluate, selfdict);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008599 else if (!aborting())
Bram Moolenaar33570922005-01-25 22:26:29 +00008600 {
8601 if (argcount == MAX_FUNC_ARGS)
Bram Moolenaar7b76b0a2009-01-28 18:09:38 +00008602 emsg_funcname(N_("E740: Too many arguments for function %s"), name);
Bram Moolenaar33570922005-01-25 22:26:29 +00008603 else
Bram Moolenaar7b76b0a2009-01-28 18:09:38 +00008604 emsg_funcname(N_("E116: Invalid arguments for function %s"), name);
Bram Moolenaar33570922005-01-25 22:26:29 +00008605 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008606
8607 while (--argcount >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008608 clear_tv(&argvars[argcount]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008609
8610 *arg = skipwhite(argp);
8611 return ret;
8612}
8613
8614
8615/*
8616 * Call a function with its resolved parameters
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02008617 * Return FAIL when the function can't be called, OK otherwise.
Bram Moolenaar280f1262006-01-30 00:14:18 +00008618 * Also returns OK when an error was encountered while executing the function.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008619 */
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01008620 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01008621call_func(
8622 char_u *funcname, /* name of the function */
8623 int len, /* length of "name" */
8624 typval_T *rettv, /* return value goes here */
8625 int argcount, /* number of "argvars" */
8626 typval_T *argvars, /* vars for arguments, must have "argcount"
Bram Moolenaareb3593b2006-04-22 22:33:57 +00008627 PLUS ONE elements! */
Bram Moolenaar7454a062016-01-30 15:14:10 +01008628 linenr_T firstline, /* first line of range */
8629 linenr_T lastline, /* last line of range */
8630 int *doesrange, /* return: function handled range */
8631 int evaluate,
8632 dict_T *selfdict) /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008633{
8634 int ret = FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008635#define ERROR_UNKNOWN 0
8636#define ERROR_TOOMANY 1
8637#define ERROR_TOOFEW 2
8638#define ERROR_SCRIPT 3
Bram Moolenaare9a41262005-01-15 22:18:47 +00008639#define ERROR_DICT 4
8640#define ERROR_NONE 5
8641#define ERROR_OTHER 6
Bram Moolenaar071d4272004-06-13 20:20:40 +00008642 int error = ERROR_NONE;
8643 int i;
8644 int llen;
8645 ufunc_T *fp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008646#define FLEN_FIXED 40
8647 char_u fname_buf[FLEN_FIXED + 1];
8648 char_u *fname;
Bram Moolenaarbc42c1e2010-05-28 22:06:46 +02008649 char_u *name;
8650
8651 /* Make a copy of the name, if it comes from a funcref variable it could
8652 * be changed or deleted in the called function. */
Bram Moolenaarf506c5b2010-06-22 06:28:58 +02008653 name = vim_strnsave(funcname, len);
Bram Moolenaarbc42c1e2010-05-28 22:06:46 +02008654 if (name == NULL)
8655 return ret;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008656
8657 /*
8658 * In a script change <SID>name() and s:name() to K_SNR 123_name().
8659 * Change <SNR>123_name() to K_SNR 123_name().
8660 * Use fname_buf[] when it fits, otherwise allocate memory (slow).
8661 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008662 llen = eval_fname_script(name);
8663 if (llen > 0)
8664 {
8665 fname_buf[0] = K_SPECIAL;
8666 fname_buf[1] = KS_EXTRA;
8667 fname_buf[2] = (int)KE_SNR;
8668 i = 3;
8669 if (eval_fname_sid(name)) /* "<SID>" or "s:" */
8670 {
8671 if (current_SID <= 0)
8672 error = ERROR_SCRIPT;
8673 else
8674 {
8675 sprintf((char *)fname_buf + 3, "%ld_", (long)current_SID);
8676 i = (int)STRLEN(fname_buf);
8677 }
8678 }
8679 if (i + STRLEN(name + llen) < FLEN_FIXED)
8680 {
8681 STRCPY(fname_buf + i, name + llen);
8682 fname = fname_buf;
8683 }
8684 else
8685 {
8686 fname = alloc((unsigned)(i + STRLEN(name + llen) + 1));
8687 if (fname == NULL)
8688 error = ERROR_OTHER;
8689 else
8690 {
8691 mch_memmove(fname, fname_buf, (size_t)i);
8692 STRCPY(fname + i, name + llen);
8693 }
8694 }
8695 }
8696 else
8697 fname = name;
8698
8699 *doesrange = FALSE;
8700
8701
8702 /* execute the function if no errors detected and executing */
8703 if (evaluate && error == ERROR_NONE)
8704 {
Bram Moolenaara4f317d2014-04-24 17:12:33 +02008705 char_u *rfname = fname;
8706
8707 /* Ignore "g:" before a function name. */
8708 if (fname[0] == 'g' && fname[1] == ':')
8709 rfname = fname + 2;
8710
Bram Moolenaar798b30b2009-04-22 10:56:16 +00008711 rettv->v_type = VAR_NUMBER; /* default rettv is number zero */
8712 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008713 error = ERROR_UNKNOWN;
8714
Bram Moolenaara4f317d2014-04-24 17:12:33 +02008715 if (!builtin_function(rfname, -1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008716 {
8717 /*
8718 * User defined function.
8719 */
Bram Moolenaara4f317d2014-04-24 17:12:33 +02008720 fp = find_func(rfname);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008721
Bram Moolenaar071d4272004-06-13 20:20:40 +00008722#ifdef FEAT_AUTOCMD
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008723 /* Trigger FuncUndefined event, may load the function. */
8724 if (fp == NULL
8725 && apply_autocmds(EVENT_FUNCUNDEFINED,
Bram Moolenaara4f317d2014-04-24 17:12:33 +02008726 rfname, rfname, TRUE, NULL)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008727 && !aborting())
Bram Moolenaar071d4272004-06-13 20:20:40 +00008728 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008729 /* executed an autocommand, search for the function again */
Bram Moolenaara4f317d2014-04-24 17:12:33 +02008730 fp = find_func(rfname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008731 }
8732#endif
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008733 /* Try loading a package. */
Bram Moolenaara4f317d2014-04-24 17:12:33 +02008734 if (fp == NULL && script_autoload(rfname, TRUE) && !aborting())
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008735 {
8736 /* loaded a package, search for the function again */
Bram Moolenaara4f317d2014-04-24 17:12:33 +02008737 fp = find_func(rfname);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008738 }
8739
Bram Moolenaar071d4272004-06-13 20:20:40 +00008740 if (fp != NULL)
8741 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008742 if (fp->uf_flags & FC_RANGE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008743 *doesrange = TRUE;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008744 if (argcount < fp->uf_args.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008745 error = ERROR_TOOFEW;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008746 else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008747 error = ERROR_TOOMANY;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008748 else if ((fp->uf_flags & FC_DICT) && selfdict == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008749 error = ERROR_DICT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008750 else
8751 {
Bram Moolenaarbe20f9f2015-02-17 12:44:09 +01008752 int did_save_redo = FALSE;
8753
Bram Moolenaar071d4272004-06-13 20:20:40 +00008754 /*
8755 * Call the user function.
8756 * Save and restore search patterns, script variables and
8757 * redo buffer.
8758 */
8759 save_search_patterns();
Bram Moolenaar20ad69c2015-12-03 13:52:52 +01008760#ifdef FEAT_INS_EXPAND
Bram Moolenaarbe20f9f2015-02-17 12:44:09 +01008761 if (!ins_compl_active())
Bram Moolenaar20ad69c2015-12-03 13:52:52 +01008762#endif
Bram Moolenaarbe20f9f2015-02-17 12:44:09 +01008763 {
8764 saveRedobuff();
8765 did_save_redo = TRUE;
8766 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008767 ++fp->uf_calls;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008768 call_user_func(fp, argcount, argvars, rettv,
Bram Moolenaare9a41262005-01-15 22:18:47 +00008769 firstline, lastline,
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008770 (fp->uf_flags & FC_DICT) ? selfdict : NULL);
8771 if (--fp->uf_calls <= 0 && isdigit(*fp->uf_name)
8772 && fp->uf_refcount <= 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00008773 /* Function was unreferenced while being used, free it
8774 * now. */
8775 func_free(fp);
Bram Moolenaarbe20f9f2015-02-17 12:44:09 +01008776 if (did_save_redo)
8777 restoreRedobuff();
Bram Moolenaar071d4272004-06-13 20:20:40 +00008778 restore_search_patterns();
8779 error = ERROR_NONE;
8780 }
8781 }
8782 }
8783 else
8784 {
8785 /*
8786 * Find the function name in the table, call its implementation.
8787 */
8788 i = find_internal_func(fname);
8789 if (i >= 0)
8790 {
8791 if (argcount < functions[i].f_min_argc)
8792 error = ERROR_TOOFEW;
8793 else if (argcount > functions[i].f_max_argc)
8794 error = ERROR_TOOMANY;
8795 else
8796 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008797 argvars[argcount].v_type = VAR_UNKNOWN;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008798 functions[i].f_func(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008799 error = ERROR_NONE;
8800 }
8801 }
8802 }
8803 /*
8804 * The function call (or "FuncUndefined" autocommand sequence) might
8805 * have been aborted by an error, an interrupt, or an explicitly thrown
8806 * exception that has not been caught so far. This situation can be
8807 * tested for by calling aborting(). For an error in an internal
8808 * function or for the "E132" error in call_user_func(), however, the
8809 * throw point at which the "force_abort" flag (temporarily reset by
8810 * emsg()) is normally updated has not been reached yet. We need to
8811 * update that flag first to make aborting() reliable.
8812 */
8813 update_force_abort();
8814 }
8815 if (error == ERROR_NONE)
8816 ret = OK;
8817
8818 /*
8819 * Report an error unless the argument evaluation or function call has been
8820 * cancelled due to an aborting error, an interrupt, or an exception.
8821 */
Bram Moolenaar8c711452005-01-14 21:53:12 +00008822 if (!aborting())
8823 {
8824 switch (error)
8825 {
8826 case ERROR_UNKNOWN:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008827 emsg_funcname(N_("E117: Unknown function: %s"), name);
Bram Moolenaar8c711452005-01-14 21:53:12 +00008828 break;
8829 case ERROR_TOOMANY:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008830 emsg_funcname(e_toomanyarg, name);
Bram Moolenaar8c711452005-01-14 21:53:12 +00008831 break;
8832 case ERROR_TOOFEW:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008833 emsg_funcname(N_("E119: Not enough arguments for function: %s"),
Bram Moolenaar8c711452005-01-14 21:53:12 +00008834 name);
8835 break;
8836 case ERROR_SCRIPT:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008837 emsg_funcname(N_("E120: Using <SID> not in a script context: %s"),
Bram Moolenaar8c711452005-01-14 21:53:12 +00008838 name);
8839 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008840 case ERROR_DICT:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008841 emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"),
Bram Moolenaare9a41262005-01-15 22:18:47 +00008842 name);
8843 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00008844 }
8845 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008846
Bram Moolenaar071d4272004-06-13 20:20:40 +00008847 if (fname != name && fname != fname_buf)
8848 vim_free(fname);
Bram Moolenaarbc42c1e2010-05-28 22:06:46 +02008849 vim_free(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008850
8851 return ret;
8852}
8853
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008854/*
8855 * Give an error message with a function name. Handle <SNR> things.
Bram Moolenaar7b76b0a2009-01-28 18:09:38 +00008856 * "ermsg" is to be passed without translation, use N_() instead of _().
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008857 */
8858 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008859emsg_funcname(char *ermsg, char_u *name)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008860{
8861 char_u *p;
8862
8863 if (*name == K_SPECIAL)
8864 p = concat_str((char_u *)"<SNR>", name + 3);
8865 else
8866 p = name;
Bram Moolenaar89d40322006-08-29 15:30:07 +00008867 EMSG2(_(ermsg), p);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008868 if (p != name)
8869 vim_free(p);
8870}
8871
Bram Moolenaar05bb9532008-07-04 09:44:11 +00008872/*
8873 * Return TRUE for a non-zero Number and a non-empty String.
8874 */
8875 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01008876non_zero_arg(typval_T *argvars)
Bram Moolenaar05bb9532008-07-04 09:44:11 +00008877{
8878 return ((argvars[0].v_type == VAR_NUMBER
8879 && argvars[0].vval.v_number != 0)
8880 || (argvars[0].v_type == VAR_STRING
8881 && argvars[0].vval.v_string != NULL
8882 && *argvars[0].vval.v_string != NUL));
8883}
8884
Bram Moolenaar071d4272004-06-13 20:20:40 +00008885/*********************************************
8886 * Implementation of the built-in functions
8887 */
8888
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008889#ifdef FEAT_FLOAT
Bram Moolenaar48e697e2016-01-23 22:17:30 +01008890static int get_float_arg(typval_T *argvars, float_T *f);
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008891
8892/*
8893 * Get the float value of "argvars[0]" into "f".
8894 * Returns FAIL when the argument is not a Number or Float.
8895 */
8896 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01008897get_float_arg(typval_T *argvars, float_T *f)
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008898{
8899 if (argvars[0].v_type == VAR_FLOAT)
8900 {
8901 *f = argvars[0].vval.v_float;
8902 return OK;
8903 }
8904 if (argvars[0].v_type == VAR_NUMBER)
8905 {
8906 *f = (float_T)argvars[0].vval.v_number;
8907 return OK;
8908 }
8909 EMSG(_("E808: Number or Float required"));
8910 return FAIL;
8911}
8912
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008913/*
8914 * "abs(expr)" function
8915 */
8916 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008917f_abs(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008918{
8919 if (argvars[0].v_type == VAR_FLOAT)
8920 {
8921 rettv->v_type = VAR_FLOAT;
8922 rettv->vval.v_float = fabs(argvars[0].vval.v_float);
8923 }
8924 else
8925 {
8926 varnumber_T n;
8927 int error = FALSE;
8928
8929 n = get_tv_number_chk(&argvars[0], &error);
8930 if (error)
8931 rettv->vval.v_number = -1;
8932 else if (n > 0)
8933 rettv->vval.v_number = n;
8934 else
8935 rettv->vval.v_number = -n;
8936 }
8937}
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008938
8939/*
8940 * "acos()" function
8941 */
8942 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008943f_acos(typval_T *argvars, typval_T *rettv)
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008944{
Bram Moolenaara1e24b92016-02-18 20:18:09 +01008945 float_T f = 0.0;
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008946
8947 rettv->v_type = VAR_FLOAT;
8948 if (get_float_arg(argvars, &f) == OK)
8949 rettv->vval.v_float = acos(f);
8950 else
8951 rettv->vval.v_float = 0.0;
8952}
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008953#endif
8954
Bram Moolenaar071d4272004-06-13 20:20:40 +00008955/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00008956 * "add(list, item)" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00008957 */
8958 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008959f_add(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008960{
Bram Moolenaar33570922005-01-25 22:26:29 +00008961 list_T *l;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008962
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008963 rettv->vval.v_number = 1; /* Default: Failed */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008964 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008965 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008966 if ((l = argvars[0].vval.v_list) != NULL
Bram Moolenaar77354e72015-04-21 16:49:05 +02008967 && !tv_check_lock(l->lv_lock,
8968 (char_u *)N_("add() argument"), TRUE)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008969 && list_append_tv(l, &argvars[1]) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008970 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008971 }
8972 else
Bram Moolenaar0d660222005-01-07 21:51:51 +00008973 EMSG(_(e_listreq));
8974}
8975
8976/*
Bram Moolenaar75bdf6a2016-01-07 21:25:08 +01008977 * "alloc_fail(id, countdown, repeat)" function
8978 */
8979 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01008980f_alloc_fail(typval_T *argvars, typval_T *rettv UNUSED)
Bram Moolenaar75bdf6a2016-01-07 21:25:08 +01008981{
8982 if (argvars[0].v_type != VAR_NUMBER
8983 || argvars[0].vval.v_number <= 0
8984 || argvars[1].v_type != VAR_NUMBER
8985 || argvars[1].vval.v_number < 0
8986 || argvars[2].v_type != VAR_NUMBER)
8987 EMSG(_(e_invarg));
8988 else
8989 {
8990 alloc_fail_id = argvars[0].vval.v_number;
Bram Moolenaara260b872016-01-15 20:48:22 +01008991 if (alloc_fail_id >= aid_last)
8992 EMSG(_(e_invarg));
Bram Moolenaar75bdf6a2016-01-07 21:25:08 +01008993 alloc_fail_countdown = argvars[1].vval.v_number;
8994 alloc_fail_repeat = argvars[2].vval.v_number;
Bram Moolenaara260b872016-01-15 20:48:22 +01008995 did_outofmem_msg = FALSE;
Bram Moolenaar75bdf6a2016-01-07 21:25:08 +01008996 }
8997}
8998
8999/*
Bram Moolenaard6e256c2011-12-14 15:32:50 +01009000 * "and(expr, expr)" function
9001 */
9002 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009003f_and(typval_T *argvars, typval_T *rettv)
Bram Moolenaard6e256c2011-12-14 15:32:50 +01009004{
9005 rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL)
9006 & get_tv_number_chk(&argvars[1], NULL);
9007}
9008
9009/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00009010 * "append(lnum, string/list)" function
9011 */
9012 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009013f_append(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +00009014{
9015 long lnum;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009016 char_u *line;
Bram Moolenaar33570922005-01-25 22:26:29 +00009017 list_T *l = NULL;
9018 listitem_T *li = NULL;
9019 typval_T *tv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009020 long added = 0;
9021
Bram Moolenaar3c1e9c22013-07-04 20:25:41 +02009022 /* When coming here from Insert mode, sync undo, so that this can be
9023 * undone separately from what was previously inserted. */
9024 if (u_sync_once == 2)
9025 {
9026 u_sync_once = 1; /* notify that u_sync() was called */
9027 u_sync(TRUE);
9028 }
9029
Bram Moolenaar0d660222005-01-07 21:51:51 +00009030 lnum = get_tv_lnum(argvars);
9031 if (lnum >= 0
9032 && lnum <= curbuf->b_ml.ml_line_count
9033 && u_save(lnum, lnum + 1) == OK)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009034 {
Bram Moolenaar0d660222005-01-07 21:51:51 +00009035 if (argvars[1].v_type == VAR_LIST)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009036 {
Bram Moolenaar0d660222005-01-07 21:51:51 +00009037 l = argvars[1].vval.v_list;
9038 if (l == NULL)
9039 return;
9040 li = l->lv_first;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009041 }
Bram Moolenaar0d660222005-01-07 21:51:51 +00009042 for (;;)
9043 {
9044 if (l == NULL)
9045 tv = &argvars[1]; /* append a string */
9046 else if (li == NULL)
9047 break; /* end of list */
9048 else
9049 tv = &li->li_tv; /* append item from list */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009050 line = get_tv_string_chk(tv);
9051 if (line == NULL) /* type error */
9052 {
9053 rettv->vval.v_number = 1; /* Failed */
9054 break;
9055 }
9056 ml_append(lnum + added, line, (colnr_T)0, FALSE);
Bram Moolenaar0d660222005-01-07 21:51:51 +00009057 ++added;
9058 if (l == NULL)
9059 break;
9060 li = li->li_next;
9061 }
9062
9063 appended_lines_mark(lnum, added);
9064 if (curwin->w_cursor.lnum > lnum)
9065 curwin->w_cursor.lnum += added;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009066 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009067 else
9068 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009069}
9070
9071/*
9072 * "argc()" function
9073 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009074 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009075f_argc(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009076{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009077 rettv->vval.v_number = ARGCOUNT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009078}
9079
9080/*
9081 * "argidx()" function
9082 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009083 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009084f_argidx(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009085{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009086 rettv->vval.v_number = curwin->w_arg_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009087}
9088
9089/*
Bram Moolenaar2d1fe052014-05-28 18:22:57 +02009090 * "arglistid()" function
9091 */
9092 static void
Bram Moolenaarf1d25012016-03-03 12:22:53 +01009093f_arglistid(typval_T *argvars, typval_T *rettv)
Bram Moolenaar2d1fe052014-05-28 18:22:57 +02009094{
9095 win_T *wp;
Bram Moolenaar2d1fe052014-05-28 18:22:57 +02009096
9097 rettv->vval.v_number = -1;
Bram Moolenaarc9703302016-01-17 21:49:33 +01009098 wp = find_tabwin(&argvars[0], &argvars[1]);
9099 if (wp != NULL)
9100 rettv->vval.v_number = wp->w_alist->id;
Bram Moolenaar2d1fe052014-05-28 18:22:57 +02009101}
9102
9103/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009104 * "argv(nr)" function
9105 */
9106 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009107f_argv(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009108{
9109 int idx;
9110
Bram Moolenaare2f98b92006-03-29 21:18:24 +00009111 if (argvars[0].v_type != VAR_UNKNOWN)
9112 {
9113 idx = get_tv_number_chk(&argvars[0], NULL);
9114 if (idx >= 0 && idx < ARGCOUNT)
9115 rettv->vval.v_string = vim_strsave(alist_name(&ARGLIST[idx]));
9116 else
9117 rettv->vval.v_string = NULL;
9118 rettv->v_type = VAR_STRING;
9119 }
9120 else if (rettv_list_alloc(rettv) == OK)
9121 for (idx = 0; idx < ARGCOUNT; ++idx)
9122 list_append_string(rettv->vval.v_list,
9123 alist_name(&ARGLIST[idx]), -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009124}
9125
Bram Moolenaar48e697e2016-01-23 22:17:30 +01009126static void prepare_assert_error(garray_T*gap);
9127static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_str, typval_T *exp_tv, typval_T *got_tv);
9128static void assert_error(garray_T *gap);
9129static void assert_bool(typval_T *argvars, int isTrue);
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01009130
9131/*
9132 * Prepare "gap" for an assert error and add the sourcing position.
9133 */
9134 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009135prepare_assert_error(garray_T *gap)
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01009136{
9137 char buf[NUMBUFLEN];
9138
9139 ga_init2(gap, 1, 100);
Bram Moolenaarcbfe3292016-01-02 20:59:10 +01009140 if (sourcing_name != NULL)
9141 {
9142 ga_concat(gap, sourcing_name);
9143 if (sourcing_lnum > 0)
9144 ga_concat(gap, (char_u *)" ");
9145 }
9146 if (sourcing_lnum > 0)
9147 {
9148 sprintf(buf, "line %ld", (long)sourcing_lnum);
9149 ga_concat(gap, (char_u *)buf);
9150 }
9151 if (sourcing_name != NULL || sourcing_lnum > 0)
9152 ga_concat(gap, (char_u *)": ");
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01009153}
9154
9155/*
Bram Moolenaar23689172016-02-15 22:37:37 +01009156 * Append "str" to "gap", escaping unprintable characters.
9157 * Changes NL to \n, CR to \r, etc.
9158 */
9159 static void
9160ga_concat_esc(garray_T *gap, char_u *str)
9161{
9162 char_u *p;
9163 char_u buf[NUMBUFLEN];
9164
9165 for (p = str; *p != NUL; ++p)
9166 switch (*p)
9167 {
9168 case BS: ga_concat(gap, (char_u *)"\\b"); break;
9169 case ESC: ga_concat(gap, (char_u *)"\\e"); break;
9170 case FF: ga_concat(gap, (char_u *)"\\f"); break;
9171 case NL: ga_concat(gap, (char_u *)"\\n"); break;
9172 case TAB: ga_concat(gap, (char_u *)"\\t"); break;
9173 case CAR: ga_concat(gap, (char_u *)"\\r"); break;
9174 case '\\': ga_concat(gap, (char_u *)"\\\\"); break;
9175 default:
9176 if (*p < ' ')
9177 {
9178 vim_snprintf((char *)buf, NUMBUFLEN, "\\x%02x", *p);
9179 ga_concat(gap, buf);
9180 }
9181 else
9182 ga_append(gap, *p);
9183 break;
9184 }
9185}
9186
9187/*
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01009188 * Fill "gap" with information about an assert error.
9189 */
9190 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009191fill_assert_error(
9192 garray_T *gap,
9193 typval_T *opt_msg_tv,
9194 char_u *exp_str,
9195 typval_T *exp_tv,
9196 typval_T *got_tv)
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01009197{
9198 char_u numbuf[NUMBUFLEN];
9199 char_u *tofree;
9200
9201 if (opt_msg_tv->v_type != VAR_UNKNOWN)
9202 {
9203 ga_concat(gap, tv2string(opt_msg_tv, &tofree, numbuf, 0));
9204 vim_free(tofree);
9205 }
9206 else
9207 {
9208 ga_concat(gap, (char_u *)"Expected ");
9209 if (exp_str == NULL)
9210 {
Bram Moolenaar23689172016-02-15 22:37:37 +01009211 ga_concat_esc(gap, tv2string(exp_tv, &tofree, numbuf, 0));
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01009212 vim_free(tofree);
9213 }
9214 else
Bram Moolenaar23689172016-02-15 22:37:37 +01009215 ga_concat_esc(gap, exp_str);
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01009216 ga_concat(gap, (char_u *)" but got ");
Bram Moolenaar23689172016-02-15 22:37:37 +01009217 ga_concat_esc(gap, tv2string(got_tv, &tofree, numbuf, 0));
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01009218 vim_free(tofree);
9219 }
9220}
Bram Moolenaar43345542015-11-29 17:35:35 +01009221
9222/*
9223 * Add an assert error to v:errors.
9224 */
9225 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009226assert_error(garray_T *gap)
Bram Moolenaar43345542015-11-29 17:35:35 +01009227{
9228 struct vimvar *vp = &vimvars[VV_ERRORS];
9229
9230 if (vp->vv_type != VAR_LIST || vimvars[VV_ERRORS].vv_list == NULL)
9231 /* Make sure v:errors is a list. */
9232 set_vim_var_list(VV_ERRORS, list_alloc());
9233 list_append_string(vimvars[VV_ERRORS].vv_list, gap->ga_data, gap->ga_len);
9234}
9235
Bram Moolenaar43345542015-11-29 17:35:35 +01009236/*
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01009237 * "assert_equal(expected, actual[, msg])" function
Bram Moolenaar43345542015-11-29 17:35:35 +01009238 */
9239 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009240f_assert_equal(typval_T *argvars, typval_T *rettv UNUSED)
Bram Moolenaar43345542015-11-29 17:35:35 +01009241{
9242 garray_T ga;
Bram Moolenaar43345542015-11-29 17:35:35 +01009243
9244 if (!tv_equal(&argvars[0], &argvars[1], FALSE, FALSE))
9245 {
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01009246 prepare_assert_error(&ga);
9247 fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1]);
9248 assert_error(&ga);
Bram Moolenaar43345542015-11-29 17:35:35 +01009249 ga_clear(&ga);
9250 }
9251}
9252
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01009253/*
Bram Moolenaara803c7f2016-01-15 15:31:39 +01009254 * "assert_exception(string[, msg])" function
9255 */
9256 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009257f_assert_exception(typval_T *argvars, typval_T *rettv UNUSED)
Bram Moolenaara803c7f2016-01-15 15:31:39 +01009258{
9259 garray_T ga;
9260 char *error;
9261
9262 error = (char *)get_tv_string_chk(&argvars[0]);
9263 if (vimvars[VV_EXCEPTION].vv_str == NULL)
9264 {
9265 prepare_assert_error(&ga);
9266 ga_concat(&ga, (char_u *)"v:exception is not set");
9267 assert_error(&ga);
9268 ga_clear(&ga);
9269 }
Bram Moolenaarda5dcd92016-01-19 14:31:20 +01009270 else if (error != NULL
9271 && strstr((char *)vimvars[VV_EXCEPTION].vv_str, error) == NULL)
Bram Moolenaara803c7f2016-01-15 15:31:39 +01009272 {
9273 prepare_assert_error(&ga);
9274 fill_assert_error(&ga, &argvars[1], NULL, &argvars[0],
9275 &vimvars[VV_EXCEPTION].vv_tv);
9276 assert_error(&ga);
9277 ga_clear(&ga);
9278 }
9279}
9280
9281/*
Bram Moolenaara260b872016-01-15 20:48:22 +01009282 * "assert_fails(cmd [, error])" function
9283 */
9284 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009285f_assert_fails(typval_T *argvars, typval_T *rettv UNUSED)
Bram Moolenaara260b872016-01-15 20:48:22 +01009286{
9287 char_u *cmd = get_tv_string_chk(&argvars[0]);
9288 garray_T ga;
9289
9290 called_emsg = FALSE;
9291 suppress_errthrow = TRUE;
9292 emsg_silent = TRUE;
9293 do_cmdline_cmd(cmd);
9294 if (!called_emsg)
9295 {
9296 prepare_assert_error(&ga);
9297 ga_concat(&ga, (char_u *)"command did not fail: ");
9298 ga_concat(&ga, cmd);
9299 assert_error(&ga);
9300 ga_clear(&ga);
9301 }
9302 else if (argvars[1].v_type != VAR_UNKNOWN)
9303 {
9304 char_u buf[NUMBUFLEN];
9305 char *error = (char *)get_tv_string_buf_chk(&argvars[1], buf);
9306
9307 if (strstr((char *)vimvars[VV_ERRMSG].vv_str, error) == NULL)
9308 {
9309 prepare_assert_error(&ga);
9310 fill_assert_error(&ga, &argvars[2], NULL, &argvars[1],
9311 &vimvars[VV_ERRMSG].vv_tv);
9312 assert_error(&ga);
9313 ga_clear(&ga);
9314 }
9315 }
9316
9317 called_emsg = FALSE;
9318 suppress_errthrow = FALSE;
9319 emsg_silent = FALSE;
9320 emsg_on_display = FALSE;
9321 set_vim_var_string(VV_ERRMSG, NULL, 0);
9322}
9323
9324/*
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01009325 * Common for assert_true() and assert_false().
9326 */
Bram Moolenaar43345542015-11-29 17:35:35 +01009327 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009328assert_bool(typval_T *argvars, int isTrue)
Bram Moolenaar43345542015-11-29 17:35:35 +01009329{
9330 int error = FALSE;
9331 garray_T ga;
Bram Moolenaar43345542015-11-29 17:35:35 +01009332
Bram Moolenaar37127922016-02-06 20:29:28 +01009333 if (argvars[0].v_type == VAR_SPECIAL
Bram Moolenaarc5f98ee2016-02-07 00:00:35 +01009334 && argvars[0].vval.v_number == (isTrue ? VVAL_TRUE : VVAL_FALSE))
Bram Moolenaar37127922016-02-06 20:29:28 +01009335 return;
Bram Moolenaar43345542015-11-29 17:35:35 +01009336 if (argvars[0].v_type != VAR_NUMBER
9337 || (get_tv_number_chk(&argvars[0], &error) == 0) == isTrue
9338 || error)
9339 {
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01009340 prepare_assert_error(&ga);
9341 fill_assert_error(&ga, &argvars[1],
Bram Moolenaarcbfe3292016-01-02 20:59:10 +01009342 (char_u *)(isTrue ? "True" : "False"),
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01009343 NULL, &argvars[0]);
9344 assert_error(&ga);
Bram Moolenaar43345542015-11-29 17:35:35 +01009345 ga_clear(&ga);
9346 }
9347}
9348
9349/*
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01009350 * "assert_false(actual[, msg])" function
Bram Moolenaar43345542015-11-29 17:35:35 +01009351 */
9352 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009353f_assert_false(typval_T *argvars, typval_T *rettv UNUSED)
Bram Moolenaar43345542015-11-29 17:35:35 +01009354{
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01009355 assert_bool(argvars, FALSE);
Bram Moolenaar43345542015-11-29 17:35:35 +01009356}
9357
9358/*
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01009359 * "assert_true(actual[, msg])" function
Bram Moolenaar43345542015-11-29 17:35:35 +01009360 */
9361 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009362f_assert_true(typval_T *argvars, typval_T *rettv UNUSED)
Bram Moolenaar43345542015-11-29 17:35:35 +01009363{
Bram Moolenaarbbfbaf92015-12-01 15:32:56 +01009364 assert_bool(argvars, TRUE);
Bram Moolenaar43345542015-11-29 17:35:35 +01009365}
9366
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009367#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009368/*
Bram Moolenaardb7c6862010-05-21 16:33:48 +02009369 * "asin()" function
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009370 */
Bram Moolenaardb7c6862010-05-21 16:33:48 +02009371 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009372f_asin(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009373{
Bram Moolenaara1e24b92016-02-18 20:18:09 +01009374 float_T f = 0.0;
Bram Moolenaardb7c6862010-05-21 16:33:48 +02009375
9376 rettv->v_type = VAR_FLOAT;
9377 if (get_float_arg(argvars, &f) == OK)
9378 rettv->vval.v_float = asin(f);
9379 else
9380 rettv->vval.v_float = 0.0;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009381}
9382
9383/*
9384 * "atan()" function
9385 */
9386 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009387f_atan(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009388{
Bram Moolenaar4db20ab2016-02-22 21:48:30 +01009389 float_T f = 0.0;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009390
9391 rettv->v_type = VAR_FLOAT;
9392 if (get_float_arg(argvars, &f) == OK)
9393 rettv->vval.v_float = atan(f);
9394 else
9395 rettv->vval.v_float = 0.0;
9396}
Bram Moolenaardb7c6862010-05-21 16:33:48 +02009397
9398/*
9399 * "atan2()" function
9400 */
9401 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009402f_atan2(typval_T *argvars, typval_T *rettv)
Bram Moolenaardb7c6862010-05-21 16:33:48 +02009403{
Bram Moolenaara1e24b92016-02-18 20:18:09 +01009404 float_T fx = 0.0, fy = 0.0;
Bram Moolenaardb7c6862010-05-21 16:33:48 +02009405
9406 rettv->v_type = VAR_FLOAT;
9407 if (get_float_arg(argvars, &fx) == OK
9408 && get_float_arg(&argvars[1], &fy) == OK)
9409 rettv->vval.v_float = atan2(fx, fy);
9410 else
9411 rettv->vval.v_float = 0.0;
9412}
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009413#endif
9414
Bram Moolenaar071d4272004-06-13 20:20:40 +00009415/*
9416 * "browse(save, title, initdir, default)" function
9417 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009418 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009419f_browse(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009420{
9421#ifdef FEAT_BROWSE
9422 int save;
9423 char_u *title;
9424 char_u *initdir;
9425 char_u *defname;
9426 char_u buf[NUMBUFLEN];
9427 char_u buf2[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009428 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009429
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009430 save = get_tv_number_chk(&argvars[0], &error);
9431 title = get_tv_string_chk(&argvars[1]);
9432 initdir = get_tv_string_buf_chk(&argvars[2], buf);
9433 defname = get_tv_string_buf_chk(&argvars[3], buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009434
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009435 if (error || title == NULL || initdir == NULL || defname == NULL)
9436 rettv->vval.v_string = NULL;
9437 else
9438 rettv->vval.v_string =
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009439 do_browse(save ? BROWSE_SAVE : 0,
9440 title, defname, NULL, initdir, NULL, curbuf);
9441#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009442 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009443#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009444 rettv->v_type = VAR_STRING;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009445}
9446
9447/*
9448 * "browsedir(title, initdir)" function
9449 */
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009450 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009451f_browsedir(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009452{
9453#ifdef FEAT_BROWSE
9454 char_u *title;
9455 char_u *initdir;
9456 char_u buf[NUMBUFLEN];
9457
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009458 title = get_tv_string_chk(&argvars[0]);
9459 initdir = get_tv_string_buf_chk(&argvars[1], buf);
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009460
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009461 if (title == NULL || initdir == NULL)
9462 rettv->vval.v_string = NULL;
9463 else
9464 rettv->vval.v_string = do_browse(BROWSE_DIR,
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009465 title, NULL, NULL, initdir, NULL, curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009466#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009467 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009468#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009469 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009470}
9471
Bram Moolenaar48e697e2016-01-23 22:17:30 +01009472static buf_T *find_buffer(typval_T *avar);
Bram Moolenaar0d660222005-01-07 21:51:51 +00009473
Bram Moolenaar071d4272004-06-13 20:20:40 +00009474/*
9475 * Find a buffer by number or exact name.
9476 */
9477 static buf_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01009478find_buffer(typval_T *avar)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009479{
9480 buf_T *buf = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009481
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009482 if (avar->v_type == VAR_NUMBER)
9483 buf = buflist_findnr((int)avar->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +00009484 else if (avar->v_type == VAR_STRING && avar->vval.v_string != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009485 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009486 buf = buflist_findname_exp(avar->vval.v_string);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00009487 if (buf == NULL)
9488 {
9489 /* No full path name match, try a match with a URL or a "nofile"
9490 * buffer, these don't use the full path. */
9491 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
9492 if (buf->b_fname != NULL
9493 && (path_with_url(buf->b_fname)
9494#ifdef FEAT_QUICKFIX
9495 || bt_nofile(buf)
9496#endif
9497 )
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009498 && STRCMP(buf->b_fname, avar->vval.v_string) == 0)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00009499 break;
9500 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009501 }
9502 return buf;
9503}
9504
9505/*
9506 * "bufexists(expr)" function
9507 */
9508 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009509f_bufexists(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009510{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009511 rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009512}
9513
9514/*
9515 * "buflisted(expr)" function
9516 */
9517 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009518f_buflisted(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009519{
9520 buf_T *buf;
9521
9522 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009523 rettv->vval.v_number = (buf != NULL && buf->b_p_bl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009524}
9525
9526/*
9527 * "bufloaded(expr)" function
9528 */
9529 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009530f_bufloaded(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009531{
9532 buf_T *buf;
9533
9534 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009535 rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009536}
9537
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01009538 buf_T *
Bram Moolenaar014069a2016-03-03 22:51:40 +01009539buflist_find_by_name(char_u *name, int curtab_only)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009540{
Bram Moolenaar071d4272004-06-13 20:20:40 +00009541 int save_magic;
9542 char_u *save_cpo;
9543 buf_T *buf;
9544
Bram Moolenaar071d4272004-06-13 20:20:40 +00009545 /* Ignore 'magic' and 'cpoptions' here to make scripts portable */
9546 save_magic = p_magic;
9547 p_magic = TRUE;
9548 save_cpo = p_cpo;
9549 p_cpo = (char_u *)"";
9550
9551 buf = buflist_findnr(buflist_findpat(name, name + STRLEN(name),
Bram Moolenaar0c279bb2013-03-19 14:25:54 +01009552 TRUE, FALSE, curtab_only));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009553
9554 p_magic = save_magic;
9555 p_cpo = save_cpo;
Bram Moolenaar014069a2016-03-03 22:51:40 +01009556 return buf;
9557}
9558
9559/*
9560 * Get buffer by number or pattern.
9561 */
9562 static buf_T *
9563get_buf_tv(typval_T *tv, int curtab_only)
9564{
9565 char_u *name = tv->vval.v_string;
9566 buf_T *buf;
9567
9568 if (tv->v_type == VAR_NUMBER)
9569 return buflist_findnr((int)tv->vval.v_number);
9570 if (tv->v_type != VAR_STRING)
9571 return NULL;
9572 if (name == NULL || *name == NUL)
9573 return curbuf;
9574 if (name[0] == '$' && name[1] == NUL)
9575 return lastbuf;
9576
9577 buf = buflist_find_by_name(name, curtab_only);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009578
9579 /* If not found, try expanding the name, like done for bufexists(). */
9580 if (buf == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009581 buf = find_buffer(tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009582
9583 return buf;
9584}
9585
9586/*
9587 * "bufname(expr)" function
9588 */
9589 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009590f_bufname(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009591{
9592 buf_T *buf;
9593
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009594 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009595 ++emsg_off;
Bram Moolenaar0c279bb2013-03-19 14:25:54 +01009596 buf = get_buf_tv(&argvars[0], FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009597 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009598 if (buf != NULL && buf->b_fname != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009599 rettv->vval.v_string = vim_strsave(buf->b_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009600 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009601 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009602 --emsg_off;
9603}
9604
9605/*
9606 * "bufnr(expr)" function
9607 */
9608 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009609f_bufnr(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009610{
9611 buf_T *buf;
Bram Moolenaar0e34f622006-03-03 23:00:03 +00009612 int error = FALSE;
9613 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009614
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009615 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009616 ++emsg_off;
Bram Moolenaar0c279bb2013-03-19 14:25:54 +01009617 buf = get_buf_tv(&argvars[0], FALSE);
Bram Moolenaar0e34f622006-03-03 23:00:03 +00009618 --emsg_off;
9619
9620 /* If the buffer isn't found and the second argument is not zero create a
9621 * new buffer. */
9622 if (buf == NULL
9623 && argvars[1].v_type != VAR_UNKNOWN
9624 && get_tv_number_chk(&argvars[1], &error) != 0
9625 && !error
9626 && (name = get_tv_string_chk(&argvars[0])) != NULL
9627 && !error)
9628 buf = buflist_new(name, NULL, (linenr_T)1, 0);
9629
Bram Moolenaar071d4272004-06-13 20:20:40 +00009630 if (buf != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009631 rettv->vval.v_number = buf->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009632 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009633 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009634}
9635
9636/*
9637 * "bufwinnr(nr)" function
9638 */
9639 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009640f_bufwinnr(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009641{
9642#ifdef FEAT_WINDOWS
9643 win_T *wp;
9644 int winnr = 0;
9645#endif
9646 buf_T *buf;
9647
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009648 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009649 ++emsg_off;
Bram Moolenaar0c279bb2013-03-19 14:25:54 +01009650 buf = get_buf_tv(&argvars[0], TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009651#ifdef FEAT_WINDOWS
9652 for (wp = firstwin; wp; wp = wp->w_next)
9653 {
9654 ++winnr;
9655 if (wp->w_buffer == buf)
9656 break;
9657 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009658 rettv->vval.v_number = (wp != NULL ? winnr : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009659#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009660 rettv->vval.v_number = (curwin->w_buffer == buf ? 1 : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009661#endif
9662 --emsg_off;
9663}
9664
9665/*
9666 * "byte2line(byte)" function
9667 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009668 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009669f_byte2line(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009670{
9671#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009672 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009673#else
9674 long boff = 0;
9675
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009676 boff = get_tv_number(&argvars[0]) - 1; /* boff gets -1 on type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009677 if (boff < 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009678 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009679 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009680 rettv->vval.v_number = ml_find_line_or_offset(curbuf,
Bram Moolenaar071d4272004-06-13 20:20:40 +00009681 (linenr_T)0, &boff);
9682#endif
9683}
9684
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00009685 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009686byteidx(typval_T *argvars, typval_T *rettv, int comp UNUSED)
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00009687{
9688#ifdef FEAT_MBYTE
9689 char_u *t;
9690#endif
9691 char_u *str;
9692 long idx;
9693
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009694 str = get_tv_string_chk(&argvars[0]);
9695 idx = get_tv_number_chk(&argvars[1], NULL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009696 rettv->vval.v_number = -1;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009697 if (str == NULL || idx < 0)
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00009698 return;
9699
9700#ifdef FEAT_MBYTE
9701 t = str;
9702 for ( ; idx > 0; idx--)
9703 {
9704 if (*t == NUL) /* EOL reached */
9705 return;
Bram Moolenaar0ffbbf92013-11-02 23:29:26 +01009706 if (enc_utf8 && comp)
9707 t += utf_ptr2len(t);
9708 else
9709 t += (*mb_ptr2len)(t);
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00009710 }
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00009711 rettv->vval.v_number = (varnumber_T)(t - str);
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00009712#else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009713 if ((size_t)idx <= STRLEN(str))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009714 rettv->vval.v_number = idx;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00009715#endif
9716}
9717
Bram Moolenaar0ffbbf92013-11-02 23:29:26 +01009718/*
9719 * "byteidx()" function
9720 */
9721 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009722f_byteidx(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0ffbbf92013-11-02 23:29:26 +01009723{
9724 byteidx(argvars, rettv, FALSE);
9725}
9726
9727/*
9728 * "byteidxcomp()" function
9729 */
9730 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009731f_byteidxcomp(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0ffbbf92013-11-02 23:29:26 +01009732{
9733 byteidx(argvars, rettv, TRUE);
9734}
9735
Bram Moolenaardb913952012-06-29 12:54:53 +02009736 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01009737func_call(
9738 char_u *name,
9739 typval_T *args,
9740 dict_T *selfdict,
9741 typval_T *rettv)
Bram Moolenaardb913952012-06-29 12:54:53 +02009742{
9743 listitem_T *item;
9744 typval_T argv[MAX_FUNC_ARGS + 1];
9745 int argc = 0;
9746 int dummy;
9747 int r = 0;
9748
9749 for (item = args->vval.v_list->lv_first; item != NULL;
9750 item = item->li_next)
9751 {
9752 if (argc == MAX_FUNC_ARGS)
9753 {
9754 EMSG(_("E699: Too many arguments"));
9755 break;
9756 }
9757 /* Make a copy of each argument. This is needed to be able to set
9758 * v_lock to VAR_FIXED in the copy without changing the original list.
9759 */
9760 copy_tv(&item->li_tv, &argv[argc++]);
9761 }
9762
9763 if (item == NULL)
9764 r = call_func(name, (int)STRLEN(name), rettv, argc, argv,
9765 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
9766 &dummy, TRUE, selfdict);
9767
9768 /* Free the arguments. */
9769 while (argc > 0)
9770 clear_tv(&argv[--argc]);
9771
9772 return r;
9773}
9774
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00009775/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009776 * "call(func, arglist)" function
9777 */
9778 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009779f_call(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009780{
9781 char_u *func;
Bram Moolenaar33570922005-01-25 22:26:29 +00009782 dict_T *selfdict = NULL;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009783
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009784 if (argvars[1].v_type != VAR_LIST)
9785 {
9786 EMSG(_(e_listreq));
9787 return;
9788 }
9789 if (argvars[1].vval.v_list == NULL)
9790 return;
9791
9792 if (argvars[0].v_type == VAR_FUNC)
9793 func = argvars[0].vval.v_string;
9794 else
9795 func = get_tv_string(&argvars[0]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009796 if (*func == NUL)
9797 return; /* type error or empty name */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009798
Bram Moolenaare9a41262005-01-15 22:18:47 +00009799 if (argvars[2].v_type != VAR_UNKNOWN)
9800 {
9801 if (argvars[2].v_type != VAR_DICT)
9802 {
9803 EMSG(_(e_dictreq));
9804 return;
9805 }
9806 selfdict = argvars[2].vval.v_dict;
9807 }
9808
Bram Moolenaardb913952012-06-29 12:54:53 +02009809 (void)func_call(func, &argvars[1], selfdict, rettv);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009810}
9811
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009812#ifdef FEAT_FLOAT
9813/*
9814 * "ceil({float})" function
9815 */
9816 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +01009817f_ceil(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009818{
Bram Moolenaara1e24b92016-02-18 20:18:09 +01009819 float_T f = 0.0;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009820
9821 rettv->v_type = VAR_FLOAT;
9822 if (get_float_arg(argvars, &f) == OK)
9823 rettv->vval.v_float = ceil(f);
9824 else
9825 rettv->vval.v_float = 0.0;
9826}
9827#endif
9828
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01009829#ifdef FEAT_JOB_CHANNEL
Bram Moolenaarcd39bbc2016-02-17 10:05:42 +01009830/*
Bram Moolenaarcd39bbc2016-02-17 10:05:42 +01009831 * "ch_close()" function
9832 */
9833 static void
9834f_ch_close(typval_T *argvars, typval_T *rettv UNUSED)
9835{
Bram Moolenaarf65333c2016-03-08 18:27:21 +01009836 channel_T *channel = get_channel_arg(&argvars[0], TRUE);
Bram Moolenaarcd39bbc2016-02-17 10:05:42 +01009837
9838 if (channel != NULL)
Bram Moolenaar187db502016-02-27 14:44:26 +01009839 {
Bram Moolenaar8b374212016-02-24 20:43:06 +01009840 channel_close(channel, FALSE);
Bram Moolenaar187db502016-02-27 14:44:26 +01009841 channel_clear(channel);
9842 }
Bram Moolenaarcd39bbc2016-02-17 10:05:42 +01009843}
9844
Bram Moolenaarc7f0ebc2016-02-27 21:10:09 +01009845/*
9846 * "ch_getbufnr()" function
9847 */
9848 static void
9849f_ch_getbufnr(typval_T *argvars, typval_T *rettv)
9850{
Bram Moolenaarf65333c2016-03-08 18:27:21 +01009851 channel_T *channel = get_channel_arg(&argvars[0], TRUE);
Bram Moolenaarc7f0ebc2016-02-27 21:10:09 +01009852
9853 rettv->vval.v_number = -1;
9854 if (channel != NULL)
9855 {
9856 char_u *what = get_tv_string(&argvars[1]);
9857 int part;
9858
9859 if (STRCMP(what, "err") == 0)
9860 part = PART_ERR;
9861 else if (STRCMP(what, "out") == 0)
9862 part = PART_OUT;
9863 else if (STRCMP(what, "in") == 0)
9864 part = PART_IN;
9865 else
9866 part = PART_SOCK;
9867 if (channel->ch_part[part].ch_buffer != NULL)
9868 rettv->vval.v_number = channel->ch_part[part].ch_buffer->b_fnum;
9869 }
9870}
9871
Bram Moolenaar02e83b42016-02-21 20:10:26 +01009872/*
9873 * "ch_getjob()" function
9874 */
9875 static void
9876f_ch_getjob(typval_T *argvars, typval_T *rettv)
9877{
Bram Moolenaarf65333c2016-03-08 18:27:21 +01009878 channel_T *channel = get_channel_arg(&argvars[0], TRUE);
Bram Moolenaar02e83b42016-02-21 20:10:26 +01009879
9880 if (channel != NULL)
9881 {
9882 rettv->v_type = VAR_JOB;
9883 rettv->vval.v_job = channel->ch_job;
9884 if (channel->ch_job != NULL)
9885 ++channel->ch_job->jv_refcount;
9886 }
9887}
Bram Moolenaar02e83b42016-02-21 20:10:26 +01009888
Bram Moolenaarcd39bbc2016-02-17 10:05:42 +01009889/*
Bram Moolenaar81661fb2016-02-18 22:23:34 +01009890 * "ch_log()" function
9891 */
9892 static void
9893f_ch_log(typval_T *argvars, typval_T *rettv UNUSED)
9894{
9895 char_u *msg = get_tv_string(&argvars[0]);
9896 channel_T *channel = NULL;
9897
9898 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarf65333c2016-03-08 18:27:21 +01009899 channel = get_channel_arg(&argvars[1], TRUE);
Bram Moolenaar81661fb2016-02-18 22:23:34 +01009900
9901 ch_log(channel, (char *)msg);
9902}
9903
9904/*
Bram Moolenaarcd39bbc2016-02-17 10:05:42 +01009905 * "ch_logfile()" function
9906 */
9907 static void
9908f_ch_logfile(typval_T *argvars, typval_T *rettv UNUSED)
9909{
9910 char_u *fname;
9911 char_u *opt = (char_u *)"";
9912 char_u buf[NUMBUFLEN];
Bram Moolenaarcd39bbc2016-02-17 10:05:42 +01009913
9914 fname = get_tv_string(&argvars[0]);
9915 if (argvars[1].v_type == VAR_STRING)
9916 opt = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01009917 ch_logfile(fname, opt);
Bram Moolenaarcd39bbc2016-02-17 10:05:42 +01009918}
Bram Moolenaarba093bc2016-02-16 19:37:29 +01009919
9920/*
Bram Moolenaarf57969a2016-02-02 20:47:49 +01009921 * "ch_open()" function
9922 */
9923 static void
9924f_ch_open(typval_T *argvars, typval_T *rettv)
9925{
Bram Moolenaar77073442016-02-13 23:23:53 +01009926 rettv->v_type = VAR_CHANNEL;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01009927 rettv->vval.v_channel = channel_open_func(argvars);
Bram Moolenaar77073442016-02-13 23:23:53 +01009928}
9929
9930/*
Bram Moolenaar6f3a5442016-02-20 19:56:13 +01009931 * "ch_read()" function
9932 */
9933 static void
9934f_ch_read(typval_T *argvars, typval_T *rettv)
9935{
9936 common_channel_read(argvars, rettv, FALSE);
9937}
9938
9939/*
9940 * "ch_readraw()" function
9941 */
9942 static void
9943f_ch_readraw(typval_T *argvars, typval_T *rettv)
9944{
9945 common_channel_read(argvars, rettv, TRUE);
9946}
9947
9948/*
Bram Moolenaar8b1862a2016-02-27 19:21:24 +01009949 * "ch_evalexpr()" function
Bram Moolenaarf57969a2016-02-02 20:47:49 +01009950 */
9951 static void
Bram Moolenaar8b1862a2016-02-27 19:21:24 +01009952f_ch_evalexpr(typval_T *argvars, typval_T *rettv)
9953{
9954 ch_expr_common(argvars, rettv, TRUE);
9955}
9956
9957/*
9958 * "ch_sendexpr()" function
9959 */
9960 static void
9961f_ch_sendexpr(typval_T *argvars, typval_T *rettv)
9962{
9963 ch_expr_common(argvars, rettv, FALSE);
9964}
9965
9966/*
Bram Moolenaar8b1862a2016-02-27 19:21:24 +01009967 * "ch_evalraw()" function
9968 */
9969 static void
9970f_ch_evalraw(typval_T *argvars, typval_T *rettv)
9971{
9972 ch_raw_common(argvars, rettv, TRUE);
9973}
9974
9975/*
9976 * "ch_sendraw()" function
9977 */
9978 static void
9979f_ch_sendraw(typval_T *argvars, typval_T *rettv)
9980{
9981 ch_raw_common(argvars, rettv, FALSE);
9982}
9983
9984/*
Bram Moolenaar40ea1da2016-02-19 22:33:35 +01009985 * "ch_setoptions()" function
9986 */
9987 static void
9988f_ch_setoptions(typval_T *argvars, typval_T *rettv UNUSED)
9989{
9990 channel_T *channel;
9991 jobopt_T opt;
9992
Bram Moolenaarf65333c2016-03-08 18:27:21 +01009993 channel = get_channel_arg(&argvars[0], TRUE);
Bram Moolenaar40ea1da2016-02-19 22:33:35 +01009994 if (channel == NULL)
9995 return;
Bram Moolenaarb6b52522016-02-20 23:30:07 +01009996 clear_job_options(&opt);
9997 if (get_job_options(&argvars[1], &opt,
9998 JO_CB_ALL + JO_TIMEOUT_ALL + JO_MODE_ALL) == FAIL)
Bram Moolenaar132006c2016-02-19 22:38:15 +01009999 return;
Bram Moolenaar40ea1da2016-02-19 22:33:35 +010010000 channel_set_options(channel, &opt);
10001}
10002
10003/*
10004 * "ch_status()" function
10005 */
10006 static void
10007f_ch_status(typval_T *argvars, typval_T *rettv)
10008{
Bram Moolenaarf65333c2016-03-08 18:27:21 +010010009 channel_T *channel;
10010
Bram Moolenaar40ea1da2016-02-19 22:33:35 +010010011 /* return an empty string by default */
10012 rettv->v_type = VAR_STRING;
Bram Moolenaarf65333c2016-03-08 18:27:21 +010010013 rettv->vval.v_string = NULL;
Bram Moolenaar40ea1da2016-02-19 22:33:35 +010010014
Bram Moolenaarf65333c2016-03-08 18:27:21 +010010015 channel = get_channel_arg(&argvars[0], FALSE);
10016 rettv->vval.v_string = vim_strsave((char_u *)channel_status(channel));
Bram Moolenaar40ea1da2016-02-19 22:33:35 +010010017}
Bram Moolenaarf57969a2016-02-02 20:47:49 +010010018#endif
10019
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010020/*
Bram Moolenaarf0acfce2006-03-17 23:21:19 +000010021 * "changenr()" function
10022 */
Bram Moolenaarf0acfce2006-03-17 23:21:19 +000010023 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010024f_changenr(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaarf0acfce2006-03-17 23:21:19 +000010025{
10026 rettv->vval.v_number = curbuf->b_u_seq_cur;
10027}
10028
10029/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010030 * "char2nr(string)" function
10031 */
10032 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010033f_char2nr(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010034{
10035#ifdef FEAT_MBYTE
10036 if (has_mbyte)
Bram Moolenaard35d7842013-01-23 17:17:10 +010010037 {
10038 int utf8 = 0;
10039
10040 if (argvars[1].v_type != VAR_UNKNOWN)
10041 utf8 = get_tv_number_chk(&argvars[1], NULL);
10042
10043 if (utf8)
10044 rettv->vval.v_number = (*utf_ptr2char)(get_tv_string(&argvars[0]));
10045 else
10046 rettv->vval.v_number = (*mb_ptr2char)(get_tv_string(&argvars[0]));
10047 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010048 else
10049#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010050 rettv->vval.v_number = get_tv_string(&argvars[0])[0];
Bram Moolenaar071d4272004-06-13 20:20:40 +000010051}
10052
10053/*
10054 * "cindent(lnum)" function
10055 */
10056 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010057f_cindent(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010058{
10059#ifdef FEAT_CINDENT
10060 pos_T pos;
10061 linenr_T lnum;
10062
10063 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010064 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010065 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
10066 {
10067 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010068 rettv->vval.v_number = get_c_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +000010069 curwin->w_cursor = pos;
10070 }
10071 else
10072#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010073 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010074}
10075
10076/*
Bram Moolenaar6ee10162007-07-26 20:58:42 +000010077 * "clearmatches()" function
10078 */
Bram Moolenaar6ee10162007-07-26 20:58:42 +000010079 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010080f_clearmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaar6ee10162007-07-26 20:58:42 +000010081{
10082#ifdef FEAT_SEARCH_EXTRA
10083 clear_matches(curwin);
10084#endif
10085}
10086
10087/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010088 * "col(string)" function
10089 */
10090 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010091f_col(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010092{
10093 colnr_T col = 0;
10094 pos_T *fp;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000010095 int fnum = curbuf->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010096
Bram Moolenaar0e34f622006-03-03 23:00:03 +000010097 fp = var2fpos(&argvars[0], FALSE, &fnum);
10098 if (fp != NULL && fnum == curbuf->b_fnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010099 {
10100 if (fp->col == MAXCOL)
10101 {
10102 /* '> can be MAXCOL, get the length of the line then */
10103 if (fp->lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000010104 col = (colnr_T)STRLEN(ml_get(fp->lnum)) + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010105 else
10106 col = MAXCOL;
10107 }
10108 else
10109 {
10110 col = fp->col + 1;
10111#ifdef FEAT_VIRTUALEDIT
10112 /* col(".") when the cursor is on the NUL at the end of the line
10113 * because of "coladd" can be seen as an extra column. */
10114 if (virtual_active() && fp == &curwin->w_cursor)
10115 {
10116 char_u *p = ml_get_cursor();
10117
10118 if (curwin->w_cursor.coladd >= (colnr_T)chartabsize(p,
10119 curwin->w_virtcol - curwin->w_cursor.coladd))
10120 {
10121# ifdef FEAT_MBYTE
10122 int l;
10123
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000010124 if (*p != NUL && p[(l = (*mb_ptr2len)(p))] == NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010125 col += l;
10126# else
10127 if (*p != NUL && p[1] == NUL)
10128 ++col;
10129# endif
10130 }
10131 }
10132#endif
10133 }
10134 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010135 rettv->vval.v_number = col;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010136}
10137
Bram Moolenaar572cb562005-08-05 21:35:02 +000010138#if defined(FEAT_INS_EXPAND)
10139/*
Bram Moolenaarade00832006-03-10 21:46:58 +000010140 * "complete()" function
10141 */
Bram Moolenaarade00832006-03-10 21:46:58 +000010142 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010143f_complete(typval_T *argvars, typval_T *rettv UNUSED)
Bram Moolenaarade00832006-03-10 21:46:58 +000010144{
10145 int startcol;
10146
10147 if ((State & INSERT) == 0)
10148 {
10149 EMSG(_("E785: complete() can only be used in Insert mode"));
10150 return;
10151 }
Bram Moolenaarce6ef252006-07-12 19:49:41 +000010152
10153 /* Check for undo allowed here, because if something was already inserted
10154 * the line was already saved for undo and this check isn't done. */
10155 if (!undo_allowed())
10156 return;
10157
Bram Moolenaarade00832006-03-10 21:46:58 +000010158 if (argvars[1].v_type != VAR_LIST || argvars[1].vval.v_list == NULL)
10159 {
10160 EMSG(_(e_invarg));
10161 return;
10162 }
10163
10164 startcol = get_tv_number_chk(&argvars[0], NULL);
10165 if (startcol <= 0)
10166 return;
10167
10168 set_completion(startcol - 1, argvars[1].vval.v_list);
10169}
10170
10171/*
Bram Moolenaar572cb562005-08-05 21:35:02 +000010172 * "complete_add()" function
10173 */
Bram Moolenaar572cb562005-08-05 21:35:02 +000010174 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010175f_complete_add(typval_T *argvars, typval_T *rettv)
Bram Moolenaar572cb562005-08-05 21:35:02 +000010176{
Bram Moolenaarceaf7b82006-03-19 22:18:55 +000010177 rettv->vval.v_number = ins_compl_add_tv(&argvars[0], 0);
Bram Moolenaar572cb562005-08-05 21:35:02 +000010178}
10179
10180/*
10181 * "complete_check()" function
10182 */
Bram Moolenaar572cb562005-08-05 21:35:02 +000010183 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010184f_complete_check(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar572cb562005-08-05 21:35:02 +000010185{
10186 int saved = RedrawingDisabled;
10187
10188 RedrawingDisabled = 0;
10189 ins_compl_check_keys(0);
10190 rettv->vval.v_number = compl_interrupted;
10191 RedrawingDisabled = saved;
10192}
10193#endif
10194
Bram Moolenaar071d4272004-06-13 20:20:40 +000010195/*
10196 * "confirm(message, buttons[, default [, type]])" function
10197 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010198 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010199f_confirm(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010200{
10201#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
10202 char_u *message;
10203 char_u *buttons = NULL;
10204 char_u buf[NUMBUFLEN];
10205 char_u buf2[NUMBUFLEN];
10206 int def = 1;
10207 int type = VIM_GENERIC;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010208 char_u *typestr;
10209 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010210
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010211 message = get_tv_string_chk(&argvars[0]);
10212 if (message == NULL)
10213 error = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010214 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010215 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010216 buttons = get_tv_string_buf_chk(&argvars[1], buf);
10217 if (buttons == NULL)
10218 error = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010219 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010220 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010221 def = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010222 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010223 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010224 typestr = get_tv_string_buf_chk(&argvars[3], buf2);
10225 if (typestr == NULL)
10226 error = TRUE;
10227 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000010228 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010229 switch (TOUPPER_ASC(*typestr))
10230 {
10231 case 'E': type = VIM_ERROR; break;
10232 case 'Q': type = VIM_QUESTION; break;
10233 case 'I': type = VIM_INFO; break;
10234 case 'W': type = VIM_WARNING; break;
10235 case 'G': type = VIM_GENERIC; break;
10236 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010237 }
10238 }
10239 }
10240 }
10241
10242 if (buttons == NULL || *buttons == NUL)
10243 buttons = (char_u *)_("&Ok");
10244
Bram Moolenaar798b30b2009-04-22 10:56:16 +000010245 if (!error)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010246 rettv->vval.v_number = do_dialog(type, NULL, message, buttons,
Bram Moolenaard2c340a2011-01-17 20:08:11 +010010247 def, NULL, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010248#endif
10249}
10250
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010251/*
10252 * "copy()" function
10253 */
10254 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010255f_copy(typval_T *argvars, typval_T *rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010256{
Bram Moolenaar81bf7082005-02-12 14:31:42 +000010257 item_copy(&argvars[0], rettv, FALSE, 0);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010258}
Bram Moolenaar071d4272004-06-13 20:20:40 +000010259
Bram Moolenaar8c8de832008-06-24 22:58:06 +000010260#ifdef FEAT_FLOAT
10261/*
10262 * "cos()" function
10263 */
10264 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010265f_cos(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8c8de832008-06-24 22:58:06 +000010266{
Bram Moolenaara1e24b92016-02-18 20:18:09 +010010267 float_T f = 0.0;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000010268
10269 rettv->v_type = VAR_FLOAT;
10270 if (get_float_arg(argvars, &f) == OK)
10271 rettv->vval.v_float = cos(f);
10272 else
10273 rettv->vval.v_float = 0.0;
10274}
Bram Moolenaardb7c6862010-05-21 16:33:48 +020010275
10276/*
10277 * "cosh()" function
10278 */
10279 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010280f_cosh(typval_T *argvars, typval_T *rettv)
Bram Moolenaardb7c6862010-05-21 16:33:48 +020010281{
Bram Moolenaara1e24b92016-02-18 20:18:09 +010010282 float_T f = 0.0;
Bram Moolenaardb7c6862010-05-21 16:33:48 +020010283
10284 rettv->v_type = VAR_FLOAT;
10285 if (get_float_arg(argvars, &f) == OK)
10286 rettv->vval.v_float = cosh(f);
10287 else
10288 rettv->vval.v_float = 0.0;
10289}
Bram Moolenaar8c8de832008-06-24 22:58:06 +000010290#endif
10291
Bram Moolenaar071d4272004-06-13 20:20:40 +000010292/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010293 * "count()" function
10294 */
10295 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010296f_count(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010297{
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010298 long n = 0;
10299 int ic = FALSE;
10300
Bram Moolenaare9a41262005-01-15 22:18:47 +000010301 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010302 {
Bram Moolenaar33570922005-01-25 22:26:29 +000010303 listitem_T *li;
10304 list_T *l;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010305 long idx;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010306
Bram Moolenaare9a41262005-01-15 22:18:47 +000010307 if ((l = argvars[0].vval.v_list) != NULL)
10308 {
10309 li = l->lv_first;
10310 if (argvars[2].v_type != VAR_UNKNOWN)
10311 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010312 int error = FALSE;
10313
10314 ic = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaare9a41262005-01-15 22:18:47 +000010315 if (argvars[3].v_type != VAR_UNKNOWN)
10316 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010317 idx = get_tv_number_chk(&argvars[3], &error);
10318 if (!error)
10319 {
10320 li = list_find(l, idx);
10321 if (li == NULL)
10322 EMSGN(_(e_listidx), idx);
10323 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000010324 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010325 if (error)
10326 li = NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010327 }
10328
10329 for ( ; li != NULL; li = li->li_next)
Bram Moolenaar67b3f992010-11-10 20:41:57 +010010330 if (tv_equal(&li->li_tv, &argvars[1], ic, FALSE))
Bram Moolenaare9a41262005-01-15 22:18:47 +000010331 ++n;
10332 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010333 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000010334 else if (argvars[0].v_type == VAR_DICT)
10335 {
Bram Moolenaar33570922005-01-25 22:26:29 +000010336 int todo;
10337 dict_T *d;
10338 hashitem_T *hi;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010339
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010340 if ((d = argvars[0].vval.v_dict) != NULL)
10341 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010342 int error = FALSE;
10343
Bram Moolenaare9a41262005-01-15 22:18:47 +000010344 if (argvars[2].v_type != VAR_UNKNOWN)
10345 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010346 ic = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaare9a41262005-01-15 22:18:47 +000010347 if (argvars[3].v_type != VAR_UNKNOWN)
10348 EMSG(_(e_invarg));
10349 }
10350
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000010351 todo = error ? 0 : (int)d->dv_hashtab.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +000010352 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010353 {
10354 if (!HASHITEM_EMPTY(hi))
10355 {
10356 --todo;
Bram Moolenaar67b3f992010-11-10 20:41:57 +010010357 if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic, FALSE))
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010358 ++n;
10359 }
10360 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000010361 }
10362 }
10363 else
10364 EMSG2(_(e_listdictarg), "count()");
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010365 rettv->vval.v_number = n;
10366}
10367
10368/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010369 * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
10370 *
10371 * Checks the existence of a cscope connection.
10372 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010373 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010374f_cscope_connection(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010375{
10376#ifdef FEAT_CSCOPE
10377 int num = 0;
10378 char_u *dbpath = NULL;
10379 char_u *prepend = NULL;
10380 char_u buf[NUMBUFLEN];
10381
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010382 if (argvars[0].v_type != VAR_UNKNOWN
10383 && argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010384 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010385 num = (int)get_tv_number(&argvars[0]);
10386 dbpath = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010387 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010388 prepend = get_tv_string_buf(&argvars[2], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010389 }
10390
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010391 rettv->vval.v_number = cs_connection(num, dbpath, prepend);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010392#endif
10393}
10394
10395/*
Bram Moolenaar24c4d532016-01-15 15:37:20 +010010396 * "cursor(lnum, col)" function, or
10397 * "cursor(list)"
Bram Moolenaar071d4272004-06-13 20:20:40 +000010398 *
Bram Moolenaar798b30b2009-04-22 10:56:16 +000010399 * Moves the cursor to the specified line and column.
10400 * Returns 0 when the position could be set, -1 otherwise.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010401 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010402 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010403f_cursor(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010404{
10405 long line, col;
Bram Moolenaara5525202006-03-02 22:52:09 +000010406#ifdef FEAT_VIRTUALEDIT
10407 long coladd = 0;
10408#endif
Bram Moolenaarc21d67e2015-12-31 22:27:55 +010010409 int set_curswant = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010410
Bram Moolenaar798b30b2009-04-22 10:56:16 +000010411 rettv->vval.v_number = -1;
Bram Moolenaara5525202006-03-02 22:52:09 +000010412 if (argvars[1].v_type == VAR_UNKNOWN)
10413 {
Bram Moolenaar0e34f622006-03-03 23:00:03 +000010414 pos_T pos;
Bram Moolenaar493c1782014-05-28 14:34:46 +020010415 colnr_T curswant = -1;
Bram Moolenaara5525202006-03-02 22:52:09 +000010416
Bram Moolenaar493c1782014-05-28 14:34:46 +020010417 if (list2fpos(argvars, &pos, NULL, &curswant) == FAIL)
Bram Moolenaar24c4d532016-01-15 15:37:20 +010010418 {
10419 EMSG(_(e_invarg));
Bram Moolenaara5525202006-03-02 22:52:09 +000010420 return;
Bram Moolenaar24c4d532016-01-15 15:37:20 +010010421 }
Bram Moolenaar0e34f622006-03-03 23:00:03 +000010422 line = pos.lnum;
10423 col = pos.col;
Bram Moolenaara5525202006-03-02 22:52:09 +000010424#ifdef FEAT_VIRTUALEDIT
Bram Moolenaar0e34f622006-03-03 23:00:03 +000010425 coladd = pos.coladd;
Bram Moolenaara5525202006-03-02 22:52:09 +000010426#endif
Bram Moolenaar493c1782014-05-28 14:34:46 +020010427 if (curswant >= 0)
Bram Moolenaarc21d67e2015-12-31 22:27:55 +010010428 {
Bram Moolenaar493c1782014-05-28 14:34:46 +020010429 curwin->w_curswant = curswant - 1;
Bram Moolenaarc21d67e2015-12-31 22:27:55 +010010430 set_curswant = FALSE;
10431 }
Bram Moolenaara5525202006-03-02 22:52:09 +000010432 }
10433 else
10434 {
10435 line = get_tv_lnum(argvars);
10436 col = get_tv_number_chk(&argvars[1], NULL);
10437#ifdef FEAT_VIRTUALEDIT
10438 if (argvars[2].v_type != VAR_UNKNOWN)
10439 coladd = get_tv_number_chk(&argvars[2], NULL);
10440#endif
10441 }
10442 if (line < 0 || col < 0
10443#ifdef FEAT_VIRTUALEDIT
10444 || coladd < 0
10445#endif
10446 )
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010447 return; /* type error; errmsg already given */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010448 if (line > 0)
10449 curwin->w_cursor.lnum = line;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010450 if (col > 0)
10451 curwin->w_cursor.col = col - 1;
10452#ifdef FEAT_VIRTUALEDIT
Bram Moolenaara5525202006-03-02 22:52:09 +000010453 curwin->w_cursor.coladd = coladd;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010454#endif
10455
10456 /* Make sure the cursor is in a valid position. */
10457 check_cursor();
10458#ifdef FEAT_MBYTE
10459 /* Correct cursor for multi-byte character. */
10460 if (has_mbyte)
10461 mb_adjust_cursor();
10462#endif
Bram Moolenaarf4b8e572004-06-24 15:53:16 +000010463
Bram Moolenaarc21d67e2015-12-31 22:27:55 +010010464 curwin->w_set_curswant = set_curswant;
Bram Moolenaar798b30b2009-04-22 10:56:16 +000010465 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010466}
10467
10468/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010469 * "deepcopy()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000010470 */
10471 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010472f_deepcopy(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010473{
Bram Moolenaar81bf7082005-02-12 14:31:42 +000010474 int noref = 0;
10475
10476 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010477 noref = get_tv_number_chk(&argvars[1], NULL);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000010478 if (noref < 0 || noref > 1)
10479 EMSG(_(e_invarg));
10480 else
Bram Moolenaar2c2398c2009-06-03 11:22:45 +000010481 {
10482 current_copyID += COPYID_INC;
10483 item_copy(&argvars[0], rettv, TRUE, noref == 0 ? current_copyID : 0);
10484 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010485}
10486
10487/*
10488 * "delete()" function
10489 */
10490 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010491f_delete(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010492{
Bram Moolenaarda440d22016-01-16 21:27:23 +010010493 char_u nbuf[NUMBUFLEN];
10494 char_u *name;
10495 char_u *flags;
10496
10497 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010498 if (check_restricted() || check_secure())
Bram Moolenaarda440d22016-01-16 21:27:23 +010010499 return;
10500
10501 name = get_tv_string(&argvars[0]);
10502 if (name == NULL || *name == NUL)
10503 {
10504 EMSG(_(e_invarg));
10505 return;
10506 }
10507
10508 if (argvars[1].v_type != VAR_UNKNOWN)
10509 flags = get_tv_string_buf(&argvars[1], nbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010510 else
Bram Moolenaarda440d22016-01-16 21:27:23 +010010511 flags = (char_u *)"";
10512
10513 if (*flags == NUL)
10514 /* delete a file */
10515 rettv->vval.v_number = mch_remove(name) == 0 ? 0 : -1;
10516 else if (STRCMP(flags, "d") == 0)
10517 /* delete an empty directory */
10518 rettv->vval.v_number = mch_rmdir(name) == 0 ? 0 : -1;
10519 else if (STRCMP(flags, "rf") == 0)
Bram Moolenaar43a34f92016-01-17 15:56:34 +010010520 /* delete a directory recursively */
Bram Moolenaarda440d22016-01-16 21:27:23 +010010521 rettv->vval.v_number = delete_recursive(name);
10522 else
10523 EMSG2(_(e_invexpr2), flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010524}
10525
10526/*
10527 * "did_filetype()" function
10528 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010529 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010530f_did_filetype(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010531{
10532#ifdef FEAT_AUTOCMD
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010533 rettv->vval.v_number = did_filetype;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010534#endif
10535}
10536
10537/*
Bram Moolenaar47136d72004-10-12 20:02:24 +000010538 * "diff_filler()" function
10539 */
Bram Moolenaar47136d72004-10-12 20:02:24 +000010540 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010541f_diff_filler(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaar47136d72004-10-12 20:02:24 +000010542{
10543#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010544 rettv->vval.v_number = diff_check_fill(curwin, get_tv_lnum(argvars));
Bram Moolenaar47136d72004-10-12 20:02:24 +000010545#endif
10546}
10547
10548/*
10549 * "diff_hlID()" function
10550 */
Bram Moolenaar47136d72004-10-12 20:02:24 +000010551 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010552f_diff_hlID(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaar47136d72004-10-12 20:02:24 +000010553{
10554#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010555 linenr_T lnum = get_tv_lnum(argvars);
Bram Moolenaar47136d72004-10-12 20:02:24 +000010556 static linenr_T prev_lnum = 0;
10557 static int changedtick = 0;
10558 static int fnum = 0;
10559 static int change_start = 0;
10560 static int change_end = 0;
Bram Moolenaar6f192452007-11-08 19:49:02 +000010561 static hlf_T hlID = (hlf_T)0;
Bram Moolenaar47136d72004-10-12 20:02:24 +000010562 int filler_lines;
10563 int col;
10564
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010565 if (lnum < 0) /* ignore type error in {lnum} arg */
10566 lnum = 0;
Bram Moolenaar47136d72004-10-12 20:02:24 +000010567 if (lnum != prev_lnum
10568 || changedtick != curbuf->b_changedtick
10569 || fnum != curbuf->b_fnum)
10570 {
10571 /* New line, buffer, change: need to get the values. */
10572 filler_lines = diff_check(curwin, lnum);
10573 if (filler_lines < 0)
10574 {
10575 if (filler_lines == -1)
10576 {
10577 change_start = MAXCOL;
10578 change_end = -1;
10579 if (diff_find_change(curwin, lnum, &change_start, &change_end))
10580 hlID = HLF_ADD; /* added line */
10581 else
10582 hlID = HLF_CHD; /* changed line */
10583 }
10584 else
10585 hlID = HLF_ADD; /* added line */
10586 }
10587 else
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000010588 hlID = (hlf_T)0;
Bram Moolenaar47136d72004-10-12 20:02:24 +000010589 prev_lnum = lnum;
10590 changedtick = curbuf->b_changedtick;
10591 fnum = curbuf->b_fnum;
10592 }
10593
10594 if (hlID == HLF_CHD || hlID == HLF_TXD)
10595 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010596 col = get_tv_number(&argvars[1]) - 1; /* ignore type error in {col} */
Bram Moolenaar47136d72004-10-12 20:02:24 +000010597 if (col >= change_start && col <= change_end)
10598 hlID = HLF_TXD; /* changed text */
10599 else
10600 hlID = HLF_CHD; /* changed line */
10601 }
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000010602 rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (int)hlID;
Bram Moolenaar47136d72004-10-12 20:02:24 +000010603#endif
10604}
10605
10606/*
Bram Moolenaar2ab375e2016-02-10 22:23:06 +010010607 * "disable_char_avail_for_testing({expr})" function
10608 */
10609 static void
10610f_disable_char_avail_for_testing(typval_T *argvars, typval_T *rettv UNUSED)
10611{
10612 disable_char_avail_for_testing = get_tv_number(&argvars[0]);
10613}
10614
10615/*
Bram Moolenaare49b69a2005-01-08 16:11:57 +000010616 * "empty({expr})" function
10617 */
10618 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010619f_empty(typval_T *argvars, typval_T *rettv)
Bram Moolenaare49b69a2005-01-08 16:11:57 +000010620{
Bram Moolenaar2fc83fc2016-02-08 22:57:24 +010010621 int n = FALSE;
Bram Moolenaare49b69a2005-01-08 16:11:57 +000010622
10623 switch (argvars[0].v_type)
10624 {
10625 case VAR_STRING:
10626 case VAR_FUNC:
10627 n = argvars[0].vval.v_string == NULL
10628 || *argvars[0].vval.v_string == NUL;
10629 break;
10630 case VAR_NUMBER:
10631 n = argvars[0].vval.v_number == 0;
10632 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000010633 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +010010634#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +000010635 n = argvars[0].vval.v_float == 0.0;
10636 break;
10637#endif
Bram Moolenaare49b69a2005-01-08 16:11:57 +000010638 case VAR_LIST:
10639 n = argvars[0].vval.v_list == NULL
10640 || argvars[0].vval.v_list->lv_first == NULL;
10641 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010642 case VAR_DICT:
10643 n = argvars[0].vval.v_dict == NULL
Bram Moolenaar33570922005-01-25 22:26:29 +000010644 || argvars[0].vval.v_dict->dv_hashtab.ht_used == 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010645 break;
Bram Moolenaar767d8c12016-01-25 20:22:54 +010010646 case VAR_SPECIAL:
10647 n = argvars[0].vval.v_number != VVAL_TRUE;
10648 break;
10649
Bram Moolenaar835dc632016-02-07 14:27:38 +010010650 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +010010651#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +010010652 n = argvars[0].vval.v_job == NULL
10653 || argvars[0].vval.v_job->jv_status != JOB_STARTED;
10654 break;
10655#endif
10656 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +010010657#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +010010658 n = argvars[0].vval.v_channel == NULL
10659 || !channel_is_open(argvars[0].vval.v_channel);
Bram Moolenaar835dc632016-02-07 14:27:38 +010010660 break;
10661#endif
Bram Moolenaara03f2332016-02-06 18:09:59 +010010662 case VAR_UNKNOWN:
10663 EMSG2(_(e_intern2), "f_empty(UNKNOWN)");
10664 n = TRUE;
10665 break;
Bram Moolenaare49b69a2005-01-08 16:11:57 +000010666 }
10667
10668 rettv->vval.v_number = n;
10669}
10670
10671/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010672 * "escape({string}, {chars})" function
10673 */
10674 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010675f_escape(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010676{
10677 char_u buf[NUMBUFLEN];
10678
Bram Moolenaar758711c2005-02-02 23:11:38 +000010679 rettv->vval.v_string = vim_strsave_escaped(get_tv_string(&argvars[0]),
10680 get_tv_string_buf(&argvars[1], buf));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010681 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010682}
10683
10684/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010685 * "eval()" function
10686 */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010687 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010688f_eval(typval_T *argvars, typval_T *rettv)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010689{
Bram Moolenaar615b9972015-01-14 17:15:05 +010010690 char_u *s, *p;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010691
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010692 s = get_tv_string_chk(&argvars[0]);
10693 if (s != NULL)
10694 s = skipwhite(s);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010695
Bram Moolenaar615b9972015-01-14 17:15:05 +010010696 p = s;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010697 if (s == NULL || eval1(&s, rettv, TRUE) == FAIL)
10698 {
Bram Moolenaar615b9972015-01-14 17:15:05 +010010699 if (p != NULL && !aborting())
10700 EMSG2(_(e_invexpr2), p);
10701 need_clr_eos = FALSE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010702 rettv->v_type = VAR_NUMBER;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010703 rettv->vval.v_number = 0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010704 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010705 else if (*s != NUL)
10706 EMSG(_(e_trailing));
10707}
10708
10709/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010710 * "eventhandler()" function
10711 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010712 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010713f_eventhandler(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010714{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010715 rettv->vval.v_number = vgetc_busy;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010716}
10717
10718/*
10719 * "executable()" function
10720 */
10721 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010722f_executable(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010723{
Bram Moolenaarb5971142015-03-21 17:32:19 +010010724 char_u *name = get_tv_string(&argvars[0]);
10725
10726 /* Check in $PATH and also check directly if there is a directory name. */
10727 rettv->vval.v_number = mch_can_exe(name, NULL, TRUE)
10728 || (gettail(name) != name && mch_can_exe(name, NULL, FALSE));
Bram Moolenaarc7f02552014-04-01 21:00:59 +020010729}
10730
10731/*
10732 * "exepath()" function
10733 */
10734 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010735f_exepath(typval_T *argvars, typval_T *rettv)
Bram Moolenaarc7f02552014-04-01 21:00:59 +020010736{
10737 char_u *p = NULL;
10738
Bram Moolenaarb5971142015-03-21 17:32:19 +010010739 (void)mch_can_exe(get_tv_string(&argvars[0]), &p, TRUE);
Bram Moolenaarc7f02552014-04-01 21:00:59 +020010740 rettv->v_type = VAR_STRING;
10741 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010742}
10743
10744/*
10745 * "exists()" function
10746 */
10747 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010748f_exists(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010749{
10750 char_u *p;
10751 char_u *name;
10752 int n = FALSE;
10753 int len = 0;
10754
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010755 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010756 if (*p == '$') /* environment variable */
10757 {
10758 /* first try "normal" environment variables (fast) */
10759 if (mch_getenv(p + 1) != NULL)
10760 n = TRUE;
10761 else
10762 {
10763 /* try expanding things like $VIM and ${HOME} */
10764 p = expand_env_save(p);
10765 if (p != NULL && *p != '$')
10766 n = TRUE;
10767 vim_free(p);
10768 }
10769 }
10770 else if (*p == '&' || *p == '+') /* option */
Bram Moolenaar79783442006-05-05 21:18:03 +000010771 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010772 n = (get_option_tv(&p, NULL, TRUE) == OK);
Bram Moolenaar79783442006-05-05 21:18:03 +000010773 if (*skipwhite(p) != NUL)
10774 n = FALSE; /* trailing garbage */
10775 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010776 else if (*p == '*') /* internal or user defined function */
10777 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010778 n = function_exists(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010779 }
10780 else if (*p == ':')
10781 {
10782 n = cmd_exists(p + 1);
10783 }
10784 else if (*p == '#')
10785 {
10786#ifdef FEAT_AUTOCMD
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +000010787 if (p[1] == '#')
10788 n = autocmd_supported(p + 2);
10789 else
10790 n = au_exists(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010791#endif
10792 }
10793 else /* internal variable */
10794 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010795 char_u *tofree;
10796 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010797
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010798 /* get_name_len() takes care of expanding curly braces */
10799 name = p;
10800 len = get_name_len(&p, &tofree, TRUE, FALSE);
10801 if (len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010802 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010803 if (tofree != NULL)
10804 name = tofree;
Bram Moolenaar1cd5e612015-05-04 11:10:27 +020010805 n = (get_var_tv(name, len, &tv, NULL, FALSE, TRUE) == OK);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010806 if (n)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010807 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010808 /* handle d.key, l[idx], f(expr) */
10809 n = (handle_subscript(&p, &tv, TRUE, FALSE) == OK);
10810 if (n)
10811 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010812 }
10813 }
Bram Moolenaar79783442006-05-05 21:18:03 +000010814 if (*p != NUL)
10815 n = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010816
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010817 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010818 }
10819
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010820 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010821}
10822
Bram Moolenaardb7c6862010-05-21 16:33:48 +020010823#ifdef FEAT_FLOAT
10824/*
10825 * "exp()" function
10826 */
10827 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010828f_exp(typval_T *argvars, typval_T *rettv)
Bram Moolenaardb7c6862010-05-21 16:33:48 +020010829{
Bram Moolenaara1e24b92016-02-18 20:18:09 +010010830 float_T f = 0.0;
Bram Moolenaardb7c6862010-05-21 16:33:48 +020010831
10832 rettv->v_type = VAR_FLOAT;
10833 if (get_float_arg(argvars, &f) == OK)
10834 rettv->vval.v_float = exp(f);
10835 else
10836 rettv->vval.v_float = 0.0;
10837}
10838#endif
10839
Bram Moolenaar071d4272004-06-13 20:20:40 +000010840/*
10841 * "expand()" function
10842 */
10843 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010844f_expand(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010845{
10846 char_u *s;
10847 int len;
10848 char_u *errormsg;
Bram Moolenaar005c3c22010-12-02 21:44:40 +010010849 int options = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010850 expand_T xpc;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010851 int error = FALSE;
Bram Moolenaar146e9c32012-03-07 19:18:23 +010010852 char_u *result;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010853
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010854 rettv->v_type = VAR_STRING;
Bram Moolenaar146e9c32012-03-07 19:18:23 +010010855 if (argvars[1].v_type != VAR_UNKNOWN
10856 && argvars[2].v_type != VAR_UNKNOWN
10857 && get_tv_number_chk(&argvars[2], &error)
10858 && !error)
10859 {
10860 rettv->v_type = VAR_LIST;
10861 rettv->vval.v_list = NULL;
10862 }
10863
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010864 s = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010865 if (*s == '%' || *s == '#' || *s == '<')
10866 {
10867 ++emsg_off;
Bram Moolenaar146e9c32012-03-07 19:18:23 +010010868 result = eval_vars(s, s, &len, NULL, &errormsg, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010869 --emsg_off;
Bram Moolenaar146e9c32012-03-07 19:18:23 +010010870 if (rettv->v_type == VAR_LIST)
10871 {
10872 if (rettv_list_alloc(rettv) != FAIL && result != NULL)
10873 list_append_string(rettv->vval.v_list, result, -1);
10874 else
10875 vim_free(result);
10876 }
10877 else
10878 rettv->vval.v_string = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010879 }
10880 else
10881 {
10882 /* When the optional second argument is non-zero, don't remove matches
Bram Moolenaarbb5ddda2008-11-28 10:01:10 +000010883 * for 'wildignore' and don't put matches for 'suffixes' at the end. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010884 if (argvars[1].v_type != VAR_UNKNOWN
10885 && get_tv_number_chk(&argvars[1], &error))
Bram Moolenaar005c3c22010-12-02 21:44:40 +010010886 options |= WILD_KEEP_ALL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010887 if (!error)
10888 {
10889 ExpandInit(&xpc);
10890 xpc.xp_context = EXPAND_FILES;
Bram Moolenaar005c3c22010-12-02 21:44:40 +010010891 if (p_wic)
10892 options += WILD_ICASE;
Bram Moolenaar146e9c32012-03-07 19:18:23 +010010893 if (rettv->v_type == VAR_STRING)
10894 rettv->vval.v_string = ExpandOne(&xpc, s, NULL,
10895 options, WILD_ALL);
10896 else if (rettv_list_alloc(rettv) != FAIL)
10897 {
10898 int i;
10899
10900 ExpandOne(&xpc, s, NULL, options, WILD_ALL_KEEP);
10901 for (i = 0; i < xpc.xp_numfiles; i++)
10902 list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1);
10903 ExpandCleanup(&xpc);
10904 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010905 }
10906 else
10907 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010908 }
10909}
10910
10911/*
Bram Moolenaara9922d62013-05-30 13:01:18 +020010912 * Go over all entries in "d2" and add them to "d1".
10913 * When "action" is "error" then a duplicate key is an error.
10914 * When "action" is "force" then a duplicate key is overwritten.
10915 * Otherwise duplicate keys are ignored ("action" is "keep").
10916 */
10917 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010918dict_extend(dict_T *d1, dict_T *d2, char_u *action)
Bram Moolenaara9922d62013-05-30 13:01:18 +020010919{
10920 dictitem_T *di1;
10921 hashitem_T *hi2;
10922 int todo;
Bram Moolenaar77354e72015-04-21 16:49:05 +020010923 char_u *arg_errmsg = (char_u *)N_("extend() argument");
Bram Moolenaara9922d62013-05-30 13:01:18 +020010924
10925 todo = (int)d2->dv_hashtab.ht_used;
10926 for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2)
10927 {
10928 if (!HASHITEM_EMPTY(hi2))
10929 {
10930 --todo;
10931 di1 = dict_find(d1, hi2->hi_key, -1);
10932 if (d1->dv_scope != 0)
10933 {
10934 /* Disallow replacing a builtin function in l: and g:.
10935 * Check the key to be valid when adding to any
10936 * scope. */
10937 if (d1->dv_scope == VAR_DEF_SCOPE
10938 && HI2DI(hi2)->di_tv.v_type == VAR_FUNC
10939 && var_check_func_name(hi2->hi_key,
10940 di1 == NULL))
10941 break;
10942 if (!valid_varname(hi2->hi_key))
10943 break;
10944 }
10945 if (di1 == NULL)
10946 {
10947 di1 = dictitem_copy(HI2DI(hi2));
10948 if (di1 != NULL && dict_add(d1, di1) == FAIL)
10949 dictitem_free(di1);
10950 }
10951 else if (*action == 'e')
10952 {
10953 EMSG2(_("E737: Key already exists: %s"), hi2->hi_key);
10954 break;
10955 }
10956 else if (*action == 'f' && HI2DI(hi2) != di1)
10957 {
Bram Moolenaar77354e72015-04-21 16:49:05 +020010958 if (tv_check_lock(di1->di_tv.v_lock, arg_errmsg, TRUE)
10959 || var_check_ro(di1->di_flags, arg_errmsg, TRUE))
Bram Moolenaar9bc174b2015-04-13 16:16:38 +020010960 break;
Bram Moolenaara9922d62013-05-30 13:01:18 +020010961 clear_tv(&di1->di_tv);
10962 copy_tv(&HI2DI(hi2)->di_tv, &di1->di_tv);
10963 }
10964 }
10965 }
10966}
10967
10968/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010969 * "extend(list, list [, idx])" function
Bram Moolenaare9a41262005-01-15 22:18:47 +000010970 * "extend(dict, dict [, action])" function
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010971 */
10972 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010010973f_extend(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010974{
Bram Moolenaar77354e72015-04-21 16:49:05 +020010975 char_u *arg_errmsg = (char_u *)N_("extend() argument");
Bram Moolenaar32f649e2011-04-11 13:46:13 +020010976
Bram Moolenaare9a41262005-01-15 22:18:47 +000010977 if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010978 {
Bram Moolenaar33570922005-01-25 22:26:29 +000010979 list_T *l1, *l2;
10980 listitem_T *item;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010981 long before;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010982 int error = FALSE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010983
Bram Moolenaare9a41262005-01-15 22:18:47 +000010984 l1 = argvars[0].vval.v_list;
10985 l2 = argvars[1].vval.v_list;
Bram Moolenaar77354e72015-04-21 16:49:05 +020010986 if (l1 != NULL && !tv_check_lock(l1->lv_lock, arg_errmsg, TRUE)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010987 && l2 != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000010988 {
10989 if (argvars[2].v_type != VAR_UNKNOWN)
10990 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010991 before = get_tv_number_chk(&argvars[2], &error);
10992 if (error)
10993 return; /* type error; errmsg already given */
10994
Bram Moolenaar758711c2005-02-02 23:11:38 +000010995 if (before == l1->lv_len)
10996 item = NULL;
10997 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000010998 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000010999 item = list_find(l1, before);
11000 if (item == NULL)
11001 {
11002 EMSGN(_(e_listidx), before);
11003 return;
11004 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000011005 }
11006 }
11007 else
11008 item = NULL;
11009 list_extend(l1, l2, item);
11010
Bram Moolenaare9a41262005-01-15 22:18:47 +000011011 copy_tv(&argvars[0], rettv);
11012 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011013 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000011014 else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT)
11015 {
Bram Moolenaara9922d62013-05-30 13:01:18 +020011016 dict_T *d1, *d2;
11017 char_u *action;
11018 int i;
Bram Moolenaare9a41262005-01-15 22:18:47 +000011019
11020 d1 = argvars[0].vval.v_dict;
11021 d2 = argvars[1].vval.v_dict;
Bram Moolenaar77354e72015-04-21 16:49:05 +020011022 if (d1 != NULL && !tv_check_lock(d1->dv_lock, arg_errmsg, TRUE)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011023 && d2 != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000011024 {
11025 /* Check the third argument. */
11026 if (argvars[2].v_type != VAR_UNKNOWN)
11027 {
11028 static char *(av[]) = {"keep", "force", "error"};
11029
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011030 action = get_tv_string_chk(&argvars[2]);
11031 if (action == NULL)
11032 return; /* type error; errmsg already given */
Bram Moolenaare9a41262005-01-15 22:18:47 +000011033 for (i = 0; i < 3; ++i)
11034 if (STRCMP(action, av[i]) == 0)
11035 break;
11036 if (i == 3)
11037 {
Bram Moolenaareb3593b2006-04-22 22:33:57 +000011038 EMSG2(_(e_invarg2), action);
Bram Moolenaare9a41262005-01-15 22:18:47 +000011039 return;
11040 }
11041 }
11042 else
11043 action = (char_u *)"force";
11044
Bram Moolenaara9922d62013-05-30 13:01:18 +020011045 dict_extend(d1, d2, action);
Bram Moolenaare9a41262005-01-15 22:18:47 +000011046
Bram Moolenaare9a41262005-01-15 22:18:47 +000011047 copy_tv(&argvars[0], rettv);
11048 }
11049 }
11050 else
11051 EMSG2(_(e_listdictarg), "extend()");
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011052}
11053
11054/*
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000011055 * "feedkeys()" function
11056 */
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000011057 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011058f_feedkeys(typval_T *argvars, typval_T *rettv UNUSED)
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000011059{
11060 int remap = TRUE;
Bram Moolenaar0a988df2015-01-27 15:19:24 +010011061 int insert = FALSE;
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000011062 char_u *keys, *flags;
11063 char_u nbuf[NUMBUFLEN];
11064 int typed = FALSE;
Bram Moolenaar5f8a14b2016-01-21 23:34:58 +010011065 int execute = FALSE;
Bram Moolenaarf193fff2006-04-27 00:02:13 +000011066 char_u *keys_esc;
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000011067
Bram Moolenaar3d43a662007-04-27 20:15:55 +000011068 /* This is not allowed in the sandbox. If the commands would still be
11069 * executed in the sandbox it would be OK, but it probably happens later,
11070 * when "sandbox" is no longer set. */
11071 if (check_secure())
11072 return;
11073
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000011074 keys = get_tv_string(&argvars[0]);
Bram Moolenaar74c5bbf2016-03-10 22:19:53 +010011075
11076 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000011077 {
Bram Moolenaar74c5bbf2016-03-10 22:19:53 +010011078 flags = get_tv_string_buf(&argvars[1], nbuf);
11079 for ( ; *flags != NUL; ++flags)
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000011080 {
Bram Moolenaar74c5bbf2016-03-10 22:19:53 +010011081 switch (*flags)
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000011082 {
Bram Moolenaar74c5bbf2016-03-10 22:19:53 +010011083 case 'n': remap = FALSE; break;
11084 case 'm': remap = TRUE; break;
11085 case 't': typed = TRUE; break;
11086 case 'i': insert = TRUE; break;
11087 case 'x': execute = TRUE; break;
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000011088 }
11089 }
Bram Moolenaar74c5bbf2016-03-10 22:19:53 +010011090 }
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000011091
Bram Moolenaar74c5bbf2016-03-10 22:19:53 +010011092 if (*keys != NUL || execute)
11093 {
Bram Moolenaarf193fff2006-04-27 00:02:13 +000011094 /* Need to escape K_SPECIAL and CSI before putting the string in the
11095 * typeahead buffer. */
11096 keys_esc = vim_strsave_escape_csi(keys);
11097 if (keys_esc != NULL)
11098 {
11099 ins_typebuf(keys_esc, (remap ? REMAP_YES : REMAP_NONE),
Bram Moolenaar0a988df2015-01-27 15:19:24 +010011100 insert ? 0 : typebuf.tb_len, !typed, FALSE);
Bram Moolenaarf193fff2006-04-27 00:02:13 +000011101 vim_free(keys_esc);
Bram Moolenaar437df8f2006-04-27 21:47:44 +000011102 if (vgetc_busy)
11103 typebuf_was_filled = TRUE;
Bram Moolenaar5f8a14b2016-01-21 23:34:58 +010011104 if (execute)
Bram Moolenaar9e496852016-03-11 19:31:47 +010011105 {
11106 int save_msg_scroll = msg_scroll;
11107
11108 /* Avoid a 1 second delay when the keys start Insert mode. */
11109 msg_scroll = FALSE;
Bram Moolenaar5f8a14b2016-01-21 23:34:58 +010011110 exec_normal(TRUE);
Bram Moolenaar9e496852016-03-11 19:31:47 +010011111 msg_scroll |= save_msg_scroll;
11112 }
Bram Moolenaarf193fff2006-04-27 00:02:13 +000011113 }
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000011114 }
11115}
11116
11117/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011118 * "filereadable()" function
11119 */
11120 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011121f_filereadable(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011122{
Bram Moolenaarc236c162008-07-13 17:41:49 +000011123 int fd;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011124 char_u *p;
11125 int n;
11126
Bram Moolenaarc236c162008-07-13 17:41:49 +000011127#ifndef O_NONBLOCK
11128# define O_NONBLOCK 0
11129#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011130 p = get_tv_string(&argvars[0]);
Bram Moolenaarc236c162008-07-13 17:41:49 +000011131 if (*p && !mch_isdir(p) && (fd = mch_open((char *)p,
11132 O_RDONLY | O_NONBLOCK, 0)) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011133 {
11134 n = TRUE;
Bram Moolenaarc236c162008-07-13 17:41:49 +000011135 close(fd);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011136 }
11137 else
11138 n = FALSE;
11139
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011140 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011141}
11142
11143/*
Bram Moolenaar0e4d8772005-06-07 21:12:49 +000011144 * Return 0 for not writable, 1 for writable file, 2 for a dir which we have
Bram Moolenaar071d4272004-06-13 20:20:40 +000011145 * rights to write into.
11146 */
11147 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011148f_filewritable(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011149{
Bram Moolenaar0e4d8772005-06-07 21:12:49 +000011150 rettv->vval.v_number = filewritable(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000011151}
11152
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011153 static void
Bram Moolenaard14e00e2016-01-31 17:30:51 +010011154findfilendir(
11155 typval_T *argvars UNUSED,
11156 typval_T *rettv,
11157 int find_what UNUSED)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011158{
11159#ifdef FEAT_SEARCHPATH
11160 char_u *fname;
11161 char_u *fresult = NULL;
11162 char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
11163 char_u *p;
11164 char_u pathbuf[NUMBUFLEN];
11165 int count = 1;
11166 int first = TRUE;
Bram Moolenaar899dddf2006-03-26 21:06:50 +000011167 int error = FALSE;
11168#endif
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011169
Bram Moolenaar899dddf2006-03-26 21:06:50 +000011170 rettv->vval.v_string = NULL;
11171 rettv->v_type = VAR_STRING;
11172
11173#ifdef FEAT_SEARCHPATH
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011174 fname = get_tv_string(&argvars[0]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011175
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011176 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011177 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011178 p = get_tv_string_buf_chk(&argvars[1], pathbuf);
11179 if (p == NULL)
Bram Moolenaar899dddf2006-03-26 21:06:50 +000011180 error = TRUE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011181 else
11182 {
11183 if (*p != NUL)
11184 path = p;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011185
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011186 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar899dddf2006-03-26 21:06:50 +000011187 count = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011188 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011189 }
11190
Bram Moolenaar899dddf2006-03-26 21:06:50 +000011191 if (count < 0 && rettv_list_alloc(rettv) == FAIL)
11192 error = TRUE;
11193
11194 if (*fname != NUL && !error)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011195 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011196 do
11197 {
Bram Moolenaardf2bc272013-06-24 22:17:32 +020011198 if (rettv->v_type == VAR_STRING || rettv->v_type == VAR_LIST)
Bram Moolenaar899dddf2006-03-26 21:06:50 +000011199 vim_free(fresult);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011200 fresult = find_file_in_path_option(first ? fname : NULL,
11201 first ? (int)STRLEN(fname) : 0,
Bram Moolenaar4d0ec162008-02-20 11:24:52 +000011202 0, first, path,
11203 find_what,
11204 curbuf->b_ffname,
11205 find_what == FINDFILE_DIR
11206 ? (char_u *)"" : curbuf->b_p_sua);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011207 first = FALSE;
Bram Moolenaar899dddf2006-03-26 21:06:50 +000011208
11209 if (fresult != NULL && rettv->v_type == VAR_LIST)
11210 list_append_string(rettv->vval.v_list, fresult, -1);
11211
11212 } while ((rettv->v_type == VAR_LIST || --count > 0) && fresult != NULL);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011213 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011214
Bram Moolenaar899dddf2006-03-26 21:06:50 +000011215 if (rettv->v_type == VAR_STRING)
11216 rettv->vval.v_string = fresult;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011217#endif
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011218}
11219
Bram Moolenaar48e697e2016-01-23 22:17:30 +010011220static void filter_map(typval_T *argvars, typval_T *rettv, int map);
11221static int filter_map_one(typval_T *tv, char_u *expr, int map, int *remp);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011222
11223/*
11224 * Implementation of map() and filter().
11225 */
11226 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011227filter_map(typval_T *argvars, typval_T *rettv, int map)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011228{
11229 char_u buf[NUMBUFLEN];
Bram Moolenaare9a41262005-01-15 22:18:47 +000011230 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +000011231 listitem_T *li, *nli;
11232 list_T *l = NULL;
11233 dictitem_T *di;
11234 hashtab_T *ht;
11235 hashitem_T *hi;
11236 dict_T *d = NULL;
11237 typval_T save_val;
11238 typval_T save_key;
Bram Moolenaare9a41262005-01-15 22:18:47 +000011239 int rem;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011240 int todo;
Bram Moolenaar32f649e2011-04-11 13:46:13 +020011241 char_u *ermsg = (char_u *)(map ? "map()" : "filter()");
Bram Moolenaar77354e72015-04-21 16:49:05 +020011242 char_u *arg_errmsg = (char_u *)(map ? N_("map() argument")
Bram Moolenaar32f649e2011-04-11 13:46:13 +020011243 : N_("filter() argument"));
Bram Moolenaar1f35bf92006-03-07 22:38:47 +000011244 int save_did_emsg;
Bram Moolenaarf506c5b2010-06-22 06:28:58 +020011245 int idx = 0;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011246
Bram Moolenaare9a41262005-01-15 22:18:47 +000011247 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011248 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011249 if ((l = argvars[0].vval.v_list) == NULL
Bram Moolenaar77354e72015-04-21 16:49:05 +020011250 || (!map && tv_check_lock(l->lv_lock, arg_errmsg, TRUE)))
Bram Moolenaare9a41262005-01-15 22:18:47 +000011251 return;
11252 }
11253 else if (argvars[0].v_type == VAR_DICT)
11254 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011255 if ((d = argvars[0].vval.v_dict) == NULL
Bram Moolenaar77354e72015-04-21 16:49:05 +020011256 || (!map && tv_check_lock(d->dv_lock, arg_errmsg, TRUE)))
Bram Moolenaare9a41262005-01-15 22:18:47 +000011257 return;
11258 }
11259 else
11260 {
Bram Moolenaar89d40322006-08-29 15:30:07 +000011261 EMSG2(_(e_listdictarg), ermsg);
Bram Moolenaare9a41262005-01-15 22:18:47 +000011262 return;
11263 }
11264
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011265 expr = get_tv_string_buf_chk(&argvars[1], buf);
11266 /* On type errors, the preceding call has already displayed an error
11267 * message. Avoid a misleading error message for an empty string that
11268 * was not passed as argument. */
11269 if (expr != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000011270 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011271 prepare_vimvar(VV_VAL, &save_val);
11272 expr = skipwhite(expr);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011273
Bram Moolenaar1f35bf92006-03-07 22:38:47 +000011274 /* We reset "did_emsg" to be able to detect whether an error
11275 * occurred during evaluation of the expression. */
11276 save_did_emsg = did_emsg;
11277 did_emsg = FALSE;
Bram Moolenaar280f1262006-01-30 00:14:18 +000011278
Bram Moolenaar627b1d32009-11-17 11:20:35 +000011279 prepare_vimvar(VV_KEY, &save_key);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011280 if (argvars[0].v_type == VAR_DICT)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011281 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011282 vimvars[VV_KEY].vv_type = VAR_STRING;
11283
11284 ht = &d->dv_hashtab;
11285 hash_lock(ht);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000011286 todo = (int)ht->ht_used;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011287 for (hi = ht->ht_array; todo > 0; ++hi)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011288 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011289 if (!HASHITEM_EMPTY(hi))
11290 {
Bram Moolenaarb738c9a2014-11-19 20:04:48 +010011291 int r;
11292
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011293 --todo;
11294 di = HI2DI(hi);
Bram Moolenaar9bc174b2015-04-13 16:16:38 +020011295 if (map &&
Bram Moolenaar77354e72015-04-21 16:49:05 +020011296 (tv_check_lock(di->di_tv.v_lock, arg_errmsg, TRUE)
11297 || var_check_ro(di->di_flags, arg_errmsg, TRUE)))
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011298 break;
11299 vimvars[VV_KEY].vv_str = vim_strsave(di->di_key);
Bram Moolenaarb738c9a2014-11-19 20:04:48 +010011300 r = filter_map_one(&di->di_tv, expr, map, &rem);
11301 clear_tv(&vimvars[VV_KEY].vv_tv);
11302 if (r == FAIL || did_emsg)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011303 break;
11304 if (!map && rem)
Bram Moolenaar9bc174b2015-04-13 16:16:38 +020011305 {
Bram Moolenaar77354e72015-04-21 16:49:05 +020011306 if (var_check_fixed(di->di_flags, arg_errmsg, TRUE)
11307 || var_check_ro(di->di_flags, arg_errmsg, TRUE))
Bram Moolenaar9bc174b2015-04-13 16:16:38 +020011308 break;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011309 dictitem_remove(d, di);
Bram Moolenaar9bc174b2015-04-13 16:16:38 +020011310 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011311 }
11312 }
11313 hash_unlock(ht);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011314 }
11315 else
11316 {
Bram Moolenaar627b1d32009-11-17 11:20:35 +000011317 vimvars[VV_KEY].vv_type = VAR_NUMBER;
11318
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011319 for (li = l->lv_first; li != NULL; li = nli)
11320 {
Bram Moolenaar77354e72015-04-21 16:49:05 +020011321 if (map && tv_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE))
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011322 break;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011323 nli = li->li_next;
Bram Moolenaarf506c5b2010-06-22 06:28:58 +020011324 vimvars[VV_KEY].vv_nr = idx;
Bram Moolenaar280f1262006-01-30 00:14:18 +000011325 if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL
Bram Moolenaar1f35bf92006-03-07 22:38:47 +000011326 || did_emsg)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011327 break;
11328 if (!map && rem)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011329 listitem_remove(l, li);
Bram Moolenaarf506c5b2010-06-22 06:28:58 +020011330 ++idx;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011331 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011332 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011333
Bram Moolenaar627b1d32009-11-17 11:20:35 +000011334 restore_vimvar(VV_KEY, &save_key);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011335 restore_vimvar(VV_VAL, &save_val);
Bram Moolenaar280f1262006-01-30 00:14:18 +000011336
Bram Moolenaar1f35bf92006-03-07 22:38:47 +000011337 did_emsg |= save_did_emsg;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011338 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000011339
11340 copy_tv(&argvars[0], rettv);
11341}
11342
11343 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010011344filter_map_one(typval_T *tv, char_u *expr, int map, int *remp)
Bram Moolenaare9a41262005-01-15 22:18:47 +000011345{
Bram Moolenaar33570922005-01-25 22:26:29 +000011346 typval_T rettv;
Bram Moolenaare9a41262005-01-15 22:18:47 +000011347 char_u *s;
Bram Moolenaarb4066a12007-09-17 19:38:08 +000011348 int retval = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000011349
Bram Moolenaar33570922005-01-25 22:26:29 +000011350 copy_tv(tv, &vimvars[VV_VAL].vv_tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +000011351 s = expr;
11352 if (eval1(&s, &rettv, TRUE) == FAIL)
Bram Moolenaarb4066a12007-09-17 19:38:08 +000011353 goto theend;
Bram Moolenaare9a41262005-01-15 22:18:47 +000011354 if (*s != NUL) /* check for trailing chars after expr */
11355 {
11356 EMSG2(_(e_invexpr2), s);
Bram Moolenaarb738c9a2014-11-19 20:04:48 +010011357 clear_tv(&rettv);
Bram Moolenaarb4066a12007-09-17 19:38:08 +000011358 goto theend;
Bram Moolenaare9a41262005-01-15 22:18:47 +000011359 }
11360 if (map)
11361 {
11362 /* map(): replace the list item value */
11363 clear_tv(tv);
Bram Moolenaar4463f292005-09-25 22:20:24 +000011364 rettv.v_lock = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +000011365 *tv = rettv;
11366 }
11367 else
11368 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011369 int error = FALSE;
11370
Bram Moolenaare9a41262005-01-15 22:18:47 +000011371 /* filter(): when expr is zero remove the item */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011372 *remp = (get_tv_number_chk(&rettv, &error) == 0);
Bram Moolenaare9a41262005-01-15 22:18:47 +000011373 clear_tv(&rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011374 /* On type error, nothing has been removed; return FAIL to stop the
11375 * loop. The error message was given by get_tv_number_chk(). */
11376 if (error)
Bram Moolenaarb4066a12007-09-17 19:38:08 +000011377 goto theend;
Bram Moolenaare9a41262005-01-15 22:18:47 +000011378 }
Bram Moolenaarb4066a12007-09-17 19:38:08 +000011379 retval = OK;
11380theend:
Bram Moolenaar33570922005-01-25 22:26:29 +000011381 clear_tv(&vimvars[VV_VAL].vv_tv);
Bram Moolenaarb4066a12007-09-17 19:38:08 +000011382 return retval;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011383}
11384
11385/*
11386 * "filter()" function
11387 */
11388 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011389f_filter(typval_T *argvars, typval_T *rettv)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011390{
11391 filter_map(argvars, rettv, FALSE);
11392}
11393
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011394/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011395 * "finddir({fname}[, {path}[, {count}]])" function
11396 */
11397 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011398f_finddir(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000011399{
Bram Moolenaar4d0ec162008-02-20 11:24:52 +000011400 findfilendir(argvars, rettv, FINDFILE_DIR);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011401}
11402
11403/*
11404 * "findfile({fname}[, {path}[, {count}]])" function
11405 */
11406 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011407f_findfile(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000011408{
Bram Moolenaar4d0ec162008-02-20 11:24:52 +000011409 findfilendir(argvars, rettv, FINDFILE_FILE);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011410}
11411
Bram Moolenaar8c8de832008-06-24 22:58:06 +000011412#ifdef FEAT_FLOAT
11413/*
11414 * "float2nr({float})" function
11415 */
11416 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011417f_float2nr(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8c8de832008-06-24 22:58:06 +000011418{
Bram Moolenaara1e24b92016-02-18 20:18:09 +010011419 float_T f = 0.0;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000011420
11421 if (get_float_arg(argvars, &f) == OK)
11422 {
11423 if (f < -0x7fffffff)
11424 rettv->vval.v_number = -0x7fffffff;
11425 else if (f > 0x7fffffff)
11426 rettv->vval.v_number = 0x7fffffff;
11427 else
11428 rettv->vval.v_number = (varnumber_T)f;
11429 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +000011430}
11431
11432/*
11433 * "floor({float})" function
11434 */
11435 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011436f_floor(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8c8de832008-06-24 22:58:06 +000011437{
Bram Moolenaara1e24b92016-02-18 20:18:09 +010011438 float_T f = 0.0;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000011439
11440 rettv->v_type = VAR_FLOAT;
11441 if (get_float_arg(argvars, &f) == OK)
11442 rettv->vval.v_float = floor(f);
11443 else
11444 rettv->vval.v_float = 0.0;
11445}
Bram Moolenaardb7c6862010-05-21 16:33:48 +020011446
11447/*
11448 * "fmod()" function
11449 */
11450 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011451f_fmod(typval_T *argvars, typval_T *rettv)
Bram Moolenaardb7c6862010-05-21 16:33:48 +020011452{
Bram Moolenaara1e24b92016-02-18 20:18:09 +010011453 float_T fx = 0.0, fy = 0.0;
Bram Moolenaardb7c6862010-05-21 16:33:48 +020011454
11455 rettv->v_type = VAR_FLOAT;
11456 if (get_float_arg(argvars, &fx) == OK
11457 && get_float_arg(&argvars[1], &fy) == OK)
11458 rettv->vval.v_float = fmod(fx, fy);
11459 else
11460 rettv->vval.v_float = 0.0;
11461}
Bram Moolenaar8c8de832008-06-24 22:58:06 +000011462#endif
11463
Bram Moolenaar0d660222005-01-07 21:51:51 +000011464/*
Bram Moolenaaraebaf892008-05-28 14:49:58 +000011465 * "fnameescape({string})" function
11466 */
11467 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011468f_fnameescape(typval_T *argvars, typval_T *rettv)
Bram Moolenaaraebaf892008-05-28 14:49:58 +000011469{
11470 rettv->vval.v_string = vim_strsave_fnameescape(
11471 get_tv_string(&argvars[0]), FALSE);
11472 rettv->v_type = VAR_STRING;
11473}
11474
11475/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011476 * "fnamemodify({fname}, {mods})" function
11477 */
11478 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011479f_fnamemodify(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011480{
11481 char_u *fname;
11482 char_u *mods;
11483 int usedlen = 0;
11484 int len;
11485 char_u *fbuf = NULL;
11486 char_u buf[NUMBUFLEN];
11487
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011488 fname = get_tv_string_chk(&argvars[0]);
11489 mods = get_tv_string_buf_chk(&argvars[1], buf);
11490 if (fname == NULL || mods == NULL)
11491 fname = NULL;
11492 else
11493 {
11494 len = (int)STRLEN(fname);
11495 (void)modify_fname(mods, &usedlen, &fname, &fbuf, &len);
11496 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011497
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011498 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011499 if (fname == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011500 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011501 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011502 rettv->vval.v_string = vim_strnsave(fname, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011503 vim_free(fbuf);
11504}
11505
Bram Moolenaar48e697e2016-01-23 22:17:30 +010011506static void foldclosed_both(typval_T *argvars, typval_T *rettv, int end);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011507
11508/*
11509 * "foldclosed()" function
11510 */
11511 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011512foldclosed_both(
11513 typval_T *argvars UNUSED,
11514 typval_T *rettv,
11515 int end UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011516{
11517#ifdef FEAT_FOLDING
11518 linenr_T lnum;
11519 linenr_T first, last;
11520
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011521 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011522 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
11523 {
11524 if (hasFoldingWin(curwin, lnum, &first, &last, FALSE, NULL))
11525 {
11526 if (end)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011527 rettv->vval.v_number = (varnumber_T)last;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011528 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011529 rettv->vval.v_number = (varnumber_T)first;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011530 return;
11531 }
11532 }
11533#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011534 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011535}
11536
11537/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011538 * "foldclosed()" function
11539 */
11540 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011541f_foldclosed(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000011542{
11543 foldclosed_both(argvars, rettv, FALSE);
11544}
11545
11546/*
11547 * "foldclosedend()" function
11548 */
11549 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011550f_foldclosedend(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000011551{
11552 foldclosed_both(argvars, rettv, TRUE);
11553}
11554
11555/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011556 * "foldlevel()" function
11557 */
11558 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011559f_foldlevel(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011560{
11561#ifdef FEAT_FOLDING
11562 linenr_T lnum;
11563
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011564 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011565 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011566 rettv->vval.v_number = foldLevel(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011567#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000011568}
11569
11570/*
11571 * "foldtext()" function
11572 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011573 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011574f_foldtext(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011575{
11576#ifdef FEAT_FOLDING
11577 linenr_T lnum;
11578 char_u *s;
11579 char_u *r;
11580 int len;
11581 char *txt;
11582#endif
11583
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011584 rettv->v_type = VAR_STRING;
11585 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011586#ifdef FEAT_FOLDING
Bram Moolenaare9a41262005-01-15 22:18:47 +000011587 if ((linenr_T)vimvars[VV_FOLDSTART].vv_nr > 0
11588 && (linenr_T)vimvars[VV_FOLDEND].vv_nr
11589 <= curbuf->b_ml.ml_line_count
11590 && vimvars[VV_FOLDDASHES].vv_str != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011591 {
11592 /* Find first non-empty line in the fold. */
Bram Moolenaare9a41262005-01-15 22:18:47 +000011593 lnum = (linenr_T)vimvars[VV_FOLDSTART].vv_nr;
11594 while (lnum < (linenr_T)vimvars[VV_FOLDEND].vv_nr)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011595 {
11596 if (!linewhite(lnum))
11597 break;
11598 ++lnum;
11599 }
11600
11601 /* Find interesting text in this line. */
11602 s = skipwhite(ml_get(lnum));
11603 /* skip C comment-start */
11604 if (s[0] == '/' && (s[1] == '*' || s[1] == '/'))
Bram Moolenaar293ee4d2004-12-09 21:34:53 +000011605 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000011606 s = skipwhite(s + 2);
Bram Moolenaar293ee4d2004-12-09 21:34:53 +000011607 if (*skipwhite(s) == NUL
Bram Moolenaare9a41262005-01-15 22:18:47 +000011608 && lnum + 1 < (linenr_T)vimvars[VV_FOLDEND].vv_nr)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +000011609 {
11610 s = skipwhite(ml_get(lnum + 1));
11611 if (*s == '*')
11612 s = skipwhite(s + 1);
11613 }
11614 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011615 txt = _("+-%s%3ld lines: ");
11616 r = alloc((unsigned)(STRLEN(txt)
Bram Moolenaare9a41262005-01-15 22:18:47 +000011617 + STRLEN(vimvars[VV_FOLDDASHES].vv_str) /* for %s */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011618 + 20 /* for %3ld */
11619 + STRLEN(s))); /* concatenated */
11620 if (r != NULL)
11621 {
Bram Moolenaare9a41262005-01-15 22:18:47 +000011622 sprintf((char *)r, txt, vimvars[VV_FOLDDASHES].vv_str,
11623 (long)((linenr_T)vimvars[VV_FOLDEND].vv_nr
11624 - (linenr_T)vimvars[VV_FOLDSTART].vv_nr + 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +000011625 len = (int)STRLEN(r);
11626 STRCAT(r, s);
11627 /* remove 'foldmarker' and 'commentstring' */
11628 foldtext_cleanup(r + len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011629 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011630 }
11631 }
11632#endif
11633}
11634
11635/*
Bram Moolenaar7b0294c2004-10-11 10:16:09 +000011636 * "foldtextresult(lnum)" function
11637 */
Bram Moolenaar7b0294c2004-10-11 10:16:09 +000011638 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011639f_foldtextresult(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar7b0294c2004-10-11 10:16:09 +000011640{
11641#ifdef FEAT_FOLDING
11642 linenr_T lnum;
11643 char_u *text;
11644 char_u buf[51];
11645 foldinfo_T foldinfo;
11646 int fold_count;
11647#endif
11648
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011649 rettv->v_type = VAR_STRING;
11650 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +000011651#ifdef FEAT_FOLDING
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011652 lnum = get_tv_lnum(argvars);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011653 /* treat illegal types and illegal string values for {lnum} the same */
11654 if (lnum < 0)
11655 lnum = 0;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +000011656 fold_count = foldedCount(curwin, lnum, &foldinfo);
11657 if (fold_count > 0)
11658 {
11659 text = get_foldtext(curwin, lnum, lnum + fold_count - 1,
11660 &foldinfo, buf);
11661 if (text == buf)
11662 text = vim_strsave(text);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011663 rettv->vval.v_string = text;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +000011664 }
11665#endif
11666}
11667
11668/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011669 * "foreground()" function
11670 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011671 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011672f_foreground(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011673{
Bram Moolenaar071d4272004-06-13 20:20:40 +000011674#ifdef FEAT_GUI
11675 if (gui.in_use)
11676 gui_mch_set_foreground();
11677#else
11678# ifdef WIN32
11679 win32_set_foreground();
11680# endif
11681#endif
11682}
11683
11684/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011685 * "function()" function
11686 */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011687 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011688f_function(typval_T *argvars, typval_T *rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011689{
11690 char_u *s;
11691
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011692 s = get_tv_string(&argvars[0]);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011693 if (s == NULL || *s == NUL || VIM_ISDIGIT(*s))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011694 EMSG2(_(e_invarg2), s);
Bram Moolenaar60bf1f52013-06-12 13:37:43 +020011695 /* Don't check an autoload name for existence here. */
11696 else if (vim_strchr(s, AUTOLOAD_CHAR) == NULL && !function_exists(s))
Bram Moolenaare49b69a2005-01-08 16:11:57 +000011697 EMSG2(_("E700: Unknown function: %s"), s);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011698 else
11699 {
Bram Moolenaar0c6633a2013-06-13 21:24:06 +020011700 if (STRNCMP(s, "s:", 2) == 0 || STRNCMP(s, "<SID>", 5) == 0)
Bram Moolenaar60bf1f52013-06-12 13:37:43 +020011701 {
11702 char sid_buf[25];
Bram Moolenaar0c6633a2013-06-13 21:24:06 +020011703 int off = *s == 's' ? 2 : 5;
Bram Moolenaar60bf1f52013-06-12 13:37:43 +020011704
Bram Moolenaar0c6633a2013-06-13 21:24:06 +020011705 /* Expand s: and <SID> into <SNR>nr_, so that the function can
11706 * also be called from another script. Using trans_function_name()
11707 * would also work, but some plugins depend on the name being
11708 * printable text. */
Bram Moolenaar60bf1f52013-06-12 13:37:43 +020011709 sprintf(sid_buf, "<SNR>%ld_", (long)current_SID);
Bram Moolenaaredb07a22013-06-12 18:13:38 +020011710 rettv->vval.v_string =
Bram Moolenaar0c6633a2013-06-13 21:24:06 +020011711 alloc((int)(STRLEN(sid_buf) + STRLEN(s + off) + 1));
Bram Moolenaar60bf1f52013-06-12 13:37:43 +020011712 if (rettv->vval.v_string != NULL)
11713 {
11714 STRCPY(rettv->vval.v_string, sid_buf);
Bram Moolenaar0c6633a2013-06-13 21:24:06 +020011715 STRCAT(rettv->vval.v_string, s + off);
Bram Moolenaar60bf1f52013-06-12 13:37:43 +020011716 }
11717 }
Bram Moolenaara1544c02013-05-30 12:35:52 +020011718 else
Bram Moolenaar60bf1f52013-06-12 13:37:43 +020011719 rettv->vval.v_string = vim_strsave(s);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011720 rettv->v_type = VAR_FUNC;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011721 }
11722}
11723
11724/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000011725 * "garbagecollect()" function
11726 */
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000011727 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011728f_garbagecollect(typval_T *argvars, typval_T *rettv UNUSED)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000011729{
Bram Moolenaar9fecb462006-09-05 10:59:47 +000011730 /* This is postponed until we are back at the toplevel, because we may be
11731 * using Lists and Dicts internally. E.g.: ":echo [garbagecollect()]". */
11732 want_garbage_collect = TRUE;
Bram Moolenaar9d2c8c12007-09-25 16:00:00 +000011733
11734 if (argvars[0].v_type != VAR_UNKNOWN && get_tv_number(&argvars[0]) == 1)
11735 garbage_collect_at_exit = TRUE;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000011736}
11737
11738/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011739 * "get()" function
11740 */
11741 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011742f_get(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000011743{
Bram Moolenaar33570922005-01-25 22:26:29 +000011744 listitem_T *li;
11745 list_T *l;
11746 dictitem_T *di;
11747 dict_T *d;
11748 typval_T *tv = NULL;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011749
Bram Moolenaare9a41262005-01-15 22:18:47 +000011750 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar0d660222005-01-07 21:51:51 +000011751 {
Bram Moolenaare9a41262005-01-15 22:18:47 +000011752 if ((l = argvars[0].vval.v_list) != NULL)
Bram Moolenaar0d660222005-01-07 21:51:51 +000011753 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011754 int error = FALSE;
11755
11756 li = list_find(l, get_tv_number_chk(&argvars[1], &error));
11757 if (!error && li != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000011758 tv = &li->li_tv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011759 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000011760 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000011761 else if (argvars[0].v_type == VAR_DICT)
11762 {
11763 if ((d = argvars[0].vval.v_dict) != NULL)
11764 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011765 di = dict_find(d, get_tv_string(&argvars[1]), -1);
Bram Moolenaare9a41262005-01-15 22:18:47 +000011766 if (di != NULL)
11767 tv = &di->di_tv;
11768 }
11769 }
11770 else
11771 EMSG2(_(e_listdictarg), "get()");
11772
11773 if (tv == NULL)
11774 {
Bram Moolenaar798b30b2009-04-22 10:56:16 +000011775 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaare9a41262005-01-15 22:18:47 +000011776 copy_tv(&argvars[2], rettv);
11777 }
11778 else
11779 copy_tv(tv, rettv);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011780}
11781
Bram Moolenaar48e697e2016-01-23 22:17:30 +010011782static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retlist, typval_T *rettv);
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011783
11784/*
11785 * Get line or list of lines from buffer "buf" into "rettv".
Bram Moolenaar342337a2005-07-21 21:11:17 +000011786 * Return a range (from start to end) of lines in rettv from the specified
11787 * buffer.
11788 * If 'retlist' is TRUE, then the lines are returned as a Vim List.
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011789 */
11790 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011791get_buffer_lines(
11792 buf_T *buf,
11793 linenr_T start,
11794 linenr_T end,
11795 int retlist,
11796 typval_T *rettv)
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011797{
11798 char_u *p;
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011799
Bram Moolenaar959a1432013-12-14 12:17:38 +010011800 rettv->v_type = VAR_STRING;
11801 rettv->vval.v_string = NULL;
Bram Moolenaar798b30b2009-04-22 10:56:16 +000011802 if (retlist && rettv_list_alloc(rettv) == FAIL)
11803 return;
Bram Moolenaar342337a2005-07-21 21:11:17 +000011804
11805 if (buf == NULL || buf->b_ml.ml_mfp == NULL || start < 0)
11806 return;
11807
11808 if (!retlist)
11809 {
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011810 if (start >= 1 && start <= buf->b_ml.ml_line_count)
11811 p = ml_get_buf(buf, start, FALSE);
11812 else
11813 p = (char_u *)"";
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011814 rettv->vval.v_string = vim_strsave(p);
11815 }
11816 else
11817 {
11818 if (end < start)
Bram Moolenaar342337a2005-07-21 21:11:17 +000011819 return;
11820
11821 if (start < 1)
11822 start = 1;
11823 if (end > buf->b_ml.ml_line_count)
11824 end = buf->b_ml.ml_line_count;
11825 while (start <= end)
Bram Moolenaareddf53b2006-02-27 00:11:10 +000011826 if (list_append_string(rettv->vval.v_list,
11827 ml_get_buf(buf, start++, FALSE), -1) == FAIL)
Bram Moolenaar342337a2005-07-21 21:11:17 +000011828 break;
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011829 }
11830}
11831
11832/*
11833 * "getbufline()" function
11834 */
11835 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011836f_getbufline(typval_T *argvars, typval_T *rettv)
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011837{
11838 linenr_T lnum;
11839 linenr_T end;
11840 buf_T *buf;
11841
11842 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
11843 ++emsg_off;
Bram Moolenaar0c279bb2013-03-19 14:25:54 +010011844 buf = get_buf_tv(&argvars[0], FALSE);
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011845 --emsg_off;
11846
Bram Moolenaar661b1822005-07-28 22:36:45 +000011847 lnum = get_tv_lnum_buf(&argvars[1], buf);
Bram Moolenaar342337a2005-07-21 21:11:17 +000011848 if (argvars[2].v_type == VAR_UNKNOWN)
11849 end = lnum;
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011850 else
Bram Moolenaar661b1822005-07-28 22:36:45 +000011851 end = get_tv_lnum_buf(&argvars[2], buf);
11852
Bram Moolenaar342337a2005-07-21 21:11:17 +000011853 get_buffer_lines(buf, lnum, end, TRUE, rettv);
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011854}
11855
Bram Moolenaar0d660222005-01-07 21:51:51 +000011856/*
11857 * "getbufvar()" function
11858 */
11859 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011860f_getbufvar(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000011861{
11862 buf_T *buf;
11863 buf_T *save_curbuf;
11864 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000011865 dictitem_T *v;
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020011866 int done = FALSE;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011867
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011868 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
11869 varname = get_tv_string_chk(&argvars[1]);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011870 ++emsg_off;
Bram Moolenaar0c279bb2013-03-19 14:25:54 +010011871 buf = get_buf_tv(&argvars[0], FALSE);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011872
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020011873 rettv->v_type = VAR_STRING;
11874 rettv->vval.v_string = NULL;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011875
11876 if (buf != NULL && varname != NULL)
11877 {
Bram Moolenaar632deed2008-06-27 18:26:11 +000011878 /* set curbuf to be our buf, temporarily */
11879 save_curbuf = curbuf;
11880 curbuf = buf;
11881
Bram Moolenaar0d660222005-01-07 21:51:51 +000011882 if (*varname == '&') /* buffer-local-option */
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020011883 {
11884 if (get_option_tv(&varname, rettv, TRUE) == OK)
11885 done = TRUE;
11886 }
Bram Moolenaar445edda2011-01-22 01:13:39 +010011887 else if (STRCMP(varname, "changedtick") == 0)
11888 {
11889 rettv->v_type = VAR_NUMBER;
11890 rettv->vval.v_number = curbuf->b_changedtick;
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020011891 done = TRUE;
Bram Moolenaar445edda2011-01-22 01:13:39 +010011892 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000011893 else
11894 {
Bram Moolenaar332ac062013-04-15 13:06:21 +020011895 /* Look up the variable. */
11896 /* Let getbufvar({nr}, "") return the "b:" dictionary. */
11897 v = find_var_in_ht(&curbuf->b_vars->dv_hashtab,
11898 'b', varname, FALSE);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011899 if (v != NULL)
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020011900 {
Bram Moolenaar33570922005-01-25 22:26:29 +000011901 copy_tv(&v->di_tv, rettv);
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020011902 done = TRUE;
11903 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000011904 }
Bram Moolenaar632deed2008-06-27 18:26:11 +000011905
11906 /* restore previous notion of curbuf */
11907 curbuf = save_curbuf;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011908 }
11909
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020011910 if (!done && argvars[2].v_type != VAR_UNKNOWN)
11911 /* use the default value */
11912 copy_tv(&argvars[2], rettv);
11913
Bram Moolenaar0d660222005-01-07 21:51:51 +000011914 --emsg_off;
11915}
11916
11917/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011918 * "getchar()" function
11919 */
11920 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010011921f_getchar(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011922{
11923 varnumber_T n;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011924 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011925
Bram Moolenaar4015b2c2006-06-22 19:01:34 +000011926 /* Position the cursor. Needed after a message that ends in a space. */
11927 windgoto(msg_row, msg_col);
11928
Bram Moolenaar071d4272004-06-13 20:20:40 +000011929 ++no_mapping;
11930 ++allow_keys;
Bram Moolenaar9c8791f2007-09-05 19:47:23 +000011931 for (;;)
11932 {
11933 if (argvars[0].v_type == VAR_UNKNOWN)
11934 /* getchar(): blocking wait. */
11935 n = safe_vgetc();
11936 else if (get_tv_number_chk(&argvars[0], &error) == 1)
11937 /* getchar(1): only check if char avail */
Bram Moolenaar9a665ba2014-05-22 18:59:58 +020011938 n = vpeekc_any();
11939 else if (error || vpeekc_any() == NUL)
Bram Moolenaar9c8791f2007-09-05 19:47:23 +000011940 /* illegal argument or getchar(0) and no char avail: return zero */
11941 n = 0;
11942 else
11943 /* getchar(0) and char avail: return char */
11944 n = safe_vgetc();
Bram Moolenaar9a665ba2014-05-22 18:59:58 +020011945
Bram Moolenaar9c8791f2007-09-05 19:47:23 +000011946 if (n == K_IGNORE)
11947 continue;
11948 break;
11949 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011950 --no_mapping;
11951 --allow_keys;
11952
Bram Moolenaar219b8702006-11-01 14:32:36 +000011953 vimvars[VV_MOUSE_WIN].vv_nr = 0;
11954 vimvars[VV_MOUSE_LNUM].vv_nr = 0;
11955 vimvars[VV_MOUSE_COL].vv_nr = 0;
11956
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011957 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011958 if (IS_SPECIAL(n) || mod_mask != 0)
11959 {
11960 char_u temp[10]; /* modifier: 3, mbyte-char: 6, NUL: 1 */
11961 int i = 0;
11962
11963 /* Turn a special key into three bytes, plus modifier. */
11964 if (mod_mask != 0)
11965 {
11966 temp[i++] = K_SPECIAL;
11967 temp[i++] = KS_MODIFIER;
11968 temp[i++] = mod_mask;
11969 }
11970 if (IS_SPECIAL(n))
11971 {
11972 temp[i++] = K_SPECIAL;
11973 temp[i++] = K_SECOND(n);
11974 temp[i++] = K_THIRD(n);
11975 }
11976#ifdef FEAT_MBYTE
11977 else if (has_mbyte)
11978 i += (*mb_char2bytes)(n, temp + i);
11979#endif
11980 else
11981 temp[i++] = n;
11982 temp[i++] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011983 rettv->v_type = VAR_STRING;
11984 rettv->vval.v_string = vim_strsave(temp);
Bram Moolenaar219b8702006-11-01 14:32:36 +000011985
11986#ifdef FEAT_MOUSE
Bram Moolenaar2526ef22013-03-16 14:20:51 +010011987 if (is_mouse_key(n))
Bram Moolenaar219b8702006-11-01 14:32:36 +000011988 {
11989 int row = mouse_row;
11990 int col = mouse_col;
11991 win_T *win;
11992 linenr_T lnum;
11993# ifdef FEAT_WINDOWS
11994 win_T *wp;
11995# endif
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +000011996 int winnr = 1;
Bram Moolenaar219b8702006-11-01 14:32:36 +000011997
11998 if (row >= 0 && col >= 0)
11999 {
12000 /* Find the window at the mouse coordinates and compute the
12001 * text position. */
12002 win = mouse_find_win(&row, &col);
12003 (void)mouse_comp_pos(win, &row, &col, &lnum);
12004# ifdef FEAT_WINDOWS
12005 for (wp = firstwin; wp != win; wp = wp->w_next)
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +000012006 ++winnr;
Bram Moolenaar219b8702006-11-01 14:32:36 +000012007# endif
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +000012008 vimvars[VV_MOUSE_WIN].vv_nr = winnr;
Bram Moolenaar219b8702006-11-01 14:32:36 +000012009 vimvars[VV_MOUSE_LNUM].vv_nr = lnum;
12010 vimvars[VV_MOUSE_COL].vv_nr = col + 1;
12011 }
12012 }
12013#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012014 }
12015}
12016
12017/*
12018 * "getcharmod()" function
12019 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012020 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012021f_getcharmod(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012022{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012023 rettv->vval.v_number = mod_mask;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012024}
12025
12026/*
Bram Moolenaardbd24b52015-08-11 14:26:19 +020012027 * "getcharsearch()" function
12028 */
12029 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012030f_getcharsearch(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaardbd24b52015-08-11 14:26:19 +020012031{
12032 if (rettv_dict_alloc(rettv) != FAIL)
12033 {
12034 dict_T *dict = rettv->vval.v_dict;
12035
12036 dict_add_nr_str(dict, "char", 0L, last_csearch());
12037 dict_add_nr_str(dict, "forward", last_csearch_forward(), NULL);
12038 dict_add_nr_str(dict, "until", last_csearch_until(), NULL);
12039 }
12040}
12041
12042/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012043 * "getcmdline()" function
12044 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012045 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012046f_getcmdline(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012047{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012048 rettv->v_type = VAR_STRING;
12049 rettv->vval.v_string = get_cmdline_str();
Bram Moolenaar071d4272004-06-13 20:20:40 +000012050}
12051
12052/*
12053 * "getcmdpos()" function
12054 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012055 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012056f_getcmdpos(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012057{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012058 rettv->vval.v_number = get_cmdline_pos() + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012059}
12060
12061/*
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000012062 * "getcmdtype()" function
12063 */
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000012064 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012065f_getcmdtype(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000012066{
12067 rettv->v_type = VAR_STRING;
12068 rettv->vval.v_string = alloc(2);
12069 if (rettv->vval.v_string != NULL)
12070 {
12071 rettv->vval.v_string[0] = get_cmdline_type();
12072 rettv->vval.v_string[1] = NUL;
12073 }
12074}
12075
12076/*
Bram Moolenaar8c1329c2014-08-06 13:36:59 +020012077 * "getcmdwintype()" function
12078 */
12079 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012080f_getcmdwintype(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar8c1329c2014-08-06 13:36:59 +020012081{
12082 rettv->v_type = VAR_STRING;
12083 rettv->vval.v_string = NULL;
12084#ifdef FEAT_CMDWIN
12085 rettv->vval.v_string = alloc(2);
12086 if (rettv->vval.v_string != NULL)
12087 {
12088 rettv->vval.v_string[0] = cmdwin_type;
12089 rettv->vval.v_string[1] = NUL;
12090 }
12091#endif
12092}
12093
12094/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012095 * "getcwd()" function
12096 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012097 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012098f_getcwd(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012099{
Bram Moolenaarc9703302016-01-17 21:49:33 +010012100 win_T *wp = NULL;
Bram Moolenaard9462e32011-04-11 21:35:11 +020012101 char_u *cwd;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012102
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012103 rettv->v_type = VAR_STRING;
Bram Moolenaard9462e32011-04-11 21:35:11 +020012104 rettv->vval.v_string = NULL;
Bram Moolenaarc9703302016-01-17 21:49:33 +010012105
12106 wp = find_tabwin(&argvars[0], &argvars[1]);
12107 if (wp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012108 {
Bram Moolenaarc9703302016-01-17 21:49:33 +010012109 if (wp->w_localdir != NULL)
12110 rettv->vval.v_string = vim_strsave(wp->w_localdir);
12111 else if(globaldir != NULL)
12112 rettv->vval.v_string = vim_strsave(globaldir);
12113 else
Bram Moolenaard9462e32011-04-11 21:35:11 +020012114 {
Bram Moolenaarc9703302016-01-17 21:49:33 +010012115 cwd = alloc(MAXPATHL);
12116 if (cwd != NULL)
12117 {
12118 if (mch_dirname(cwd, MAXPATHL) != FAIL)
12119 rettv->vval.v_string = vim_strsave(cwd);
12120 vim_free(cwd);
12121 }
Bram Moolenaard9462e32011-04-11 21:35:11 +020012122 }
Bram Moolenaarc9703302016-01-17 21:49:33 +010012123#ifdef BACKSLASH_IN_FILENAME
12124 if (rettv->vval.v_string != NULL)
12125 slash_adjust(rettv->vval.v_string);
12126#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012127 }
12128}
12129
12130/*
Bram Moolenaar46c9c732004-12-12 11:37:09 +000012131 * "getfontname()" function
12132 */
12133 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012134f_getfontname(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar46c9c732004-12-12 11:37:09 +000012135{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012136 rettv->v_type = VAR_STRING;
12137 rettv->vval.v_string = NULL;
Bram Moolenaar46c9c732004-12-12 11:37:09 +000012138#ifdef FEAT_GUI
12139 if (gui.in_use)
12140 {
12141 GuiFont font;
12142 char_u *name = NULL;
12143
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012144 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +000012145 {
12146 /* Get the "Normal" font. Either the name saved by
12147 * hl_set_font_name() or from the font ID. */
12148 font = gui.norm_font;
12149 name = hl_get_font_name();
12150 }
12151 else
12152 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012153 name = get_tv_string(&argvars[0]);
Bram Moolenaar46c9c732004-12-12 11:37:09 +000012154 if (STRCMP(name, "*") == 0) /* don't use font dialog */
12155 return;
12156 font = gui_mch_get_font(name, FALSE);
12157 if (font == NOFONT)
12158 return; /* Invalid font name, return empty string. */
12159 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012160 rettv->vval.v_string = gui_mch_get_fontname(font, name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012161 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +000012162 gui_mch_free_font(font);
12163 }
12164#endif
12165}
12166
12167/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012168 * "getfperm({fname})" function
12169 */
12170 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012171f_getfperm(typval_T *argvars, typval_T *rettv)
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012172{
12173 char_u *fname;
12174 struct stat st;
12175 char_u *perm = NULL;
12176 char_u flags[] = "rwx";
12177 int i;
12178
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012179 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012180
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012181 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012182 if (mch_stat((char *)fname, &st) >= 0)
12183 {
12184 perm = vim_strsave((char_u *)"---------");
12185 if (perm != NULL)
12186 {
12187 for (i = 0; i < 9; i++)
12188 {
12189 if (st.st_mode & (1 << (8 - i)))
12190 perm[i] = flags[i % 3];
12191 }
12192 }
12193 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012194 rettv->vval.v_string = perm;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012195}
12196
12197/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012198 * "getfsize({fname})" function
12199 */
12200 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012201f_getfsize(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012202{
12203 char_u *fname;
12204 struct stat st;
12205
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012206 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012207
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012208 rettv->v_type = VAR_NUMBER;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012209
12210 if (mch_stat((char *)fname, &st) >= 0)
12211 {
12212 if (mch_isdir(fname))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012213 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012214 else
Bram Moolenaard827ada2007-06-19 15:19:55 +000012215 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012216 rettv->vval.v_number = (varnumber_T)st.st_size;
Bram Moolenaard827ada2007-06-19 15:19:55 +000012217
12218 /* non-perfect check for overflow */
12219 if ((off_t)rettv->vval.v_number != (off_t)st.st_size)
12220 rettv->vval.v_number = -2;
12221 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012222 }
12223 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012224 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012225}
12226
12227/*
12228 * "getftime({fname})" function
12229 */
12230 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012231f_getftime(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012232{
12233 char_u *fname;
12234 struct stat st;
12235
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012236 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012237
12238 if (mch_stat((char *)fname, &st) >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012239 rettv->vval.v_number = (varnumber_T)st.st_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012240 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012241 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012242}
12243
12244/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012245 * "getftype({fname})" function
12246 */
12247 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012248f_getftype(typval_T *argvars, typval_T *rettv)
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012249{
12250 char_u *fname;
12251 struct stat st;
12252 char_u *type = NULL;
12253 char *t;
12254
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012255 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012256
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012257 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012258 if (mch_lstat((char *)fname, &st) >= 0)
12259 {
12260#ifdef S_ISREG
12261 if (S_ISREG(st.st_mode))
12262 t = "file";
12263 else if (S_ISDIR(st.st_mode))
12264 t = "dir";
12265# ifdef S_ISLNK
12266 else if (S_ISLNK(st.st_mode))
12267 t = "link";
12268# endif
12269# ifdef S_ISBLK
12270 else if (S_ISBLK(st.st_mode))
12271 t = "bdev";
12272# endif
12273# ifdef S_ISCHR
12274 else if (S_ISCHR(st.st_mode))
12275 t = "cdev";
12276# endif
12277# ifdef S_ISFIFO
12278 else if (S_ISFIFO(st.st_mode))
12279 t = "fifo";
12280# endif
12281# ifdef S_ISSOCK
12282 else if (S_ISSOCK(st.st_mode))
12283 t = "fifo";
12284# endif
12285 else
12286 t = "other";
12287#else
12288# ifdef S_IFMT
12289 switch (st.st_mode & S_IFMT)
12290 {
12291 case S_IFREG: t = "file"; break;
12292 case S_IFDIR: t = "dir"; break;
12293# ifdef S_IFLNK
12294 case S_IFLNK: t = "link"; break;
12295# endif
12296# ifdef S_IFBLK
12297 case S_IFBLK: t = "bdev"; break;
12298# endif
12299# ifdef S_IFCHR
12300 case S_IFCHR: t = "cdev"; break;
12301# endif
12302# ifdef S_IFIFO
12303 case S_IFIFO: t = "fifo"; break;
12304# endif
12305# ifdef S_IFSOCK
12306 case S_IFSOCK: t = "socket"; break;
12307# endif
12308 default: t = "other";
12309 }
12310# else
12311 if (mch_isdir(fname))
12312 t = "dir";
12313 else
12314 t = "file";
12315# endif
12316#endif
12317 type = vim_strsave((char_u *)t);
12318 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012319 rettv->vval.v_string = type;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012320}
12321
12322/*
Bram Moolenaar80fc0432005-07-20 22:06:07 +000012323 * "getline(lnum, [end])" function
Bram Moolenaar0d660222005-01-07 21:51:51 +000012324 */
12325 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012326f_getline(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000012327{
12328 linenr_T lnum;
12329 linenr_T end;
Bram Moolenaar342337a2005-07-21 21:11:17 +000012330 int retlist;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012331
12332 lnum = get_tv_lnum(argvars);
Bram Moolenaar80fc0432005-07-20 22:06:07 +000012333 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar342337a2005-07-21 21:11:17 +000012334 {
Bram Moolenaar80fc0432005-07-20 22:06:07 +000012335 end = 0;
Bram Moolenaar342337a2005-07-21 21:11:17 +000012336 retlist = FALSE;
12337 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000012338 else
Bram Moolenaar342337a2005-07-21 21:11:17 +000012339 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000012340 end = get_tv_lnum(&argvars[1]);
Bram Moolenaar342337a2005-07-21 21:11:17 +000012341 retlist = TRUE;
12342 }
Bram Moolenaar80fc0432005-07-20 22:06:07 +000012343
Bram Moolenaar342337a2005-07-21 21:11:17 +000012344 get_buffer_lines(curbuf, lnum, end, retlist, rettv);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012345}
12346
12347/*
Bram Moolenaar6ee10162007-07-26 20:58:42 +000012348 * "getmatches()" function
12349 */
Bram Moolenaar6ee10162007-07-26 20:58:42 +000012350 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012351f_getmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaar6ee10162007-07-26 20:58:42 +000012352{
12353#ifdef FEAT_SEARCH_EXTRA
12354 dict_T *dict;
12355 matchitem_T *cur = curwin->w_match_head;
Bram Moolenaarb3414592014-06-17 17:48:32 +020012356 int i;
Bram Moolenaar6ee10162007-07-26 20:58:42 +000012357
Bram Moolenaar6ee10162007-07-26 20:58:42 +000012358 if (rettv_list_alloc(rettv) == OK)
12359 {
12360 while (cur != NULL)
12361 {
12362 dict = dict_alloc();
12363 if (dict == NULL)
12364 return;
Bram Moolenaarb3414592014-06-17 17:48:32 +020012365 if (cur->match.regprog == NULL)
12366 {
12367 /* match added with matchaddpos() */
12368 for (i = 0; i < MAXPOSMATCH; ++i)
12369 {
12370 llpos_T *llpos;
12371 char buf[6];
12372 list_T *l;
12373
12374 llpos = &cur->pos.pos[i];
12375 if (llpos->lnum == 0)
12376 break;
12377 l = list_alloc();
12378 if (l == NULL)
12379 break;
12380 list_append_number(l, (varnumber_T)llpos->lnum);
12381 if (llpos->col > 0)
12382 {
12383 list_append_number(l, (varnumber_T)llpos->col);
12384 list_append_number(l, (varnumber_T)llpos->len);
12385 }
12386 sprintf(buf, "pos%d", i + 1);
12387 dict_add_list(dict, buf, l);
12388 }
12389 }
12390 else
12391 {
12392 dict_add_nr_str(dict, "pattern", 0L, cur->pattern);
12393 }
Bram Moolenaar6ee10162007-07-26 20:58:42 +000012394 dict_add_nr_str(dict, "group", 0L, syn_id2name(cur->hlg_id));
Bram Moolenaar6ee10162007-07-26 20:58:42 +000012395 dict_add_nr_str(dict, "priority", (long)cur->priority, NULL);
12396 dict_add_nr_str(dict, "id", (long)cur->id, NULL);
Bram Moolenaar6561d522015-07-21 15:48:27 +020012397# ifdef FEAT_CONCEAL
12398 if (cur->conceal_char)
12399 {
12400 char_u buf[MB_MAXBYTES + 1];
12401
12402 buf[(*mb_char2bytes)((int)cur->conceal_char, buf)] = NUL;
12403 dict_add_nr_str(dict, "conceal", 0L, (char_u *)&buf);
12404 }
12405# endif
Bram Moolenaar6ee10162007-07-26 20:58:42 +000012406 list_append_dict(rettv->vval.v_list, dict);
12407 cur = cur->next;
12408 }
12409 }
12410#endif
12411}
12412
12413/*
Bram Moolenaar18081e32008-02-20 19:11:07 +000012414 * "getpid()" function
12415 */
Bram Moolenaar18081e32008-02-20 19:11:07 +000012416 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012417f_getpid(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar18081e32008-02-20 19:11:07 +000012418{
12419 rettv->vval.v_number = mch_get_pid();
12420}
12421
Bram Moolenaar48e697e2016-01-23 22:17:30 +010012422static void getpos_both(typval_T *argvars, typval_T *rettv, int getcurpos);
Bram Moolenaar6f6c0f82014-05-28 20:31:42 +020012423
12424/*
12425 * "getcurpos()" function
12426 */
12427 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012428f_getcurpos(typval_T *argvars, typval_T *rettv)
Bram Moolenaar6f6c0f82014-05-28 20:31:42 +020012429{
12430 getpos_both(argvars, rettv, TRUE);
12431}
12432
Bram Moolenaar18081e32008-02-20 19:11:07 +000012433/*
Bram Moolenaara5525202006-03-02 22:52:09 +000012434 * "getpos(string)" function
12435 */
12436 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012437f_getpos(typval_T *argvars, typval_T *rettv)
Bram Moolenaara5525202006-03-02 22:52:09 +000012438{
Bram Moolenaar6f6c0f82014-05-28 20:31:42 +020012439 getpos_both(argvars, rettv, FALSE);
12440}
12441
12442 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012443getpos_both(
12444 typval_T *argvars,
12445 typval_T *rettv,
12446 int getcurpos)
Bram Moolenaar6f6c0f82014-05-28 20:31:42 +020012447{
Bram Moolenaara5525202006-03-02 22:52:09 +000012448 pos_T *fp;
12449 list_T *l;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000012450 int fnum = -1;
Bram Moolenaara5525202006-03-02 22:52:09 +000012451
12452 if (rettv_list_alloc(rettv) == OK)
12453 {
12454 l = rettv->vval.v_list;
Bram Moolenaar6f6c0f82014-05-28 20:31:42 +020012455 if (getcurpos)
12456 fp = &curwin->w_cursor;
12457 else
12458 fp = var2fpos(&argvars[0], TRUE, &fnum);
Bram Moolenaar0e34f622006-03-03 23:00:03 +000012459 if (fnum != -1)
12460 list_append_number(l, (varnumber_T)fnum);
12461 else
12462 list_append_number(l, (varnumber_T)0);
Bram Moolenaara5525202006-03-02 22:52:09 +000012463 list_append_number(l, (fp != NULL) ? (varnumber_T)fp->lnum
12464 : (varnumber_T)0);
Bram Moolenaare65f7322007-10-02 20:08:54 +000012465 list_append_number(l, (fp != NULL)
12466 ? (varnumber_T)(fp->col == MAXCOL ? MAXCOL : fp->col + 1)
Bram Moolenaara5525202006-03-02 22:52:09 +000012467 : (varnumber_T)0);
12468 list_append_number(l,
12469#ifdef FEAT_VIRTUALEDIT
12470 (fp != NULL) ? (varnumber_T)fp->coladd :
12471#endif
12472 (varnumber_T)0);
Bram Moolenaar6f6c0f82014-05-28 20:31:42 +020012473 if (getcurpos)
Bram Moolenaar2ab375e2016-02-10 22:23:06 +010012474 {
12475 update_curswant();
Bram Moolenaar084abae2015-01-14 19:00:38 +010012476 list_append_number(l, curwin->w_curswant == MAXCOL ?
12477 (varnumber_T)MAXCOL : (varnumber_T)curwin->w_curswant + 1);
Bram Moolenaar2ab375e2016-02-10 22:23:06 +010012478 }
Bram Moolenaara5525202006-03-02 22:52:09 +000012479 }
12480 else
12481 rettv->vval.v_number = FALSE;
12482}
12483
12484/*
Bram Moolenaar280f1262006-01-30 00:14:18 +000012485 * "getqflist()" and "getloclist()" functions
Bram Moolenaar2641f772005-03-25 21:58:17 +000012486 */
Bram Moolenaar2641f772005-03-25 21:58:17 +000012487 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012488f_getqflist(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaar2641f772005-03-25 21:58:17 +000012489{
12490#ifdef FEAT_QUICKFIX
Bram Moolenaar280f1262006-01-30 00:14:18 +000012491 win_T *wp;
Bram Moolenaar2641f772005-03-25 21:58:17 +000012492#endif
12493
Bram Moolenaar2641f772005-03-25 21:58:17 +000012494#ifdef FEAT_QUICKFIX
Bram Moolenaareddf53b2006-02-27 00:11:10 +000012495 if (rettv_list_alloc(rettv) == OK)
Bram Moolenaar2641f772005-03-25 21:58:17 +000012496 {
Bram Moolenaar280f1262006-01-30 00:14:18 +000012497 wp = NULL;
12498 if (argvars[0].v_type != VAR_UNKNOWN) /* getloclist() */
12499 {
Bram Moolenaar99ebf042006-04-15 20:28:54 +000012500 wp = find_win_by_nr(&argvars[0], NULL);
Bram Moolenaar280f1262006-01-30 00:14:18 +000012501 if (wp == NULL)
12502 return;
12503 }
12504
Bram Moolenaareddf53b2006-02-27 00:11:10 +000012505 (void)get_errorlist(wp, rettv->vval.v_list);
Bram Moolenaar2641f772005-03-25 21:58:17 +000012506 }
12507#endif
12508}
12509
12510/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012511 * "getreg()" function
12512 */
12513 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012514f_getreg(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012515{
12516 char_u *strregname;
12517 int regname;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000012518 int arg2 = FALSE;
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +020012519 int return_list = FALSE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012520 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012521
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012522 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000012523 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012524 strregname = get_tv_string_chk(&argvars[0]);
12525 error = strregname == NULL;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000012526 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +020012527 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012528 arg2 = get_tv_number_chk(&argvars[1], &error);
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +020012529 if (!error && argvars[2].v_type != VAR_UNKNOWN)
12530 return_list = get_tv_number_chk(&argvars[2], &error);
12531 }
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000012532 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012533 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000012534 strregname = vimvars[VV_REG].vv_str;
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +020012535
12536 if (error)
12537 return;
12538
Bram Moolenaar071d4272004-06-13 20:20:40 +000012539 regname = (strregname == NULL ? '"' : *strregname);
12540 if (regname == 0)
12541 regname = '"';
12542
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +020012543 if (return_list)
12544 {
12545 rettv->v_type = VAR_LIST;
12546 rettv->vval.v_list = (list_T *)get_reg_contents(regname,
12547 (arg2 ? GREG_EXPR_SRC : 0) | GREG_LIST);
Bram Moolenaar42d84f82014-11-12 18:49:16 +010012548 if (rettv->vval.v_list != NULL)
12549 ++rettv->vval.v_list->lv_refcount;
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +020012550 }
12551 else
12552 {
12553 rettv->v_type = VAR_STRING;
12554 rettv->vval.v_string = get_reg_contents(regname,
12555 arg2 ? GREG_EXPR_SRC : 0);
12556 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012557}
12558
12559/*
12560 * "getregtype()" function
12561 */
12562 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012563f_getregtype(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012564{
12565 char_u *strregname;
12566 int regname;
12567 char_u buf[NUMBUFLEN + 2];
12568 long reglen = 0;
12569
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012570 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012571 {
12572 strregname = get_tv_string_chk(&argvars[0]);
12573 if (strregname == NULL) /* type error; errmsg already given */
12574 {
12575 rettv->v_type = VAR_STRING;
12576 rettv->vval.v_string = NULL;
12577 return;
12578 }
12579 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012580 else
12581 /* Default to v:register */
Bram Moolenaare9a41262005-01-15 22:18:47 +000012582 strregname = vimvars[VV_REG].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012583
12584 regname = (strregname == NULL ? '"' : *strregname);
12585 if (regname == 0)
12586 regname = '"';
12587
12588 buf[0] = NUL;
12589 buf[1] = NUL;
12590 switch (get_reg_type(regname, &reglen))
12591 {
12592 case MLINE: buf[0] = 'V'; break;
12593 case MCHAR: buf[0] = 'v'; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012594 case MBLOCK:
12595 buf[0] = Ctrl_V;
12596 sprintf((char *)buf + 1, "%ld", reglen + 1);
12597 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012598 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012599 rettv->v_type = VAR_STRING;
12600 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012601}
12602
12603/*
Bram Moolenaar06b5d512010-05-22 15:37:44 +020012604 * "gettabvar()" function
12605 */
12606 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012607f_gettabvar(typval_T *argvars, typval_T *rettv)
Bram Moolenaar06b5d512010-05-22 15:37:44 +020012608{
Bram Moolenaar3089a102014-09-09 23:11:49 +020012609 win_T *oldcurwin;
Bram Moolenaar0e2ea1b2014-09-09 16:13:08 +020012610 tabpage_T *tp, *oldtabpage;
Bram Moolenaar06b5d512010-05-22 15:37:44 +020012611 dictitem_T *v;
12612 char_u *varname;
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020012613 int done = FALSE;
Bram Moolenaar06b5d512010-05-22 15:37:44 +020012614
12615 rettv->v_type = VAR_STRING;
12616 rettv->vval.v_string = NULL;
12617
12618 varname = get_tv_string_chk(&argvars[1]);
12619 tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL));
12620 if (tp != NULL && varname != NULL)
12621 {
Bram Moolenaar3089a102014-09-09 23:11:49 +020012622 /* Set tp to be our tabpage, temporarily. Also set the window to the
12623 * first window in the tabpage, otherwise the window is not valid. */
Bram Moolenaar7e47d1a2015-08-25 16:19:05 +020012624 if (switch_win(&oldcurwin, &oldtabpage,
12625 tp->tp_firstwin == NULL ? firstwin : tp->tp_firstwin, tp, TRUE)
Bram Moolenaar5d2bae82014-09-19 14:26:36 +020012626 == OK)
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020012627 {
Bram Moolenaar5d2bae82014-09-19 14:26:36 +020012628 /* look up the variable */
12629 /* Let gettabvar({nr}, "") return the "t:" dictionary. */
12630 v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't', varname, FALSE);
12631 if (v != NULL)
12632 {
12633 copy_tv(&v->di_tv, rettv);
12634 done = TRUE;
12635 }
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020012636 }
Bram Moolenaar0e2ea1b2014-09-09 16:13:08 +020012637
12638 /* restore previous notion of curwin */
12639 restore_win(oldcurwin, oldtabpage, TRUE);
Bram Moolenaar06b5d512010-05-22 15:37:44 +020012640 }
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020012641
12642 if (!done && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar63dbda12013-02-20 21:12:10 +010012643 copy_tv(&argvars[2], rettv);
Bram Moolenaar06b5d512010-05-22 15:37:44 +020012644}
12645
12646/*
Bram Moolenaar99ebf042006-04-15 20:28:54 +000012647 * "gettabwinvar()" function
12648 */
12649 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012650f_gettabwinvar(typval_T *argvars, typval_T *rettv)
Bram Moolenaar99ebf042006-04-15 20:28:54 +000012651{
12652 getwinvar(argvars, rettv, 1);
12653}
12654
12655/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012656 * "getwinposx()" function
12657 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012658 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012659f_getwinposx(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012660{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012661 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012662#ifdef FEAT_GUI
12663 if (gui.in_use)
12664 {
12665 int x, y;
12666
12667 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012668 rettv->vval.v_number = x;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012669 }
12670#endif
12671}
12672
12673/*
Bram Moolenaar9cdf86b2016-03-13 19:04:51 +010012674 * "win_findbuf()" function
12675 */
12676 static void
12677f_win_findbuf(typval_T *argvars, typval_T *rettv)
12678{
12679 if (rettv_list_alloc(rettv) != FAIL)
12680 win_findbuf(argvars, rettv->vval.v_list);
12681}
12682
12683/*
Bram Moolenaar86edef62016-03-13 18:07:30 +010012684 * "win_getid()" function
12685 */
12686 static void
12687f_win_getid(typval_T *argvars, typval_T *rettv)
12688{
12689 rettv->vval.v_number = win_getid(argvars);
12690}
12691
12692/*
12693 * "win_gotoid()" function
12694 */
12695 static void
12696f_win_gotoid(typval_T *argvars, typval_T *rettv)
12697{
12698 rettv->vval.v_number = win_gotoid(argvars);
12699}
12700
12701/*
12702 * "win_id2tabwin()" function
12703 */
12704 static void
12705f_win_id2tabwin(typval_T *argvars, typval_T *rettv)
12706{
12707 if (rettv_list_alloc(rettv) != FAIL)
12708 win_id2tabwin(argvars, rettv->vval.v_list);
12709}
12710
12711/*
12712 * "win_id2win()" function
12713 */
12714 static void
12715f_win_id2win(typval_T *argvars, typval_T *rettv)
12716{
12717 rettv->vval.v_number = win_id2win(argvars);
12718}
12719
12720/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012721 * "getwinposy()" function
12722 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012723 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012724f_getwinposy(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012725{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012726 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012727#ifdef FEAT_GUI
12728 if (gui.in_use)
12729 {
12730 int x, y;
12731
12732 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012733 rettv->vval.v_number = y;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012734 }
12735#endif
12736}
12737
Bram Moolenaar99ebf042006-04-15 20:28:54 +000012738/*
Bram Moolenaar8c8de832008-06-24 22:58:06 +000012739 * Find window specified by "vp" in tabpage "tp".
Bram Moolenaar99ebf042006-04-15 20:28:54 +000012740 */
Bram Moolenaara40058a2005-07-11 22:42:07 +000012741 static win_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +010012742find_win_by_nr(
12743 typval_T *vp,
12744 tabpage_T *tp UNUSED) /* NULL for current tab page */
Bram Moolenaara40058a2005-07-11 22:42:07 +000012745{
12746#ifdef FEAT_WINDOWS
12747 win_T *wp;
12748#endif
12749 int nr;
12750
12751 nr = get_tv_number_chk(vp, NULL);
12752
12753#ifdef FEAT_WINDOWS
12754 if (nr < 0)
12755 return NULL;
12756 if (nr == 0)
12757 return curwin;
12758
Bram Moolenaar99ebf042006-04-15 20:28:54 +000012759 for (wp = (tp == NULL || tp == curtab) ? firstwin : tp->tp_firstwin;
12760 wp != NULL; wp = wp->w_next)
Bram Moolenaara40058a2005-07-11 22:42:07 +000012761 if (--nr <= 0)
12762 break;
12763 return wp;
12764#else
12765 if (nr == 0 || nr == 1)
12766 return curwin;
12767 return NULL;
12768#endif
12769}
12770
Bram Moolenaar071d4272004-06-13 20:20:40 +000012771/*
Bram Moolenaarc9703302016-01-17 21:49:33 +010012772 * Find window specified by "wvp" in tabpage "tvp".
12773 */
12774 static win_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +010012775find_tabwin(
12776 typval_T *wvp, /* VAR_UNKNOWN for current window */
12777 typval_T *tvp) /* VAR_UNKNOWN for current tab page */
Bram Moolenaarc9703302016-01-17 21:49:33 +010012778{
12779 win_T *wp = NULL;
12780 tabpage_T *tp = NULL;
12781 long n;
12782
12783 if (wvp->v_type != VAR_UNKNOWN)
12784 {
12785 if (tvp->v_type != VAR_UNKNOWN)
12786 {
12787 n = get_tv_number(tvp);
12788 if (n >= 0)
12789 tp = find_tabpage(n);
12790 }
12791 else
12792 tp = curtab;
12793
12794 if (tp != NULL)
12795 wp = find_win_by_nr(wvp, tp);
12796 }
12797 else
12798 wp = curwin;
12799
12800 return wp;
12801}
12802
12803/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012804 * "getwinvar()" function
12805 */
12806 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012807f_getwinvar(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012808{
Bram Moolenaar99ebf042006-04-15 20:28:54 +000012809 getwinvar(argvars, rettv, 0);
12810}
12811
12812/*
12813 * getwinvar() and gettabwinvar()
12814 */
12815 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012816getwinvar(
12817 typval_T *argvars,
12818 typval_T *rettv,
12819 int off) /* 1 for gettabwinvar() */
Bram Moolenaar99ebf042006-04-15 20:28:54 +000012820{
Bram Moolenaarba117c22015-09-29 16:53:22 +020012821 win_T *win;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012822 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000012823 dictitem_T *v;
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020012824 tabpage_T *tp = NULL;
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020012825 int done = FALSE;
Bram Moolenaarba117c22015-09-29 16:53:22 +020012826#ifdef FEAT_WINDOWS
12827 win_T *oldcurwin;
12828 tabpage_T *oldtabpage;
12829 int need_switch_win;
12830#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012831
Bram Moolenaar99ebf042006-04-15 20:28:54 +000012832#ifdef FEAT_WINDOWS
12833 if (off == 1)
12834 tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL));
12835 else
12836 tp = curtab;
12837#endif
12838 win = find_win_by_nr(&argvars[off], tp);
12839 varname = get_tv_string_chk(&argvars[off + 1]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012840 ++emsg_off;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012841
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020012842 rettv->v_type = VAR_STRING;
12843 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012844
12845 if (win != NULL && varname != NULL)
12846 {
Bram Moolenaarba117c22015-09-29 16:53:22 +020012847#ifdef FEAT_WINDOWS
Bram Moolenaar105bc352013-05-17 16:03:57 +020012848 /* Set curwin to be our win, temporarily. Also set the tabpage,
Bram Moolenaarba117c22015-09-29 16:53:22 +020012849 * otherwise the window is not valid. Only do this when needed,
12850 * autocommands get blocked. */
12851 need_switch_win = !(tp == curtab && win == curwin);
12852 if (!need_switch_win
12853 || switch_win(&oldcurwin, &oldtabpage, win, tp, TRUE) == OK)
12854#endif
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020012855 {
Bram Moolenaar5d2bae82014-09-19 14:26:36 +020012856 if (*varname == '&') /* window-local-option */
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020012857 {
Bram Moolenaar5d2bae82014-09-19 14:26:36 +020012858 if (get_option_tv(&varname, rettv, 1) == OK)
12859 done = TRUE;
12860 }
12861 else
12862 {
12863 /* Look up the variable. */
12864 /* Let getwinvar({nr}, "") return the "w:" dictionary. */
12865 v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w',
12866 varname, FALSE);
12867 if (v != NULL)
12868 {
12869 copy_tv(&v->di_tv, rettv);
12870 done = TRUE;
12871 }
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020012872 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012873 }
Bram Moolenaar69a7e432006-10-10 10:55:47 +000012874
Bram Moolenaarba117c22015-09-29 16:53:22 +020012875#ifdef FEAT_WINDOWS
12876 if (need_switch_win)
12877 /* restore previous notion of curwin */
12878 restore_win(oldcurwin, oldtabpage, TRUE);
12879#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012880 }
12881
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020012882 if (!done && argvars[off + 2].v_type != VAR_UNKNOWN)
12883 /* use the default return value */
12884 copy_tv(&argvars[off + 2], rettv);
12885
Bram Moolenaar071d4272004-06-13 20:20:40 +000012886 --emsg_off;
12887}
12888
12889/*
12890 * "glob()" function
12891 */
12892 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012893f_glob(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012894{
Bram Moolenaar005c3c22010-12-02 21:44:40 +010012895 int options = WILD_SILENT|WILD_USE_NL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012896 expand_T xpc;
Bram Moolenaarbb5ddda2008-11-28 10:01:10 +000012897 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012898
Bram Moolenaarbb5ddda2008-11-28 10:01:10 +000012899 /* When the optional second argument is non-zero, don't remove matches
Bram Moolenaar146e9c32012-03-07 19:18:23 +010012900 * for 'wildignore' and don't put matches for 'suffixes' at the end. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012901 rettv->v_type = VAR_STRING;
Bram Moolenaar146e9c32012-03-07 19:18:23 +010012902 if (argvars[1].v_type != VAR_UNKNOWN)
12903 {
12904 if (get_tv_number_chk(&argvars[1], &error))
12905 options |= WILD_KEEP_ALL;
Bram Moolenaara245bc72015-03-05 19:35:25 +010012906 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar146e9c32012-03-07 19:18:23 +010012907 {
Bram Moolenaara245bc72015-03-05 19:35:25 +010012908 if (get_tv_number_chk(&argvars[2], &error))
12909 {
12910 rettv->v_type = VAR_LIST;
12911 rettv->vval.v_list = NULL;
12912 }
12913 if (argvars[3].v_type != VAR_UNKNOWN
12914 && get_tv_number_chk(&argvars[3], &error))
12915 options |= WILD_ALLLINKS;
Bram Moolenaar146e9c32012-03-07 19:18:23 +010012916 }
12917 }
Bram Moolenaarbb5ddda2008-11-28 10:01:10 +000012918 if (!error)
12919 {
12920 ExpandInit(&xpc);
12921 xpc.xp_context = EXPAND_FILES;
Bram Moolenaar005c3c22010-12-02 21:44:40 +010012922 if (p_wic)
12923 options += WILD_ICASE;
Bram Moolenaar146e9c32012-03-07 19:18:23 +010012924 if (rettv->v_type == VAR_STRING)
12925 rettv->vval.v_string = ExpandOne(&xpc, get_tv_string(&argvars[0]),
Bram Moolenaar005c3c22010-12-02 21:44:40 +010012926 NULL, options, WILD_ALL);
Bram Moolenaar146e9c32012-03-07 19:18:23 +010012927 else if (rettv_list_alloc(rettv) != FAIL)
12928 {
12929 int i;
12930
12931 ExpandOne(&xpc, get_tv_string(&argvars[0]),
12932 NULL, options, WILD_ALL_KEEP);
12933 for (i = 0; i < xpc.xp_numfiles; i++)
12934 list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1);
12935
12936 ExpandCleanup(&xpc);
12937 }
Bram Moolenaarbb5ddda2008-11-28 10:01:10 +000012938 }
12939 else
12940 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012941}
12942
12943/*
12944 * "globpath()" function
12945 */
12946 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012947f_globpath(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012948{
Bram Moolenaarbb5ddda2008-11-28 10:01:10 +000012949 int flags = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012950 char_u buf1[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012951 char_u *file = get_tv_string_buf_chk(&argvars[1], buf1);
Bram Moolenaarbb5ddda2008-11-28 10:01:10 +000012952 int error = FALSE;
Bram Moolenaar1b1063a2014-05-07 18:35:30 +020012953 garray_T ga;
12954 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012955
Bram Moolenaarbb5ddda2008-11-28 10:01:10 +000012956 /* When the optional second argument is non-zero, don't remove matches
12957 * for 'wildignore' and don't put matches for 'suffixes' at the end. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012958 rettv->v_type = VAR_STRING;
Bram Moolenaar1b1063a2014-05-07 18:35:30 +020012959 if (argvars[2].v_type != VAR_UNKNOWN)
12960 {
12961 if (get_tv_number_chk(&argvars[2], &error))
12962 flags |= WILD_KEEP_ALL;
Bram Moolenaara245bc72015-03-05 19:35:25 +010012963 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar1b1063a2014-05-07 18:35:30 +020012964 {
Bram Moolenaara245bc72015-03-05 19:35:25 +010012965 if (get_tv_number_chk(&argvars[3], &error))
12966 {
12967 rettv->v_type = VAR_LIST;
12968 rettv->vval.v_list = NULL;
12969 }
12970 if (argvars[4].v_type != VAR_UNKNOWN
12971 && get_tv_number_chk(&argvars[4], &error))
12972 flags |= WILD_ALLLINKS;
Bram Moolenaar1b1063a2014-05-07 18:35:30 +020012973 }
12974 }
12975 if (file != NULL && !error)
12976 {
12977 ga_init2(&ga, (int)sizeof(char_u *), 10);
12978 globpath(get_tv_string(&argvars[0]), file, &ga, flags);
12979 if (rettv->v_type == VAR_STRING)
12980 rettv->vval.v_string = ga_concat_strings(&ga, "\n");
12981 else if (rettv_list_alloc(rettv) != FAIL)
12982 for (i = 0; i < ga.ga_len; ++i)
12983 list_append_string(rettv->vval.v_list,
12984 ((char_u **)(ga.ga_data))[i], -1);
12985 ga_clear_strings(&ga);
12986 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012987 else
Bram Moolenaar1b1063a2014-05-07 18:35:30 +020012988 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012989}
12990
12991/*
Bram Moolenaar825e7ab2015-03-20 17:36:42 +010012992 * "glob2regpat()" function
12993 */
12994 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010012995f_glob2regpat(typval_T *argvars, typval_T *rettv)
Bram Moolenaar825e7ab2015-03-20 17:36:42 +010012996{
12997 char_u *pat = get_tv_string_chk(&argvars[0]);
12998
12999 rettv->v_type = VAR_STRING;
Bram Moolenaar7465c632016-01-25 22:20:27 +010013000 rettv->vval.v_string = (pat == NULL)
13001 ? NULL : file_pat_to_reg_pat(pat, NULL, NULL, FALSE);
Bram Moolenaar825e7ab2015-03-20 17:36:42 +010013002}
13003
13004/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013005 * "has()" function
13006 */
13007 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010013008f_has(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013009{
13010 int i;
13011 char_u *name;
13012 int n = FALSE;
13013 static char *(has_list[]) =
13014 {
13015#ifdef AMIGA
13016 "amiga",
13017# ifdef FEAT_ARP
13018 "arp",
13019# endif
13020#endif
13021#ifdef __BEOS__
13022 "beos",
13023#endif
Bram Moolenaar241a8aa2005-12-06 20:04:44 +000013024#ifdef MACOS
Bram Moolenaar071d4272004-06-13 20:20:40 +000013025 "mac",
13026#endif
13027#if defined(MACOS_X_UNIX)
Bram Moolenaarf8df7ad2016-02-16 14:07:40 +010013028 "macunix", /* built with 'darwin' enabled */
13029#endif
13030#if defined(__APPLE__) && __APPLE__ == 1
13031 "osx", /* built with or without 'darwin' enabled */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013032#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013033#ifdef __QNX__
13034 "qnx",
13035#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013036#ifdef UNIX
13037 "unix",
13038#endif
13039#ifdef VMS
13040 "vms",
13041#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013042#ifdef WIN32
13043 "win32",
13044#endif
13045#if defined(UNIX) && (defined(__CYGWIN32__) || defined(__CYGWIN__))
13046 "win32unix",
13047#endif
Bram Moolenaare37d7992010-01-12 13:18:33 +010013048#if defined(WIN64) || defined(_WIN64)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013049 "win64",
13050#endif
13051#ifdef EBCDIC
13052 "ebcdic",
13053#endif
13054#ifndef CASE_INSENSITIVE_FILENAME
13055 "fname_case",
13056#endif
Bram Moolenaarb5ef5e12013-08-30 16:35:44 +020013057#ifdef HAVE_ACL
13058 "acl",
13059#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013060#ifdef FEAT_ARABIC
13061 "arabic",
13062#endif
13063#ifdef FEAT_AUTOCMD
13064 "autocmd",
13065#endif
13066#ifdef FEAT_BEVAL
13067 "balloon_eval",
Bram Moolenaar342337a2005-07-21 21:11:17 +000013068# ifndef FEAT_GUI_W32 /* other GUIs always have multiline balloons */
13069 "balloon_multiline",
13070# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013071#endif
13072#if defined(SOME_BUILTIN_TCAPS) || defined(ALL_BUILTIN_TCAPS)
13073 "builtin_terms",
13074# ifdef ALL_BUILTIN_TCAPS
13075 "all_builtin_terms",
13076# endif
13077#endif
Bram Moolenaar77c604d2012-07-10 13:41:14 +020013078#if defined(FEAT_BROWSE) && (defined(USE_FILE_CHOOSER) \
13079 || defined(FEAT_GUI_W32) \
13080 || defined(FEAT_GUI_MOTIF))
13081 "browsefilter",
13082#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013083#ifdef FEAT_BYTEOFF
13084 "byte_offset",
13085#endif
Bram Moolenaar509ce2a2016-03-11 22:52:15 +010013086#ifdef FEAT_JOB_CHANNEL
Bram Moolenaare0874f82016-01-24 20:36:41 +010013087 "channel",
13088#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013089#ifdef FEAT_CINDENT
13090 "cindent",
13091#endif
13092#ifdef FEAT_CLIENTSERVER
13093 "clientserver",
13094#endif
13095#ifdef FEAT_CLIPBOARD
13096 "clipboard",
13097#endif
13098#ifdef FEAT_CMDL_COMPL
13099 "cmdline_compl",
13100#endif
13101#ifdef FEAT_CMDHIST
13102 "cmdline_hist",
13103#endif
13104#ifdef FEAT_COMMENTS
13105 "comments",
13106#endif
Bram Moolenaar860cae12010-06-05 23:22:07 +020013107#ifdef FEAT_CONCEAL
13108 "conceal",
13109#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013110#ifdef FEAT_CRYPT
13111 "cryptv",
Bram Moolenaar36d7cd82016-01-15 22:08:23 +010013112 "crypt-blowfish",
13113 "crypt-blowfish2",
Bram Moolenaar071d4272004-06-13 20:20:40 +000013114#endif
13115#ifdef FEAT_CSCOPE
13116 "cscope",
13117#endif
Bram Moolenaar860cae12010-06-05 23:22:07 +020013118#ifdef FEAT_CURSORBIND
13119 "cursorbind",
13120#endif
Bram Moolenaarac6e65f2005-08-29 22:25:38 +000013121#ifdef CURSOR_SHAPE
13122 "cursorshape",
13123#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013124#ifdef DEBUG
13125 "debug",
13126#endif
13127#ifdef FEAT_CON_DIALOG
13128 "dialog_con",
13129#endif
13130#ifdef FEAT_GUI_DIALOG
13131 "dialog_gui",
13132#endif
13133#ifdef FEAT_DIFF
13134 "diff",
13135#endif
13136#ifdef FEAT_DIGRAPHS
13137 "digraphs",
13138#endif
Bram Moolenaarb5a7a8b2014-08-06 14:52:30 +020013139#ifdef FEAT_DIRECTX
13140 "directx",
13141#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013142#ifdef FEAT_DND
13143 "dnd",
13144#endif
13145#ifdef FEAT_EMACS_TAGS
13146 "emacs_tags",
13147#endif
13148 "eval", /* always present, of course! */
Bram Moolenaare2c38102016-01-31 14:55:40 +010013149 "ex_extra", /* graduated feature */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013150#ifdef FEAT_SEARCH_EXTRA
13151 "extra_search",
13152#endif
13153#ifdef FEAT_FKMAP
13154 "farsi",
13155#endif
13156#ifdef FEAT_SEARCHPATH
13157 "file_in_path",
13158#endif
Bram Moolenaar68a33fc2012-04-25 16:50:48 +020013159#ifdef FEAT_FILTERPIPE
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000013160 "filterpipe",
13161#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013162#ifdef FEAT_FIND_ID
13163 "find_in_path",
13164#endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +000013165#ifdef FEAT_FLOAT
13166 "float",
13167#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013168#ifdef FEAT_FOLDING
13169 "folding",
13170#endif
13171#ifdef FEAT_FOOTER
13172 "footer",
13173#endif
13174#if !defined(USE_SYSTEM) && defined(UNIX)
13175 "fork",
13176#endif
13177#ifdef FEAT_GETTEXT
13178 "gettext",
13179#endif
13180#ifdef FEAT_GUI
13181 "gui",
13182#endif
13183#ifdef FEAT_GUI_ATHENA
13184# ifdef FEAT_GUI_NEXTAW
13185 "gui_neXtaw",
13186# else
13187 "gui_athena",
13188# endif
13189#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013190#ifdef FEAT_GUI_GTK
13191 "gui_gtk",
Bram Moolenaar98921892016-02-23 17:14:37 +010013192# ifdef USE_GTK3
13193 "gui_gtk3",
13194# else
Bram Moolenaar071d4272004-06-13 20:20:40 +000013195 "gui_gtk2",
Bram Moolenaar98921892016-02-23 17:14:37 +010013196# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013197#endif
Bram Moolenaar7b188622007-09-25 10:51:12 +000013198#ifdef FEAT_GUI_GNOME
13199 "gui_gnome",
13200#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013201#ifdef FEAT_GUI_MAC
13202 "gui_mac",
13203#endif
13204#ifdef FEAT_GUI_MOTIF
13205 "gui_motif",
13206#endif
13207#ifdef FEAT_GUI_PHOTON
13208 "gui_photon",
13209#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013210#ifdef FEAT_GUI_W32
13211 "gui_win32",
13212#endif
13213#ifdef FEAT_HANGULIN
13214 "hangul_input",
13215#endif
13216#if defined(HAVE_ICONV_H) && defined(USE_ICONV)
13217 "iconv",
13218#endif
13219#ifdef FEAT_INS_EXPAND
13220 "insert_expand",
13221#endif
Bram Moolenaar509ce2a2016-03-11 22:52:15 +010013222#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +010013223 "job",
13224#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013225#ifdef FEAT_JUMPLIST
13226 "jumplist",
13227#endif
13228#ifdef FEAT_KEYMAP
13229 "keymap",
13230#endif
13231#ifdef FEAT_LANGMAP
13232 "langmap",
13233#endif
13234#ifdef FEAT_LIBCALL
13235 "libcall",
13236#endif
13237#ifdef FEAT_LINEBREAK
13238 "linebreak",
13239#endif
13240#ifdef FEAT_LISP
13241 "lispindent",
13242#endif
13243#ifdef FEAT_LISTCMDS
13244 "listcmds",
13245#endif
13246#ifdef FEAT_LOCALMAP
13247 "localmap",
13248#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +020013249#ifdef FEAT_LUA
13250# ifndef DYNAMIC_LUA
13251 "lua",
13252# endif
13253#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013254#ifdef FEAT_MENU
13255 "menu",
13256#endif
13257#ifdef FEAT_SESSION
13258 "mksession",
13259#endif
13260#ifdef FEAT_MODIFY_FNAME
13261 "modify_fname",
13262#endif
13263#ifdef FEAT_MOUSE
13264 "mouse",
13265#endif
13266#ifdef FEAT_MOUSESHAPE
13267 "mouseshape",
13268#endif
13269#if defined(UNIX) || defined(VMS)
13270# ifdef FEAT_MOUSE_DEC
13271 "mouse_dec",
13272# endif
13273# ifdef FEAT_MOUSE_GPM
13274 "mouse_gpm",
13275# endif
13276# ifdef FEAT_MOUSE_JSB
13277 "mouse_jsbterm",
13278# endif
13279# ifdef FEAT_MOUSE_NET
13280 "mouse_netterm",
13281# endif
13282# ifdef FEAT_MOUSE_PTERM
13283 "mouse_pterm",
13284# endif
Bram Moolenaarcfb80702012-10-21 02:17:45 +020013285# ifdef FEAT_MOUSE_SGR
13286 "mouse_sgr",
13287# endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +000013288# ifdef FEAT_SYSMOUSE
13289 "mouse_sysmouse",
13290# endif
Bram Moolenaarcfb80702012-10-21 02:17:45 +020013291# ifdef FEAT_MOUSE_URXVT
13292 "mouse_urxvt",
13293# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013294# ifdef FEAT_MOUSE_XTERM
13295 "mouse_xterm",
13296# endif
13297#endif
13298#ifdef FEAT_MBYTE
13299 "multi_byte",
13300#endif
13301#ifdef FEAT_MBYTE_IME
13302 "multi_byte_ime",
13303#endif
13304#ifdef FEAT_MULTI_LANG
13305 "multi_lang",
13306#endif
Bram Moolenaar325b7a22004-07-05 15:58:32 +000013307#ifdef FEAT_MZSCHEME
Bram Moolenaar33570922005-01-25 22:26:29 +000013308#ifndef DYNAMIC_MZSCHEME
Bram Moolenaar325b7a22004-07-05 15:58:32 +000013309 "mzscheme",
13310#endif
Bram Moolenaar33570922005-01-25 22:26:29 +000013311#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013312#ifdef FEAT_OLE
13313 "ole",
13314#endif
Bram Moolenaarf6fee0e2016-02-21 23:02:49 +010013315 "packages",
Bram Moolenaar071d4272004-06-13 20:20:40 +000013316#ifdef FEAT_PATH_EXTRA
13317 "path_extra",
13318#endif
13319#ifdef FEAT_PERL
13320#ifndef DYNAMIC_PERL
13321 "perl",
13322#endif
13323#endif
Bram Moolenaar55debbe2010-05-23 23:34:36 +020013324#ifdef FEAT_PERSISTENT_UNDO
13325 "persistent_undo",
13326#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013327#ifdef FEAT_PYTHON
13328#ifndef DYNAMIC_PYTHON
13329 "python",
13330#endif
13331#endif
Bram Moolenaarbd5e15f2010-07-17 21:19:38 +020013332#ifdef FEAT_PYTHON3
13333#ifndef DYNAMIC_PYTHON3
13334 "python3",
13335#endif
13336#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013337#ifdef FEAT_POSTSCRIPT
13338 "postscript",
13339#endif
13340#ifdef FEAT_PRINTER
13341 "printer",
13342#endif
Bram Moolenaar05159a02005-02-26 23:04:13 +000013343#ifdef FEAT_PROFILE
13344 "profile",
13345#endif
Bram Moolenaare580b0c2006-03-21 21:33:03 +000013346#ifdef FEAT_RELTIME
13347 "reltime",
13348#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013349#ifdef FEAT_QUICKFIX
13350 "quickfix",
13351#endif
13352#ifdef FEAT_RIGHTLEFT
13353 "rightleft",
13354#endif
13355#if defined(FEAT_RUBY) && !defined(DYNAMIC_RUBY)
13356 "ruby",
13357#endif
13358#ifdef FEAT_SCROLLBIND
13359 "scrollbind",
13360#endif
13361#ifdef FEAT_CMDL_INFO
13362 "showcmd",
13363 "cmdline_info",
13364#endif
13365#ifdef FEAT_SIGNS
13366 "signs",
13367#endif
13368#ifdef FEAT_SMARTINDENT
13369 "smartindent",
13370#endif
Bram Moolenaaref94eec2009-11-11 13:22:11 +000013371#ifdef STARTUPTIME
13372 "startuptime",
13373#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013374#ifdef FEAT_STL_OPT
13375 "statusline",
13376#endif
13377#ifdef FEAT_SUN_WORKSHOP
13378 "sun_workshop",
13379#endif
13380#ifdef FEAT_NETBEANS_INTG
13381 "netbeans_intg",
13382#endif
Bram Moolenaar3c56a962006-03-12 22:19:04 +000013383#ifdef FEAT_SPELL
Bram Moolenaar0e4d8772005-06-07 21:12:49 +000013384 "spell",
13385#endif
13386#ifdef FEAT_SYN_HL
Bram Moolenaar071d4272004-06-13 20:20:40 +000013387 "syntax",
13388#endif
13389#if defined(USE_SYSTEM) || !defined(UNIX)
13390 "system",
13391#endif
13392#ifdef FEAT_TAG_BINS
13393 "tag_binary",
13394#endif
13395#ifdef FEAT_TAG_OLDSTATIC
13396 "tag_old_static",
13397#endif
13398#ifdef FEAT_TAG_ANYWHITE
13399 "tag_any_white",
13400#endif
13401#ifdef FEAT_TCL
13402# ifndef DYNAMIC_TCL
13403 "tcl",
13404# endif
13405#endif
13406#ifdef TERMINFO
13407 "terminfo",
13408#endif
13409#ifdef FEAT_TERMRESPONSE
13410 "termresponse",
13411#endif
13412#ifdef FEAT_TEXTOBJ
13413 "textobjects",
13414#endif
13415#ifdef HAVE_TGETENT
13416 "tgetent",
13417#endif
13418#ifdef FEAT_TITLE
13419 "title",
13420#endif
13421#ifdef FEAT_TOOLBAR
13422 "toolbar",
13423#endif
Bram Moolenaarbf9680e2010-12-02 21:43:16 +010013424#if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
13425 "unnamedplus",
13426#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013427#ifdef FEAT_USR_CMDS
13428 "user-commands", /* was accidentally included in 5.4 */
13429 "user_commands",
13430#endif
13431#ifdef FEAT_VIMINFO
13432 "viminfo",
13433#endif
13434#ifdef FEAT_VERTSPLIT
13435 "vertsplit",
13436#endif
13437#ifdef FEAT_VIRTUALEDIT
13438 "virtualedit",
13439#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013440 "visual",
Bram Moolenaar071d4272004-06-13 20:20:40 +000013441#ifdef FEAT_VISUALEXTRA
13442 "visualextra",
13443#endif
13444#ifdef FEAT_VREPLACE
13445 "vreplace",
13446#endif
13447#ifdef FEAT_WILDIGN
13448 "wildignore",
13449#endif
13450#ifdef FEAT_WILDMENU
13451 "wildmenu",
13452#endif
13453#ifdef FEAT_WINDOWS
13454 "windows",
13455#endif
13456#ifdef FEAT_WAK
13457 "winaltkeys",
13458#endif
13459#ifdef FEAT_WRITEBACKUP
13460 "writebackup",
13461#endif
13462#ifdef FEAT_XIM
13463 "xim",
13464#endif
13465#ifdef FEAT_XFONTSET
13466 "xfontset",
13467#endif
Bram Moolenaar79a2a492012-01-04 14:35:37 +010013468#ifdef FEAT_XPM_W32
Bram Moolenaarb5ef5e12013-08-30 16:35:44 +020013469 "xpm",
13470 "xpm_w32", /* for backward compatibility */
13471#else
13472# if defined(HAVE_XPM)
13473 "xpm",
13474# endif
Bram Moolenaar79a2a492012-01-04 14:35:37 +010013475#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013476#ifdef USE_XSMP
13477 "xsmp",
13478#endif
13479#ifdef USE_XSMP_INTERACT
13480 "xsmp_interact",
13481#endif
13482#ifdef FEAT_XCLIPBOARD
13483 "xterm_clipboard",
13484#endif
13485#ifdef FEAT_XTERM_SAVE
13486 "xterm_save",
13487#endif
13488#if defined(UNIX) && defined(FEAT_X11)
13489 "X11",
13490#endif
13491 NULL
13492 };
13493
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013494 name = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013495 for (i = 0; has_list[i] != NULL; ++i)
13496 if (STRICMP(name, has_list[i]) == 0)
13497 {
13498 n = TRUE;
13499 break;
13500 }
13501
13502 if (n == FALSE)
13503 {
13504 if (STRNICMP(name, "patch", 5) == 0)
Bram Moolenaar7f3be402014-04-01 22:08:54 +020013505 {
13506 if (name[5] == '-'
13507 && STRLEN(name) > 11
13508 && vim_isdigit(name[6])
13509 && vim_isdigit(name[8])
13510 && vim_isdigit(name[10]))
13511 {
13512 int major = atoi((char *)name + 6);
13513 int minor = atoi((char *)name + 8);
Bram Moolenaar7f3be402014-04-01 22:08:54 +020013514
13515 /* Expect "patch-9.9.01234". */
13516 n = (major < VIM_VERSION_MAJOR
13517 || (major == VIM_VERSION_MAJOR
13518 && (minor < VIM_VERSION_MINOR
13519 || (minor == VIM_VERSION_MINOR
Bram Moolenaar6716d9a2014-04-02 12:12:08 +020013520 && has_patch(atoi((char *)name + 10))))));
Bram Moolenaar7f3be402014-04-01 22:08:54 +020013521 }
13522 else
13523 n = has_patch(atoi((char *)name + 5));
13524 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013525 else if (STRICMP(name, "vim_starting") == 0)
13526 n = (starting != 0);
Bram Moolenaar42022d52008-12-09 09:57:49 +000013527#ifdef FEAT_MBYTE
13528 else if (STRICMP(name, "multi_byte_encoding") == 0)
13529 n = has_mbyte;
13530#endif
Bram Moolenaar342337a2005-07-21 21:11:17 +000013531#if defined(FEAT_BEVAL) && defined(FEAT_GUI_W32)
13532 else if (STRICMP(name, "balloon_multiline") == 0)
13533 n = multiline_balloon_available();
13534#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013535#ifdef DYNAMIC_TCL
13536 else if (STRICMP(name, "tcl") == 0)
13537 n = tcl_enabled(FALSE);
13538#endif
13539#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
13540 else if (STRICMP(name, "iconv") == 0)
13541 n = iconv_enabled(FALSE);
13542#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +020013543#ifdef DYNAMIC_LUA
13544 else if (STRICMP(name, "lua") == 0)
13545 n = lua_enabled(FALSE);
13546#endif
Bram Moolenaar33570922005-01-25 22:26:29 +000013547#ifdef DYNAMIC_MZSCHEME
13548 else if (STRICMP(name, "mzscheme") == 0)
13549 n = mzscheme_enabled(FALSE);
13550#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013551#ifdef DYNAMIC_RUBY
13552 else if (STRICMP(name, "ruby") == 0)
13553 n = ruby_enabled(FALSE);
13554#endif
Bram Moolenaarbd5e15f2010-07-17 21:19:38 +020013555#ifdef FEAT_PYTHON
Bram Moolenaar071d4272004-06-13 20:20:40 +000013556#ifdef DYNAMIC_PYTHON
13557 else if (STRICMP(name, "python") == 0)
13558 n = python_enabled(FALSE);
13559#endif
Bram Moolenaarbd5e15f2010-07-17 21:19:38 +020013560#endif
13561#ifdef FEAT_PYTHON3
13562#ifdef DYNAMIC_PYTHON3
13563 else if (STRICMP(name, "python3") == 0)
13564 n = python3_enabled(FALSE);
13565#endif
13566#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013567#ifdef DYNAMIC_PERL
13568 else if (STRICMP(name, "perl") == 0)
13569 n = perl_enabled(FALSE);
13570#endif
13571#ifdef FEAT_GUI
13572 else if (STRICMP(name, "gui_running") == 0)
13573 n = (gui.in_use || gui.starting);
13574# ifdef FEAT_GUI_W32
13575 else if (STRICMP(name, "gui_win32s") == 0)
13576 n = gui_is_win32s();
13577# endif
13578# ifdef FEAT_BROWSE
13579 else if (STRICMP(name, "browse") == 0)
13580 n = gui.in_use; /* gui_mch_browse() works when GUI is running */
13581# endif
13582#endif
13583#ifdef FEAT_SYN_HL
13584 else if (STRICMP(name, "syntax_items") == 0)
Bram Moolenaar860cae12010-06-05 23:22:07 +020013585 n = syntax_present(curwin);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013586#endif
13587#if defined(WIN3264)
13588 else if (STRICMP(name, "win95") == 0)
13589 n = mch_windows95();
13590#endif
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +000013591#ifdef FEAT_NETBEANS_INTG
13592 else if (STRICMP(name, "netbeans_enabled") == 0)
Bram Moolenaarb26e6322010-05-22 21:34:09 +020013593 n = netbeans_active();
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +000013594#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013595 }
13596
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013597 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013598}
13599
13600/*
Bram Moolenaare9a41262005-01-15 22:18:47 +000013601 * "has_key()" function
13602 */
13603 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010013604f_has_key(typval_T *argvars, typval_T *rettv)
Bram Moolenaare9a41262005-01-15 22:18:47 +000013605{
Bram Moolenaare9a41262005-01-15 22:18:47 +000013606 if (argvars[0].v_type != VAR_DICT)
13607 {
13608 EMSG(_(e_dictreq));
13609 return;
13610 }
13611 if (argvars[0].vval.v_dict == NULL)
13612 return;
13613
13614 rettv->vval.v_number = dict_find(argvars[0].vval.v_dict,
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000013615 get_tv_string(&argvars[1]), -1) != NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000013616}
13617
13618/*
Bram Moolenaard267b9c2007-04-26 15:06:45 +000013619 * "haslocaldir()" function
13620 */
Bram Moolenaard267b9c2007-04-26 15:06:45 +000013621 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010013622f_haslocaldir(typval_T *argvars, typval_T *rettv)
Bram Moolenaard267b9c2007-04-26 15:06:45 +000013623{
Bram Moolenaarc9703302016-01-17 21:49:33 +010013624 win_T *wp = NULL;
13625
13626 wp = find_tabwin(&argvars[0], &argvars[1]);
13627 rettv->vval.v_number = (wp != NULL && wp->w_localdir != NULL);
Bram Moolenaard267b9c2007-04-26 15:06:45 +000013628}
13629
13630/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013631 * "hasmapto()" function
13632 */
13633 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010013634f_hasmapto(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013635{
13636 char_u *name;
13637 char_u *mode;
13638 char_u buf[NUMBUFLEN];
Bram Moolenaar2c932302006-03-18 21:42:09 +000013639 int abbr = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013640
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013641 name = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013642 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013643 mode = (char_u *)"nvo";
13644 else
Bram Moolenaar2c932302006-03-18 21:42:09 +000013645 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013646 mode = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar2c932302006-03-18 21:42:09 +000013647 if (argvars[2].v_type != VAR_UNKNOWN)
13648 abbr = get_tv_number(&argvars[2]);
13649 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013650
Bram Moolenaar2c932302006-03-18 21:42:09 +000013651 if (map_to_exists(name, mode, abbr))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013652 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013653 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013654 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013655}
13656
13657/*
13658 * "histadd()" function
13659 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013660 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010013661f_histadd(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013662{
13663#ifdef FEAT_CMDHIST
13664 int histype;
13665 char_u *str;
13666 char_u buf[NUMBUFLEN];
13667#endif
13668
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013669 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013670 if (check_restricted() || check_secure())
13671 return;
13672#ifdef FEAT_CMDHIST
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013673 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
13674 histype = str != NULL ? get_histtype(str) : -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013675 if (histype >= 0)
13676 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013677 str = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013678 if (*str != NUL)
13679 {
Bram Moolenaarc7be3f32009-12-24 14:01:12 +000013680 init_history();
Bram Moolenaar071d4272004-06-13 20:20:40 +000013681 add_to_history(histype, str, FALSE, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013682 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013683 return;
13684 }
13685 }
13686#endif
13687}
13688
13689/*
13690 * "histdel()" function
13691 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013692 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010013693f_histdel(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013694{
13695#ifdef FEAT_CMDHIST
13696 int n;
13697 char_u buf[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013698 char_u *str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013699
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013700 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
13701 if (str == NULL)
13702 n = 0;
13703 else if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013704 /* only one argument: clear entire history */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013705 n = clr_history(get_histtype(str));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013706 else if (argvars[1].v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013707 /* index given: remove that entry */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013708 n = del_history_idx(get_histtype(str),
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013709 (int)get_tv_number(&argvars[1]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000013710 else
13711 /* string given: remove all matching entries */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013712 n = del_history_entry(get_histtype(str),
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013713 get_tv_string_buf(&argvars[1], buf));
13714 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013715#endif
13716}
13717
13718/*
13719 * "histget()" function
13720 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013721 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010013722f_histget(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013723{
13724#ifdef FEAT_CMDHIST
13725 int type;
13726 int idx;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013727 char_u *str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013728
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013729 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
13730 if (str == NULL)
13731 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013732 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013733 {
13734 type = get_histtype(str);
13735 if (argvars[1].v_type == VAR_UNKNOWN)
13736 idx = get_history_idx(type);
13737 else
13738 idx = (int)get_tv_number_chk(&argvars[1], NULL);
13739 /* -1 on type error */
13740 rettv->vval.v_string = vim_strsave(get_history_entry(type, idx));
13741 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013742#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013743 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013744#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013745 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013746}
13747
13748/*
13749 * "histnr()" function
13750 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013751 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010013752f_histnr(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013753{
13754 int i;
13755
13756#ifdef FEAT_CMDHIST
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013757 char_u *history = get_tv_string_chk(&argvars[0]);
13758
13759 i = history == NULL ? HIST_CMD - 1 : get_histtype(history);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013760 if (i >= HIST_CMD && i < HIST_COUNT)
13761 i = get_history_idx(i);
13762 else
13763#endif
13764 i = -1;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013765 rettv->vval.v_number = i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013766}
13767
13768/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013769 * "highlightID(name)" function
13770 */
13771 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010013772f_hlID(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013773{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013774 rettv->vval.v_number = syn_name2id(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000013775}
13776
13777/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000013778 * "highlight_exists()" function
13779 */
13780 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010013781f_hlexists(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000013782{
13783 rettv->vval.v_number = highlight_exists(get_tv_string(&argvars[0]));
13784}
13785
13786/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013787 * "hostname()" function
13788 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013789 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010013790f_hostname(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013791{
13792 char_u hostname[256];
13793
13794 mch_get_host_name(hostname, 256);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013795 rettv->v_type = VAR_STRING;
13796 rettv->vval.v_string = vim_strsave(hostname);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013797}
13798
13799/*
13800 * iconv() function
13801 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013802 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010013803f_iconv(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013804{
13805#ifdef FEAT_MBYTE
13806 char_u buf1[NUMBUFLEN];
13807 char_u buf2[NUMBUFLEN];
13808 char_u *from, *to, *str;
13809 vimconv_T vimconv;
13810#endif
13811
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013812 rettv->v_type = VAR_STRING;
13813 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013814
13815#ifdef FEAT_MBYTE
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013816 str = get_tv_string(&argvars[0]);
13817 from = enc_canonize(enc_skip(get_tv_string_buf(&argvars[1], buf1)));
13818 to = enc_canonize(enc_skip(get_tv_string_buf(&argvars[2], buf2)));
Bram Moolenaar071d4272004-06-13 20:20:40 +000013819 vimconv.vc_type = CONV_NONE;
13820 convert_setup(&vimconv, from, to);
13821
13822 /* If the encodings are equal, no conversion needed. */
13823 if (vimconv.vc_type == CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013824 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013825 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013826 rettv->vval.v_string = string_convert(&vimconv, str, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013827
13828 convert_setup(&vimconv, NULL, NULL);
13829 vim_free(from);
13830 vim_free(to);
13831#endif
13832}
13833
13834/*
13835 * "indent()" function
13836 */
13837 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010013838f_indent(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013839{
13840 linenr_T lnum;
13841
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013842 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013843 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013844 rettv->vval.v_number = get_indent_lnum(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013845 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013846 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013847}
13848
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013849/*
13850 * "index()" function
13851 */
13852 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010013853f_index(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013854{
Bram Moolenaar33570922005-01-25 22:26:29 +000013855 list_T *l;
13856 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013857 long idx = 0;
13858 int ic = FALSE;
13859
13860 rettv->vval.v_number = -1;
13861 if (argvars[0].v_type != VAR_LIST)
13862 {
13863 EMSG(_(e_listreq));
13864 return;
13865 }
13866 l = argvars[0].vval.v_list;
13867 if (l != NULL)
13868 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000013869 item = l->lv_first;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013870 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000013871 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013872 int error = FALSE;
13873
Bram Moolenaar758711c2005-02-02 23:11:38 +000013874 /* Start at specified item. Use the cached index that list_find()
13875 * sets, so that a negative number also works. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013876 item = list_find(l, get_tv_number_chk(&argvars[2], &error));
Bram Moolenaar758711c2005-02-02 23:11:38 +000013877 idx = l->lv_idx;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000013878 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013879 ic = get_tv_number_chk(&argvars[3], &error);
13880 if (error)
13881 item = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000013882 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013883
Bram Moolenaar758711c2005-02-02 23:11:38 +000013884 for ( ; item != NULL; item = item->li_next, ++idx)
Bram Moolenaar67b3f992010-11-10 20:41:57 +010013885 if (tv_equal(&item->li_tv, &argvars[1], ic, FALSE))
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013886 {
13887 rettv->vval.v_number = idx;
13888 break;
13889 }
13890 }
13891}
13892
Bram Moolenaar071d4272004-06-13 20:20:40 +000013893static int inputsecret_flag = 0;
13894
Bram Moolenaar48e697e2016-01-23 22:17:30 +010013895static void get_user_input(typval_T *argvars, typval_T *rettv, int inputdialog);
Bram Moolenaarecbaf552006-07-13 06:31:00 +000013896
Bram Moolenaar071d4272004-06-13 20:20:40 +000013897/*
Bram Moolenaarecbaf552006-07-13 06:31:00 +000013898 * This function is used by f_input() and f_inputdialog() functions. The third
13899 * argument to f_input() specifies the type of completion to use at the
13900 * prompt. The third argument to f_inputdialog() specifies the value to return
13901 * when the user cancels the prompt.
Bram Moolenaar071d4272004-06-13 20:20:40 +000013902 */
13903 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010013904get_user_input(
13905 typval_T *argvars,
13906 typval_T *rettv,
13907 int inputdialog)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013908{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013909 char_u *prompt = get_tv_string_chk(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013910 char_u *p = NULL;
13911 int c;
13912 char_u buf[NUMBUFLEN];
13913 int cmd_silent_save = cmd_silent;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013914 char_u *defstr = (char_u *)"";
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000013915 int xp_type = EXPAND_NOTHING;
13916 char_u *xp_arg = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013917
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013918 rettv->v_type = VAR_STRING;
Bram Moolenaarce85c562007-09-16 12:21:16 +000013919 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013920
13921#ifdef NO_CONSOLE_INPUT
13922 /* While starting up, there is no place to enter text. */
13923 if (no_console_input())
Bram Moolenaar071d4272004-06-13 20:20:40 +000013924 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013925#endif
13926
13927 cmd_silent = FALSE; /* Want to see the prompt. */
13928 if (prompt != NULL)
13929 {
13930 /* Only the part of the message after the last NL is considered as
13931 * prompt for the command line */
13932 p = vim_strrchr(prompt, '\n');
13933 if (p == NULL)
13934 p = prompt;
13935 else
13936 {
13937 ++p;
13938 c = *p;
13939 *p = NUL;
13940 msg_start();
13941 msg_clr_eos();
13942 msg_puts_attr(prompt, echo_attr);
13943 msg_didout = FALSE;
13944 msg_starthere();
13945 *p = c;
13946 }
13947 cmdline_row = msg_row;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013948
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013949 if (argvars[1].v_type != VAR_UNKNOWN)
13950 {
13951 defstr = get_tv_string_buf_chk(&argvars[1], buf);
13952 if (defstr != NULL)
13953 stuffReadbuffSpec(defstr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013954
Bram Moolenaarecbaf552006-07-13 06:31:00 +000013955 if (!inputdialog && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar4463f292005-09-25 22:20:24 +000013956 {
13957 char_u *xp_name;
Bram Moolenaar86c9ee22006-05-13 11:33:27 +000013958 int xp_namelen;
Bram Moolenaar4463f292005-09-25 22:20:24 +000013959 long argt;
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000013960
Bram Moolenaarb5c9cb52012-07-16 19:27:29 +020013961 /* input() with a third argument: completion */
Bram Moolenaar4463f292005-09-25 22:20:24 +000013962 rettv->vval.v_string = NULL;
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000013963
Bram Moolenaar4463f292005-09-25 22:20:24 +000013964 xp_name = get_tv_string_buf_chk(&argvars[2], buf);
13965 if (xp_name == NULL)
13966 return;
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000013967
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000013968 xp_namelen = (int)STRLEN(xp_name);
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000013969
Bram Moolenaar4463f292005-09-25 22:20:24 +000013970 if (parse_compl_arg(xp_name, xp_namelen, &xp_type, &argt,
13971 &xp_arg) == FAIL)
13972 return;
13973 }
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000013974 }
13975
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013976 if (defstr != NULL)
Bram Moolenaar35a7c682013-10-02 16:46:28 +020013977 {
Bram Moolenaar35a7c682013-10-02 16:46:28 +020013978 int save_ex_normal_busy = ex_normal_busy;
13979 ex_normal_busy = 0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013980 rettv->vval.v_string =
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000013981 getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr,
13982 xp_type, xp_arg);
Bram Moolenaar35a7c682013-10-02 16:46:28 +020013983 ex_normal_busy = save_ex_normal_busy;
Bram Moolenaar35a7c682013-10-02 16:46:28 +020013984 }
Bram Moolenaar04b27512012-08-08 14:33:21 +020013985 if (inputdialog && rettv->vval.v_string == NULL
Bram Moolenaarb5c9cb52012-07-16 19:27:29 +020013986 && argvars[1].v_type != VAR_UNKNOWN
13987 && argvars[2].v_type != VAR_UNKNOWN)
13988 rettv->vval.v_string = vim_strsave(get_tv_string_buf(
13989 &argvars[2], buf));
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000013990
13991 vim_free(xp_arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013992
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013993 /* since the user typed this, no need to wait for return */
13994 need_wait_return = FALSE;
13995 msg_didout = FALSE;
13996 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013997 cmd_silent = cmd_silent_save;
13998}
13999
14000/*
Bram Moolenaarecbaf552006-07-13 06:31:00 +000014001 * "input()" function
14002 * Also handles inputsecret() when inputsecret is set.
14003 */
14004 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014005f_input(typval_T *argvars, typval_T *rettv)
Bram Moolenaarecbaf552006-07-13 06:31:00 +000014006{
14007 get_user_input(argvars, rettv, FALSE);
14008}
14009
14010/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014011 * "inputdialog()" function
14012 */
14013 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014014f_inputdialog(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014015{
14016#if defined(FEAT_GUI_TEXTDIALOG)
14017 /* Use a GUI dialog if the GUI is running and 'c' is not in 'guioptions' */
14018 if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
14019 {
14020 char_u *message;
14021 char_u buf[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014022 char_u *defstr = (char_u *)"";
Bram Moolenaar071d4272004-06-13 20:20:40 +000014023
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014024 message = get_tv_string_chk(&argvars[0]);
14025 if (argvars[1].v_type != VAR_UNKNOWN
Bram Moolenaarc05f93f2006-05-02 22:09:31 +000014026 && (defstr = get_tv_string_buf_chk(&argvars[1], buf)) != NULL)
Bram Moolenaarce0842a2005-07-18 21:58:11 +000014027 vim_strncpy(IObuff, defstr, IOSIZE - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014028 else
14029 IObuff[0] = NUL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014030 if (message != NULL && defstr != NULL
14031 && do_dialog(VIM_QUESTION, NULL, message,
Bram Moolenaard2c340a2011-01-17 20:08:11 +010014032 (char_u *)_("&OK\n&Cancel"), 1, IObuff, FALSE) == 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014033 rettv->vval.v_string = vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014034 else
14035 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014036 if (message != NULL && defstr != NULL
14037 && argvars[1].v_type != VAR_UNKNOWN
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014038 && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014039 rettv->vval.v_string = vim_strsave(
14040 get_tv_string_buf(&argvars[2], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +000014041 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014042 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014043 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014044 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014045 }
14046 else
14047#endif
Bram Moolenaarecbaf552006-07-13 06:31:00 +000014048 get_user_input(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014049}
14050
Bram Moolenaar6efa2b32005-09-10 19:26:26 +000014051/*
14052 * "inputlist()" function
14053 */
14054 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014055f_inputlist(typval_T *argvars, typval_T *rettv)
Bram Moolenaar6efa2b32005-09-10 19:26:26 +000014056{
14057 listitem_T *li;
14058 int selected;
14059 int mouse_used;
14060
Bram Moolenaar6efa2b32005-09-10 19:26:26 +000014061#ifdef NO_CONSOLE_INPUT
14062 /* While starting up, there is no place to enter text. */
14063 if (no_console_input())
14064 return;
14065#endif
14066 if (argvars[0].v_type != VAR_LIST || argvars[0].vval.v_list == NULL)
14067 {
14068 EMSG2(_(e_listarg), "inputlist()");
14069 return;
14070 }
14071
14072 msg_start();
Bram Moolenaar412f7442006-07-23 19:51:57 +000014073 msg_row = Rows - 1; /* for when 'cmdheight' > 1 */
Bram Moolenaar6efa2b32005-09-10 19:26:26 +000014074 lines_left = Rows; /* avoid more prompt */
14075 msg_scroll = TRUE;
14076 msg_clr_eos();
14077
14078 for (li = argvars[0].vval.v_list->lv_first; li != NULL; li = li->li_next)
14079 {
14080 msg_puts(get_tv_string(&li->li_tv));
14081 msg_putchar('\n');
14082 }
14083
14084 /* Ask for choice. */
14085 selected = prompt_for_number(&mouse_used);
14086 if (mouse_used)
14087 selected -= lines_left;
14088
14089 rettv->vval.v_number = selected;
14090}
14091
14092
Bram Moolenaar071d4272004-06-13 20:20:40 +000014093static garray_T ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL};
14094
14095/*
14096 * "inputrestore()" function
14097 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014098 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014099f_inputrestore(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014100{
14101 if (ga_userinput.ga_len > 0)
14102 {
14103 --ga_userinput.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014104 restore_typeahead((tasave_T *)(ga_userinput.ga_data)
14105 + ga_userinput.ga_len);
Bram Moolenaar798b30b2009-04-22 10:56:16 +000014106 /* default return is zero == OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014107 }
14108 else if (p_verbose > 1)
14109 {
Bram Moolenaar54ee7752005-05-31 22:22:17 +000014110 verb_msg((char_u *)_("called inputrestore() more often than inputsave()"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014111 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014112 }
14113}
14114
14115/*
14116 * "inputsave()" function
14117 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014118 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014119f_inputsave(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014120{
Bram Moolenaar8c8de832008-06-24 22:58:06 +000014121 /* Add an entry to the stack of typeahead storage. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014122 if (ga_grow(&ga_userinput, 1) == OK)
14123 {
14124 save_typeahead((tasave_T *)(ga_userinput.ga_data)
14125 + ga_userinput.ga_len);
14126 ++ga_userinput.ga_len;
Bram Moolenaar798b30b2009-04-22 10:56:16 +000014127 /* default return is zero == OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014128 }
14129 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014130 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014131}
14132
14133/*
14134 * "inputsecret()" function
14135 */
14136 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014137f_inputsecret(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014138{
14139 ++cmdline_star;
14140 ++inputsecret_flag;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014141 f_input(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014142 --cmdline_star;
14143 --inputsecret_flag;
14144}
14145
14146/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014147 * "insert()" function
14148 */
14149 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014150f_insert(typval_T *argvars, typval_T *rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014151{
14152 long before = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000014153 listitem_T *item;
14154 list_T *l;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014155 int error = FALSE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014156
14157 if (argvars[0].v_type != VAR_LIST)
Bram Moolenaar0d660222005-01-07 21:51:51 +000014158 EMSG2(_(e_listarg), "insert()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014159 else if ((l = argvars[0].vval.v_list) != NULL
Bram Moolenaar77354e72015-04-21 16:49:05 +020014160 && !tv_check_lock(l->lv_lock, (char_u *)N_("insert() argument"), TRUE))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014161 {
14162 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014163 before = get_tv_number_chk(&argvars[2], &error);
14164 if (error)
14165 return; /* type error; errmsg already given */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014166
Bram Moolenaar758711c2005-02-02 23:11:38 +000014167 if (before == l->lv_len)
14168 item = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014169 else
14170 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000014171 item = list_find(l, before);
14172 if (item == NULL)
14173 {
14174 EMSGN(_(e_listidx), before);
14175 l = NULL;
14176 }
14177 }
14178 if (l != NULL)
14179 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +000014180 list_insert_tv(l, &argvars[1], item);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000014181 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014182 }
14183 }
14184}
14185
14186/*
Bram Moolenaard6e256c2011-12-14 15:32:50 +010014187 * "invert(expr)" function
14188 */
14189 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014190f_invert(typval_T *argvars, typval_T *rettv)
Bram Moolenaard6e256c2011-12-14 15:32:50 +010014191{
14192 rettv->vval.v_number = ~get_tv_number_chk(&argvars[0], NULL);
14193}
14194
14195/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014196 * "isdirectory()" function
14197 */
14198 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014199f_isdirectory(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014200{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014201 rettv->vval.v_number = mch_isdir(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000014202}
14203
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014204/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014205 * "islocked()" function
14206 */
14207 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014208f_islocked(typval_T *argvars, typval_T *rettv)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014209{
14210 lval_T lv;
14211 char_u *end;
14212 dictitem_T *di;
14213
14214 rettv->vval.v_number = -1;
Bram Moolenaar6d977d62014-01-14 15:24:39 +010014215 end = get_lval(get_tv_string(&argvars[0]), NULL, &lv, FALSE, FALSE,
14216 GLV_NO_AUTOLOAD, FNE_CHECK_START);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014217 if (end != NULL && lv.ll_name != NULL)
14218 {
14219 if (*end != NUL)
14220 EMSG(_(e_trailing));
14221 else
14222 {
14223 if (lv.ll_tv == NULL)
14224 {
14225 if (check_changedtick(lv.ll_name))
14226 rettv->vval.v_number = 1; /* always locked */
14227 else
14228 {
Bram Moolenaar6d977d62014-01-14 15:24:39 +010014229 di = find_var(lv.ll_name, NULL, TRUE);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014230 if (di != NULL)
14231 {
14232 /* Consider a variable locked when:
14233 * 1. the variable itself is locked
14234 * 2. the value of the variable is locked.
14235 * 3. the List or Dict value is locked.
14236 */
14237 rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK)
14238 || tv_islocked(&di->di_tv));
14239 }
14240 }
14241 }
14242 else if (lv.ll_range)
Bram Moolenaar910f66f2006-04-05 20:41:53 +000014243 EMSG(_("E786: Range not allowed"));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014244 else if (lv.ll_newkey != NULL)
14245 EMSG2(_(e_dictkey), lv.ll_newkey);
14246 else if (lv.ll_list != NULL)
14247 /* List item. */
14248 rettv->vval.v_number = tv_islocked(&lv.ll_li->li_tv);
14249 else
14250 /* Dictionary item. */
14251 rettv->vval.v_number = tv_islocked(&lv.ll_di->di_tv);
14252 }
14253 }
14254
14255 clear_lval(&lv);
14256}
14257
Bram Moolenaarf1b6ac72016-02-23 21:26:43 +010014258#if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
14259/*
14260 * "isnan()" function
14261 */
14262 static void
14263f_isnan(typval_T *argvars, typval_T *rettv)
14264{
14265 rettv->vval.v_number = argvars[0].v_type == VAR_FLOAT
14266 && isnan(argvars[0].vval.v_float);
14267}
14268#endif
14269
Bram Moolenaar48e697e2016-01-23 22:17:30 +010014270static void dict_list(typval_T *argvars, typval_T *rettv, int what);
Bram Moolenaar8c711452005-01-14 21:53:12 +000014271
14272/*
14273 * Turn a dict into a list:
14274 * "what" == 0: list of keys
14275 * "what" == 1: list of values
14276 * "what" == 2: list of items
14277 */
14278 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014279dict_list(typval_T *argvars, typval_T *rettv, int what)
Bram Moolenaar8c711452005-01-14 21:53:12 +000014280{
Bram Moolenaar33570922005-01-25 22:26:29 +000014281 list_T *l2;
14282 dictitem_T *di;
14283 hashitem_T *hi;
14284 listitem_T *li;
14285 listitem_T *li2;
14286 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000014287 int todo;
Bram Moolenaar8c711452005-01-14 21:53:12 +000014288
Bram Moolenaar8c711452005-01-14 21:53:12 +000014289 if (argvars[0].v_type != VAR_DICT)
14290 {
14291 EMSG(_(e_dictreq));
14292 return;
14293 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000014294 if ((d = argvars[0].vval.v_dict) == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000014295 return;
14296
Bram Moolenaareddf53b2006-02-27 00:11:10 +000014297 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000014298 return;
Bram Moolenaar8c711452005-01-14 21:53:12 +000014299
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000014300 todo = (int)d->dv_hashtab.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +000014301 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +000014302 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000014303 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar8c711452005-01-14 21:53:12 +000014304 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000014305 --todo;
14306 di = HI2DI(hi);
Bram Moolenaar8c711452005-01-14 21:53:12 +000014307
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000014308 li = listitem_alloc();
14309 if (li == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000014310 break;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000014311 list_append(rettv->vval.v_list, li);
Bram Moolenaar8c711452005-01-14 21:53:12 +000014312
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000014313 if (what == 0)
14314 {
14315 /* keys() */
14316 li->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014317 li->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000014318 li->li_tv.vval.v_string = vim_strsave(di->di_key);
14319 }
14320 else if (what == 1)
14321 {
14322 /* values() */
14323 copy_tv(&di->di_tv, &li->li_tv);
14324 }
14325 else
14326 {
14327 /* items() */
14328 l2 = list_alloc();
14329 li->li_tv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014330 li->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000014331 li->li_tv.vval.v_list = l2;
14332 if (l2 == NULL)
14333 break;
14334 ++l2->lv_refcount;
14335
14336 li2 = listitem_alloc();
14337 if (li2 == NULL)
14338 break;
14339 list_append(l2, li2);
14340 li2->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014341 li2->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000014342 li2->li_tv.vval.v_string = vim_strsave(di->di_key);
14343
14344 li2 = listitem_alloc();
14345 if (li2 == NULL)
14346 break;
14347 list_append(l2, li2);
14348 copy_tv(&di->di_tv, &li2->li_tv);
14349 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000014350 }
14351 }
14352}
14353
14354/*
14355 * "items(dict)" function
14356 */
14357 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014358f_items(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8c711452005-01-14 21:53:12 +000014359{
14360 dict_list(argvars, rettv, 2);
14361}
14362
Bram Moolenaar509ce2a2016-03-11 22:52:15 +010014363#if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
Bram Moolenaar65edff82016-02-21 16:40:11 +010014364/*
14365 * Get the job from the argument.
14366 * Returns NULL if the job is invalid.
14367 */
14368 static job_T *
14369get_job_arg(typval_T *tv)
14370{
14371 job_T *job;
14372
14373 if (tv->v_type != VAR_JOB)
14374 {
14375 EMSG2(_(e_invarg2), get_tv_string(tv));
14376 return NULL;
14377 }
14378 job = tv->vval.v_job;
14379
14380 if (job == NULL)
14381 EMSG(_("E916: not a valid job"));
14382 return job;
14383}
Bram Moolenaarfa4bce72016-02-13 23:50:08 +010014384
Bram Moolenaar835dc632016-02-07 14:27:38 +010014385/*
Bram Moolenaar6463ca22016-02-13 17:04:46 +010014386 * "job_getchannel()" function
14387 */
14388 static void
14389f_job_getchannel(typval_T *argvars, typval_T *rettv)
14390{
Bram Moolenaar65edff82016-02-21 16:40:11 +010014391 job_T *job = get_job_arg(&argvars[0]);
Bram Moolenaar6463ca22016-02-13 17:04:46 +010014392
Bram Moolenaar65edff82016-02-21 16:40:11 +010014393 if (job != NULL)
14394 {
Bram Moolenaar77073442016-02-13 23:23:53 +010014395 rettv->v_type = VAR_CHANNEL;
14396 rettv->vval.v_channel = job->jv_channel;
14397 if (job->jv_channel != NULL)
14398 ++job->jv_channel->ch_refcount;
Bram Moolenaar6463ca22016-02-13 17:04:46 +010014399 }
14400}
14401
14402/*
Bram Moolenaar8950a562016-03-12 15:22:55 +010014403 * "job_info()" function
14404 */
14405 static void
14406f_job_info(typval_T *argvars, typval_T *rettv)
14407{
14408 job_T *job = get_job_arg(&argvars[0]);
14409
14410 if (job != NULL && rettv_dict_alloc(rettv) != FAIL)
14411 job_info(job, rettv->vval.v_dict);
14412}
14413
14414/*
Bram Moolenaar65edff82016-02-21 16:40:11 +010014415 * "job_setoptions()" function
14416 */
14417 static void
14418f_job_setoptions(typval_T *argvars, typval_T *rettv UNUSED)
14419{
14420 job_T *job = get_job_arg(&argvars[0]);
14421 jobopt_T opt;
14422
14423 if (job == NULL)
14424 return;
14425 clear_job_options(&opt);
Bram Moolenaaree1cffc2016-02-21 19:14:41 +010014426 if (get_job_options(&argvars[1], &opt, JO_STOPONEXIT + JO_EXIT_CB) == FAIL)
Bram Moolenaar65edff82016-02-21 16:40:11 +010014427 return;
14428 job_set_options(job, &opt);
14429}
14430
14431/*
Bram Moolenaar835dc632016-02-07 14:27:38 +010014432 * "job_start()" function
14433 */
14434 static void
Bram Moolenaar151f6562016-03-07 21:19:38 +010014435f_job_start(typval_T *argvars, typval_T *rettv)
Bram Moolenaar835dc632016-02-07 14:27:38 +010014436{
Bram Moolenaar835dc632016-02-07 14:27:38 +010014437 rettv->v_type = VAR_JOB;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +010014438 rettv->vval.v_job = job_start(argvars);
Bram Moolenaaree1cffc2016-02-21 19:14:41 +010014439}
14440
14441/*
Bram Moolenaar835dc632016-02-07 14:27:38 +010014442 * "job_status()" function
14443 */
14444 static void
Bram Moolenaar6463ca22016-02-13 17:04:46 +010014445f_job_status(typval_T *argvars, typval_T *rettv)
Bram Moolenaar835dc632016-02-07 14:27:38 +010014446{
Bram Moolenaar65edff82016-02-21 16:40:11 +010014447 job_T *job = get_job_arg(&argvars[0]);
Bram Moolenaar835dc632016-02-07 14:27:38 +010014448
Bram Moolenaar65edff82016-02-21 16:40:11 +010014449 if (job != NULL)
Bram Moolenaar835dc632016-02-07 14:27:38 +010014450 {
Bram Moolenaar835dc632016-02-07 14:27:38 +010014451 rettv->v_type = VAR_STRING;
Bram Moolenaar8950a562016-03-12 15:22:55 +010014452 rettv->vval.v_string = vim_strsave((char_u *)job_status(job));
Bram Moolenaar835dc632016-02-07 14:27:38 +010014453 }
14454}
14455
14456/*
14457 * "job_stop()" function
14458 */
14459 static void
Bram Moolenaar8e2c9422016-03-12 13:43:33 +010014460f_job_stop(typval_T *argvars, typval_T *rettv)
Bram Moolenaar835dc632016-02-07 14:27:38 +010014461{
Bram Moolenaar65edff82016-02-21 16:40:11 +010014462 job_T *job = get_job_arg(&argvars[0]);
14463
14464 if (job != NULL)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +010014465 rettv->vval.v_number = job_stop(job, argvars);
Bram Moolenaar835dc632016-02-07 14:27:38 +010014466}
14467#endif
14468
Bram Moolenaar071d4272004-06-13 20:20:40 +000014469/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014470 * "join()" function
14471 */
14472 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014473f_join(typval_T *argvars, typval_T *rettv)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014474{
14475 garray_T ga;
14476 char_u *sep;
14477
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014478 if (argvars[0].v_type != VAR_LIST)
14479 {
14480 EMSG(_(e_listreq));
14481 return;
14482 }
14483 if (argvars[0].vval.v_list == NULL)
14484 return;
14485 if (argvars[1].v_type == VAR_UNKNOWN)
14486 sep = (char_u *)" ";
14487 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014488 sep = get_tv_string_chk(&argvars[1]);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014489
14490 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014491
14492 if (sep != NULL)
14493 {
14494 ga_init2(&ga, (int)sizeof(char), 80);
Bram Moolenaarb71eaae2006-01-20 23:10:18 +000014495 list_join(&ga, argvars[0].vval.v_list, sep, TRUE, 0);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014496 ga_append(&ga, NUL);
14497 rettv->vval.v_string = (char_u *)ga.ga_data;
14498 }
14499 else
14500 rettv->vval.v_string = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014501}
14502
14503/*
Bram Moolenaar7823a3b2016-02-11 21:08:32 +010014504 * "js_decode()" function
Bram Moolenaar595e64e2016-02-07 19:19:53 +010014505 */
14506 static void
Bram Moolenaar7823a3b2016-02-11 21:08:32 +010014507f_js_decode(typval_T *argvars, typval_T *rettv)
Bram Moolenaar595e64e2016-02-07 19:19:53 +010014508{
14509 js_read_T reader;
14510
14511 reader.js_buf = get_tv_string(&argvars[0]);
14512 reader.js_fill = NULL;
14513 reader.js_used = 0;
14514 if (json_decode_all(&reader, rettv, JSON_JS) != OK)
14515 EMSG(_(e_invarg));
14516}
14517
14518/*
Bram Moolenaar7823a3b2016-02-11 21:08:32 +010014519 * "js_encode()" function
Bram Moolenaar595e64e2016-02-07 19:19:53 +010014520 */
14521 static void
Bram Moolenaar7823a3b2016-02-11 21:08:32 +010014522f_js_encode(typval_T *argvars, typval_T *rettv)
Bram Moolenaar595e64e2016-02-07 19:19:53 +010014523{
14524 rettv->v_type = VAR_STRING;
14525 rettv->vval.v_string = json_encode(&argvars[0], JSON_JS);
14526}
14527
14528/*
Bram Moolenaar7823a3b2016-02-11 21:08:32 +010014529 * "json_decode()" function
Bram Moolenaar520e1e42016-01-23 19:46:28 +010014530 */
14531 static void
Bram Moolenaar7823a3b2016-02-11 21:08:32 +010014532f_json_decode(typval_T *argvars, typval_T *rettv)
Bram Moolenaar520e1e42016-01-23 19:46:28 +010014533{
14534 js_read_T reader;
14535
14536 reader.js_buf = get_tv_string(&argvars[0]);
Bram Moolenaar56ead342016-02-02 18:20:08 +010014537 reader.js_fill = NULL;
Bram Moolenaar520e1e42016-01-23 19:46:28 +010014538 reader.js_used = 0;
Bram Moolenaar595e64e2016-02-07 19:19:53 +010014539 if (json_decode_all(&reader, rettv, 0) != OK)
Bram Moolenaar11e0afa2016-02-01 22:41:00 +010014540 EMSG(_(e_invarg));
Bram Moolenaar520e1e42016-01-23 19:46:28 +010014541}
14542
14543/*
Bram Moolenaar7823a3b2016-02-11 21:08:32 +010014544 * "json_encode()" function
Bram Moolenaar520e1e42016-01-23 19:46:28 +010014545 */
14546 static void
Bram Moolenaar7823a3b2016-02-11 21:08:32 +010014547f_json_encode(typval_T *argvars, typval_T *rettv)
Bram Moolenaar520e1e42016-01-23 19:46:28 +010014548{
14549 rettv->v_type = VAR_STRING;
Bram Moolenaar595e64e2016-02-07 19:19:53 +010014550 rettv->vval.v_string = json_encode(&argvars[0], 0);
Bram Moolenaar520e1e42016-01-23 19:46:28 +010014551}
14552
14553/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000014554 * "keys()" function
14555 */
14556 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014557f_keys(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8c711452005-01-14 21:53:12 +000014558{
14559 dict_list(argvars, rettv, 0);
14560}
14561
14562/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014563 * "last_buffer_nr()" function.
14564 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014565 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014566f_last_buffer_nr(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014567{
14568 int n = 0;
14569 buf_T *buf;
14570
14571 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
14572 if (n < buf->b_fnum)
14573 n = buf->b_fnum;
14574
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014575 rettv->vval.v_number = n;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014576}
14577
14578/*
14579 * "len()" function
14580 */
14581 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014582f_len(typval_T *argvars, typval_T *rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014583{
14584 switch (argvars[0].v_type)
14585 {
14586 case VAR_STRING:
14587 case VAR_NUMBER:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014588 rettv->vval.v_number = (varnumber_T)STRLEN(
14589 get_tv_string(&argvars[0]));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014590 break;
14591 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014592 rettv->vval.v_number = list_len(argvars[0].vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014593 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +000014594 case VAR_DICT:
14595 rettv->vval.v_number = dict_len(argvars[0].vval.v_dict);
14596 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +010014597 case VAR_UNKNOWN:
14598 case VAR_SPECIAL:
14599 case VAR_FLOAT:
14600 case VAR_FUNC:
Bram Moolenaar835dc632016-02-07 14:27:38 +010014601 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +010014602 case VAR_CHANNEL:
Bram Moolenaare49b69a2005-01-08 16:11:57 +000014603 EMSG(_("E701: Invalid type for len()"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014604 break;
14605 }
14606}
14607
Bram Moolenaar48e697e2016-01-23 22:17:30 +010014608static void libcall_common(typval_T *argvars, typval_T *rettv, int type);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014609
14610 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014611libcall_common(typval_T *argvars, typval_T *rettv, int type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014612{
14613#ifdef FEAT_LIBCALL
14614 char_u *string_in;
14615 char_u **string_result;
14616 int nr_result;
14617#endif
14618
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014619 rettv->v_type = type;
Bram Moolenaar798b30b2009-04-22 10:56:16 +000014620 if (type != VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014621 rettv->vval.v_string = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014622
14623 if (check_restricted() || check_secure())
14624 return;
14625
14626#ifdef FEAT_LIBCALL
14627 /* The first two args must be strings, otherwise its meaningless */
14628 if (argvars[0].v_type == VAR_STRING && argvars[1].v_type == VAR_STRING)
14629 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000014630 string_in = NULL;
14631 if (argvars[2].v_type == VAR_STRING)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014632 string_in = argvars[2].vval.v_string;
14633 if (type == VAR_NUMBER)
14634 string_result = NULL;
14635 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014636 string_result = &rettv->vval.v_string;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014637 if (mch_libcall(argvars[0].vval.v_string,
14638 argvars[1].vval.v_string,
14639 string_in,
14640 argvars[2].vval.v_number,
14641 string_result,
14642 &nr_result) == OK
14643 && type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014644 rettv->vval.v_number = nr_result;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014645 }
14646#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000014647}
14648
14649/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000014650 * "libcall()" function
14651 */
14652 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014653f_libcall(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000014654{
14655 libcall_common(argvars, rettv, VAR_STRING);
14656}
14657
14658/*
14659 * "libcallnr()" function
14660 */
14661 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014662f_libcallnr(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000014663{
14664 libcall_common(argvars, rettv, VAR_NUMBER);
14665}
14666
14667/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014668 * "line(string)" function
14669 */
14670 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014671f_line(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014672{
14673 linenr_T lnum = 0;
14674 pos_T *fp;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000014675 int fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014676
Bram Moolenaar0e34f622006-03-03 23:00:03 +000014677 fp = var2fpos(&argvars[0], TRUE, &fnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014678 if (fp != NULL)
14679 lnum = fp->lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014680 rettv->vval.v_number = lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014681}
14682
14683/*
14684 * "line2byte(lnum)" function
14685 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014686 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014687f_line2byte(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014688{
14689#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014690 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014691#else
14692 linenr_T lnum;
14693
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014694 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014695 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014696 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014697 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014698 rettv->vval.v_number = ml_find_line_or_offset(curbuf, lnum, NULL);
14699 if (rettv->vval.v_number >= 0)
14700 ++rettv->vval.v_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014701#endif
14702}
14703
14704/*
14705 * "lispindent(lnum)" function
14706 */
14707 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014708f_lispindent(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014709{
14710#ifdef FEAT_LISP
14711 pos_T pos;
14712 linenr_T lnum;
14713
14714 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014715 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014716 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
14717 {
14718 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014719 rettv->vval.v_number = get_lisp_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +000014720 curwin->w_cursor = pos;
14721 }
14722 else
14723#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014724 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014725}
14726
14727/*
14728 * "localtime()" function
14729 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014730 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014731f_localtime(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014732{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014733 rettv->vval.v_number = (varnumber_T)time(NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014734}
14735
Bram Moolenaar48e697e2016-01-23 22:17:30 +010014736static void get_maparg(typval_T *argvars, typval_T *rettv, int exact);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014737
14738 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014739get_maparg(typval_T *argvars, typval_T *rettv, int exact)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014740{
14741 char_u *keys;
14742 char_u *which;
14743 char_u buf[NUMBUFLEN];
14744 char_u *keys_buf = NULL;
14745 char_u *rhs;
14746 int mode;
Bram Moolenaar2c932302006-03-18 21:42:09 +000014747 int abbr = FALSE;
Bram Moolenaar3fe37d62012-02-06 00:13:22 +010014748 int get_dict = FALSE;
Bram Moolenaarbd743252010-10-20 21:23:33 +020014749 mapblock_T *mp;
14750 int buffer_local;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014751
14752 /* return empty string for failure */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014753 rettv->v_type = VAR_STRING;
14754 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014755
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014756 keys = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014757 if (*keys == NUL)
14758 return;
14759
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014760 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar2c932302006-03-18 21:42:09 +000014761 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014762 which = get_tv_string_buf_chk(&argvars[1], buf);
Bram Moolenaar2c932302006-03-18 21:42:09 +000014763 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarbd743252010-10-20 21:23:33 +020014764 {
Bram Moolenaar2c932302006-03-18 21:42:09 +000014765 abbr = get_tv_number(&argvars[2]);
Bram Moolenaarbd743252010-10-20 21:23:33 +020014766 if (argvars[3].v_type != VAR_UNKNOWN)
14767 get_dict = get_tv_number(&argvars[3]);
14768 }
Bram Moolenaar2c932302006-03-18 21:42:09 +000014769 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014770 else
14771 which = (char_u *)"";
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014772 if (which == NULL)
14773 return;
14774
Bram Moolenaar071d4272004-06-13 20:20:40 +000014775 mode = get_map_mode(&which, 0);
14776
Bram Moolenaar3fb9eda2006-05-03 21:29:58 +000014777 keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, FALSE);
Bram Moolenaarbd743252010-10-20 21:23:33 +020014778 rhs = check_map(keys, mode, exact, FALSE, abbr, &mp, &buffer_local);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014779 vim_free(keys_buf);
Bram Moolenaarbd743252010-10-20 21:23:33 +020014780
14781 if (!get_dict)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014782 {
Bram Moolenaarbd743252010-10-20 21:23:33 +020014783 /* Return a string. */
14784 if (rhs != NULL)
14785 rettv->vval.v_string = str2special_save(rhs, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014786
Bram Moolenaarbd743252010-10-20 21:23:33 +020014787 }
14788 else if (rettv_dict_alloc(rettv) != FAIL && rhs != NULL)
14789 {
14790 /* Return a dictionary. */
14791 char_u *lhs = str2special_save(mp->m_keys, TRUE);
14792 char_u *mapmode = map_mode_to_chars(mp->m_mode);
14793 dict_T *dict = rettv->vval.v_dict;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014794
Bram Moolenaarbd743252010-10-20 21:23:33 +020014795 dict_add_nr_str(dict, "lhs", 0L, lhs);
14796 dict_add_nr_str(dict, "rhs", 0L, mp->m_orig_str);
14797 dict_add_nr_str(dict, "noremap", mp->m_noremap ? 1L : 0L , NULL);
14798 dict_add_nr_str(dict, "expr", mp->m_expr ? 1L : 0L, NULL);
14799 dict_add_nr_str(dict, "silent", mp->m_silent ? 1L : 0L, NULL);
14800 dict_add_nr_str(dict, "sid", (long)mp->m_script_ID, NULL);
14801 dict_add_nr_str(dict, "buffer", (long)buffer_local, NULL);
Bram Moolenaar72179e12013-06-29 13:58:31 +020014802 dict_add_nr_str(dict, "nowait", mp->m_nowait ? 1L : 0L, NULL);
Bram Moolenaarbd743252010-10-20 21:23:33 +020014803 dict_add_nr_str(dict, "mode", 0L, mapmode);
14804
14805 vim_free(lhs);
14806 vim_free(mapmode);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014807 }
14808}
14809
Bram Moolenaar8c8de832008-06-24 22:58:06 +000014810#ifdef FEAT_FLOAT
14811/*
Bram Moolenaardb7c6862010-05-21 16:33:48 +020014812 * "log()" function
14813 */
14814 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014815f_log(typval_T *argvars, typval_T *rettv)
Bram Moolenaardb7c6862010-05-21 16:33:48 +020014816{
Bram Moolenaara1e24b92016-02-18 20:18:09 +010014817 float_T f = 0.0;
Bram Moolenaardb7c6862010-05-21 16:33:48 +020014818
14819 rettv->v_type = VAR_FLOAT;
14820 if (get_float_arg(argvars, &f) == OK)
14821 rettv->vval.v_float = log(f);
14822 else
14823 rettv->vval.v_float = 0.0;
14824}
14825
14826/*
Bram Moolenaar8c8de832008-06-24 22:58:06 +000014827 * "log10()" function
14828 */
14829 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014830f_log10(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8c8de832008-06-24 22:58:06 +000014831{
Bram Moolenaara1e24b92016-02-18 20:18:09 +010014832 float_T f = 0.0;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000014833
14834 rettv->v_type = VAR_FLOAT;
14835 if (get_float_arg(argvars, &f) == OK)
14836 rettv->vval.v_float = log10(f);
14837 else
14838 rettv->vval.v_float = 0.0;
14839}
14840#endif
14841
Bram Moolenaar1dced572012-04-05 16:54:08 +020014842#ifdef FEAT_LUA
14843/*
14844 * "luaeval()" function
14845 */
14846 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014847f_luaeval(typval_T *argvars, typval_T *rettv)
Bram Moolenaar1dced572012-04-05 16:54:08 +020014848{
14849 char_u *str;
14850 char_u buf[NUMBUFLEN];
14851
14852 str = get_tv_string_buf(&argvars[0], buf);
14853 do_luaeval(str, argvars + 1, rettv);
14854}
14855#endif
14856
Bram Moolenaar071d4272004-06-13 20:20:40 +000014857/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014858 * "map()" function
14859 */
14860 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014861f_map(typval_T *argvars, typval_T *rettv)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014862{
14863 filter_map(argvars, rettv, TRUE);
14864}
14865
14866/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000014867 * "maparg()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000014868 */
14869 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014870f_maparg(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014871{
Bram Moolenaar0d660222005-01-07 21:51:51 +000014872 get_maparg(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014873}
14874
14875/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000014876 * "mapcheck()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000014877 */
14878 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014879f_mapcheck(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014880{
Bram Moolenaar0d660222005-01-07 21:51:51 +000014881 get_maparg(argvars, rettv, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014882}
14883
Bram Moolenaar48e697e2016-01-23 22:17:30 +010014884static void find_some_match(typval_T *argvars, typval_T *rettv, int start);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014885
14886 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010014887find_some_match(typval_T *argvars, typval_T *rettv, int type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014888{
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014889 char_u *str = NULL;
Bram Moolenaar9feaf622014-02-22 22:18:47 +010014890 long len = 0;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014891 char_u *expr = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014892 char_u *pat;
14893 regmatch_T regmatch;
14894 char_u patbuf[NUMBUFLEN];
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014895 char_u strbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000014896 char_u *save_cpo;
14897 long start = 0;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000014898 long nth = 1;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000014899 colnr_T startcol = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014900 int match = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000014901 list_T *l = NULL;
14902 listitem_T *li = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014903 long idx = 0;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014904 char_u *tofree = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014905
14906 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
14907 save_cpo = p_cpo;
14908 p_cpo = (char_u *)"";
14909
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014910 rettv->vval.v_number = -1;
14911 if (type == 3)
14912 {
14913 /* return empty list when there are no matches */
Bram Moolenaareddf53b2006-02-27 00:11:10 +000014914 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014915 goto theend;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014916 }
14917 else if (type == 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014918 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014919 rettv->v_type = VAR_STRING;
14920 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014921 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014922
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014923 if (argvars[0].v_type == VAR_LIST)
14924 {
14925 if ((l = argvars[0].vval.v_list) == NULL)
14926 goto theend;
14927 li = l->lv_first;
14928 }
14929 else
Bram Moolenaar9feaf622014-02-22 22:18:47 +010014930 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014931 expr = str = get_tv_string(&argvars[0]);
Bram Moolenaar9feaf622014-02-22 22:18:47 +010014932 len = (long)STRLEN(str);
14933 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014934
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014935 pat = get_tv_string_buf_chk(&argvars[1], patbuf);
14936 if (pat == NULL)
14937 goto theend;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014938
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014939 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014940 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014941 int error = FALSE;
14942
14943 start = get_tv_number_chk(&argvars[2], &error);
14944 if (error)
14945 goto theend;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014946 if (l != NULL)
14947 {
14948 li = list_find(l, start);
14949 if (li == NULL)
14950 goto theend;
Bram Moolenaar758711c2005-02-02 23:11:38 +000014951 idx = l->lv_idx; /* use the cached index */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014952 }
14953 else
14954 {
14955 if (start < 0)
14956 start = 0;
Bram Moolenaar9feaf622014-02-22 22:18:47 +010014957 if (start > len)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014958 goto theend;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000014959 /* When "count" argument is there ignore matches before "start",
14960 * otherwise skip part of the string. Differs when pattern is "^"
14961 * or "\<". */
14962 if (argvars[3].v_type != VAR_UNKNOWN)
14963 startcol = start;
14964 else
Bram Moolenaar9feaf622014-02-22 22:18:47 +010014965 {
Bram Moolenaar0e34f622006-03-03 23:00:03 +000014966 str += start;
Bram Moolenaar9feaf622014-02-22 22:18:47 +010014967 len -= start;
14968 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014969 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000014970
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014971 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014972 nth = get_tv_number_chk(&argvars[3], &error);
14973 if (error)
14974 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014975 }
14976
14977 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
14978 if (regmatch.regprog != NULL)
14979 {
14980 regmatch.rm_ic = p_ic;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000014981
Bram Moolenaard8e9bb22005-07-09 21:14:46 +000014982 for (;;)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000014983 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014984 if (l != NULL)
14985 {
14986 if (li == NULL)
14987 {
14988 match = FALSE;
14989 break;
14990 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014991 vim_free(tofree);
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000014992 str = echo_string(&li->li_tv, &tofree, strbuf, 0);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014993 if (str == NULL)
14994 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014995 }
14996
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000014997 match = vim_regexec_nl(&regmatch, str, (colnr_T)startcol);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014998
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014999 if (match && --nth <= 0)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000015000 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015001 if (l == NULL && !match)
15002 break;
15003
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000015004 /* Advance to just after the match. */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015005 if (l != NULL)
15006 {
15007 li = li->li_next;
15008 ++idx;
15009 }
15010 else
15011 {
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000015012#ifdef FEAT_MBYTE
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000015013 startcol = (colnr_T)(regmatch.startp[0]
15014 + (*mb_ptr2len)(regmatch.startp[0]) - str);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000015015#else
Bram Moolenaar8765a4a2010-07-27 22:41:43 +020015016 startcol = (colnr_T)(regmatch.startp[0] + 1 - str);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000015017#endif
Bram Moolenaar9feaf622014-02-22 22:18:47 +010015018 if (startcol > (colnr_T)len
15019 || str + startcol <= regmatch.startp[0])
15020 {
15021 match = FALSE;
15022 break;
15023 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015024 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000015025 }
15026
15027 if (match)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015028 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015029 if (type == 3)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015030 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015031 int i;
15032
15033 /* return list with matched string and submatches */
15034 for (i = 0; i < NSUBEXP; ++i)
15035 {
15036 if (regmatch.endp[i] == NULL)
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000015037 {
15038 if (list_append_string(rettv->vval.v_list,
15039 (char_u *)"", 0) == FAIL)
15040 break;
15041 }
15042 else if (list_append_string(rettv->vval.v_list,
Bram Moolenaar4463f292005-09-25 22:20:24 +000015043 regmatch.startp[i],
15044 (int)(regmatch.endp[i] - regmatch.startp[i]))
15045 == FAIL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015046 break;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015047 }
15048 }
15049 else if (type == 2)
15050 {
15051 /* return matched string */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015052 if (l != NULL)
15053 copy_tv(&li->li_tv, rettv);
15054 else
15055 rettv->vval.v_string = vim_strnsave(regmatch.startp[0],
Bram Moolenaar071d4272004-06-13 20:20:40 +000015056 (int)(regmatch.endp[0] - regmatch.startp[0]));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015057 }
15058 else if (l != NULL)
15059 rettv->vval.v_number = idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015060 else
15061 {
15062 if (type != 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015063 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +000015064 (varnumber_T)(regmatch.startp[0] - str);
15065 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015066 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +000015067 (varnumber_T)(regmatch.endp[0] - str);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000015068 rettv->vval.v_number += (varnumber_T)(str - expr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015069 }
15070 }
Bram Moolenaar473de612013-06-08 18:19:48 +020015071 vim_regfree(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015072 }
15073
15074theend:
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015075 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015076 p_cpo = save_cpo;
15077}
15078
15079/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000015080 * "match()" function
15081 */
15082 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015083f_match(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000015084{
15085 find_some_match(argvars, rettv, 1);
15086}
15087
15088/*
Bram Moolenaar6ee10162007-07-26 20:58:42 +000015089 * "matchadd()" function
15090 */
15091 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015092f_matchadd(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaar6ee10162007-07-26 20:58:42 +000015093{
15094#ifdef FEAT_SEARCH_EXTRA
15095 char_u buf[NUMBUFLEN];
15096 char_u *grp = get_tv_string_buf_chk(&argvars[0], buf); /* group */
15097 char_u *pat = get_tv_string_buf_chk(&argvars[1], buf); /* pattern */
15098 int prio = 10; /* default priority */
15099 int id = -1;
15100 int error = FALSE;
Bram Moolenaar6561d522015-07-21 15:48:27 +020015101 char_u *conceal_char = NULL;
Bram Moolenaar6ee10162007-07-26 20:58:42 +000015102
15103 rettv->vval.v_number = -1;
15104
15105 if (grp == NULL || pat == NULL)
15106 return;
15107 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar2240aeb2007-07-27 19:33:14 +000015108 {
Bram Moolenaar6ee10162007-07-26 20:58:42 +000015109 prio = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaar2240aeb2007-07-27 19:33:14 +000015110 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar6561d522015-07-21 15:48:27 +020015111 {
Bram Moolenaar2240aeb2007-07-27 19:33:14 +000015112 id = get_tv_number_chk(&argvars[3], &error);
Bram Moolenaar6561d522015-07-21 15:48:27 +020015113 if (argvars[4].v_type != VAR_UNKNOWN)
15114 {
15115 if (argvars[4].v_type != VAR_DICT)
15116 {
15117 EMSG(_(e_dictreq));
15118 return;
15119 }
15120 if (dict_find(argvars[4].vval.v_dict,
15121 (char_u *)"conceal", -1) != NULL)
15122 conceal_char = get_dict_string(argvars[4].vval.v_dict,
15123 (char_u *)"conceal", FALSE);
15124 }
15125 }
Bram Moolenaar2240aeb2007-07-27 19:33:14 +000015126 }
Bram Moolenaar6ee10162007-07-26 20:58:42 +000015127 if (error == TRUE)
15128 return;
15129 if (id >= 1 && id <= 3)
15130 {
15131 EMSGN("E798: ID is reserved for \":match\": %ld", id);
15132 return;
15133 }
15134
Bram Moolenaar6561d522015-07-21 15:48:27 +020015135 rettv->vval.v_number = match_add(curwin, grp, pat, prio, id, NULL,
15136 conceal_char);
Bram Moolenaarb3414592014-06-17 17:48:32 +020015137#endif
15138}
15139
15140/*
15141 * "matchaddpos()" function
15142 */
15143 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015144f_matchaddpos(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaarb3414592014-06-17 17:48:32 +020015145{
15146#ifdef FEAT_SEARCH_EXTRA
15147 char_u buf[NUMBUFLEN];
15148 char_u *group;
15149 int prio = 10;
15150 int id = -1;
15151 int error = FALSE;
15152 list_T *l;
Bram Moolenaar6561d522015-07-21 15:48:27 +020015153 char_u *conceal_char = NULL;
Bram Moolenaarb3414592014-06-17 17:48:32 +020015154
15155 rettv->vval.v_number = -1;
15156
15157 group = get_tv_string_buf_chk(&argvars[0], buf);
15158 if (group == NULL)
15159 return;
15160
15161 if (argvars[1].v_type != VAR_LIST)
15162 {
15163 EMSG2(_(e_listarg), "matchaddpos()");
15164 return;
15165 }
15166 l = argvars[1].vval.v_list;
15167 if (l == NULL)
15168 return;
15169
15170 if (argvars[2].v_type != VAR_UNKNOWN)
15171 {
15172 prio = get_tv_number_chk(&argvars[2], &error);
15173 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar6561d522015-07-21 15:48:27 +020015174 {
Bram Moolenaarb3414592014-06-17 17:48:32 +020015175 id = get_tv_number_chk(&argvars[3], &error);
Bram Moolenaar6561d522015-07-21 15:48:27 +020015176 if (argvars[4].v_type != VAR_UNKNOWN)
15177 {
15178 if (argvars[4].v_type != VAR_DICT)
15179 {
15180 EMSG(_(e_dictreq));
15181 return;
15182 }
15183 if (dict_find(argvars[4].vval.v_dict,
15184 (char_u *)"conceal", -1) != NULL)
15185 conceal_char = get_dict_string(argvars[4].vval.v_dict,
15186 (char_u *)"conceal", FALSE);
15187 }
15188 }
Bram Moolenaarb3414592014-06-17 17:48:32 +020015189 }
15190 if (error == TRUE)
15191 return;
15192
15193 /* id == 3 is ok because matchaddpos() is supposed to substitute :3match */
15194 if (id == 1 || id == 2)
15195 {
15196 EMSGN("E798: ID is reserved for \":match\": %ld", id);
15197 return;
15198 }
15199
Bram Moolenaar6561d522015-07-21 15:48:27 +020015200 rettv->vval.v_number = match_add(curwin, group, NULL, prio, id, l,
15201 conceal_char);
Bram Moolenaar6ee10162007-07-26 20:58:42 +000015202#endif
15203}
15204
15205/*
Bram Moolenaar910f66f2006-04-05 20:41:53 +000015206 * "matcharg()" function
15207 */
15208 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015209f_matcharg(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar910f66f2006-04-05 20:41:53 +000015210{
15211 if (rettv_list_alloc(rettv) == OK)
15212 {
15213#ifdef FEAT_SEARCH_EXTRA
Bram Moolenaar6ee10162007-07-26 20:58:42 +000015214 int id = get_tv_number(&argvars[0]);
15215 matchitem_T *m;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000015216
Bram Moolenaar6ee10162007-07-26 20:58:42 +000015217 if (id >= 1 && id <= 3)
Bram Moolenaar910f66f2006-04-05 20:41:53 +000015218 {
Bram Moolenaar6ee10162007-07-26 20:58:42 +000015219 if ((m = (matchitem_T *)get_match(curwin, id)) != NULL)
15220 {
15221 list_append_string(rettv->vval.v_list,
15222 syn_id2name(m->hlg_id), -1);
15223 list_append_string(rettv->vval.v_list, m->pattern, -1);
15224 }
15225 else
15226 {
Bram Moolenaar5f4c8402014-01-06 06:19:11 +010015227 list_append_string(rettv->vval.v_list, NULL, -1);
15228 list_append_string(rettv->vval.v_list, NULL, -1);
Bram Moolenaar6ee10162007-07-26 20:58:42 +000015229 }
Bram Moolenaar910f66f2006-04-05 20:41:53 +000015230 }
15231#endif
15232 }
15233}
15234
15235/*
Bram Moolenaar6ee10162007-07-26 20:58:42 +000015236 * "matchdelete()" function
15237 */
15238 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015239f_matchdelete(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaar6ee10162007-07-26 20:58:42 +000015240{
15241#ifdef FEAT_SEARCH_EXTRA
15242 rettv->vval.v_number = match_delete(curwin,
15243 (int)get_tv_number(&argvars[0]), TRUE);
15244#endif
15245}
15246
15247/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000015248 * "matchend()" function
15249 */
15250 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015251f_matchend(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000015252{
15253 find_some_match(argvars, rettv, 0);
15254}
15255
15256/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015257 * "matchlist()" function
15258 */
15259 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015260f_matchlist(typval_T *argvars, typval_T *rettv)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015261{
15262 find_some_match(argvars, rettv, 3);
15263}
15264
15265/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000015266 * "matchstr()" function
15267 */
15268 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015269f_matchstr(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000015270{
15271 find_some_match(argvars, rettv, 2);
15272}
15273
Bram Moolenaar48e697e2016-01-23 22:17:30 +010015274static void max_min(typval_T *argvars, typval_T *rettv, int domax);
Bram Moolenaar6cc16192005-01-08 21:49:45 +000015275
15276 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015277max_min(typval_T *argvars, typval_T *rettv, int domax)
Bram Moolenaar6cc16192005-01-08 21:49:45 +000015278{
Bram Moolenaar6cc16192005-01-08 21:49:45 +000015279 long n = 0;
15280 long i;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015281 int error = FALSE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000015282
15283 if (argvars[0].v_type == VAR_LIST)
15284 {
Bram Moolenaar33570922005-01-25 22:26:29 +000015285 list_T *l;
15286 listitem_T *li;
Bram Moolenaare9a41262005-01-15 22:18:47 +000015287
Bram Moolenaar6cc16192005-01-08 21:49:45 +000015288 l = argvars[0].vval.v_list;
15289 if (l != NULL)
15290 {
15291 li = l->lv_first;
15292 if (li != NULL)
15293 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015294 n = get_tv_number_chk(&li->li_tv, &error);
Bram Moolenaard8e9bb22005-07-09 21:14:46 +000015295 for (;;)
Bram Moolenaar6cc16192005-01-08 21:49:45 +000015296 {
15297 li = li->li_next;
15298 if (li == NULL)
15299 break;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015300 i = get_tv_number_chk(&li->li_tv, &error);
Bram Moolenaar6cc16192005-01-08 21:49:45 +000015301 if (domax ? i > n : i < n)
15302 n = i;
15303 }
15304 }
15305 }
15306 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000015307 else if (argvars[0].v_type == VAR_DICT)
15308 {
Bram Moolenaar33570922005-01-25 22:26:29 +000015309 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015310 int first = TRUE;
Bram Moolenaar33570922005-01-25 22:26:29 +000015311 hashitem_T *hi;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015312 int todo;
Bram Moolenaare9a41262005-01-15 22:18:47 +000015313
15314 d = argvars[0].vval.v_dict;
15315 if (d != NULL)
15316 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000015317 todo = (int)d->dv_hashtab.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +000015318 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaare9a41262005-01-15 22:18:47 +000015319 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015320 if (!HASHITEM_EMPTY(hi))
Bram Moolenaare9a41262005-01-15 22:18:47 +000015321 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015322 --todo;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015323 i = get_tv_number_chk(&HI2DI(hi)->di_tv, &error);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015324 if (first)
15325 {
15326 n = i;
15327 first = FALSE;
15328 }
15329 else if (domax ? i > n : i < n)
Bram Moolenaare9a41262005-01-15 22:18:47 +000015330 n = i;
15331 }
15332 }
15333 }
15334 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +000015335 else
Bram Moolenaar758711c2005-02-02 23:11:38 +000015336 EMSG(_(e_listdictarg));
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015337 rettv->vval.v_number = error ? 0 : n;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000015338}
15339
15340/*
15341 * "max()" function
15342 */
15343 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015344f_max(typval_T *argvars, typval_T *rettv)
Bram Moolenaar6cc16192005-01-08 21:49:45 +000015345{
15346 max_min(argvars, rettv, TRUE);
15347}
15348
15349/*
15350 * "min()" function
15351 */
15352 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015353f_min(typval_T *argvars, typval_T *rettv)
Bram Moolenaar6cc16192005-01-08 21:49:45 +000015354{
15355 max_min(argvars, rettv, FALSE);
15356}
15357
Bram Moolenaar48e697e2016-01-23 22:17:30 +010015358static int mkdir_recurse(char_u *dir, int prot);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015359
15360/*
15361 * Create the directory in which "dir" is located, and higher levels when
15362 * needed.
15363 */
15364 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010015365mkdir_recurse(char_u *dir, int prot)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015366{
15367 char_u *p;
15368 char_u *updir;
15369 int r = FAIL;
15370
15371 /* Get end of directory name in "dir".
15372 * We're done when it's "/" or "c:/". */
15373 p = gettail_sep(dir);
15374 if (p <= get_past_head(dir))
15375 return OK;
15376
15377 /* If the directory exists we're done. Otherwise: create it.*/
15378 updir = vim_strnsave(dir, (int)(p - dir));
15379 if (updir == NULL)
15380 return FAIL;
15381 if (mch_isdir(updir))
15382 r = OK;
15383 else if (mkdir_recurse(updir, prot) == OK)
15384 r = vim_mkdir_emsg(updir, prot);
15385 vim_free(updir);
15386 return r;
15387}
15388
15389#ifdef vim_mkdir
15390/*
15391 * "mkdir()" function
15392 */
15393 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015394f_mkdir(typval_T *argvars, typval_T *rettv)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015395{
15396 char_u *dir;
15397 char_u buf[NUMBUFLEN];
15398 int prot = 0755;
15399
15400 rettv->vval.v_number = FAIL;
15401 if (check_restricted() || check_secure())
15402 return;
15403
15404 dir = get_tv_string_buf(&argvars[0], buf);
Bram Moolenaar195ef0c2013-08-30 16:00:08 +020015405 if (*dir == NUL)
15406 rettv->vval.v_number = FAIL;
15407 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015408 {
Bram Moolenaar195ef0c2013-08-30 16:00:08 +020015409 if (*gettail(dir) == NUL)
15410 /* remove trailing slashes */
15411 *gettail_sep(dir) = NUL;
15412
15413 if (argvars[1].v_type != VAR_UNKNOWN)
15414 {
15415 if (argvars[2].v_type != VAR_UNKNOWN)
15416 prot = get_tv_number_chk(&argvars[2], NULL);
15417 if (prot != -1 && STRCMP(get_tv_string(&argvars[1]), "p") == 0)
15418 mkdir_recurse(dir, prot);
15419 }
15420 rettv->vval.v_number = prot == -1 ? FAIL : vim_mkdir_emsg(dir, prot);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015421 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015422}
15423#endif
15424
Bram Moolenaar0d660222005-01-07 21:51:51 +000015425/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000015426 * "mode()" function
15427 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015428 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015429f_mode(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015430{
Bram Moolenaar8c8de832008-06-24 22:58:06 +000015431 char_u buf[3];
15432
15433 buf[1] = NUL;
15434 buf[2] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015435
Bram Moolenaar071d4272004-06-13 20:20:40 +000015436 if (VIsual_active)
15437 {
15438 if (VIsual_select)
15439 buf[0] = VIsual_mode + 's' - 'v';
15440 else
15441 buf[0] = VIsual_mode;
15442 }
Bram Moolenaarf7ff6e82014-03-23 15:13:05 +010015443 else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE
Bram Moolenaar8c8de832008-06-24 22:58:06 +000015444 || State == CONFIRM)
15445 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000015446 buf[0] = 'r';
Bram Moolenaar8c8de832008-06-24 22:58:06 +000015447 if (State == ASKMORE)
15448 buf[1] = 'm';
15449 else if (State == CONFIRM)
15450 buf[1] = '?';
15451 }
15452 else if (State == EXTERNCMD)
15453 buf[0] = '!';
Bram Moolenaar071d4272004-06-13 20:20:40 +000015454 else if (State & INSERT)
15455 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +000015456#ifdef FEAT_VREPLACE
15457 if (State & VREPLACE_FLAG)
15458 {
15459 buf[0] = 'R';
15460 buf[1] = 'v';
15461 }
15462 else
15463#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000015464 if (State & REPLACE_FLAG)
15465 buf[0] = 'R';
15466 else
15467 buf[0] = 'i';
15468 }
15469 else if (State & CMDLINE)
Bram Moolenaar8c8de832008-06-24 22:58:06 +000015470 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000015471 buf[0] = 'c';
Bram Moolenaar8c8de832008-06-24 22:58:06 +000015472 if (exmode_active)
15473 buf[1] = 'v';
15474 }
15475 else if (exmode_active)
15476 {
15477 buf[0] = 'c';
15478 buf[1] = 'e';
15479 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015480 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +000015481 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000015482 buf[0] = 'n';
Bram Moolenaar8c8de832008-06-24 22:58:06 +000015483 if (finish_op)
15484 buf[1] = 'o';
15485 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015486
Bram Moolenaar05bb9532008-07-04 09:44:11 +000015487 /* Clear out the minor mode when the argument is not a non-zero number or
15488 * non-empty string. */
15489 if (!non_zero_arg(&argvars[0]))
Bram Moolenaar8c8de832008-06-24 22:58:06 +000015490 buf[1] = NUL;
15491
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015492 rettv->vval.v_string = vim_strsave(buf);
15493 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015494}
15495
Bram Moolenaar429fa852013-04-15 12:27:36 +020015496#if defined(FEAT_MZSCHEME) || defined(PROTO)
Bram Moolenaar7e506b62010-01-19 15:55:06 +010015497/*
15498 * "mzeval()" function
15499 */
15500 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015501f_mzeval(typval_T *argvars, typval_T *rettv)
Bram Moolenaar7e506b62010-01-19 15:55:06 +010015502{
15503 char_u *str;
15504 char_u buf[NUMBUFLEN];
15505
15506 str = get_tv_string_buf(&argvars[0], buf);
15507 do_mzeval(str, rettv);
15508}
Bram Moolenaar75676462013-01-30 14:55:42 +010015509
15510 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015511mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv)
Bram Moolenaar75676462013-01-30 14:55:42 +010015512{
15513 typval_T argvars[3];
15514
15515 argvars[0].v_type = VAR_STRING;
15516 argvars[0].vval.v_string = name;
15517 copy_tv(args, &argvars[1]);
15518 argvars[2].v_type = VAR_UNKNOWN;
15519 f_call(argvars, rettv);
15520 clear_tv(&argvars[1]);
15521}
Bram Moolenaar7e506b62010-01-19 15:55:06 +010015522#endif
15523
Bram Moolenaar071d4272004-06-13 20:20:40 +000015524/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000015525 * "nextnonblank()" function
15526 */
15527 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015528f_nextnonblank(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000015529{
15530 linenr_T lnum;
15531
15532 for (lnum = get_tv_lnum(argvars); ; ++lnum)
15533 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015534 if (lnum < 0 || lnum > curbuf->b_ml.ml_line_count)
Bram Moolenaar0d660222005-01-07 21:51:51 +000015535 {
15536 lnum = 0;
15537 break;
15538 }
15539 if (*skipwhite(ml_get(lnum)) != NUL)
15540 break;
15541 }
15542 rettv->vval.v_number = lnum;
15543}
15544
15545/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000015546 * "nr2char()" function
15547 */
15548 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015549f_nr2char(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015550{
15551 char_u buf[NUMBUFLEN];
15552
15553#ifdef FEAT_MBYTE
15554 if (has_mbyte)
Bram Moolenaard35d7842013-01-23 17:17:10 +010015555 {
15556 int utf8 = 0;
15557
15558 if (argvars[1].v_type != VAR_UNKNOWN)
15559 utf8 = get_tv_number_chk(&argvars[1], NULL);
15560 if (utf8)
15561 buf[(*utf_char2bytes)((int)get_tv_number(&argvars[0]), buf)] = NUL;
15562 else
15563 buf[(*mb_char2bytes)((int)get_tv_number(&argvars[0]), buf)] = NUL;
15564 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015565 else
15566#endif
15567 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015568 buf[0] = (char_u)get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015569 buf[1] = NUL;
15570 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015571 rettv->v_type = VAR_STRING;
15572 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015573}
15574
15575/*
Bram Moolenaard6e256c2011-12-14 15:32:50 +010015576 * "or(expr, expr)" function
15577 */
15578 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015579f_or(typval_T *argvars, typval_T *rettv)
Bram Moolenaard6e256c2011-12-14 15:32:50 +010015580{
15581 rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL)
15582 | get_tv_number_chk(&argvars[1], NULL);
15583}
15584
15585/*
Bram Moolenaar910f66f2006-04-05 20:41:53 +000015586 * "pathshorten()" function
15587 */
15588 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015589f_pathshorten(typval_T *argvars, typval_T *rettv)
Bram Moolenaar910f66f2006-04-05 20:41:53 +000015590{
15591 char_u *p;
15592
15593 rettv->v_type = VAR_STRING;
15594 p = get_tv_string_chk(&argvars[0]);
15595 if (p == NULL)
15596 rettv->vval.v_string = NULL;
15597 else
15598 {
15599 p = vim_strsave(p);
15600 rettv->vval.v_string = p;
15601 if (p != NULL)
15602 shorten_dir(p);
15603 }
15604}
15605
Bram Moolenaare9b892e2016-01-17 21:15:58 +010015606#ifdef FEAT_PERL
15607/*
15608 * "perleval()" function
15609 */
15610 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015611f_perleval(typval_T *argvars, typval_T *rettv)
Bram Moolenaare9b892e2016-01-17 21:15:58 +010015612{
15613 char_u *str;
15614 char_u buf[NUMBUFLEN];
15615
15616 str = get_tv_string_buf(&argvars[0], buf);
15617 do_perleval(str, rettv);
15618}
15619#endif
15620
Bram Moolenaar8c8de832008-06-24 22:58:06 +000015621#ifdef FEAT_FLOAT
15622/*
15623 * "pow()" function
15624 */
15625 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015626f_pow(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8c8de832008-06-24 22:58:06 +000015627{
Bram Moolenaara1e24b92016-02-18 20:18:09 +010015628 float_T fx = 0.0, fy = 0.0;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000015629
15630 rettv->v_type = VAR_FLOAT;
15631 if (get_float_arg(argvars, &fx) == OK
15632 && get_float_arg(&argvars[1], &fy) == OK)
15633 rettv->vval.v_float = pow(fx, fy);
15634 else
15635 rettv->vval.v_float = 0.0;
15636}
15637#endif
15638
Bram Moolenaar910f66f2006-04-05 20:41:53 +000015639/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000015640 * "prevnonblank()" function
15641 */
15642 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015643f_prevnonblank(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000015644{
15645 linenr_T lnum;
15646
15647 lnum = get_tv_lnum(argvars);
15648 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
15649 lnum = 0;
15650 else
15651 while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL)
15652 --lnum;
15653 rettv->vval.v_number = lnum;
15654}
15655
Bram Moolenaara6c840d2005-08-22 22:59:46 +000015656/* This dummy va_list is here because:
15657 * - passing a NULL pointer doesn't work when va_list isn't a pointer
15658 * - locally in the function results in a "used before set" warning
15659 * - using va_start() to initialize it gives "function with fixed args" error */
15660static va_list ap;
Bram Moolenaara6c840d2005-08-22 22:59:46 +000015661
Bram Moolenaar8c711452005-01-14 21:53:12 +000015662/*
Bram Moolenaar4be06f92005-07-29 22:36:03 +000015663 * "printf()" function
15664 */
15665 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015666f_printf(typval_T *argvars, typval_T *rettv)
Bram Moolenaar4be06f92005-07-29 22:36:03 +000015667{
Bram Moolenaarba4ef272016-01-30 21:48:49 +010015668 char_u buf[NUMBUFLEN];
15669 int len;
15670 char_u *s;
15671 int saved_did_emsg = did_emsg;
15672 char *fmt;
15673
Bram Moolenaar4be06f92005-07-29 22:36:03 +000015674 rettv->v_type = VAR_STRING;
15675 rettv->vval.v_string = NULL;
Bram Moolenaar4be06f92005-07-29 22:36:03 +000015676
Bram Moolenaarba4ef272016-01-30 21:48:49 +010015677 /* Get the required length, allocate the buffer and do it for real. */
15678 did_emsg = FALSE;
15679 fmt = (char *)get_tv_string_buf(&argvars[0], buf);
15680 len = vim_vsnprintf(NULL, 0, fmt, ap, argvars + 1);
15681 if (!did_emsg)
15682 {
15683 s = alloc(len + 1);
15684 if (s != NULL)
Bram Moolenaar4be06f92005-07-29 22:36:03 +000015685 {
Bram Moolenaarba4ef272016-01-30 21:48:49 +010015686 rettv->vval.v_string = s;
15687 (void)vim_vsnprintf((char *)s, len + 1, fmt, ap, argvars + 1);
Bram Moolenaar4be06f92005-07-29 22:36:03 +000015688 }
Bram Moolenaar4be06f92005-07-29 22:36:03 +000015689 }
Bram Moolenaarba4ef272016-01-30 21:48:49 +010015690 did_emsg |= saved_did_emsg;
Bram Moolenaar4be06f92005-07-29 22:36:03 +000015691}
15692
15693/*
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000015694 * "pumvisible()" function
15695 */
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000015696 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015697f_pumvisible(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000015698{
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000015699#ifdef FEAT_INS_EXPAND
15700 if (pum_visible())
15701 rettv->vval.v_number = 1;
15702#endif
15703}
15704
Bram Moolenaardb913952012-06-29 12:54:53 +020015705#ifdef FEAT_PYTHON3
15706/*
15707 * "py3eval()" function
15708 */
15709 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015710f_py3eval(typval_T *argvars, typval_T *rettv)
Bram Moolenaardb913952012-06-29 12:54:53 +020015711{
15712 char_u *str;
15713 char_u buf[NUMBUFLEN];
15714
15715 str = get_tv_string_buf(&argvars[0], buf);
15716 do_py3eval(str, rettv);
15717}
15718#endif
15719
15720#ifdef FEAT_PYTHON
15721/*
15722 * "pyeval()" function
15723 */
15724 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015725f_pyeval(typval_T *argvars, typval_T *rettv)
Bram Moolenaardb913952012-06-29 12:54:53 +020015726{
15727 char_u *str;
15728 char_u buf[NUMBUFLEN];
15729
15730 str = get_tv_string_buf(&argvars[0], buf);
15731 do_pyeval(str, rettv);
15732}
15733#endif
15734
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000015735/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000015736 * "range()" function
15737 */
15738 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015739f_range(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8c711452005-01-14 21:53:12 +000015740{
15741 long start;
15742 long end;
15743 long stride = 1;
15744 long i;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015745 int error = FALSE;
Bram Moolenaar8c711452005-01-14 21:53:12 +000015746
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015747 start = get_tv_number_chk(&argvars[0], &error);
Bram Moolenaar8c711452005-01-14 21:53:12 +000015748 if (argvars[1].v_type == VAR_UNKNOWN)
15749 {
15750 end = start - 1;
15751 start = 0;
15752 }
15753 else
15754 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015755 end = get_tv_number_chk(&argvars[1], &error);
Bram Moolenaar8c711452005-01-14 21:53:12 +000015756 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015757 stride = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaar8c711452005-01-14 21:53:12 +000015758 }
15759
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015760 if (error)
15761 return; /* type error; errmsg already given */
Bram Moolenaar8c711452005-01-14 21:53:12 +000015762 if (stride == 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015763 EMSG(_("E726: Stride is zero"));
Bram Moolenaar92124a32005-06-17 22:03:40 +000015764 else if (stride > 0 ? end + 1 < start : end - 1 > start)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015765 EMSG(_("E727: Start past end"));
Bram Moolenaar8c711452005-01-14 21:53:12 +000015766 else
15767 {
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015768 if (rettv_list_alloc(rettv) == OK)
Bram Moolenaar8c711452005-01-14 21:53:12 +000015769 for (i = start; stride > 0 ? i <= end : i >= end; i += stride)
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015770 if (list_append_number(rettv->vval.v_list,
15771 (varnumber_T)i) == FAIL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000015772 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000015773 }
15774}
15775
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015776/*
15777 * "readfile()" function
15778 */
15779 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010015780f_readfile(typval_T *argvars, typval_T *rettv)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015781{
15782 int binary = FALSE;
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015783 int failed = FALSE;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015784 char_u *fname;
15785 FILE *fd;
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015786 char_u buf[(IOSIZE/256)*256]; /* rounded to avoid odd + 1 */
15787 int io_size = sizeof(buf);
15788 int readlen; /* size of last fread() */
15789 char_u *prev = NULL; /* previously read bytes, if any */
15790 long prevlen = 0; /* length of data in prev */
15791 long prevsize = 0; /* size of prev buffer */
15792 long maxline = MAXLNUM;
15793 long cnt = 0;
15794 char_u *p; /* position in buf */
15795 char_u *start; /* start of current line */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015796
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015797 if (argvars[1].v_type != VAR_UNKNOWN)
15798 {
15799 if (STRCMP(get_tv_string(&argvars[1]), "b") == 0)
15800 binary = TRUE;
15801 if (argvars[2].v_type != VAR_UNKNOWN)
15802 maxline = get_tv_number(&argvars[2]);
15803 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015804
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015805 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015806 return;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015807
15808 /* Always open the file in binary mode, library functions have a mind of
15809 * their own about CR-LF conversion. */
15810 fname = get_tv_string(&argvars[0]);
15811 if (*fname == NUL || (fd = mch_fopen((char *)fname, READBIN)) == NULL)
15812 {
15813 EMSG2(_(e_notopen), *fname == NUL ? (char_u *)_("<empty>") : fname);
15814 return;
15815 }
15816
Bram Moolenaarb982ca52005-03-28 21:02:15 +000015817 while (cnt < maxline || maxline < 0)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015818 {
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015819 readlen = (int)fread(buf, 1, io_size, fd);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015820
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015821 /* This for loop processes what was read, but is also entered at end
15822 * of file so that either:
15823 * - an incomplete line gets written
15824 * - a "binary" file gets an empty line at the end if it ends in a
15825 * newline. */
15826 for (p = buf, start = buf;
15827 p < buf + readlen || (readlen <= 0 && (prevlen > 0 || binary));
15828 ++p)
15829 {
15830 if (*p == '\n' || readlen <= 0)
15831 {
15832 listitem_T *li;
15833 char_u *s = NULL;
15834 long_u len = p - start;
15835
15836 /* Finished a line. Remove CRs before NL. */
15837 if (readlen > 0 && !binary)
15838 {
15839 while (len > 0 && start[len - 1] == '\r')
15840 --len;
15841 /* removal may cross back to the "prev" string */
15842 if (len == 0)
15843 while (prevlen > 0 && prev[prevlen - 1] == '\r')
15844 --prevlen;
15845 }
15846 if (prevlen == 0)
Bram Moolenaar68ba0dd2012-02-11 20:44:10 +010015847 s = vim_strnsave(start, (int)len);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015848 else
15849 {
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015850 /* Change "prev" buffer to be the right size. This way
15851 * the bytes are only copied once, and very long lines are
15852 * allocated only once. */
15853 if ((s = vim_realloc(prev, prevlen + len + 1)) != NULL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015854 {
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015855 mch_memmove(s + prevlen, start, len);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015856 s[prevlen + len] = NUL;
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015857 prev = NULL; /* the list will own the string */
15858 prevlen = prevsize = 0;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015859 }
15860 }
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015861 if (s == NULL)
15862 {
15863 do_outofmem_msg((long_u) prevlen + len + 1);
15864 failed = TRUE;
15865 break;
15866 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015867
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015868 if ((li = listitem_alloc()) == NULL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015869 {
15870 vim_free(s);
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015871 failed = TRUE;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015872 break;
15873 }
15874 li->li_tv.v_type = VAR_STRING;
15875 li->li_tv.v_lock = 0;
15876 li->li_tv.vval.v_string = s;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015877 list_append(rettv->vval.v_list, li);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015878
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015879 start = p + 1; /* step over newline */
15880 if ((++cnt >= maxline && maxline >= 0) || readlen <= 0)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015881 break;
15882 }
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015883 else if (*p == NUL)
15884 *p = '\n';
Bram Moolenaar06583f12010-08-07 20:30:49 +020015885#ifdef FEAT_MBYTE
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015886 /* Check for utf8 "bom"; U+FEFF is encoded as EF BB BF. Do this
15887 * when finding the BF and check the previous two bytes. */
15888 else if (*p == 0xbf && enc_utf8 && !binary)
Bram Moolenaar06583f12010-08-07 20:30:49 +020015889 {
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015890 /* Find the two bytes before the 0xbf. If p is at buf, or buf
15891 * + 1, these may be in the "prev" string. */
15892 char_u back1 = p >= buf + 1 ? p[-1]
15893 : prevlen >= 1 ? prev[prevlen - 1] : NUL;
15894 char_u back2 = p >= buf + 2 ? p[-2]
15895 : p == buf + 1 && prevlen >= 1 ? prev[prevlen - 1]
15896 : prevlen >= 2 ? prev[prevlen - 2] : NUL;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015897
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015898 if (back2 == 0xef && back1 == 0xbb)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015899 {
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015900 char_u *dest = p - 2;
15901
15902 /* Usually a BOM is at the beginning of a file, and so at
15903 * the beginning of a line; then we can just step over it.
15904 */
15905 if (start == dest)
15906 start = p + 1;
15907 else
Bram Moolenaar27b60562011-04-01 16:07:46 +020015908 {
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015909 /* have to shuffle buf to close gap */
15910 int adjust_prevlen = 0;
15911
15912 if (dest < buf)
15913 {
Bram Moolenaar68ba0dd2012-02-11 20:44:10 +010015914 adjust_prevlen = (int)(buf - dest); /* must be 1 or 2 */
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015915 dest = buf;
15916 }
15917 if (readlen > p - buf + 1)
15918 mch_memmove(dest, p + 1, readlen - (p - buf) - 1);
15919 readlen -= 3 - adjust_prevlen;
15920 prevlen -= adjust_prevlen;
15921 p = dest - 1;
Bram Moolenaar27b60562011-04-01 16:07:46 +020015922 }
15923 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015924 }
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015925#endif
15926 } /* for */
15927
15928 if (failed || (cnt >= maxline && maxline >= 0) || readlen <= 0)
15929 break;
15930 if (start < p)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015931 {
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015932 /* There's part of a line in buf, store it in "prev". */
15933 if (p - start + prevlen >= prevsize)
15934 {
15935 /* need bigger "prev" buffer */
15936 char_u *newprev;
15937
15938 /* A common use case is ordinary text files and "prev" gets a
15939 * fragment of a line, so the first allocation is made
15940 * small, to avoid repeatedly 'allocing' large and
15941 * 'reallocing' small. */
15942 if (prevsize == 0)
Bram Moolenaar68ba0dd2012-02-11 20:44:10 +010015943 prevsize = (long)(p - start);
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015944 else
15945 {
15946 long grow50pc = (prevsize * 3) / 2;
Bram Moolenaar68ba0dd2012-02-11 20:44:10 +010015947 long growmin = (long)((p - start) * 2 + prevlen);
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015948 prevsize = grow50pc > growmin ? grow50pc : growmin;
15949 }
Bram Moolenaar455981e2012-05-18 18:34:19 +020015950 newprev = prev == NULL ? alloc(prevsize)
15951 : vim_realloc(prev, prevsize);
15952 if (newprev == NULL)
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015953 {
15954 do_outofmem_msg((long_u)prevsize);
15955 failed = TRUE;
15956 break;
15957 }
15958 prev = newprev;
15959 }
15960 /* Add the line part to end of "prev". */
15961 mch_memmove(prev + prevlen, start, p - start);
Bram Moolenaar68ba0dd2012-02-11 20:44:10 +010015962 prevlen += (long)(p - start);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015963 }
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015964 } /* while */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015965
Bram Moolenaarb982ca52005-03-28 21:02:15 +000015966 /*
15967 * For a negative line count use only the lines at the end of the file,
15968 * free the rest.
15969 */
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015970 if (!failed && maxline < 0)
Bram Moolenaarb982ca52005-03-28 21:02:15 +000015971 while (cnt > -maxline)
15972 {
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015973 listitem_remove(rettv->vval.v_list, rettv->vval.v_list->lv_first);
Bram Moolenaarb982ca52005-03-28 21:02:15 +000015974 --cnt;
15975 }
15976
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015977 if (failed)
15978 {
15979 list_free(rettv->vval.v_list, TRUE);
15980 /* readfile doc says an empty list is returned on error */
15981 rettv->vval.v_list = list_alloc();
15982 }
15983
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015984 vim_free(prev);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015985 fclose(fd);
15986}
15987
Bram Moolenaare580b0c2006-03-21 21:33:03 +000015988#if defined(FEAT_RELTIME)
Bram Moolenaar48e697e2016-01-23 22:17:30 +010015989static int list2proftime(typval_T *arg, proftime_T *tm);
Bram Moolenaare580b0c2006-03-21 21:33:03 +000015990
15991/*
15992 * Convert a List to proftime_T.
15993 * Return FAIL when there is something wrong.
15994 */
15995 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010015996list2proftime(typval_T *arg, proftime_T *tm)
Bram Moolenaare580b0c2006-03-21 21:33:03 +000015997{
15998 long n1, n2;
15999 int error = FALSE;
16000
16001 if (arg->v_type != VAR_LIST || arg->vval.v_list == NULL
16002 || arg->vval.v_list->lv_len != 2)
16003 return FAIL;
16004 n1 = list_find_nr(arg->vval.v_list, 0L, &error);
16005 n2 = list_find_nr(arg->vval.v_list, 1L, &error);
16006# ifdef WIN3264
Bram Moolenaardb552d602006-03-23 22:59:57 +000016007 tm->HighPart = n1;
16008 tm->LowPart = n2;
Bram Moolenaare580b0c2006-03-21 21:33:03 +000016009# else
16010 tm->tv_sec = n1;
16011 tm->tv_usec = n2;
16012# endif
16013 return error ? FAIL : OK;
16014}
16015#endif /* FEAT_RELTIME */
16016
16017/*
16018 * "reltime()" function
16019 */
16020 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010016021f_reltime(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaare580b0c2006-03-21 21:33:03 +000016022{
16023#ifdef FEAT_RELTIME
16024 proftime_T res;
16025 proftime_T start;
16026
16027 if (argvars[0].v_type == VAR_UNKNOWN)
16028 {
16029 /* No arguments: get current time. */
16030 profile_start(&res);
16031 }
16032 else if (argvars[1].v_type == VAR_UNKNOWN)
16033 {
16034 if (list2proftime(&argvars[0], &res) == FAIL)
16035 return;
16036 profile_end(&res);
16037 }
16038 else
16039 {
16040 /* Two arguments: compute the difference. */
16041 if (list2proftime(&argvars[0], &start) == FAIL
16042 || list2proftime(&argvars[1], &res) == FAIL)
16043 return;
16044 profile_sub(&res, &start);
16045 }
16046
16047 if (rettv_list_alloc(rettv) == OK)
16048 {
16049 long n1, n2;
16050
16051# ifdef WIN3264
Bram Moolenaardb552d602006-03-23 22:59:57 +000016052 n1 = res.HighPart;
16053 n2 = res.LowPart;
Bram Moolenaare580b0c2006-03-21 21:33:03 +000016054# else
16055 n1 = res.tv_sec;
16056 n2 = res.tv_usec;
16057# endif
16058 list_append_number(rettv->vval.v_list, (varnumber_T)n1);
16059 list_append_number(rettv->vval.v_list, (varnumber_T)n2);
16060 }
16061#endif
16062}
16063
Bram Moolenaar79c2c882016-02-07 21:19:28 +010016064#ifdef FEAT_FLOAT
16065/*
16066 * "reltimefloat()" function
16067 */
16068 static void
16069f_reltimefloat(typval_T *argvars UNUSED, typval_T *rettv)
16070{
16071# ifdef FEAT_RELTIME
16072 proftime_T tm;
16073# endif
16074
16075 rettv->v_type = VAR_FLOAT;
16076 rettv->vval.v_float = 0;
16077# ifdef FEAT_RELTIME
16078 if (list2proftime(&argvars[0], &tm) == OK)
16079 rettv->vval.v_float = profile_float(&tm);
16080# endif
16081}
16082#endif
16083
Bram Moolenaare580b0c2006-03-21 21:33:03 +000016084/*
16085 * "reltimestr()" function
16086 */
16087 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010016088f_reltimestr(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaare580b0c2006-03-21 21:33:03 +000016089{
16090#ifdef FEAT_RELTIME
16091 proftime_T tm;
16092#endif
16093
16094 rettv->v_type = VAR_STRING;
16095 rettv->vval.v_string = NULL;
16096#ifdef FEAT_RELTIME
16097 if (list2proftime(&argvars[0], &tm) == OK)
16098 rettv->vval.v_string = vim_strsave((char_u *)profile_msg(&tm));
16099#endif
16100}
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000016101
Bram Moolenaar0d660222005-01-07 21:51:51 +000016102#if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
Bram Moolenaar48e697e2016-01-23 22:17:30 +010016103static void make_connection(void);
16104static int check_connection(void);
Bram Moolenaar0d660222005-01-07 21:51:51 +000016105
16106 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010016107make_connection(void)
Bram Moolenaar0d660222005-01-07 21:51:51 +000016108{
16109 if (X_DISPLAY == NULL
16110# ifdef FEAT_GUI
16111 && !gui.in_use
16112# endif
16113 )
16114 {
16115 x_force_connect = TRUE;
16116 setup_term_clip();
16117 x_force_connect = FALSE;
16118 }
16119}
16120
16121 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010016122check_connection(void)
Bram Moolenaar0d660222005-01-07 21:51:51 +000016123{
16124 make_connection();
16125 if (X_DISPLAY == NULL)
16126 {
16127 EMSG(_("E240: No connection to Vim server"));
16128 return FAIL;
16129 }
16130 return OK;
16131}
16132#endif
16133
16134#ifdef FEAT_CLIENTSERVER
Bram Moolenaar48e697e2016-01-23 22:17:30 +010016135static void remote_common(typval_T *argvars, typval_T *rettv, int expr);
Bram Moolenaar0d660222005-01-07 21:51:51 +000016136
16137 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010016138remote_common(typval_T *argvars, typval_T *rettv, int expr)
Bram Moolenaar0d660222005-01-07 21:51:51 +000016139{
16140 char_u *server_name;
16141 char_u *keys;
16142 char_u *r = NULL;
16143 char_u buf[NUMBUFLEN];
16144# ifdef WIN32
16145 HWND w;
16146# else
16147 Window w;
16148# endif
16149
16150 if (check_restricted() || check_secure())
16151 return;
16152
16153# ifdef FEAT_X11
16154 if (check_connection() == FAIL)
16155 return;
16156# endif
16157
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016158 server_name = get_tv_string_chk(&argvars[0]);
16159 if (server_name == NULL)
16160 return; /* type error; errmsg already given */
Bram Moolenaar0d660222005-01-07 21:51:51 +000016161 keys = get_tv_string_buf(&argvars[1], buf);
16162# ifdef WIN32
16163 if (serverSendToVim(server_name, keys, &r, &w, expr, TRUE) < 0)
16164# else
16165 if (serverSendToVim(X_DISPLAY, server_name, keys, &r, &w, expr, 0, TRUE)
16166 < 0)
16167# endif
16168 {
16169 if (r != NULL)
16170 EMSG(r); /* sending worked but evaluation failed */
16171 else
16172 EMSG2(_("E241: Unable to send to %s"), server_name);
16173 return;
16174 }
16175
16176 rettv->vval.v_string = r;
16177
16178 if (argvars[2].v_type != VAR_UNKNOWN)
16179 {
Bram Moolenaar33570922005-01-25 22:26:29 +000016180 dictitem_T v;
Bram Moolenaar555b2802005-05-19 21:08:39 +000016181 char_u str[30];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016182 char_u *idvar;
Bram Moolenaar0d660222005-01-07 21:51:51 +000016183
Bram Moolenaareb3593b2006-04-22 22:33:57 +000016184 sprintf((char *)str, PRINTF_HEX_LONG_U, (long_u)w);
Bram Moolenaar33570922005-01-25 22:26:29 +000016185 v.di_tv.v_type = VAR_STRING;
16186 v.di_tv.vval.v_string = vim_strsave(str);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016187 idvar = get_tv_string_chk(&argvars[2]);
16188 if (idvar != NULL)
16189 set_var(idvar, &v.di_tv, FALSE);
Bram Moolenaar33570922005-01-25 22:26:29 +000016190 vim_free(v.di_tv.vval.v_string);
Bram Moolenaar0d660222005-01-07 21:51:51 +000016191 }
16192}
16193#endif
16194
16195/*
16196 * "remote_expr()" function
16197 */
Bram Moolenaar0d660222005-01-07 21:51:51 +000016198 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010016199f_remote_expr(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000016200{
16201 rettv->v_type = VAR_STRING;
16202 rettv->vval.v_string = NULL;
16203#ifdef FEAT_CLIENTSERVER
16204 remote_common(argvars, rettv, TRUE);
16205#endif
16206}
16207
16208/*
16209 * "remote_foreground()" function
16210 */
Bram Moolenaar0d660222005-01-07 21:51:51 +000016211 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010016212f_remote_foreground(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaar0d660222005-01-07 21:51:51 +000016213{
Bram Moolenaar0d660222005-01-07 21:51:51 +000016214#ifdef FEAT_CLIENTSERVER
16215# ifdef WIN32
16216 /* On Win32 it's done in this application. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016217 {
16218 char_u *server_name = get_tv_string_chk(&argvars[0]);
16219
16220 if (server_name != NULL)
16221 serverForeground(server_name);
16222 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000016223# else
16224 /* Send a foreground() expression to the server. */
16225 argvars[1].v_type = VAR_STRING;
16226 argvars[1].vval.v_string = vim_strsave((char_u *)"foreground()");
16227 argvars[2].v_type = VAR_UNKNOWN;
16228 remote_common(argvars, rettv, TRUE);
16229 vim_free(argvars[1].vval.v_string);
16230# endif
16231#endif
16232}
16233
Bram Moolenaar0d660222005-01-07 21:51:51 +000016234 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010016235f_remote_peek(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000016236{
16237#ifdef FEAT_CLIENTSERVER
Bram Moolenaar33570922005-01-25 22:26:29 +000016238 dictitem_T v;
Bram Moolenaar0d660222005-01-07 21:51:51 +000016239 char_u *s = NULL;
16240# ifdef WIN32
Bram Moolenaareb3593b2006-04-22 22:33:57 +000016241 long_u n = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000016242# endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016243 char_u *serverid;
Bram Moolenaar0d660222005-01-07 21:51:51 +000016244
16245 if (check_restricted() || check_secure())
16246 {
16247 rettv->vval.v_number = -1;
16248 return;
16249 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016250 serverid = get_tv_string_chk(&argvars[0]);
16251 if (serverid == NULL)
16252 {
16253 rettv->vval.v_number = -1;
16254 return; /* type error; errmsg already given */
16255 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000016256# ifdef WIN32
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +010016257 sscanf((const char *)serverid, SCANF_HEX_LONG_U, &n);
Bram Moolenaar0d660222005-01-07 21:51:51 +000016258 if (n == 0)
16259 rettv->vval.v_number = -1;
16260 else
16261 {
16262 s = serverGetReply((HWND)n, FALSE, FALSE, FALSE);
16263 rettv->vval.v_number = (s != NULL);
16264 }
16265# else
Bram Moolenaar0d660222005-01-07 21:51:51 +000016266 if (check_connection() == FAIL)
16267 return;
16268
16269 rettv->vval.v_number = serverPeekReply(X_DISPLAY,
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016270 serverStrToWin(serverid), &s);
Bram Moolenaar0d660222005-01-07 21:51:51 +000016271# endif
16272
16273 if (argvars[1].v_type != VAR_UNKNOWN && rettv->vval.v_number > 0)
16274 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016275 char_u *retvar;
16276
Bram Moolenaar33570922005-01-25 22:26:29 +000016277 v.di_tv.v_type = VAR_STRING;
16278 v.di_tv.vval.v_string = vim_strsave(s);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016279 retvar = get_tv_string_chk(&argvars[1]);
16280 if (retvar != NULL)
16281 set_var(retvar, &v.di_tv, FALSE);
Bram Moolenaar33570922005-01-25 22:26:29 +000016282 vim_free(v.di_tv.vval.v_string);
Bram Moolenaar0d660222005-01-07 21:51:51 +000016283 }
16284#else
16285 rettv->vval.v_number = -1;
16286#endif
16287}
16288
Bram Moolenaar0d660222005-01-07 21:51:51 +000016289 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010016290f_remote_read(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000016291{
16292 char_u *r = NULL;
16293
16294#ifdef FEAT_CLIENTSERVER
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016295 char_u *serverid = get_tv_string_chk(&argvars[0]);
16296
16297 if (serverid != NULL && !check_restricted() && !check_secure())
Bram Moolenaar0d660222005-01-07 21:51:51 +000016298 {
16299# ifdef WIN32
16300 /* The server's HWND is encoded in the 'id' parameter */
Bram Moolenaareb3593b2006-04-22 22:33:57 +000016301 long_u n = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000016302
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +010016303 sscanf((char *)serverid, SCANF_HEX_LONG_U, &n);
Bram Moolenaar0d660222005-01-07 21:51:51 +000016304 if (n != 0)
16305 r = serverGetReply((HWND)n, FALSE, TRUE, TRUE);
16306 if (r == NULL)
16307# else
16308 if (check_connection() == FAIL || serverReadReply(X_DISPLAY,
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016309 serverStrToWin(serverid), &r, FALSE) < 0)
Bram Moolenaar0d660222005-01-07 21:51:51 +000016310# endif
16311 EMSG(_("E277: Unable to read a server reply"));
16312 }
16313#endif
16314 rettv->v_type = VAR_STRING;
16315 rettv->vval.v_string = r;
16316}
16317
16318/*
16319 * "remote_send()" function
16320 */
Bram Moolenaar0d660222005-01-07 21:51:51 +000016321 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010016322f_remote_send(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000016323{
16324 rettv->v_type = VAR_STRING;
16325 rettv->vval.v_string = NULL;
16326#ifdef FEAT_CLIENTSERVER
16327 remote_common(argvars, rettv, FALSE);
16328#endif
16329}
16330
16331/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000016332 * "remove()" function
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016333 */
16334 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010016335f_remove(typval_T *argvars, typval_T *rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016336{
Bram Moolenaar33570922005-01-25 22:26:29 +000016337 list_T *l;
16338 listitem_T *item, *item2;
16339 listitem_T *li;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016340 long idx;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016341 long end;
Bram Moolenaar8c711452005-01-14 21:53:12 +000016342 char_u *key;
Bram Moolenaar33570922005-01-25 22:26:29 +000016343 dict_T *d;
16344 dictitem_T *di;
Bram Moolenaar77354e72015-04-21 16:49:05 +020016345 char_u *arg_errmsg = (char_u *)N_("remove() argument");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016346
Bram Moolenaar8c711452005-01-14 21:53:12 +000016347 if (argvars[0].v_type == VAR_DICT)
16348 {
16349 if (argvars[2].v_type != VAR_UNKNOWN)
16350 EMSG2(_(e_toomanyarg), "remove()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016351 else if ((d = argvars[0].vval.v_dict) != NULL
Bram Moolenaar77354e72015-04-21 16:49:05 +020016352 && !tv_check_lock(d->dv_lock, arg_errmsg, TRUE))
Bram Moolenaar8c711452005-01-14 21:53:12 +000016353 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016354 key = get_tv_string_chk(&argvars[1]);
16355 if (key != NULL)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000016356 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016357 di = dict_find(d, key, -1);
16358 if (di == NULL)
16359 EMSG2(_(e_dictkey), key);
Bram Moolenaar77354e72015-04-21 16:49:05 +020016360 else if (!var_check_fixed(di->di_flags, arg_errmsg, TRUE)
16361 && !var_check_ro(di->di_flags, arg_errmsg, TRUE))
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016362 {
16363 *rettv = di->di_tv;
16364 init_tv(&di->di_tv);
16365 dictitem_remove(d, di);
16366 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000016367 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000016368 }
16369 }
16370 else if (argvars[0].v_type != VAR_LIST)
16371 EMSG2(_(e_listdictarg), "remove()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016372 else if ((l = argvars[0].vval.v_list) != NULL
Bram Moolenaar77354e72015-04-21 16:49:05 +020016373 && !tv_check_lock(l->lv_lock, arg_errmsg, TRUE))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016374 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016375 int error = FALSE;
16376
16377 idx = get_tv_number_chk(&argvars[1], &error);
16378 if (error)
16379 ; /* type error: do nothing, errmsg already given */
16380 else if ((item = list_find(l, idx)) == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016381 EMSGN(_(e_listidx), idx);
16382 else
16383 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016384 if (argvars[2].v_type == VAR_UNKNOWN)
16385 {
16386 /* Remove one item, return its value. */
Bram Moolenaar3ec7f4e2014-05-07 17:31:37 +020016387 vimlist_remove(l, item, item);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016388 *rettv = item->li_tv;
16389 vim_free(item);
16390 }
16391 else
16392 {
16393 /* Remove range of items, return list with values. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016394 end = get_tv_number_chk(&argvars[2], &error);
16395 if (error)
16396 ; /* type error: do nothing */
16397 else if ((item2 = list_find(l, end)) == NULL)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016398 EMSGN(_(e_listidx), end);
16399 else
16400 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000016401 int cnt = 0;
16402
16403 for (li = item; li != NULL; li = li->li_next)
16404 {
16405 ++cnt;
16406 if (li == item2)
16407 break;
16408 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016409 if (li == NULL) /* didn't find "item2" after "item" */
16410 EMSG(_(e_invrange));
16411 else
16412 {
Bram Moolenaar3ec7f4e2014-05-07 17:31:37 +020016413 vimlist_remove(l, item, item2);
Bram Moolenaareddf53b2006-02-27 00:11:10 +000016414 if (rettv_list_alloc(rettv) == OK)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016415 {
Bram Moolenaareddf53b2006-02-27 00:11:10 +000016416 l = rettv->vval.v_list;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016417 l->lv_first = item;
16418 l->lv_last = item2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016419 item->li_prev = NULL;
16420 item2->li_next = NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +000016421 l->lv_len = cnt;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016422 }
16423 }
16424 }
16425 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016426 }
16427 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016428}
16429
16430/*
16431 * "rename({from}, {to})" function
16432 */
16433 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010016434f_rename(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016435{
16436 char_u buf[NUMBUFLEN];
16437
16438 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016439 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016440 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016441 rettv->vval.v_number = vim_rename(get_tv_string(&argvars[0]),
16442 get_tv_string_buf(&argvars[1], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +000016443}
16444
16445/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016446 * "repeat()" function
16447 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016448 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010016449f_repeat(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016450{
16451 char_u *p;
16452 int n;
16453 int slen;
16454 int len;
16455 char_u *r;
16456 int i;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016457
16458 n = get_tv_number(&argvars[1]);
16459 if (argvars[0].v_type == VAR_LIST)
16460 {
Bram Moolenaareddf53b2006-02-27 00:11:10 +000016461 if (rettv_list_alloc(rettv) == OK && argvars[0].vval.v_list != NULL)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016462 while (n-- > 0)
Bram Moolenaareddf53b2006-02-27 00:11:10 +000016463 if (list_extend(rettv->vval.v_list,
16464 argvars[0].vval.v_list, NULL) == FAIL)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016465 break;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016466 }
16467 else
16468 {
16469 p = get_tv_string(&argvars[0]);
16470 rettv->v_type = VAR_STRING;
16471 rettv->vval.v_string = NULL;
16472
16473 slen = (int)STRLEN(p);
16474 len = slen * n;
16475 if (len <= 0)
16476 return;
16477
16478 r = alloc(len + 1);
16479 if (r != NULL)
16480 {
16481 for (i = 0; i < n; i++)
16482 mch_memmove(r + i * slen, p, (size_t)slen);
16483 r[len] = NUL;
16484 }
16485
16486 rettv->vval.v_string = r;
16487 }
16488}
16489
16490/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000016491 * "resolve()" function
16492 */
16493 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010016494f_resolve(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016495{
16496 char_u *p;
Bram Moolenaard9462e32011-04-11 21:35:11 +020016497#ifdef HAVE_READLINK
16498 char_u *buf = NULL;
16499#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000016500
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016501 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016502#ifdef FEAT_SHORTCUT
16503 {
16504 char_u *v = NULL;
16505
16506 v = mch_resolve_shortcut(p);
16507 if (v != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016508 rettv->vval.v_string = v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016509 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016510 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016511 }
16512#else
16513# ifdef HAVE_READLINK
16514 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000016515 char_u *cpy;
16516 int len;
16517 char_u *remain = NULL;
16518 char_u *q;
16519 int is_relative_to_current = FALSE;
16520 int has_trailing_pathsep = FALSE;
16521 int limit = 100;
16522
16523 p = vim_strsave(p);
16524
16525 if (p[0] == '.' && (vim_ispathsep(p[1])
16526 || (p[1] == '.' && (vim_ispathsep(p[2])))))
16527 is_relative_to_current = TRUE;
16528
16529 len = STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000016530 if (len > 0 && after_pathsep(p, p + len))
Bram Moolenaar1385c3e2011-05-19 14:59:10 +020016531 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000016532 has_trailing_pathsep = TRUE;
Bram Moolenaar1385c3e2011-05-19 14:59:10 +020016533 p[len - 1] = NUL; /* the trailing slash breaks readlink() */
16534 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016535
16536 q = getnextcomp(p);
16537 if (*q != NUL)
16538 {
16539 /* Separate the first path component in "p", and keep the
16540 * remainder (beginning with the path separator). */
16541 remain = vim_strsave(q - 1);
16542 q[-1] = NUL;
16543 }
16544
Bram Moolenaard9462e32011-04-11 21:35:11 +020016545 buf = alloc(MAXPATHL + 1);
16546 if (buf == NULL)
16547 goto fail;
16548
Bram Moolenaar071d4272004-06-13 20:20:40 +000016549 for (;;)
16550 {
16551 for (;;)
16552 {
16553 len = readlink((char *)p, (char *)buf, MAXPATHL);
16554 if (len <= 0)
16555 break;
16556 buf[len] = NUL;
16557
16558 if (limit-- == 0)
16559 {
16560 vim_free(p);
16561 vim_free(remain);
16562 EMSG(_("E655: Too many symbolic links (cycle?)"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016563 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016564 goto fail;
16565 }
16566
16567 /* Ensure that the result will have a trailing path separator
16568 * if the argument has one. */
16569 if (remain == NULL && has_trailing_pathsep)
16570 add_pathsep(buf);
16571
16572 /* Separate the first path component in the link value and
16573 * concatenate the remainders. */
16574 q = getnextcomp(vim_ispathsep(*buf) ? buf + 1 : buf);
16575 if (*q != NUL)
16576 {
16577 if (remain == NULL)
16578 remain = vim_strsave(q - 1);
16579 else
16580 {
Bram Moolenaar900b4d72005-12-12 22:05:50 +000016581 cpy = concat_str(q - 1, remain);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016582 if (cpy != NULL)
16583 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000016584 vim_free(remain);
16585 remain = cpy;
16586 }
16587 }
16588 q[-1] = NUL;
16589 }
16590
16591 q = gettail(p);
16592 if (q > p && *q == NUL)
16593 {
16594 /* Ignore trailing path separator. */
16595 q[-1] = NUL;
16596 q = gettail(p);
16597 }
16598 if (q > p && !mch_isFullName(buf))
16599 {
16600 /* symlink is relative to directory of argument */
16601 cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1));
16602 if (cpy != NULL)
16603 {
16604 STRCPY(cpy, p);
16605 STRCPY(gettail(cpy), buf);
16606 vim_free(p);
16607 p = cpy;
16608 }
16609 }
16610 else
16611 {
16612 vim_free(p);
16613 p = vim_strsave(buf);
16614 }
16615 }
16616
16617 if (remain == NULL)
16618 break;
16619
16620 /* Append the first path component of "remain" to "p". */
16621 q = getnextcomp(remain + 1);
16622 len = q - remain - (*q != NUL);
16623 cpy = vim_strnsave(p, STRLEN(p) + len);
16624 if (cpy != NULL)
16625 {
16626 STRNCAT(cpy, remain, len);
16627 vim_free(p);
16628 p = cpy;
16629 }
16630 /* Shorten "remain". */
16631 if (*q != NUL)
Bram Moolenaar8c8de832008-06-24 22:58:06 +000016632 STRMOVE(remain, q - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016633 else
16634 {
16635 vim_free(remain);
16636 remain = NULL;
16637 }
16638 }
16639
16640 /* If the result is a relative path name, make it explicitly relative to
16641 * the current directory if and only if the argument had this form. */
16642 if (!vim_ispathsep(*p))
16643 {
16644 if (is_relative_to_current
16645 && *p != NUL
16646 && !(p[0] == '.'
16647 && (p[1] == NUL
16648 || vim_ispathsep(p[1])
16649 || (p[1] == '.'
16650 && (p[2] == NUL
16651 || vim_ispathsep(p[2]))))))
16652 {
16653 /* Prepend "./". */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016654 cpy = concat_str((char_u *)"./", p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016655 if (cpy != NULL)
16656 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000016657 vim_free(p);
16658 p = cpy;
16659 }
16660 }
16661 else if (!is_relative_to_current)
16662 {
16663 /* Strip leading "./". */
16664 q = p;
16665 while (q[0] == '.' && vim_ispathsep(q[1]))
16666 q += 2;
16667 if (q > p)
Bram Moolenaar8c8de832008-06-24 22:58:06 +000016668 STRMOVE(p, p + 2);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016669 }
16670 }
16671
16672 /* Ensure that the result will have no trailing path separator
16673 * if the argument had none. But keep "/" or "//". */
16674 if (!has_trailing_pathsep)
16675 {
16676 q = p + STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000016677 if (after_pathsep(p, q))
16678 *gettail_sep(p) = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016679 }
16680
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016681 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016682 }
16683# else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016684 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016685# endif
16686#endif
16687
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016688 simplify_filename(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016689
16690#ifdef HAVE_READLINK
16691fail:
Bram Moolenaard9462e32011-04-11 21:35:11 +020016692 vim_free(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016693#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016694 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016695}
16696
16697/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000016698 * "reverse({list})" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000016699 */
16700 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010016701f_reverse(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016702{
Bram Moolenaar33570922005-01-25 22:26:29 +000016703 list_T *l;
16704 listitem_T *li, *ni;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016705
Bram Moolenaar0d660222005-01-07 21:51:51 +000016706 if (argvars[0].v_type != VAR_LIST)
16707 EMSG2(_(e_listarg), "reverse()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016708 else if ((l = argvars[0].vval.v_list) != NULL
Bram Moolenaar77354e72015-04-21 16:49:05 +020016709 && !tv_check_lock(l->lv_lock,
16710 (char_u *)N_("reverse() argument"), TRUE))
Bram Moolenaar0d660222005-01-07 21:51:51 +000016711 {
16712 li = l->lv_last;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016713 l->lv_first = l->lv_last = NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +000016714 l->lv_len = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000016715 while (li != NULL)
16716 {
16717 ni = li->li_prev;
16718 list_append(l, li);
16719 li = ni;
16720 }
16721 rettv->vval.v_list = l;
16722 rettv->v_type = VAR_LIST;
16723 ++l->lv_refcount;
Bram Moolenaar52514562008-04-01 11:12:09 +000016724 l->lv_idx = l->lv_len - l->lv_idx - 1;
Bram Moolenaar0d660222005-01-07 21:51:51 +000016725 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016726}
16727
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016728#define SP_NOMOVE 0x01 /* don't move cursor */
16729#define SP_REPEAT 0x02 /* repeat to find outer pair */
16730#define SP_RETCOUNT 0x04 /* return matchcount */
16731#define SP_SETPCMARK 0x08 /* set previous context mark */
16732#define SP_START 0x10 /* accept match at start position */
16733#define SP_SUBPAT 0x20 /* return nr of matching sub-pattern */
16734#define SP_END 0x40 /* leave cursor at end of match */
Bram Moolenaarad4d8a12015-12-28 19:20:36 +010016735#define SP_COLUMN 0x80 /* start at cursor column */
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000016736
Bram Moolenaar48e697e2016-01-23 22:17:30 +010016737static int get_search_arg(typval_T *varp, int *flagsp);
Bram Moolenaar0d660222005-01-07 21:51:51 +000016738
16739/*
16740 * Get flags for a search function.
16741 * Possibly sets "p_ws".
16742 * Returns BACKWARD, FORWARD or zero (for an error).
16743 */
16744 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010016745get_search_arg(typval_T *varp, int *flagsp)
Bram Moolenaar0d660222005-01-07 21:51:51 +000016746{
16747 int dir = FORWARD;
16748 char_u *flags;
16749 char_u nbuf[NUMBUFLEN];
16750 int mask;
16751
16752 if (varp->v_type != VAR_UNKNOWN)
16753 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016754 flags = get_tv_string_buf_chk(varp, nbuf);
16755 if (flags == NULL)
16756 return 0; /* type error; errmsg already given */
Bram Moolenaar0d660222005-01-07 21:51:51 +000016757 while (*flags != NUL)
16758 {
16759 switch (*flags)
16760 {
16761 case 'b': dir = BACKWARD; break;
16762 case 'w': p_ws = TRUE; break;
16763 case 'W': p_ws = FALSE; break;
16764 default: mask = 0;
16765 if (flagsp != NULL)
16766 switch (*flags)
16767 {
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016768 case 'c': mask = SP_START; break;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016769 case 'e': mask = SP_END; break;
16770 case 'm': mask = SP_RETCOUNT; break;
16771 case 'n': mask = SP_NOMOVE; break;
16772 case 'p': mask = SP_SUBPAT; break;
16773 case 'r': mask = SP_REPEAT; break;
16774 case 's': mask = SP_SETPCMARK; break;
Bram Moolenaarad4d8a12015-12-28 19:20:36 +010016775 case 'z': mask = SP_COLUMN; break;
Bram Moolenaar0d660222005-01-07 21:51:51 +000016776 }
16777 if (mask == 0)
16778 {
16779 EMSG2(_(e_invarg2), flags);
16780 dir = 0;
16781 }
16782 else
16783 *flagsp |= mask;
16784 }
16785 if (dir == 0)
16786 break;
16787 ++flags;
16788 }
16789 }
16790 return dir;
16791}
16792
Bram Moolenaar071d4272004-06-13 20:20:40 +000016793/*
Bram Moolenaarad4d8a12015-12-28 19:20:36 +010016794 * Shared by search() and searchpos() functions.
Bram Moolenaar071d4272004-06-13 20:20:40 +000016795 */
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016796 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010016797search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016798{
Bram Moolenaar362e1a32006-03-06 23:29:24 +000016799 int flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016800 char_u *pat;
16801 pos_T pos;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000016802 pos_T save_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016803 int save_p_ws = p_ws;
16804 int dir;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016805 int retval = 0; /* default: FAIL */
Bram Moolenaareddf53b2006-02-27 00:11:10 +000016806 long lnum_stop = 0;
Bram Moolenaar76929292008-01-06 19:07:36 +000016807 proftime_T tm;
16808#ifdef FEAT_RELTIME
16809 long time_limit = 0;
16810#endif
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016811 int options = SEARCH_KEEP;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016812 int subpatnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016813
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016814 pat = get_tv_string(&argvars[0]);
Bram Moolenaar362e1a32006-03-06 23:29:24 +000016815 dir = get_search_arg(&argvars[1], flagsp); /* may set p_ws */
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000016816 if (dir == 0)
16817 goto theend;
Bram Moolenaar362e1a32006-03-06 23:29:24 +000016818 flags = *flagsp;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016819 if (flags & SP_START)
16820 options |= SEARCH_START;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016821 if (flags & SP_END)
16822 options |= SEARCH_END;
Bram Moolenaarad4d8a12015-12-28 19:20:36 +010016823 if (flags & SP_COLUMN)
16824 options |= SEARCH_COL;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000016825
Bram Moolenaar76929292008-01-06 19:07:36 +000016826 /* Optional arguments: line number to stop searching and timeout. */
16827 if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaareddf53b2006-02-27 00:11:10 +000016828 {
16829 lnum_stop = get_tv_number_chk(&argvars[2], NULL);
16830 if (lnum_stop < 0)
16831 goto theend;
Bram Moolenaar76929292008-01-06 19:07:36 +000016832#ifdef FEAT_RELTIME
16833 if (argvars[3].v_type != VAR_UNKNOWN)
16834 {
16835 time_limit = get_tv_number_chk(&argvars[3], NULL);
16836 if (time_limit < 0)
16837 goto theend;
16838 }
16839#endif
Bram Moolenaareddf53b2006-02-27 00:11:10 +000016840 }
16841
Bram Moolenaar76929292008-01-06 19:07:36 +000016842#ifdef FEAT_RELTIME
16843 /* Set the time limit, if there is one. */
16844 profile_setlimit(time_limit, &tm);
16845#endif
16846
Bram Moolenaar231334e2005-07-25 20:46:57 +000016847 /*
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016848 * This function does not accept SP_REPEAT and SP_RETCOUNT flags.
Bram Moolenaar231334e2005-07-25 20:46:57 +000016849 * Check to make sure only those flags are set.
16850 * Also, Only the SP_NOMOVE or the SP_SETPCMARK flag can be set. Both
16851 * flags cannot be set. Check for that condition also.
16852 */
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016853 if (((flags & (SP_REPEAT | SP_RETCOUNT)) != 0)
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016854 || ((flags & SP_NOMOVE) && (flags & SP_SETPCMARK)))
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000016855 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016856 EMSG2(_(e_invarg2), get_tv_string(&argvars[1]));
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000016857 goto theend;
16858 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016859
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000016860 pos = save_cursor = curwin->w_cursor;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016861 subpatnum = searchit(curwin, curbuf, &pos, dir, pat, 1L,
Bram Moolenaar76929292008-01-06 19:07:36 +000016862 options, RE_SEARCH, (linenr_T)lnum_stop, &tm);
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016863 if (subpatnum != FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016864 {
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016865 if (flags & SP_SUBPAT)
16866 retval = subpatnum;
16867 else
16868 retval = pos.lnum;
Bram Moolenaar231334e2005-07-25 20:46:57 +000016869 if (flags & SP_SETPCMARK)
16870 setpcmark();
Bram Moolenaar071d4272004-06-13 20:20:40 +000016871 curwin->w_cursor = pos;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016872 if (match_pos != NULL)
16873 {
16874 /* Store the match cursor position */
16875 match_pos->lnum = pos.lnum;
16876 match_pos->col = pos.col + 1;
16877 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016878 /* "/$" will put the cursor after the end of the line, may need to
16879 * correct that here */
16880 check_cursor();
16881 }
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000016882
16883 /* If 'n' flag is used: restore cursor position. */
16884 if (flags & SP_NOMOVE)
16885 curwin->w_cursor = save_cursor;
Bram Moolenaar7a42fa32007-07-10 11:28:55 +000016886 else
16887 curwin->w_set_curswant = TRUE;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000016888theend:
Bram Moolenaar071d4272004-06-13 20:20:40 +000016889 p_ws = save_p_ws;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016890
16891 return retval;
16892}
16893
Bram Moolenaar8c8de832008-06-24 22:58:06 +000016894#ifdef FEAT_FLOAT
Bram Moolenaara2e14fc2013-06-10 20:10:44 +020016895
16896/*
16897 * round() is not in C90, use ceil() or floor() instead.
16898 */
16899 float_T
Bram Moolenaar7454a062016-01-30 15:14:10 +010016900vim_round(float_T f)
Bram Moolenaara2e14fc2013-06-10 20:10:44 +020016901{
16902 return f > 0 ? floor(f + 0.5) : ceil(f - 0.5);
16903}
16904
Bram Moolenaar8c8de832008-06-24 22:58:06 +000016905/*
16906 * "round({float})" function
16907 */
16908 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010016909f_round(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8c8de832008-06-24 22:58:06 +000016910{
Bram Moolenaara1e24b92016-02-18 20:18:09 +010016911 float_T f = 0.0;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000016912
16913 rettv->v_type = VAR_FLOAT;
16914 if (get_float_arg(argvars, &f) == OK)
Bram Moolenaara2e14fc2013-06-10 20:10:44 +020016915 rettv->vval.v_float = vim_round(f);
Bram Moolenaar8c8de832008-06-24 22:58:06 +000016916 else
16917 rettv->vval.v_float = 0.0;
16918}
16919#endif
16920
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016921/*
Bram Moolenaar9a773482013-06-11 18:40:13 +020016922 * "screenattr()" function
16923 */
16924 static void
Bram Moolenaarf1d25012016-03-03 12:22:53 +010016925f_screenattr(typval_T *argvars, typval_T *rettv)
Bram Moolenaar9a773482013-06-11 18:40:13 +020016926{
16927 int row;
16928 int col;
16929 int c;
16930
16931 row = get_tv_number_chk(&argvars[0], NULL) - 1;
16932 col = get_tv_number_chk(&argvars[1], NULL) - 1;
16933 if (row < 0 || row >= screen_Rows
16934 || col < 0 || col >= screen_Columns)
16935 c = -1;
16936 else
16937 c = ScreenAttrs[LineOffset[row] + col];
16938 rettv->vval.v_number = c;
16939}
16940
16941/*
16942 * "screenchar()" function
16943 */
16944 static void
Bram Moolenaarf1d25012016-03-03 12:22:53 +010016945f_screenchar(typval_T *argvars, typval_T *rettv)
Bram Moolenaar9a773482013-06-11 18:40:13 +020016946{
16947 int row;
16948 int col;
16949 int off;
16950 int c;
16951
16952 row = get_tv_number_chk(&argvars[0], NULL) - 1;
16953 col = get_tv_number_chk(&argvars[1], NULL) - 1;
16954 if (row < 0 || row >= screen_Rows
16955 || col < 0 || col >= screen_Columns)
16956 c = -1;
16957 else
16958 {
16959 off = LineOffset[row] + col;
16960#ifdef FEAT_MBYTE
16961 if (enc_utf8 && ScreenLinesUC[off] != 0)
16962 c = ScreenLinesUC[off];
16963 else
16964#endif
16965 c = ScreenLines[off];
16966 }
16967 rettv->vval.v_number = c;
16968}
16969
16970/*
Bram Moolenaar9750bb12012-12-05 16:10:42 +010016971 * "screencol()" function
16972 *
16973 * First column is 1 to be consistent with virtcol().
16974 */
16975 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010016976f_screencol(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar9750bb12012-12-05 16:10:42 +010016977{
16978 rettv->vval.v_number = screen_screencol() + 1;
16979}
16980
16981/*
16982 * "screenrow()" function
16983 */
16984 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010016985f_screenrow(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar9750bb12012-12-05 16:10:42 +010016986{
16987 rettv->vval.v_number = screen_screenrow() + 1;
16988}
16989
16990/*
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016991 * "search()" function
16992 */
16993 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010016994f_search(typval_T *argvars, typval_T *rettv)
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016995{
Bram Moolenaar362e1a32006-03-06 23:29:24 +000016996 int flags = 0;
16997
16998 rettv->vval.v_number = search_cmn(argvars, NULL, &flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016999}
17000
Bram Moolenaar071d4272004-06-13 20:20:40 +000017001/*
Bram Moolenaardd2436f2005-09-05 22:14:46 +000017002 * "searchdecl()" function
17003 */
17004 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017005f_searchdecl(typval_T *argvars, typval_T *rettv)
Bram Moolenaardd2436f2005-09-05 22:14:46 +000017006{
17007 int locally = 1;
Bram Moolenaare6facf92005-09-13 21:22:27 +000017008 int thisblock = 0;
Bram Moolenaardd2436f2005-09-05 22:14:46 +000017009 int error = FALSE;
17010 char_u *name;
17011
17012 rettv->vval.v_number = 1; /* default: FAIL */
17013
17014 name = get_tv_string_chk(&argvars[0]);
17015 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaare6facf92005-09-13 21:22:27 +000017016 {
Bram Moolenaardd2436f2005-09-05 22:14:46 +000017017 locally = get_tv_number_chk(&argvars[1], &error) == 0;
Bram Moolenaare6facf92005-09-13 21:22:27 +000017018 if (!error && argvars[2].v_type != VAR_UNKNOWN)
17019 thisblock = get_tv_number_chk(&argvars[2], &error) != 0;
17020 }
Bram Moolenaardd2436f2005-09-05 22:14:46 +000017021 if (!error && name != NULL)
17022 rettv->vval.v_number = find_decl(name, (int)STRLEN(name),
Bram Moolenaare6facf92005-09-13 21:22:27 +000017023 locally, thisblock, SEARCH_KEEP) == FAIL;
Bram Moolenaardd2436f2005-09-05 22:14:46 +000017024}
17025
17026/*
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017027 * Used by searchpair() and searchpairpos()
Bram Moolenaar071d4272004-06-13 20:20:40 +000017028 */
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017029 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010017030searchpair_cmn(typval_T *argvars, pos_T *match_pos)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017031{
17032 char_u *spat, *mpat, *epat;
17033 char_u *skip;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017034 int save_p_ws = p_ws;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017035 int dir;
17036 int flags = 0;
17037 char_u nbuf1[NUMBUFLEN];
17038 char_u nbuf2[NUMBUFLEN];
17039 char_u nbuf3[NUMBUFLEN];
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017040 int retval = 0; /* default: FAIL */
Bram Moolenaareddf53b2006-02-27 00:11:10 +000017041 long lnum_stop = 0;
Bram Moolenaar76929292008-01-06 19:07:36 +000017042 long time_limit = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017043
Bram Moolenaar071d4272004-06-13 20:20:40 +000017044 /* Get the three pattern arguments: start, middle, end. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017045 spat = get_tv_string_chk(&argvars[0]);
17046 mpat = get_tv_string_buf_chk(&argvars[1], nbuf1);
17047 epat = get_tv_string_buf_chk(&argvars[2], nbuf2);
17048 if (spat == NULL || mpat == NULL || epat == NULL)
17049 goto theend; /* type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017050
Bram Moolenaar071d4272004-06-13 20:20:40 +000017051 /* Handle the optional fourth argument: flags */
17052 dir = get_search_arg(&argvars[3], &flags); /* may set p_ws */
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000017053 if (dir == 0)
17054 goto theend;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000017055
17056 /* Don't accept SP_END or SP_SUBPAT.
Bram Moolenaar231334e2005-07-25 20:46:57 +000017057 * Only one of the SP_NOMOVE or SP_SETPCMARK flags can be set.
17058 */
Bram Moolenaar768b8c42006-03-04 21:58:33 +000017059 if ((flags & (SP_END | SP_SUBPAT)) != 0
17060 || ((flags & SP_NOMOVE) && (flags & SP_SETPCMARK)))
Bram Moolenaar231334e2005-07-25 20:46:57 +000017061 {
Bram Moolenaar768b8c42006-03-04 21:58:33 +000017062 EMSG2(_(e_invarg2), get_tv_string(&argvars[3]));
Bram Moolenaar231334e2005-07-25 20:46:57 +000017063 goto theend;
17064 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017065
Bram Moolenaar92de73d2008-01-22 10:59:38 +000017066 /* Using 'r' implies 'W', otherwise it doesn't work. */
17067 if (flags & SP_REPEAT)
17068 p_ws = FALSE;
17069
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017070 /* Optional fifth argument: skip expression */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017071 if (argvars[3].v_type == VAR_UNKNOWN
17072 || argvars[4].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017073 skip = (char_u *)"";
17074 else
Bram Moolenaareddf53b2006-02-27 00:11:10 +000017075 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017076 skip = get_tv_string_buf_chk(&argvars[4], nbuf3);
Bram Moolenaareddf53b2006-02-27 00:11:10 +000017077 if (argvars[5].v_type != VAR_UNKNOWN)
17078 {
17079 lnum_stop = get_tv_number_chk(&argvars[5], NULL);
17080 if (lnum_stop < 0)
17081 goto theend;
Bram Moolenaar76929292008-01-06 19:07:36 +000017082#ifdef FEAT_RELTIME
17083 if (argvars[6].v_type != VAR_UNKNOWN)
17084 {
17085 time_limit = get_tv_number_chk(&argvars[6], NULL);
17086 if (time_limit < 0)
17087 goto theend;
17088 }
17089#endif
Bram Moolenaareddf53b2006-02-27 00:11:10 +000017090 }
17091 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017092 if (skip == NULL)
17093 goto theend; /* type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017094
Bram Moolenaareddf53b2006-02-27 00:11:10 +000017095 retval = do_searchpair(spat, mpat, epat, dir, skip, flags,
Bram Moolenaar76929292008-01-06 19:07:36 +000017096 match_pos, lnum_stop, time_limit);
Bram Moolenaar9fad3082005-07-19 22:22:13 +000017097
17098theend:
17099 p_ws = save_p_ws;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017100
17101 return retval;
17102}
17103
17104/*
17105 * "searchpair()" function
17106 */
17107 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017108f_searchpair(typval_T *argvars, typval_T *rettv)
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017109{
17110 rettv->vval.v_number = searchpair_cmn(argvars, NULL);
17111}
17112
17113/*
17114 * "searchpairpos()" function
17115 */
17116 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017117f_searchpairpos(typval_T *argvars, typval_T *rettv)
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017118{
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017119 pos_T match_pos;
17120 int lnum = 0;
17121 int col = 0;
17122
Bram Moolenaareddf53b2006-02-27 00:11:10 +000017123 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017124 return;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017125
17126 if (searchpair_cmn(argvars, &match_pos) > 0)
17127 {
17128 lnum = match_pos.lnum;
17129 col = match_pos.col;
17130 }
17131
Bram Moolenaareddf53b2006-02-27 00:11:10 +000017132 list_append_number(rettv->vval.v_list, (varnumber_T)lnum);
17133 list_append_number(rettv->vval.v_list, (varnumber_T)col);
Bram Moolenaar9fad3082005-07-19 22:22:13 +000017134}
17135
17136/*
17137 * Search for a start/middle/end thing.
17138 * Used by searchpair(), see its documentation for the details.
17139 * Returns 0 or -1 for no match,
17140 */
17141 long
Bram Moolenaar7454a062016-01-30 15:14:10 +010017142do_searchpair(
17143 char_u *spat, /* start pattern */
17144 char_u *mpat, /* middle pattern */
17145 char_u *epat, /* end pattern */
17146 int dir, /* BACKWARD or FORWARD */
17147 char_u *skip, /* skip expression */
17148 int flags, /* SP_SETPCMARK and other SP_ values */
17149 pos_T *match_pos,
17150 linenr_T lnum_stop, /* stop at this line if not zero */
17151 long time_limit UNUSED) /* stop after this many msec */
Bram Moolenaar9fad3082005-07-19 22:22:13 +000017152{
17153 char_u *save_cpo;
17154 char_u *pat, *pat2 = NULL, *pat3 = NULL;
17155 long retval = 0;
17156 pos_T pos;
17157 pos_T firstpos;
17158 pos_T foundpos;
17159 pos_T save_cursor;
17160 pos_T save_pos;
17161 int n;
17162 int r;
17163 int nest = 1;
17164 int err;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000017165 int options = SEARCH_KEEP;
Bram Moolenaar76929292008-01-06 19:07:36 +000017166 proftime_T tm;
Bram Moolenaar9fad3082005-07-19 22:22:13 +000017167
17168 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
17169 save_cpo = p_cpo;
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +000017170 p_cpo = empty_option;
Bram Moolenaar9fad3082005-07-19 22:22:13 +000017171
Bram Moolenaar76929292008-01-06 19:07:36 +000017172#ifdef FEAT_RELTIME
17173 /* Set the time limit, if there is one. */
17174 profile_setlimit(time_limit, &tm);
17175#endif
17176
Bram Moolenaar9fad3082005-07-19 22:22:13 +000017177 /* Make two search patterns: start/end (pat2, for in nested pairs) and
17178 * start/middle/end (pat3, for the top pair). */
17179 pat2 = alloc((unsigned)(STRLEN(spat) + STRLEN(epat) + 15));
17180 pat3 = alloc((unsigned)(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 23));
17181 if (pat2 == NULL || pat3 == NULL)
17182 goto theend;
17183 sprintf((char *)pat2, "\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat);
17184 if (*mpat == NUL)
17185 STRCPY(pat3, pat2);
17186 else
17187 sprintf((char *)pat3, "\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)",
17188 spat, epat, mpat);
Bram Moolenaar0e34f622006-03-03 23:00:03 +000017189 if (flags & SP_START)
17190 options |= SEARCH_START;
Bram Moolenaar9fad3082005-07-19 22:22:13 +000017191
Bram Moolenaar071d4272004-06-13 20:20:40 +000017192 save_cursor = curwin->w_cursor;
17193 pos = curwin->w_cursor;
Bram Moolenaar261bfea2006-03-01 22:12:31 +000017194 clearpos(&firstpos);
17195 clearpos(&foundpos);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017196 pat = pat3;
17197 for (;;)
17198 {
17199 n = searchit(curwin, curbuf, &pos, dir, pat, 1L,
Bram Moolenaar76929292008-01-06 19:07:36 +000017200 options, RE_SEARCH, lnum_stop, &tm);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017201 if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos)))
17202 /* didn't find it or found the first match again: FAIL */
17203 break;
17204
17205 if (firstpos.lnum == 0)
17206 firstpos = pos;
Bram Moolenaarc9a2d2e2005-04-24 22:09:56 +000017207 if (equalpos(pos, foundpos))
17208 {
17209 /* Found the same position again. Can happen with a pattern that
17210 * has "\zs" at the end and searching backwards. Advance one
17211 * character and try again. */
17212 if (dir == BACKWARD)
17213 decl(&pos);
17214 else
17215 incl(&pos);
17216 }
17217 foundpos = pos;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017218
Bram Moolenaar92de73d2008-01-22 10:59:38 +000017219 /* clear the start flag to avoid getting stuck here */
17220 options &= ~SEARCH_START;
17221
Bram Moolenaar071d4272004-06-13 20:20:40 +000017222 /* If the skip pattern matches, ignore this match. */
17223 if (*skip != NUL)
17224 {
17225 save_pos = curwin->w_cursor;
17226 curwin->w_cursor = pos;
17227 r = eval_to_bool(skip, &err, NULL, FALSE);
17228 curwin->w_cursor = save_pos;
17229 if (err)
17230 {
17231 /* Evaluating {skip} caused an error, break here. */
17232 curwin->w_cursor = save_cursor;
Bram Moolenaar9fad3082005-07-19 22:22:13 +000017233 retval = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017234 break;
17235 }
17236 if (r)
17237 continue;
17238 }
17239
17240 if ((dir == BACKWARD && n == 3) || (dir == FORWARD && n == 2))
17241 {
17242 /* Found end when searching backwards or start when searching
17243 * forward: nested pair. */
17244 ++nest;
17245 pat = pat2; /* nested, don't search for middle */
17246 }
17247 else
17248 {
17249 /* Found end when searching forward or start when searching
17250 * backward: end of (nested) pair; or found middle in outer pair. */
17251 if (--nest == 1)
17252 pat = pat3; /* outer level, search for middle */
17253 }
17254
17255 if (nest == 0)
17256 {
17257 /* Found the match: return matchcount or line number. */
17258 if (flags & SP_RETCOUNT)
Bram Moolenaar9fad3082005-07-19 22:22:13 +000017259 ++retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017260 else
Bram Moolenaar9fad3082005-07-19 22:22:13 +000017261 retval = pos.lnum;
Bram Moolenaar231334e2005-07-25 20:46:57 +000017262 if (flags & SP_SETPCMARK)
17263 setpcmark();
Bram Moolenaar071d4272004-06-13 20:20:40 +000017264 curwin->w_cursor = pos;
17265 if (!(flags & SP_REPEAT))
17266 break;
17267 nest = 1; /* search for next unmatched */
17268 }
17269 }
17270
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017271 if (match_pos != NULL)
17272 {
17273 /* Store the match cursor position */
17274 match_pos->lnum = curwin->w_cursor.lnum;
17275 match_pos->col = curwin->w_cursor.col + 1;
17276 }
17277
Bram Moolenaar071d4272004-06-13 20:20:40 +000017278 /* If 'n' flag is used or search failed: restore cursor position. */
Bram Moolenaar9fad3082005-07-19 22:22:13 +000017279 if ((flags & SP_NOMOVE) || retval == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017280 curwin->w_cursor = save_cursor;
17281
17282theend:
17283 vim_free(pat2);
17284 vim_free(pat3);
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +000017285 if (p_cpo == empty_option)
17286 p_cpo = save_cpo;
17287 else
17288 /* Darn, evaluating the {skip} expression changed the value. */
17289 free_string_option(save_cpo);
Bram Moolenaar9fad3082005-07-19 22:22:13 +000017290
17291 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017292}
17293
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017294/*
17295 * "searchpos()" function
17296 */
17297 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017298f_searchpos(typval_T *argvars, typval_T *rettv)
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017299{
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017300 pos_T match_pos;
17301 int lnum = 0;
17302 int col = 0;
Bram Moolenaar362e1a32006-03-06 23:29:24 +000017303 int n;
17304 int flags = 0;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017305
Bram Moolenaareddf53b2006-02-27 00:11:10 +000017306 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017307 return;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017308
Bram Moolenaar362e1a32006-03-06 23:29:24 +000017309 n = search_cmn(argvars, &match_pos, &flags);
17310 if (n > 0)
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017311 {
17312 lnum = match_pos.lnum;
17313 col = match_pos.col;
17314 }
17315
Bram Moolenaareddf53b2006-02-27 00:11:10 +000017316 list_append_number(rettv->vval.v_list, (varnumber_T)lnum);
17317 list_append_number(rettv->vval.v_list, (varnumber_T)col);
Bram Moolenaar362e1a32006-03-06 23:29:24 +000017318 if (flags & SP_SUBPAT)
17319 list_append_number(rettv->vval.v_list, (varnumber_T)n);
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017320}
17321
Bram Moolenaar0d660222005-01-07 21:51:51 +000017322 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017323f_server2client(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017324{
Bram Moolenaar0d660222005-01-07 21:51:51 +000017325#ifdef FEAT_CLIENTSERVER
17326 char_u buf[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017327 char_u *server = get_tv_string_chk(&argvars[0]);
17328 char_u *reply = get_tv_string_buf_chk(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017329
Bram Moolenaar0d660222005-01-07 21:51:51 +000017330 rettv->vval.v_number = -1;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017331 if (server == NULL || reply == NULL)
17332 return;
Bram Moolenaar0d660222005-01-07 21:51:51 +000017333 if (check_restricted() || check_secure())
17334 return;
17335# ifdef FEAT_X11
17336 if (check_connection() == FAIL)
17337 return;
17338# endif
17339
17340 if (serverSendReply(server, reply) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017341 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000017342 EMSG(_("E258: Unable to send to client"));
17343 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017344 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000017345 rettv->vval.v_number = 0;
17346#else
17347 rettv->vval.v_number = -1;
17348#endif
17349}
17350
Bram Moolenaar0d660222005-01-07 21:51:51 +000017351 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017352f_serverlist(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000017353{
17354 char_u *r = NULL;
17355
17356#ifdef FEAT_CLIENTSERVER
17357# ifdef WIN32
17358 r = serverGetVimNames();
17359# else
17360 make_connection();
17361 if (X_DISPLAY != NULL)
17362 r = serverGetVimNames(X_DISPLAY);
17363# endif
17364#endif
17365 rettv->v_type = VAR_STRING;
17366 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017367}
17368
17369/*
17370 * "setbufvar()" function
17371 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017372 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017373f_setbufvar(typval_T *argvars, typval_T *rettv UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017374{
17375 buf_T *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017376 aco_save_T aco;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017377 char_u *varname, *bufvarname;
Bram Moolenaar33570922005-01-25 22:26:29 +000017378 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017379 char_u nbuf[NUMBUFLEN];
17380
17381 if (check_restricted() || check_secure())
17382 return;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017383 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
17384 varname = get_tv_string_chk(&argvars[1]);
Bram Moolenaar0c279bb2013-03-19 14:25:54 +010017385 buf = get_buf_tv(&argvars[0], FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017386 varp = &argvars[2];
17387
17388 if (buf != NULL && varname != NULL && varp != NULL)
17389 {
17390 /* set curbuf to be our buf, temporarily */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017391 aucmd_prepbuf(&aco, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017392
17393 if (*varname == '&')
17394 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017395 long numval;
17396 char_u *strval;
17397 int error = FALSE;
17398
Bram Moolenaar071d4272004-06-13 20:20:40 +000017399 ++varname;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017400 numval = get_tv_number_chk(varp, &error);
17401 strval = get_tv_string_buf_chk(varp, nbuf);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017402 if (!error && strval != NULL)
17403 set_option_value(varname, numval, strval, OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017404 }
17405 else
17406 {
17407 bufvarname = alloc((unsigned)STRLEN(varname) + 3);
17408 if (bufvarname != NULL)
17409 {
17410 STRCPY(bufvarname, "b:");
17411 STRCPY(bufvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000017412 set_var(bufvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017413 vim_free(bufvarname);
17414 }
17415 }
17416
17417 /* reset notion of buffer */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017418 aucmd_restbuf(&aco);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017419 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017420}
17421
Bram Moolenaardbd24b52015-08-11 14:26:19 +020017422 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017423f_setcharsearch(typval_T *argvars, typval_T *rettv UNUSED)
Bram Moolenaardbd24b52015-08-11 14:26:19 +020017424{
17425 dict_T *d;
17426 dictitem_T *di;
17427 char_u *csearch;
17428
17429 if (argvars[0].v_type != VAR_DICT)
17430 {
17431 EMSG(_(e_dictreq));
17432 return;
17433 }
17434
17435 if ((d = argvars[0].vval.v_dict) != NULL)
17436 {
17437 csearch = get_dict_string(d, (char_u *)"char", FALSE);
17438 if (csearch != NULL)
17439 {
Bram Moolenaar8e8b4862015-08-12 22:56:58 +020017440#ifdef FEAT_MBYTE
Bram Moolenaardbd24b52015-08-11 14:26:19 +020017441 if (enc_utf8)
17442 {
17443 int pcc[MAX_MCO];
17444 int c = utfc_ptr2char(csearch, pcc);
Bram Moolenaar8e8b4862015-08-12 22:56:58 +020017445
Bram Moolenaardbd24b52015-08-11 14:26:19 +020017446 set_last_csearch(c, csearch, utfc_ptr2len(csearch));
17447 }
17448 else
Bram Moolenaar8e8b4862015-08-12 22:56:58 +020017449#endif
Bram Moolenaar3cfd5282015-08-13 23:28:43 +020017450 set_last_csearch(PTR2CHAR(csearch),
17451 csearch, MB_PTR2LEN(csearch));
Bram Moolenaardbd24b52015-08-11 14:26:19 +020017452 }
17453
17454 di = dict_find(d, (char_u *)"forward", -1);
17455 if (di != NULL)
17456 set_csearch_direction(get_tv_number(&di->di_tv)
17457 ? FORWARD : BACKWARD);
17458
17459 di = dict_find(d, (char_u *)"until", -1);
17460 if (di != NULL)
17461 set_csearch_until(!!get_tv_number(&di->di_tv));
17462 }
17463}
17464
Bram Moolenaar071d4272004-06-13 20:20:40 +000017465/*
17466 * "setcmdpos()" function
17467 */
17468 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017469f_setcmdpos(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017470{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017471 int pos = (int)get_tv_number(&argvars[0]) - 1;
17472
17473 if (pos >= 0)
17474 rettv->vval.v_number = set_cmdline_pos(pos);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017475}
17476
17477/*
Bram Moolenaar80492532016-03-08 17:08:53 +010017478 * "setfperm({fname}, {mode})" function
17479 */
17480 static void
17481f_setfperm(typval_T *argvars, typval_T *rettv)
17482{
17483 char_u *fname;
17484 char_u modebuf[NUMBUFLEN];
17485 char_u *mode_str;
17486 int i;
17487 int mask;
17488 int mode = 0;
17489
17490 rettv->vval.v_number = 0;
17491 fname = get_tv_string_chk(&argvars[0]);
17492 if (fname == NULL)
17493 return;
17494 mode_str = get_tv_string_buf_chk(&argvars[1], modebuf);
17495 if (mode_str == NULL)
17496 return;
17497 if (STRLEN(mode_str) != 9)
17498 {
17499 EMSG2(_(e_invarg2), mode_str);
17500 return;
17501 }
17502
17503 mask = 1;
17504 for (i = 8; i >= 0; --i)
17505 {
17506 if (mode_str[i] != '-')
17507 mode |= mask;
17508 mask = mask << 1;
17509 }
17510 rettv->vval.v_number = mch_setperm(fname, mode) == OK;
17511}
17512
17513/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000017514 * "setline()" function
17515 */
17516 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017517f_setline(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017518{
17519 linenr_T lnum;
Bram Moolenaar0e6830e2005-05-27 20:23:44 +000017520 char_u *line = NULL;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000017521 list_T *l = NULL;
17522 listitem_T *li = NULL;
17523 long added = 0;
17524 linenr_T lcount = curbuf->b_ml.ml_line_count;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017525
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000017526 lnum = get_tv_lnum(&argvars[0]);
17527 if (argvars[1].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017528 {
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000017529 l = argvars[1].vval.v_list;
17530 li = l->lv_first;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017531 }
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000017532 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017533 line = get_tv_string_chk(&argvars[1]);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000017534
Bram Moolenaar798b30b2009-04-22 10:56:16 +000017535 /* default result is zero == OK */
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000017536 for (;;)
17537 {
17538 if (l != NULL)
17539 {
17540 /* list argument, get next string */
17541 if (li == NULL)
17542 break;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017543 line = get_tv_string_chk(&li->li_tv);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000017544 li = li->li_next;
17545 }
17546
17547 rettv->vval.v_number = 1; /* FAIL */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017548 if (line == NULL || lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000017549 break;
Bram Moolenaar3c1e9c22013-07-04 20:25:41 +020017550
17551 /* When coming here from Insert mode, sync undo, so that this can be
17552 * undone separately from what was previously inserted. */
17553 if (u_sync_once == 2)
17554 {
17555 u_sync_once = 1; /* notify that u_sync() was called */
17556 u_sync(TRUE);
17557 }
17558
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000017559 if (lnum <= curbuf->b_ml.ml_line_count)
17560 {
17561 /* existing line, replace it */
17562 if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK)
17563 {
17564 changed_bytes(lnum, 0);
Bram Moolenaar87c19962007-04-26 08:54:21 +000017565 if (lnum == curwin->w_cursor.lnum)
17566 check_cursor_col();
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000017567 rettv->vval.v_number = 0; /* OK */
17568 }
17569 }
17570 else if (added > 0 || u_save(lnum - 1, lnum) == OK)
17571 {
17572 /* lnum is one past the last line, append the line */
17573 ++added;
17574 if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK)
17575 rettv->vval.v_number = 0; /* OK */
17576 }
17577
17578 if (l == NULL) /* only one string argument */
17579 break;
17580 ++lnum;
17581 }
17582
17583 if (added > 0)
17584 appended_lines_mark(lcount, added);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017585}
17586
Bram Moolenaar48e697e2016-01-23 22:17:30 +010017587static void set_qf_ll_list(win_T *wp, typval_T *list_arg, typval_T *action_arg, typval_T *rettv);
Bram Moolenaard9ff7d52008-03-20 12:23:49 +000017588
Bram Moolenaar071d4272004-06-13 20:20:40 +000017589/*
Bram Moolenaar17c7c012006-01-26 22:25:15 +000017590 * Used by "setqflist()" and "setloclist()" functions
Bram Moolenaar2641f772005-03-25 21:58:17 +000017591 */
Bram Moolenaar2641f772005-03-25 21:58:17 +000017592 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017593set_qf_ll_list(
17594 win_T *wp UNUSED,
17595 typval_T *list_arg UNUSED,
17596 typval_T *action_arg UNUSED,
17597 typval_T *rettv)
Bram Moolenaar2641f772005-03-25 21:58:17 +000017598{
Bram Moolenaar0ac93792006-01-21 22:16:51 +000017599#ifdef FEAT_QUICKFIX
Bram Moolenaarf4630b62005-05-20 21:31:17 +000017600 char_u *act;
17601 int action = ' ';
Bram Moolenaar0ac93792006-01-21 22:16:51 +000017602#endif
Bram Moolenaarf4630b62005-05-20 21:31:17 +000017603
Bram Moolenaar2641f772005-03-25 21:58:17 +000017604 rettv->vval.v_number = -1;
17605
17606#ifdef FEAT_QUICKFIX
Bram Moolenaar17c7c012006-01-26 22:25:15 +000017607 if (list_arg->v_type != VAR_LIST)
Bram Moolenaar2641f772005-03-25 21:58:17 +000017608 EMSG(_(e_listreq));
17609 else
17610 {
Bram Moolenaar17c7c012006-01-26 22:25:15 +000017611 list_T *l = list_arg->vval.v_list;
Bram Moolenaar2641f772005-03-25 21:58:17 +000017612
Bram Moolenaar17c7c012006-01-26 22:25:15 +000017613 if (action_arg->v_type == VAR_STRING)
Bram Moolenaarf4630b62005-05-20 21:31:17 +000017614 {
Bram Moolenaar17c7c012006-01-26 22:25:15 +000017615 act = get_tv_string_chk(action_arg);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017616 if (act == NULL)
17617 return; /* type error; errmsg already given */
Bram Moolenaarf4630b62005-05-20 21:31:17 +000017618 if (*act == 'a' || *act == 'r')
17619 action = *act;
17620 }
17621
Bram Moolenaar81484f42012-12-05 15:16:47 +010017622 if (l != NULL && set_errorlist(wp, l, action,
17623 (char_u *)(wp == NULL ? "setqflist()" : "setloclist()")) == OK)
Bram Moolenaar2641f772005-03-25 21:58:17 +000017624 rettv->vval.v_number = 0;
17625 }
17626#endif
17627}
17628
17629/*
Bram Moolenaar17c7c012006-01-26 22:25:15 +000017630 * "setloclist()" function
17631 */
Bram Moolenaar17c7c012006-01-26 22:25:15 +000017632 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017633f_setloclist(typval_T *argvars, typval_T *rettv)
Bram Moolenaar17c7c012006-01-26 22:25:15 +000017634{
17635 win_T *win;
17636
17637 rettv->vval.v_number = -1;
17638
Bram Moolenaar99ebf042006-04-15 20:28:54 +000017639 win = find_win_by_nr(&argvars[0], NULL);
Bram Moolenaar17c7c012006-01-26 22:25:15 +000017640 if (win != NULL)
17641 set_qf_ll_list(win, &argvars[1], &argvars[2], rettv);
17642}
17643
17644/*
Bram Moolenaar6ee10162007-07-26 20:58:42 +000017645 * "setmatches()" function
17646 */
17647 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017648f_setmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaar6ee10162007-07-26 20:58:42 +000017649{
17650#ifdef FEAT_SEARCH_EXTRA
17651 list_T *l;
17652 listitem_T *li;
17653 dict_T *d;
Bram Moolenaar0fce4252015-06-19 16:32:57 +020017654 list_T *s = NULL;
Bram Moolenaar6ee10162007-07-26 20:58:42 +000017655
17656 rettv->vval.v_number = -1;
17657 if (argvars[0].v_type != VAR_LIST)
17658 {
17659 EMSG(_(e_listreq));
17660 return;
17661 }
17662 if ((l = argvars[0].vval.v_list) != NULL)
17663 {
17664
17665 /* To some extent make sure that we are dealing with a list from
17666 * "getmatches()". */
17667 li = l->lv_first;
17668 while (li != NULL)
17669 {
17670 if (li->li_tv.v_type != VAR_DICT
17671 || (d = li->li_tv.vval.v_dict) == NULL)
17672 {
17673 EMSG(_(e_invarg));
17674 return;
17675 }
17676 if (!(dict_find(d, (char_u *)"group", -1) != NULL
Bram Moolenaar0fce4252015-06-19 16:32:57 +020017677 && (dict_find(d, (char_u *)"pattern", -1) != NULL
17678 || dict_find(d, (char_u *)"pos1", -1) != NULL)
Bram Moolenaar6ee10162007-07-26 20:58:42 +000017679 && dict_find(d, (char_u *)"priority", -1) != NULL
17680 && dict_find(d, (char_u *)"id", -1) != NULL))
17681 {
17682 EMSG(_(e_invarg));
17683 return;
17684 }
17685 li = li->li_next;
17686 }
17687
17688 clear_matches(curwin);
17689 li = l->lv_first;
17690 while (li != NULL)
17691 {
Bram Moolenaar0fce4252015-06-19 16:32:57 +020017692 int i = 0;
Bram Moolenaar6a7e2a62015-06-19 21:06:11 +020017693 char_u buf[5];
Bram Moolenaar0fce4252015-06-19 16:32:57 +020017694 dictitem_T *di;
Bram Moolenaar6561d522015-07-21 15:48:27 +020017695 char_u *group;
17696 int priority;
17697 int id;
17698 char_u *conceal;
Bram Moolenaar0fce4252015-06-19 16:32:57 +020017699
Bram Moolenaar6ee10162007-07-26 20:58:42 +000017700 d = li->li_tv.vval.v_dict;
Bram Moolenaar0fce4252015-06-19 16:32:57 +020017701 if (dict_find(d, (char_u *)"pattern", -1) == NULL)
17702 {
17703 if (s == NULL)
17704 {
17705 s = list_alloc();
17706 if (s == NULL)
17707 return;
17708 }
17709
17710 /* match from matchaddpos() */
17711 for (i = 1; i < 9; i++)
17712 {
17713 sprintf((char *)buf, (char *)"pos%d", i);
17714 if ((di = dict_find(d, (char_u *)buf, -1)) != NULL)
17715 {
17716 if (di->di_tv.v_type != VAR_LIST)
17717 return;
17718
17719 list_append_tv(s, &di->di_tv);
17720 s->lv_refcount++;
17721 }
17722 else
17723 break;
17724 }
17725 }
Bram Moolenaar6561d522015-07-21 15:48:27 +020017726
17727 group = get_dict_string(d, (char_u *)"group", FALSE);
17728 priority = (int)get_dict_number(d, (char_u *)"priority");
17729 id = (int)get_dict_number(d, (char_u *)"id");
17730 conceal = dict_find(d, (char_u *)"conceal", -1) != NULL
17731 ? get_dict_string(d, (char_u *)"conceal", FALSE)
17732 : NULL;
Bram Moolenaar0fce4252015-06-19 16:32:57 +020017733 if (i == 0)
17734 {
Bram Moolenaar6561d522015-07-21 15:48:27 +020017735 match_add(curwin, group,
Bram Moolenaar6ee10162007-07-26 20:58:42 +000017736 get_dict_string(d, (char_u *)"pattern", FALSE),
Bram Moolenaar6561d522015-07-21 15:48:27 +020017737 priority, id, NULL, conceal);
Bram Moolenaar0fce4252015-06-19 16:32:57 +020017738 }
17739 else
17740 {
Bram Moolenaar6561d522015-07-21 15:48:27 +020017741 match_add(curwin, group, NULL, priority, id, s, conceal);
Bram Moolenaar0fce4252015-06-19 16:32:57 +020017742 list_unref(s);
17743 s = NULL;
17744 }
17745
Bram Moolenaar6ee10162007-07-26 20:58:42 +000017746 li = li->li_next;
17747 }
17748 rettv->vval.v_number = 0;
17749 }
17750#endif
17751}
17752
17753/*
Bram Moolenaar0e34f622006-03-03 23:00:03 +000017754 * "setpos()" function
17755 */
Bram Moolenaar0e34f622006-03-03 23:00:03 +000017756 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017757f_setpos(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0e34f622006-03-03 23:00:03 +000017758{
17759 pos_T pos;
17760 int fnum;
17761 char_u *name;
Bram Moolenaar493c1782014-05-28 14:34:46 +020017762 colnr_T curswant = -1;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000017763
Bram Moolenaar08250432008-02-13 11:42:46 +000017764 rettv->vval.v_number = -1;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000017765 name = get_tv_string_chk(argvars);
17766 if (name != NULL)
17767 {
Bram Moolenaar493c1782014-05-28 14:34:46 +020017768 if (list2fpos(&argvars[1], &pos, &fnum, &curswant) == OK)
Bram Moolenaar0e34f622006-03-03 23:00:03 +000017769 {
Bram Moolenaar742d1ec2009-12-31 12:18:30 +000017770 if (--pos.col < 0)
17771 pos.col = 0;
Bram Moolenaar08250432008-02-13 11:42:46 +000017772 if (name[0] == '.' && name[1] == NUL)
Bram Moolenaar0e34f622006-03-03 23:00:03 +000017773 {
Bram Moolenaar08250432008-02-13 11:42:46 +000017774 /* set cursor */
Bram Moolenaar0e34f622006-03-03 23:00:03 +000017775 if (fnum == curbuf->b_fnum)
17776 {
17777 curwin->w_cursor = pos;
Bram Moolenaar493c1782014-05-28 14:34:46 +020017778 if (curswant >= 0)
Bram Moolenaarc21d67e2015-12-31 22:27:55 +010017779 {
Bram Moolenaar493c1782014-05-28 14:34:46 +020017780 curwin->w_curswant = curswant - 1;
Bram Moolenaarc21d67e2015-12-31 22:27:55 +010017781 curwin->w_set_curswant = FALSE;
17782 }
Bram Moolenaar0e34f622006-03-03 23:00:03 +000017783 check_cursor();
Bram Moolenaar08250432008-02-13 11:42:46 +000017784 rettv->vval.v_number = 0;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000017785 }
17786 else
17787 EMSG(_(e_invarg));
17788 }
Bram Moolenaar08250432008-02-13 11:42:46 +000017789 else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL)
17790 {
17791 /* set mark */
17792 if (setmark_pos(name[1], &pos, fnum) == OK)
17793 rettv->vval.v_number = 0;
17794 }
Bram Moolenaar0e34f622006-03-03 23:00:03 +000017795 else
17796 EMSG(_(e_invarg));
17797 }
17798 }
17799}
17800
17801/*
Bram Moolenaar17c7c012006-01-26 22:25:15 +000017802 * "setqflist()" function
17803 */
Bram Moolenaar17c7c012006-01-26 22:25:15 +000017804 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017805f_setqflist(typval_T *argvars, typval_T *rettv)
Bram Moolenaar17c7c012006-01-26 22:25:15 +000017806{
17807 set_qf_ll_list(NULL, &argvars[0], &argvars[1], rettv);
17808}
17809
17810/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000017811 * "setreg()" function
17812 */
17813 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017814f_setreg(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017815{
17816 int regname;
17817 char_u *strregname;
17818 char_u *stropt;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017819 char_u *strval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017820 int append;
17821 char_u yank_type;
17822 long block_len;
17823
17824 block_len = -1;
17825 yank_type = MAUTO;
17826 append = FALSE;
17827
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017828 strregname = get_tv_string_chk(argvars);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017829 rettv->vval.v_number = 1; /* FAIL is default */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017830
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017831 if (strregname == NULL)
17832 return; /* type error; errmsg already given */
17833 regname = *strregname;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017834 if (regname == 0 || regname == '@')
17835 regname = '"';
Bram Moolenaar071d4272004-06-13 20:20:40 +000017836
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017837 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017838 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017839 stropt = get_tv_string_chk(&argvars[2]);
17840 if (stropt == NULL)
17841 return; /* type error */
17842 for (; *stropt != NUL; ++stropt)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017843 switch (*stropt)
17844 {
17845 case 'a': case 'A': /* append */
17846 append = TRUE;
17847 break;
17848 case 'v': case 'c': /* character-wise selection */
17849 yank_type = MCHAR;
17850 break;
17851 case 'V': case 'l': /* line-wise selection */
17852 yank_type = MLINE;
17853 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017854 case 'b': case Ctrl_V: /* block-wise selection */
17855 yank_type = MBLOCK;
17856 if (VIM_ISDIGIT(stropt[1]))
17857 {
17858 ++stropt;
17859 block_len = getdigits(&stropt) - 1;
17860 --stropt;
17861 }
17862 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017863 }
17864 }
17865
Bram Moolenaar5a50c222014-04-02 22:17:10 +020017866 if (argvars[1].v_type == VAR_LIST)
17867 {
17868 char_u **lstval;
Bram Moolenaar7d647822014-04-05 21:28:56 +020017869 char_u **allocval;
17870 char_u buf[NUMBUFLEN];
Bram Moolenaar5a50c222014-04-02 22:17:10 +020017871 char_u **curval;
Bram Moolenaar7d647822014-04-05 21:28:56 +020017872 char_u **curallocval;
Bram Moolenaar5a50c222014-04-02 22:17:10 +020017873 int len = argvars[1].vval.v_list->lv_len;
17874 listitem_T *li;
17875
Bram Moolenaar7d647822014-04-05 21:28:56 +020017876 /* First half: use for pointers to result lines; second half: use for
17877 * pointers to allocated copies. */
17878 lstval = (char_u **)alloc(sizeof(char_u *) * ((len + 1) * 2));
Bram Moolenaar5a50c222014-04-02 22:17:10 +020017879 if (lstval == NULL)
17880 return;
17881 curval = lstval;
Bram Moolenaar7d647822014-04-05 21:28:56 +020017882 allocval = lstval + len + 2;
17883 curallocval = allocval;
Bram Moolenaar5a50c222014-04-02 22:17:10 +020017884
17885 for (li = argvars[1].vval.v_list->lv_first; li != NULL;
17886 li = li->li_next)
17887 {
Bram Moolenaar7d647822014-04-05 21:28:56 +020017888 strval = get_tv_string_buf_chk(&li->li_tv, buf);
Bram Moolenaar5a50c222014-04-02 22:17:10 +020017889 if (strval == NULL)
Bram Moolenaar7d647822014-04-05 21:28:56 +020017890 goto free_lstval;
17891 if (strval == buf)
Bram Moolenaar5a50c222014-04-02 22:17:10 +020017892 {
Bram Moolenaar7d647822014-04-05 21:28:56 +020017893 /* Need to make a copy, next get_tv_string_buf_chk() will
17894 * overwrite the string. */
17895 strval = vim_strsave(buf);
17896 if (strval == NULL)
17897 goto free_lstval;
17898 *curallocval++ = strval;
Bram Moolenaar5a50c222014-04-02 22:17:10 +020017899 }
17900 *curval++ = strval;
17901 }
17902 *curval++ = NULL;
17903
17904 write_reg_contents_lst(regname, lstval, -1,
17905 append, yank_type, block_len);
Bram Moolenaar7d647822014-04-05 21:28:56 +020017906free_lstval:
17907 while (curallocval > allocval)
17908 vim_free(*--curallocval);
Bram Moolenaar5a50c222014-04-02 22:17:10 +020017909 vim_free(lstval);
17910 }
17911 else
17912 {
17913 strval = get_tv_string_chk(&argvars[1]);
17914 if (strval == NULL)
17915 return;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017916 write_reg_contents_ex(regname, strval, -1,
Bram Moolenaar071d4272004-06-13 20:20:40 +000017917 append, yank_type, block_len);
Bram Moolenaar5a50c222014-04-02 22:17:10 +020017918 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017919 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017920}
17921
Bram Moolenaar99ebf042006-04-15 20:28:54 +000017922/*
Bram Moolenaar06b5d512010-05-22 15:37:44 +020017923 * "settabvar()" function
17924 */
17925 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017926f_settabvar(typval_T *argvars, typval_T *rettv)
Bram Moolenaar06b5d512010-05-22 15:37:44 +020017927{
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020017928#ifdef FEAT_WINDOWS
Bram Moolenaar06b5d512010-05-22 15:37:44 +020017929 tabpage_T *save_curtab;
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020017930 tabpage_T *tp;
17931#endif
Bram Moolenaar06b5d512010-05-22 15:37:44 +020017932 char_u *varname, *tabvarname;
17933 typval_T *varp;
Bram Moolenaar06b5d512010-05-22 15:37:44 +020017934
17935 rettv->vval.v_number = 0;
17936
17937 if (check_restricted() || check_secure())
17938 return;
17939
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020017940#ifdef FEAT_WINDOWS
Bram Moolenaar06b5d512010-05-22 15:37:44 +020017941 tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL));
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020017942#endif
Bram Moolenaar06b5d512010-05-22 15:37:44 +020017943 varname = get_tv_string_chk(&argvars[1]);
17944 varp = &argvars[2];
17945
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020017946 if (varname != NULL && varp != NULL
17947#ifdef FEAT_WINDOWS
17948 && tp != NULL
17949#endif
17950 )
Bram Moolenaar06b5d512010-05-22 15:37:44 +020017951 {
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020017952#ifdef FEAT_WINDOWS
Bram Moolenaar06b5d512010-05-22 15:37:44 +020017953 save_curtab = curtab;
Bram Moolenaar49e649f2013-05-06 04:50:35 +020017954 goto_tabpage_tp(tp, FALSE, FALSE);
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020017955#endif
Bram Moolenaar06b5d512010-05-22 15:37:44 +020017956
17957 tabvarname = alloc((unsigned)STRLEN(varname) + 3);
17958 if (tabvarname != NULL)
17959 {
17960 STRCPY(tabvarname, "t:");
17961 STRCPY(tabvarname + 2, varname);
17962 set_var(tabvarname, varp, TRUE);
17963 vim_free(tabvarname);
17964 }
17965
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020017966#ifdef FEAT_WINDOWS
Bram Moolenaar06b5d512010-05-22 15:37:44 +020017967 /* Restore current tabpage */
17968 if (valid_tabpage(save_curtab))
Bram Moolenaar49e649f2013-05-06 04:50:35 +020017969 goto_tabpage_tp(save_curtab, FALSE, FALSE);
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020017970#endif
Bram Moolenaar06b5d512010-05-22 15:37:44 +020017971 }
17972}
17973
17974/*
Bram Moolenaar99ebf042006-04-15 20:28:54 +000017975 * "settabwinvar()" function
17976 */
17977 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017978f_settabwinvar(typval_T *argvars, typval_T *rettv)
Bram Moolenaar99ebf042006-04-15 20:28:54 +000017979{
17980 setwinvar(argvars, rettv, 1);
17981}
Bram Moolenaar071d4272004-06-13 20:20:40 +000017982
17983/*
Bram Moolenaar99ebf042006-04-15 20:28:54 +000017984 * "setwinvar()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000017985 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017986 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017987f_setwinvar(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017988{
Bram Moolenaar99ebf042006-04-15 20:28:54 +000017989 setwinvar(argvars, rettv, 0);
17990}
17991
17992/*
17993 * "setwinvar()" and "settabwinvar()" functions
17994 */
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +020017995
Bram Moolenaar99ebf042006-04-15 20:28:54 +000017996 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010017997setwinvar(typval_T *argvars, typval_T *rettv UNUSED, int off)
Bram Moolenaar99ebf042006-04-15 20:28:54 +000017998{
Bram Moolenaar071d4272004-06-13 20:20:40 +000017999 win_T *win;
18000#ifdef FEAT_WINDOWS
18001 win_T *save_curwin;
Bram Moolenaar99ebf042006-04-15 20:28:54 +000018002 tabpage_T *save_curtab;
Bram Moolenaarba117c22015-09-29 16:53:22 +020018003 int need_switch_win;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018004#endif
18005 char_u *varname, *winvarname;
Bram Moolenaar33570922005-01-25 22:26:29 +000018006 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018007 char_u nbuf[NUMBUFLEN];
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020018008 tabpage_T *tp = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018009
18010 if (check_restricted() || check_secure())
18011 return;
Bram Moolenaar99ebf042006-04-15 20:28:54 +000018012
18013#ifdef FEAT_WINDOWS
18014 if (off == 1)
18015 tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL));
18016 else
18017 tp = curtab;
18018#endif
18019 win = find_win_by_nr(&argvars[off], tp);
18020 varname = get_tv_string_chk(&argvars[off + 1]);
18021 varp = &argvars[off + 2];
Bram Moolenaar071d4272004-06-13 20:20:40 +000018022
18023 if (win != NULL && varname != NULL && varp != NULL)
18024 {
18025#ifdef FEAT_WINDOWS
Bram Moolenaarba117c22015-09-29 16:53:22 +020018026 need_switch_win = !(tp == curtab && win == curwin);
18027 if (!need_switch_win
18028 || switch_win(&save_curwin, &save_curtab, win, tp, TRUE) == OK)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018029#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000018030 {
Bram Moolenaar5d2bae82014-09-19 14:26:36 +020018031 if (*varname == '&')
Bram Moolenaar071d4272004-06-13 20:20:40 +000018032 {
Bram Moolenaar5d2bae82014-09-19 14:26:36 +020018033 long numval;
18034 char_u *strval;
18035 int error = FALSE;
18036
18037 ++varname;
18038 numval = get_tv_number_chk(varp, &error);
18039 strval = get_tv_string_buf_chk(varp, nbuf);
18040 if (!error && strval != NULL)
18041 set_option_value(varname, numval, strval, OPT_LOCAL);
18042 }
18043 else
18044 {
18045 winvarname = alloc((unsigned)STRLEN(varname) + 3);
18046 if (winvarname != NULL)
18047 {
18048 STRCPY(winvarname, "w:");
18049 STRCPY(winvarname + 2, varname);
18050 set_var(winvarname, varp, TRUE);
18051 vim_free(winvarname);
18052 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018053 }
18054 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018055#ifdef FEAT_WINDOWS
Bram Moolenaarba117c22015-09-29 16:53:22 +020018056 if (need_switch_win)
18057 restore_win(save_curwin, save_curtab, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018058#endif
18059 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018060}
18061
Bram Moolenaaraf9aeb92013-02-13 17:35:04 +010018062#ifdef FEAT_CRYPT
18063/*
18064 * "sha256({string})" function
18065 */
18066 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018067f_sha256(typval_T *argvars, typval_T *rettv)
Bram Moolenaaraf9aeb92013-02-13 17:35:04 +010018068{
18069 char_u *p;
18070
18071 p = get_tv_string(&argvars[0]);
18072 rettv->vval.v_string = vim_strsave(
18073 sha256_bytes(p, (int)STRLEN(p), NULL, 0));
18074 rettv->v_type = VAR_STRING;
18075}
18076#endif /* FEAT_CRYPT */
18077
Bram Moolenaar071d4272004-06-13 20:20:40 +000018078/*
Bram Moolenaar60a495f2006-10-03 12:44:42 +000018079 * "shellescape({string})" function
18080 */
18081 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018082f_shellescape(typval_T *argvars, typval_T *rettv)
Bram Moolenaar60a495f2006-10-03 12:44:42 +000018083{
Bram Moolenaar05bb9532008-07-04 09:44:11 +000018084 rettv->vval.v_string = vim_strsave_shellescape(
Bram Moolenaar26df0922014-02-23 23:39:13 +010018085 get_tv_string(&argvars[0]), non_zero_arg(&argvars[1]), TRUE);
Bram Moolenaar60a495f2006-10-03 12:44:42 +000018086 rettv->v_type = VAR_STRING;
18087}
18088
18089/*
Bram Moolenaar2d17fa32012-10-21 00:45:18 +020018090 * shiftwidth() function
18091 */
18092 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018093f_shiftwidth(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar2d17fa32012-10-21 00:45:18 +020018094{
Bram Moolenaar6bcbcc52013-11-05 07:13:41 +010018095 rettv->vval.v_number = get_sw_value(curbuf);
Bram Moolenaar2d17fa32012-10-21 00:45:18 +020018096}
18097
18098/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000018099 * "simplify()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000018100 */
18101 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018102f_simplify(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018103{
Bram Moolenaar0d660222005-01-07 21:51:51 +000018104 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018105
Bram Moolenaar0d660222005-01-07 21:51:51 +000018106 p = get_tv_string(&argvars[0]);
18107 rettv->vval.v_string = vim_strsave(p);
18108 simplify_filename(rettv->vval.v_string); /* simplify in place */
18109 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018110}
18111
Bram Moolenaar8c8de832008-06-24 22:58:06 +000018112#ifdef FEAT_FLOAT
18113/*
18114 * "sin()" function
18115 */
18116 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018117f_sin(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8c8de832008-06-24 22:58:06 +000018118{
Bram Moolenaara1e24b92016-02-18 20:18:09 +010018119 float_T f = 0.0;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000018120
18121 rettv->v_type = VAR_FLOAT;
18122 if (get_float_arg(argvars, &f) == OK)
18123 rettv->vval.v_float = sin(f);
18124 else
18125 rettv->vval.v_float = 0.0;
18126}
Bram Moolenaardb7c6862010-05-21 16:33:48 +020018127
18128/*
18129 * "sinh()" function
18130 */
18131 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018132f_sinh(typval_T *argvars, typval_T *rettv)
Bram Moolenaardb7c6862010-05-21 16:33:48 +020018133{
Bram Moolenaara1e24b92016-02-18 20:18:09 +010018134 float_T f = 0.0;
Bram Moolenaardb7c6862010-05-21 16:33:48 +020018135
18136 rettv->v_type = VAR_FLOAT;
18137 if (get_float_arg(argvars, &f) == OK)
18138 rettv->vval.v_float = sinh(f);
18139 else
18140 rettv->vval.v_float = 0.0;
18141}
Bram Moolenaar8c8de832008-06-24 22:58:06 +000018142#endif
18143
Bram Moolenaar0d660222005-01-07 21:51:51 +000018144static int
18145#ifdef __BORLANDC__
18146 _RTLENTRYF
18147#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +010018148 item_compare(const void *s1, const void *s2);
Bram Moolenaar0d660222005-01-07 21:51:51 +000018149static int
18150#ifdef __BORLANDC__
18151 _RTLENTRYF
18152#endif
Bram Moolenaar48e697e2016-01-23 22:17:30 +010018153 item_compare2(const void *s1, const void *s2);
Bram Moolenaar0d660222005-01-07 21:51:51 +000018154
Bram Moolenaar6bf55482014-07-09 17:51:51 +020018155/* struct used in the array that's given to qsort() */
18156typedef struct
18157{
18158 listitem_T *item;
18159 int idx;
18160} sortItem_T;
18161
Bram Moolenaar0b962472016-02-22 22:51:33 +010018162/* struct storing information about current sort */
18163typedef struct
18164{
18165 int item_compare_ic;
18166 int item_compare_numeric;
18167 int item_compare_numbers;
Bram Moolenaarf7edf402016-01-19 23:36:15 +010018168#ifdef FEAT_FLOAT
Bram Moolenaar0b962472016-02-22 22:51:33 +010018169 int item_compare_float;
Bram Moolenaarf7edf402016-01-19 23:36:15 +010018170#endif
Bram Moolenaar0b962472016-02-22 22:51:33 +010018171 char_u *item_compare_func;
18172 dict_T *item_compare_selfdict;
18173 int item_compare_func_err;
18174 int item_compare_keep_zero;
18175} sortinfo_T;
18176static sortinfo_T *sortinfo = NULL;
Bram Moolenaar48e697e2016-01-23 22:17:30 +010018177static void do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort);
Bram Moolenaar0d660222005-01-07 21:51:51 +000018178#define ITEM_COMPARE_FAIL 999
18179
Bram Moolenaar071d4272004-06-13 20:20:40 +000018180/*
Bram Moolenaar327aa022014-03-25 18:24:23 +010018181 * Compare functions for f_sort() and f_uniq() below.
Bram Moolenaar071d4272004-06-13 20:20:40 +000018182 */
Bram Moolenaar0d660222005-01-07 21:51:51 +000018183 static int
18184#ifdef __BORLANDC__
18185_RTLENTRYF
18186#endif
Bram Moolenaar7454a062016-01-30 15:14:10 +010018187item_compare(const void *s1, const void *s2)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018188{
Bram Moolenaar6bf55482014-07-09 17:51:51 +020018189 sortItem_T *si1, *si2;
Bram Moolenaar1b338d22014-08-22 13:13:27 +020018190 typval_T *tv1, *tv2;
Bram Moolenaar0d660222005-01-07 21:51:51 +000018191 char_u *p1, *p2;
Bram Moolenaar1b338d22014-08-22 13:13:27 +020018192 char_u *tofree1 = NULL, *tofree2 = NULL;
Bram Moolenaar0d660222005-01-07 21:51:51 +000018193 int res;
18194 char_u numbuf1[NUMBUFLEN];
18195 char_u numbuf2[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000018196
Bram Moolenaar6bf55482014-07-09 17:51:51 +020018197 si1 = (sortItem_T *)s1;
18198 si2 = (sortItem_T *)s2;
Bram Moolenaar1b338d22014-08-22 13:13:27 +020018199 tv1 = &si1->item->li_tv;
18200 tv2 = &si2->item->li_tv;
Bram Moolenaarb00da1d2015-12-03 16:33:12 +010018201
Bram Moolenaar0b962472016-02-22 22:51:33 +010018202 if (sortinfo->item_compare_numbers)
Bram Moolenaarb00da1d2015-12-03 16:33:12 +010018203 {
18204 long v1 = get_tv_number(tv1);
18205 long v2 = get_tv_number(tv2);
18206
18207 return v1 == v2 ? 0 : v1 > v2 ? 1 : -1;
18208 }
18209
Bram Moolenaarf7edf402016-01-19 23:36:15 +010018210#ifdef FEAT_FLOAT
Bram Moolenaar0b962472016-02-22 22:51:33 +010018211 if (sortinfo->item_compare_float)
Bram Moolenaarf7edf402016-01-19 23:36:15 +010018212 {
18213 float_T v1 = get_tv_float(tv1);
18214 float_T v2 = get_tv_float(tv2);
18215
18216 return v1 == v2 ? 0 : v1 > v2 ? 1 : -1;
18217 }
18218#endif
18219
Bram Moolenaar1b338d22014-08-22 13:13:27 +020018220 /* tv2string() puts quotes around a string and allocates memory. Don't do
18221 * that for string variables. Use a single quote when comparing with a
18222 * non-string to do what the docs promise. */
18223 if (tv1->v_type == VAR_STRING)
18224 {
Bram Moolenaar0b962472016-02-22 22:51:33 +010018225 if (tv2->v_type != VAR_STRING || sortinfo->item_compare_numeric)
Bram Moolenaar1b338d22014-08-22 13:13:27 +020018226 p1 = (char_u *)"'";
18227 else
18228 p1 = tv1->vval.v_string;
18229 }
18230 else
18231 p1 = tv2string(tv1, &tofree1, numbuf1, 0);
18232 if (tv2->v_type == VAR_STRING)
18233 {
Bram Moolenaar0b962472016-02-22 22:51:33 +010018234 if (tv1->v_type != VAR_STRING || sortinfo->item_compare_numeric)
Bram Moolenaar1b338d22014-08-22 13:13:27 +020018235 p2 = (char_u *)"'";
18236 else
18237 p2 = tv2->vval.v_string;
18238 }
18239 else
18240 p2 = tv2string(tv2, &tofree2, numbuf2, 0);
Bram Moolenaar92c5aba2007-08-14 20:29:31 +000018241 if (p1 == NULL)
18242 p1 = (char_u *)"";
18243 if (p2 == NULL)
18244 p2 = (char_u *)"";
Bram Moolenaar0b962472016-02-22 22:51:33 +010018245 if (!sortinfo->item_compare_numeric)
Bram Moolenaare8a34922014-06-25 17:31:09 +020018246 {
Bram Moolenaar0b962472016-02-22 22:51:33 +010018247 if (sortinfo->item_compare_ic)
Bram Moolenaare8a34922014-06-25 17:31:09 +020018248 res = STRICMP(p1, p2);
18249 else
18250 res = STRCMP(p1, p2);
18251 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018252 else
Bram Moolenaare8a34922014-06-25 17:31:09 +020018253 {
18254 double n1, n2;
18255 n1 = strtod((char *)p1, (char **)&p1);
18256 n2 = strtod((char *)p2, (char **)&p2);
18257 res = n1 == n2 ? 0 : n1 > n2 ? 1 : -1;
18258 }
Bram Moolenaarc35e3de2014-07-02 19:06:18 +020018259
Bram Moolenaar1b338d22014-08-22 13:13:27 +020018260 /* When the result would be zero, compare the item indexes. Makes the
18261 * sort stable. */
Bram Moolenaar0b962472016-02-22 22:51:33 +010018262 if (res == 0 && !sortinfo->item_compare_keep_zero)
Bram Moolenaar6bf55482014-07-09 17:51:51 +020018263 res = si1->idx > si2->idx ? 1 : -1;
Bram Moolenaarc35e3de2014-07-02 19:06:18 +020018264
Bram Moolenaar0d660222005-01-07 21:51:51 +000018265 vim_free(tofree1);
18266 vim_free(tofree2);
18267 return res;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018268}
18269
18270 static int
Bram Moolenaar0d660222005-01-07 21:51:51 +000018271#ifdef __BORLANDC__
18272_RTLENTRYF
Bram Moolenaar071d4272004-06-13 20:20:40 +000018273#endif
Bram Moolenaar7454a062016-01-30 15:14:10 +010018274item_compare2(const void *s1, const void *s2)
Bram Moolenaar0d660222005-01-07 21:51:51 +000018275{
Bram Moolenaar6bf55482014-07-09 17:51:51 +020018276 sortItem_T *si1, *si2;
Bram Moolenaar0d660222005-01-07 21:51:51 +000018277 int res;
Bram Moolenaar33570922005-01-25 22:26:29 +000018278 typval_T rettv;
Bram Moolenaareb3593b2006-04-22 22:33:57 +000018279 typval_T argv[3];
Bram Moolenaar0d660222005-01-07 21:51:51 +000018280 int dummy;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018281
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018282 /* shortcut after failure in previous call; compare all items equal */
Bram Moolenaar0b962472016-02-22 22:51:33 +010018283 if (sortinfo->item_compare_func_err)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018284 return 0;
18285
Bram Moolenaar6bf55482014-07-09 17:51:51 +020018286 si1 = (sortItem_T *)s1;
18287 si2 = (sortItem_T *)s2;
18288
Bram Moolenaarc35e3de2014-07-02 19:06:18 +020018289 /* Copy the values. This is needed to be able to set v_lock to VAR_FIXED
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000018290 * in the copy without changing the original list items. */
Bram Moolenaar6bf55482014-07-09 17:51:51 +020018291 copy_tv(&si1->item->li_tv, &argv[0]);
18292 copy_tv(&si2->item->li_tv, &argv[1]);
Bram Moolenaar0d660222005-01-07 21:51:51 +000018293
18294 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
Bram Moolenaar0b962472016-02-22 22:51:33 +010018295 res = call_func(sortinfo->item_compare_func,
Bram Moolenaar4e221c92016-02-23 13:20:22 +010018296 (int)STRLEN(sortinfo->item_compare_func),
Bram Moolenaar5f894962011-06-19 02:55:37 +020018297 &rettv, 2, argv, 0L, 0L, &dummy, TRUE,
Bram Moolenaar0b962472016-02-22 22:51:33 +010018298 sortinfo->item_compare_selfdict);
Bram Moolenaar0d660222005-01-07 21:51:51 +000018299 clear_tv(&argv[0]);
18300 clear_tv(&argv[1]);
18301
18302 if (res == FAIL)
18303 res = ITEM_COMPARE_FAIL;
18304 else
Bram Moolenaar0b962472016-02-22 22:51:33 +010018305 res = get_tv_number_chk(&rettv, &sortinfo->item_compare_func_err);
18306 if (sortinfo->item_compare_func_err)
Bram Moolenaar61c4e2c2008-08-25 02:49:18 +000018307 res = ITEM_COMPARE_FAIL; /* return value has wrong type */
Bram Moolenaar0d660222005-01-07 21:51:51 +000018308 clear_tv(&rettv);
Bram Moolenaarc35e3de2014-07-02 19:06:18 +020018309
18310 /* When the result would be zero, compare the pointers themselves. Makes
18311 * the sort stable. */
Bram Moolenaar0b962472016-02-22 22:51:33 +010018312 if (res == 0 && !sortinfo->item_compare_keep_zero)
Bram Moolenaar6bf55482014-07-09 17:51:51 +020018313 res = si1->idx > si2->idx ? 1 : -1;
Bram Moolenaarc35e3de2014-07-02 19:06:18 +020018314
Bram Moolenaar0d660222005-01-07 21:51:51 +000018315 return res;
18316}
18317
18318/*
18319 * "sort({list})" function
18320 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018321 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018322do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018323{
Bram Moolenaar33570922005-01-25 22:26:29 +000018324 list_T *l;
18325 listitem_T *li;
Bram Moolenaar6bf55482014-07-09 17:51:51 +020018326 sortItem_T *ptrs;
Bram Moolenaar0b962472016-02-22 22:51:33 +010018327 sortinfo_T *old_sortinfo;
18328 sortinfo_T info;
Bram Moolenaar0d660222005-01-07 21:51:51 +000018329 long len;
18330 long i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018331
Bram Moolenaar0b962472016-02-22 22:51:33 +010018332 /* Pointer to current info struct used in compare function. Save and
18333 * restore the current one for nested calls. */
18334 old_sortinfo = sortinfo;
18335 sortinfo = &info;
18336
Bram Moolenaar0d660222005-01-07 21:51:51 +000018337 if (argvars[0].v_type != VAR_LIST)
Bram Moolenaar327aa022014-03-25 18:24:23 +010018338 EMSG2(_(e_listarg), sort ? "sort()" : "uniq()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000018339 else
18340 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000018341 l = argvars[0].vval.v_list;
Bram Moolenaar32f649e2011-04-11 13:46:13 +020018342 if (l == NULL || tv_check_lock(l->lv_lock,
Bram Moolenaar77354e72015-04-21 16:49:05 +020018343 (char_u *)(sort ? N_("sort() argument") : N_("uniq() argument")),
18344 TRUE))
Bram Moolenaar0b962472016-02-22 22:51:33 +010018345 goto theend;
Bram Moolenaar0d660222005-01-07 21:51:51 +000018346 rettv->vval.v_list = l;
18347 rettv->v_type = VAR_LIST;
18348 ++l->lv_refcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018349
Bram Moolenaar0d660222005-01-07 21:51:51 +000018350 len = list_len(l);
18351 if (len <= 1)
Bram Moolenaar0b962472016-02-22 22:51:33 +010018352 goto theend; /* short list sorts pretty quickly */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018353
Bram Moolenaar0b962472016-02-22 22:51:33 +010018354 info.item_compare_ic = FALSE;
18355 info.item_compare_numeric = FALSE;
18356 info.item_compare_numbers = FALSE;
Bram Moolenaarf7edf402016-01-19 23:36:15 +010018357#ifdef FEAT_FLOAT
Bram Moolenaar0b962472016-02-22 22:51:33 +010018358 info.item_compare_float = FALSE;
Bram Moolenaarf7edf402016-01-19 23:36:15 +010018359#endif
Bram Moolenaar0b962472016-02-22 22:51:33 +010018360 info.item_compare_func = NULL;
18361 info.item_compare_selfdict = NULL;
Bram Moolenaar0d660222005-01-07 21:51:51 +000018362 if (argvars[1].v_type != VAR_UNKNOWN)
18363 {
Bram Moolenaar5f894962011-06-19 02:55:37 +020018364 /* optional second argument: {func} */
Bram Moolenaar0d660222005-01-07 21:51:51 +000018365 if (argvars[1].v_type == VAR_FUNC)
Bram Moolenaar0b962472016-02-22 22:51:33 +010018366 info.item_compare_func = argvars[1].vval.v_string;
Bram Moolenaar0d660222005-01-07 21:51:51 +000018367 else
18368 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018369 int error = FALSE;
18370
18371 i = get_tv_number_chk(&argvars[1], &error);
18372 if (error)
Bram Moolenaar0b962472016-02-22 22:51:33 +010018373 goto theend; /* type error; errmsg already given */
Bram Moolenaar0d660222005-01-07 21:51:51 +000018374 if (i == 1)
Bram Moolenaar0b962472016-02-22 22:51:33 +010018375 info.item_compare_ic = TRUE;
Bram Moolenaar5131c142016-02-29 22:05:26 +010018376 else if (argvars[1].v_type != VAR_NUMBER)
Bram Moolenaar0b962472016-02-22 22:51:33 +010018377 info.item_compare_func = get_tv_string(&argvars[1]);
Bram Moolenaar5131c142016-02-29 22:05:26 +010018378 else if (i != 0)
18379 {
18380 EMSG(_(e_invarg));
18381 goto theend;
18382 }
Bram Moolenaar0b962472016-02-22 22:51:33 +010018383 if (info.item_compare_func != NULL)
Bram Moolenaare8a34922014-06-25 17:31:09 +020018384 {
Bram Moolenaar5131c142016-02-29 22:05:26 +010018385 if (*info.item_compare_func == NUL)
18386 {
18387 /* empty string means default sort */
18388 info.item_compare_func = NULL;
18389 }
18390 else if (STRCMP(info.item_compare_func, "n") == 0)
Bram Moolenaare8a34922014-06-25 17:31:09 +020018391 {
Bram Moolenaar0b962472016-02-22 22:51:33 +010018392 info.item_compare_func = NULL;
18393 info.item_compare_numeric = TRUE;
Bram Moolenaare8a34922014-06-25 17:31:09 +020018394 }
Bram Moolenaar0b962472016-02-22 22:51:33 +010018395 else if (STRCMP(info.item_compare_func, "N") == 0)
Bram Moolenaarb00da1d2015-12-03 16:33:12 +010018396 {
Bram Moolenaar0b962472016-02-22 22:51:33 +010018397 info.item_compare_func = NULL;
18398 info.item_compare_numbers = TRUE;
Bram Moolenaarb00da1d2015-12-03 16:33:12 +010018399 }
Bram Moolenaarf7edf402016-01-19 23:36:15 +010018400#ifdef FEAT_FLOAT
Bram Moolenaar0b962472016-02-22 22:51:33 +010018401 else if (STRCMP(info.item_compare_func, "f") == 0)
Bram Moolenaarf7edf402016-01-19 23:36:15 +010018402 {
Bram Moolenaar0b962472016-02-22 22:51:33 +010018403 info.item_compare_func = NULL;
18404 info.item_compare_float = TRUE;
Bram Moolenaarf7edf402016-01-19 23:36:15 +010018405 }
18406#endif
Bram Moolenaar0b962472016-02-22 22:51:33 +010018407 else if (STRCMP(info.item_compare_func, "i") == 0)
Bram Moolenaare8a34922014-06-25 17:31:09 +020018408 {
Bram Moolenaar0b962472016-02-22 22:51:33 +010018409 info.item_compare_func = NULL;
18410 info.item_compare_ic = TRUE;
Bram Moolenaare8a34922014-06-25 17:31:09 +020018411 }
18412 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000018413 }
Bram Moolenaar5f894962011-06-19 02:55:37 +020018414
18415 if (argvars[2].v_type != VAR_UNKNOWN)
18416 {
18417 /* optional third argument: {dict} */
18418 if (argvars[2].v_type != VAR_DICT)
18419 {
18420 EMSG(_(e_dictreq));
Bram Moolenaar0b962472016-02-22 22:51:33 +010018421 goto theend;
Bram Moolenaar5f894962011-06-19 02:55:37 +020018422 }
Bram Moolenaar0b962472016-02-22 22:51:33 +010018423 info.item_compare_selfdict = argvars[2].vval.v_dict;
Bram Moolenaar5f894962011-06-19 02:55:37 +020018424 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000018425 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018426
Bram Moolenaar0d660222005-01-07 21:51:51 +000018427 /* Make an array with each entry pointing to an item in the List. */
Bram Moolenaar6bf55482014-07-09 17:51:51 +020018428 ptrs = (sortItem_T *)alloc((int)(len * sizeof(sortItem_T)));
Bram Moolenaar0d660222005-01-07 21:51:51 +000018429 if (ptrs == NULL)
Bram Moolenaar0b962472016-02-22 22:51:33 +010018430 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018431
Bram Moolenaar327aa022014-03-25 18:24:23 +010018432 i = 0;
18433 if (sort)
18434 {
18435 /* sort(): ptrs will be the list to sort */
18436 for (li = l->lv_first; li != NULL; li = li->li_next)
Bram Moolenaar6bf55482014-07-09 17:51:51 +020018437 {
18438 ptrs[i].item = li;
18439 ptrs[i].idx = i;
18440 ++i;
18441 }
Bram Moolenaar327aa022014-03-25 18:24:23 +010018442
Bram Moolenaar0b962472016-02-22 22:51:33 +010018443 info.item_compare_func_err = FALSE;
18444 info.item_compare_keep_zero = FALSE;
Bram Moolenaar327aa022014-03-25 18:24:23 +010018445 /* test the compare function */
Bram Moolenaar0b962472016-02-22 22:51:33 +010018446 if (info.item_compare_func != NULL
Bram Moolenaar327aa022014-03-25 18:24:23 +010018447 && item_compare2((void *)&ptrs[0], (void *)&ptrs[1])
Bram Moolenaar0d660222005-01-07 21:51:51 +000018448 == ITEM_COMPARE_FAIL)
Bram Moolenaar327aa022014-03-25 18:24:23 +010018449 EMSG(_("E702: Sort compare function failed"));
18450 else
18451 {
18452 /* Sort the array with item pointers. */
Bram Moolenaar6bf55482014-07-09 17:51:51 +020018453 qsort((void *)ptrs, (size_t)len, sizeof(sortItem_T),
Bram Moolenaar0b962472016-02-22 22:51:33 +010018454 info.item_compare_func == NULL
18455 ? item_compare : item_compare2);
Bram Moolenaar327aa022014-03-25 18:24:23 +010018456
Bram Moolenaar0b962472016-02-22 22:51:33 +010018457 if (!info.item_compare_func_err)
Bram Moolenaar327aa022014-03-25 18:24:23 +010018458 {
18459 /* Clear the List and append the items in sorted order. */
18460 l->lv_first = l->lv_last = l->lv_idx_item = NULL;
18461 l->lv_len = 0;
18462 for (i = 0; i < len; ++i)
Bram Moolenaar6bf55482014-07-09 17:51:51 +020018463 list_append(l, ptrs[i].item);
Bram Moolenaar327aa022014-03-25 18:24:23 +010018464 }
18465 }
18466 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018467 else
Bram Moolenaar0d660222005-01-07 21:51:51 +000018468 {
Bram Moolenaar48e697e2016-01-23 22:17:30 +010018469 int (*item_compare_func_ptr)(const void *, const void *);
Bram Moolenaar327aa022014-03-25 18:24:23 +010018470
18471 /* f_uniq(): ptrs will be a stack of items to remove */
Bram Moolenaar0b962472016-02-22 22:51:33 +010018472 info.item_compare_func_err = FALSE;
18473 info.item_compare_keep_zero = TRUE;
18474 item_compare_func_ptr = info.item_compare_func
Bram Moolenaar327aa022014-03-25 18:24:23 +010018475 ? item_compare2 : item_compare;
18476
18477 for (li = l->lv_first; li != NULL && li->li_next != NULL;
18478 li = li->li_next)
18479 {
18480 if (item_compare_func_ptr((void *)&li, (void *)&li->li_next)
18481 == 0)
Bram Moolenaar6bf55482014-07-09 17:51:51 +020018482 ptrs[i++].item = li;
Bram Moolenaar0b962472016-02-22 22:51:33 +010018483 if (info.item_compare_func_err)
Bram Moolenaar327aa022014-03-25 18:24:23 +010018484 {
18485 EMSG(_("E882: Uniq compare function failed"));
18486 break;
18487 }
18488 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000018489
Bram Moolenaar0b962472016-02-22 22:51:33 +010018490 if (!info.item_compare_func_err)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018491 {
Bram Moolenaar327aa022014-03-25 18:24:23 +010018492 while (--i >= 0)
18493 {
Bram Moolenaar6bf55482014-07-09 17:51:51 +020018494 li = ptrs[i].item->li_next;
18495 ptrs[i].item->li_next = li->li_next;
Bram Moolenaar327aa022014-03-25 18:24:23 +010018496 if (li->li_next != NULL)
Bram Moolenaar6bf55482014-07-09 17:51:51 +020018497 li->li_next->li_prev = ptrs[i].item;
Bram Moolenaar327aa022014-03-25 18:24:23 +010018498 else
Bram Moolenaar6bf55482014-07-09 17:51:51 +020018499 l->lv_last = ptrs[i].item;
Bram Moolenaar327aa022014-03-25 18:24:23 +010018500 list_fix_watch(l, li);
18501 listitem_free(li);
18502 l->lv_len--;
18503 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018504 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000018505 }
18506
18507 vim_free(ptrs);
18508 }
Bram Moolenaar0b962472016-02-22 22:51:33 +010018509theend:
18510 sortinfo = old_sortinfo;
Bram Moolenaar0d660222005-01-07 21:51:51 +000018511}
18512
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018513/*
Bram Moolenaar327aa022014-03-25 18:24:23 +010018514 * "sort({list})" function
18515 */
18516 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018517f_sort(typval_T *argvars, typval_T *rettv)
Bram Moolenaar327aa022014-03-25 18:24:23 +010018518{
18519 do_sort_uniq(argvars, rettv, TRUE);
18520}
18521
18522/*
18523 * "uniq({list})" function
18524 */
18525 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018526f_uniq(typval_T *argvars, typval_T *rettv)
Bram Moolenaar327aa022014-03-25 18:24:23 +010018527{
18528 do_sort_uniq(argvars, rettv, FALSE);
18529}
18530
18531/*
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +000018532 * "soundfold({word})" function
18533 */
18534 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018535f_soundfold(typval_T *argvars, typval_T *rettv)
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +000018536{
18537 char_u *s;
18538
18539 rettv->v_type = VAR_STRING;
18540 s = get_tv_string(&argvars[0]);
Bram Moolenaar3c56a962006-03-12 22:19:04 +000018541#ifdef FEAT_SPELL
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +000018542 rettv->vval.v_string = eval_soundfold(s);
18543#else
18544 rettv->vval.v_string = vim_strsave(s);
18545#endif
18546}
18547
18548/*
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018549 * "spellbadword()" function
18550 */
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018551 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018552f_spellbadword(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018553{
Bram Moolenaar4463f292005-09-25 22:20:24 +000018554 char_u *word = (char_u *)"";
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000018555 hlf_T attr = HLF_COUNT;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000018556 int len = 0;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018557
Bram Moolenaareddf53b2006-02-27 00:11:10 +000018558 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar4463f292005-09-25 22:20:24 +000018559 return;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018560
Bram Moolenaar3c56a962006-03-12 22:19:04 +000018561#ifdef FEAT_SPELL
Bram Moolenaar4463f292005-09-25 22:20:24 +000018562 if (argvars[0].v_type == VAR_UNKNOWN)
18563 {
18564 /* Find the start and length of the badly spelled word. */
18565 len = spell_move_to(curwin, FORWARD, TRUE, TRUE, &attr);
18566 if (len != 0)
18567 word = ml_get_cursor();
18568 }
Bram Moolenaar860cae12010-06-05 23:22:07 +020018569 else if (curwin->w_p_spell && *curbuf->b_s.b_p_spl != NUL)
Bram Moolenaar4463f292005-09-25 22:20:24 +000018570 {
18571 char_u *str = get_tv_string_chk(&argvars[0]);
18572 int capcol = -1;
18573
18574 if (str != NULL)
18575 {
18576 /* Check the argument for spelling. */
18577 while (*str != NUL)
18578 {
Bram Moolenaar4770d092006-01-12 23:22:24 +000018579 len = spell_check(curwin, str, &attr, &capcol, FALSE);
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000018580 if (attr != HLF_COUNT)
Bram Moolenaar4463f292005-09-25 22:20:24 +000018581 {
18582 word = str;
18583 break;
18584 }
18585 str += len;
18586 }
18587 }
18588 }
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018589#endif
Bram Moolenaar4463f292005-09-25 22:20:24 +000018590
Bram Moolenaareddf53b2006-02-27 00:11:10 +000018591 list_append_string(rettv->vval.v_list, word, len);
18592 list_append_string(rettv->vval.v_list, (char_u *)(
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000018593 attr == HLF_SPB ? "bad" :
18594 attr == HLF_SPR ? "rare" :
18595 attr == HLF_SPL ? "local" :
18596 attr == HLF_SPC ? "caps" :
18597 ""), -1);
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018598}
18599
18600/*
18601 * "spellsuggest()" function
18602 */
18603 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018604f_spellsuggest(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018605{
Bram Moolenaar3c56a962006-03-12 22:19:04 +000018606#ifdef FEAT_SPELL
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018607 char_u *str;
Bram Moolenaar69e0ff92005-09-30 21:23:56 +000018608 int typeerr = FALSE;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018609 int maxcount;
18610 garray_T ga;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018611 int i;
Bram Moolenaar69e0ff92005-09-30 21:23:56 +000018612 listitem_T *li;
18613 int need_capital = FALSE;
18614#endif
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018615
Bram Moolenaareddf53b2006-02-27 00:11:10 +000018616 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018617 return;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018618
Bram Moolenaar3c56a962006-03-12 22:19:04 +000018619#ifdef FEAT_SPELL
Bram Moolenaar860cae12010-06-05 23:22:07 +020018620 if (curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL)
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018621 {
18622 str = get_tv_string(&argvars[0]);
18623 if (argvars[1].v_type != VAR_UNKNOWN)
18624 {
Bram Moolenaar69e0ff92005-09-30 21:23:56 +000018625 maxcount = get_tv_number_chk(&argvars[1], &typeerr);
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018626 if (maxcount <= 0)
18627 return;
Bram Moolenaar69e0ff92005-09-30 21:23:56 +000018628 if (argvars[2].v_type != VAR_UNKNOWN)
18629 {
18630 need_capital = get_tv_number_chk(&argvars[2], &typeerr);
18631 if (typeerr)
18632 return;
18633 }
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018634 }
18635 else
18636 maxcount = 25;
18637
Bram Moolenaar4770d092006-01-12 23:22:24 +000018638 spell_suggest_list(&ga, str, maxcount, need_capital, FALSE);
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018639
18640 for (i = 0; i < ga.ga_len; ++i)
18641 {
18642 str = ((char_u **)ga.ga_data)[i];
18643
18644 li = listitem_alloc();
18645 if (li == NULL)
18646 vim_free(str);
18647 else
18648 {
18649 li->li_tv.v_type = VAR_STRING;
18650 li->li_tv.v_lock = 0;
18651 li->li_tv.vval.v_string = str;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000018652 list_append(rettv->vval.v_list, li);
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018653 }
18654 }
18655 ga_clear(&ga);
18656 }
18657#endif
18658}
18659
Bram Moolenaar0d660222005-01-07 21:51:51 +000018660 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018661f_split(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000018662{
18663 char_u *str;
18664 char_u *end;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000018665 char_u *pat = NULL;
Bram Moolenaar0d660222005-01-07 21:51:51 +000018666 regmatch_T regmatch;
18667 char_u patbuf[NUMBUFLEN];
18668 char_u *save_cpo;
18669 int match;
Bram Moolenaar0d660222005-01-07 21:51:51 +000018670 colnr_T col = 0;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000018671 int keepempty = FALSE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018672 int typeerr = FALSE;
Bram Moolenaar0d660222005-01-07 21:51:51 +000018673
18674 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
18675 save_cpo = p_cpo;
18676 p_cpo = (char_u *)"";
18677
18678 str = get_tv_string(&argvars[0]);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000018679 if (argvars[1].v_type != VAR_UNKNOWN)
18680 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018681 pat = get_tv_string_buf_chk(&argvars[1], patbuf);
18682 if (pat == NULL)
18683 typeerr = TRUE;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000018684 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018685 keepempty = get_tv_number_chk(&argvars[2], &typeerr);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000018686 }
18687 if (pat == NULL || *pat == NUL)
18688 pat = (char_u *)"[\\x01- ]\\+";
Bram Moolenaar0d660222005-01-07 21:51:51 +000018689
Bram Moolenaareddf53b2006-02-27 00:11:10 +000018690 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018691 return;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018692 if (typeerr)
18693 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018694
Bram Moolenaar0d660222005-01-07 21:51:51 +000018695 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
18696 if (regmatch.regprog != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018697 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000018698 regmatch.rm_ic = FALSE;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000018699 while (*str != NUL || keepempty)
Bram Moolenaar0d660222005-01-07 21:51:51 +000018700 {
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000018701 if (*str == NUL)
18702 match = FALSE; /* empty item at the end */
18703 else
18704 match = vim_regexec_nl(&regmatch, str, col);
Bram Moolenaar0d660222005-01-07 21:51:51 +000018705 if (match)
18706 end = regmatch.startp[0];
18707 else
18708 end = str + STRLEN(str);
Bram Moolenaareddf53b2006-02-27 00:11:10 +000018709 if (keepempty || end > str || (rettv->vval.v_list->lv_len > 0
18710 && *str != NUL && match && end < regmatch.endp[0]))
Bram Moolenaar0d660222005-01-07 21:51:51 +000018711 {
Bram Moolenaareddf53b2006-02-27 00:11:10 +000018712 if (list_append_string(rettv->vval.v_list, str,
18713 (int)(end - str)) == FAIL)
Bram Moolenaar0d660222005-01-07 21:51:51 +000018714 break;
Bram Moolenaar0d660222005-01-07 21:51:51 +000018715 }
18716 if (!match)
18717 break;
18718 /* Advance to just after the match. */
18719 if (regmatch.endp[0] > str)
18720 col = 0;
18721 else
18722 {
18723 /* Don't get stuck at the same match. */
18724#ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000018725 col = (*mb_ptr2len)(regmatch.endp[0]);
Bram Moolenaar0d660222005-01-07 21:51:51 +000018726#else
18727 col = 1;
18728#endif
18729 }
18730 str = regmatch.endp[0];
18731 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018732
Bram Moolenaar473de612013-06-08 18:19:48 +020018733 vim_regfree(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018734 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018735
Bram Moolenaar0d660222005-01-07 21:51:51 +000018736 p_cpo = save_cpo;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018737}
18738
Bram Moolenaar8c8de832008-06-24 22:58:06 +000018739#ifdef FEAT_FLOAT
18740/*
18741 * "sqrt()" function
18742 */
18743 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018744f_sqrt(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8c8de832008-06-24 22:58:06 +000018745{
Bram Moolenaara1e24b92016-02-18 20:18:09 +010018746 float_T f = 0.0;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000018747
18748 rettv->v_type = VAR_FLOAT;
18749 if (get_float_arg(argvars, &f) == OK)
18750 rettv->vval.v_float = sqrt(f);
18751 else
18752 rettv->vval.v_float = 0.0;
18753}
18754
18755/*
18756 * "str2float()" function
18757 */
18758 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018759f_str2float(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8c8de832008-06-24 22:58:06 +000018760{
18761 char_u *p = skipwhite(get_tv_string(&argvars[0]));
18762
18763 if (*p == '+')
18764 p = skipwhite(p + 1);
18765 (void)string2float(p, &rettv->vval.v_float);
18766 rettv->v_type = VAR_FLOAT;
18767}
18768#endif
18769
Bram Moolenaar2c932302006-03-18 21:42:09 +000018770/*
18771 * "str2nr()" function
18772 */
18773 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018774f_str2nr(typval_T *argvars, typval_T *rettv)
Bram Moolenaar2c932302006-03-18 21:42:09 +000018775{
18776 int base = 10;
18777 char_u *p;
18778 long n;
Bram Moolenaar887c1fe2016-01-02 17:56:35 +010018779 int what;
Bram Moolenaar2c932302006-03-18 21:42:09 +000018780
18781 if (argvars[1].v_type != VAR_UNKNOWN)
18782 {
18783 base = get_tv_number(&argvars[1]);
Bram Moolenaar887c1fe2016-01-02 17:56:35 +010018784 if (base != 2 && base != 8 && base != 10 && base != 16)
Bram Moolenaar2c932302006-03-18 21:42:09 +000018785 {
18786 EMSG(_(e_invarg));
18787 return;
18788 }
18789 }
18790
18791 p = skipwhite(get_tv_string(&argvars[0]));
Bram Moolenaar8c8de832008-06-24 22:58:06 +000018792 if (*p == '+')
18793 p = skipwhite(p + 1);
Bram Moolenaar887c1fe2016-01-02 17:56:35 +010018794 switch (base)
18795 {
18796 case 2: what = STR2NR_BIN + STR2NR_FORCE; break;
18797 case 8: what = STR2NR_OCT + STR2NR_FORCE; break;
18798 case 16: what = STR2NR_HEX + STR2NR_FORCE; break;
18799 default: what = 0;
18800 }
18801 vim_str2nr(p, NULL, NULL, what, &n, NULL, 0);
Bram Moolenaar2c932302006-03-18 21:42:09 +000018802 rettv->vval.v_number = n;
18803}
18804
Bram Moolenaar071d4272004-06-13 20:20:40 +000018805#ifdef HAVE_STRFTIME
18806/*
18807 * "strftime({format}[, {time}])" function
18808 */
18809 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018810f_strftime(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018811{
18812 char_u result_buf[256];
18813 struct tm *curtime;
18814 time_t seconds;
18815 char_u *p;
18816
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018817 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018818
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018819 p = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000018820 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018821 seconds = time(NULL);
18822 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018823 seconds = (time_t)get_tv_number(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018824 curtime = localtime(&seconds);
18825 /* MSVC returns NULL for an invalid value of seconds. */
18826 if (curtime == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018827 rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
Bram Moolenaar071d4272004-06-13 20:20:40 +000018828 else
18829 {
18830# ifdef FEAT_MBYTE
18831 vimconv_T conv;
18832 char_u *enc;
18833
18834 conv.vc_type = CONV_NONE;
18835 enc = enc_locale();
18836 convert_setup(&conv, p_enc, enc);
18837 if (conv.vc_type != CONV_NONE)
18838 p = string_convert(&conv, p, NULL);
18839# endif
18840 if (p != NULL)
18841 (void)strftime((char *)result_buf, sizeof(result_buf),
18842 (char *)p, curtime);
18843 else
18844 result_buf[0] = NUL;
18845
18846# ifdef FEAT_MBYTE
18847 if (conv.vc_type != CONV_NONE)
18848 vim_free(p);
18849 convert_setup(&conv, enc, p_enc);
18850 if (conv.vc_type != CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018851 rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018852 else
18853# endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018854 rettv->vval.v_string = vim_strsave(result_buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018855
18856# ifdef FEAT_MBYTE
18857 /* Release conversion descriptors */
18858 convert_setup(&conv, NULL, NULL);
18859 vim_free(enc);
18860# endif
18861 }
18862}
18863#endif
18864
18865/*
18866 * "stridx()" function
18867 */
18868 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018869f_stridx(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018870{
18871 char_u buf[NUMBUFLEN];
18872 char_u *needle;
18873 char_u *haystack;
Bram Moolenaar33570922005-01-25 22:26:29 +000018874 char_u *save_haystack;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018875 char_u *pos;
Bram Moolenaar33570922005-01-25 22:26:29 +000018876 int start_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018877
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018878 needle = get_tv_string_chk(&argvars[1]);
18879 save_haystack = haystack = get_tv_string_buf_chk(&argvars[0], buf);
Bram Moolenaar33570922005-01-25 22:26:29 +000018880 rettv->vval.v_number = -1;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018881 if (needle == NULL || haystack == NULL)
18882 return; /* type error; errmsg already given */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018883
Bram Moolenaar33570922005-01-25 22:26:29 +000018884 if (argvars[2].v_type != VAR_UNKNOWN)
18885 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018886 int error = FALSE;
18887
18888 start_idx = get_tv_number_chk(&argvars[2], &error);
18889 if (error || start_idx >= (int)STRLEN(haystack))
Bram Moolenaar33570922005-01-25 22:26:29 +000018890 return;
Bram Moolenaar532c7802005-01-27 14:44:31 +000018891 if (start_idx >= 0)
18892 haystack += start_idx;
Bram Moolenaar33570922005-01-25 22:26:29 +000018893 }
18894
18895 pos = (char_u *)strstr((char *)haystack, (char *)needle);
18896 if (pos != NULL)
18897 rettv->vval.v_number = (varnumber_T)(pos - save_haystack);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018898}
18899
18900/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000018901 * "string()" function
18902 */
18903 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018904f_string(typval_T *argvars, typval_T *rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000018905{
18906 char_u *tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000018907 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +000018908
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018909 rettv->v_type = VAR_STRING;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +000018910 rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf, 0);
Bram Moolenaar8c8de832008-06-24 22:58:06 +000018911 /* Make a copy if we have a value but it's not in allocated memory. */
Bram Moolenaar92c5aba2007-08-14 20:29:31 +000018912 if (rettv->vval.v_string != NULL && tofree == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018913 rettv->vval.v_string = vim_strsave(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018914}
18915
18916/*
18917 * "strlen()" function
18918 */
18919 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018920f_strlen(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018921{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018922 rettv->vval.v_number = (varnumber_T)(STRLEN(
18923 get_tv_string(&argvars[0])));
Bram Moolenaar071d4272004-06-13 20:20:40 +000018924}
18925
18926/*
Bram Moolenaar72597a52010-07-18 15:31:08 +020018927 * "strchars()" function
18928 */
18929 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018930f_strchars(typval_T *argvars, typval_T *rettv)
Bram Moolenaar72597a52010-07-18 15:31:08 +020018931{
18932 char_u *s = get_tv_string(&argvars[0]);
Bram Moolenaar641e48c2015-06-25 16:09:26 +020018933 int skipcc = 0;
Bram Moolenaar72597a52010-07-18 15:31:08 +020018934#ifdef FEAT_MBYTE
18935 varnumber_T len = 0;
Bram Moolenaar641e48c2015-06-25 16:09:26 +020018936 int (*func_mb_ptr2char_adv)(char_u **pp);
Bram Moolenaar72597a52010-07-18 15:31:08 +020018937#endif
Bram Moolenaar641e48c2015-06-25 16:09:26 +020018938
18939 if (argvars[1].v_type != VAR_UNKNOWN)
18940 skipcc = get_tv_number_chk(&argvars[1], NULL);
18941 if (skipcc < 0 || skipcc > 1)
18942 EMSG(_(e_invarg));
18943 else
18944 {
18945#ifdef FEAT_MBYTE
18946 func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv;
18947 while (*s != NUL)
18948 {
18949 func_mb_ptr2char_adv(&s);
18950 ++len;
18951 }
18952 rettv->vval.v_number = len;
18953#else
18954 rettv->vval.v_number = (varnumber_T)(STRLEN(s));
18955#endif
18956 }
Bram Moolenaar72597a52010-07-18 15:31:08 +020018957}
18958
18959/*
Bram Moolenaardc536092010-07-18 15:45:49 +020018960 * "strdisplaywidth()" function
18961 */
18962 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018963f_strdisplaywidth(typval_T *argvars, typval_T *rettv)
Bram Moolenaardc536092010-07-18 15:45:49 +020018964{
18965 char_u *s = get_tv_string(&argvars[0]);
18966 int col = 0;
18967
18968 if (argvars[1].v_type != VAR_UNKNOWN)
18969 col = get_tv_number(&argvars[1]);
18970
Bram Moolenaar8a09b982010-07-22 22:20:57 +020018971 rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, s) - col);
Bram Moolenaardc536092010-07-18 15:45:49 +020018972}
18973
18974/*
Bram Moolenaar72597a52010-07-18 15:31:08 +020018975 * "strwidth()" function
18976 */
18977 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018978f_strwidth(typval_T *argvars, typval_T *rettv)
Bram Moolenaar72597a52010-07-18 15:31:08 +020018979{
18980 char_u *s = get_tv_string(&argvars[0]);
18981
18982 rettv->vval.v_number = (varnumber_T)(
18983#ifdef FEAT_MBYTE
18984 mb_string2cells(s, -1)
18985#else
18986 STRLEN(s)
18987#endif
18988 );
18989}
18990
18991/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000018992 * "strpart()" function
18993 */
18994 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010018995f_strpart(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018996{
18997 char_u *p;
18998 int n;
18999 int len;
19000 int slen;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000019001 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019002
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019003 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019004 slen = (int)STRLEN(p);
19005
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000019006 n = get_tv_number_chk(&argvars[1], &error);
19007 if (error)
19008 len = 0;
19009 else if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019010 len = get_tv_number(&argvars[2]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019011 else
19012 len = slen - n; /* default len: all bytes that are available. */
19013
19014 /*
19015 * Only return the overlap between the specified part and the actual
19016 * string.
19017 */
19018 if (n < 0)
19019 {
19020 len += n;
19021 n = 0;
19022 }
19023 else if (n > slen)
19024 n = slen;
19025 if (len < 0)
19026 len = 0;
19027 else if (n + len > slen)
19028 len = slen - n;
19029
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019030 rettv->v_type = VAR_STRING;
19031 rettv->vval.v_string = vim_strnsave(p + n, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019032}
19033
19034/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000019035 * "strridx()" function
19036 */
19037 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019038f_strridx(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000019039{
19040 char_u buf[NUMBUFLEN];
19041 char_u *needle;
19042 char_u *haystack;
19043 char_u *rest;
19044 char_u *lastmatch = NULL;
Bram Moolenaar532c7802005-01-27 14:44:31 +000019045 int haystack_len, end_idx;
Bram Moolenaar0d660222005-01-07 21:51:51 +000019046
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000019047 needle = get_tv_string_chk(&argvars[1]);
19048 haystack = get_tv_string_buf_chk(&argvars[0], buf);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000019049
19050 rettv->vval.v_number = -1;
19051 if (needle == NULL || haystack == NULL)
19052 return; /* type error; errmsg already given */
Bram Moolenaareb3593b2006-04-22 22:33:57 +000019053
19054 haystack_len = (int)STRLEN(haystack);
Bram Moolenaar05159a02005-02-26 23:04:13 +000019055 if (argvars[2].v_type != VAR_UNKNOWN)
19056 {
19057 /* Third argument: upper limit for index */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000019058 end_idx = get_tv_number_chk(&argvars[2], NULL);
Bram Moolenaar05159a02005-02-26 23:04:13 +000019059 if (end_idx < 0)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000019060 return; /* can never find a match */
Bram Moolenaar05159a02005-02-26 23:04:13 +000019061 }
19062 else
19063 end_idx = haystack_len;
19064
Bram Moolenaar0d660222005-01-07 21:51:51 +000019065 if (*needle == NUL)
Bram Moolenaar05159a02005-02-26 23:04:13 +000019066 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000019067 /* Empty string matches past the end. */
Bram Moolenaar05159a02005-02-26 23:04:13 +000019068 lastmatch = haystack + end_idx;
19069 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000019070 else
Bram Moolenaar532c7802005-01-27 14:44:31 +000019071 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000019072 for (rest = haystack; *rest != '\0'; ++rest)
19073 {
19074 rest = (char_u *)strstr((char *)rest, (char *)needle);
Bram Moolenaar532c7802005-01-27 14:44:31 +000019075 if (rest == NULL || rest > haystack + end_idx)
Bram Moolenaar0d660222005-01-07 21:51:51 +000019076 break;
19077 lastmatch = rest;
19078 }
Bram Moolenaar532c7802005-01-27 14:44:31 +000019079 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000019080
19081 if (lastmatch == NULL)
19082 rettv->vval.v_number = -1;
19083 else
19084 rettv->vval.v_number = (varnumber_T)(lastmatch - haystack);
19085}
19086
19087/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000019088 * "strtrans()" function
19089 */
19090 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019091f_strtrans(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019092{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019093 rettv->v_type = VAR_STRING;
19094 rettv->vval.v_string = transstr(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000019095}
19096
19097/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000019098 * "submatch()" function
19099 */
19100 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019101f_submatch(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000019102{
Bram Moolenaar41571762014-04-02 19:00:58 +020019103 int error = FALSE;
Bram Moolenaar41571762014-04-02 19:00:58 +020019104 int no;
19105 int retList = 0;
19106
19107 no = (int)get_tv_number_chk(&argvars[0], &error);
19108 if (error)
19109 return;
19110 error = FALSE;
19111 if (argvars[1].v_type != VAR_UNKNOWN)
19112 retList = get_tv_number_chk(&argvars[1], &error);
19113 if (error)
19114 return;
19115
19116 if (retList == 0)
19117 {
19118 rettv->v_type = VAR_STRING;
19119 rettv->vval.v_string = reg_submatch(no);
19120 }
19121 else
19122 {
19123 rettv->v_type = VAR_LIST;
19124 rettv->vval.v_list = reg_submatch_list(no);
19125 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000019126}
19127
19128/*
19129 * "substitute()" function
19130 */
19131 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019132f_substitute(typval_T *argvars, typval_T *rettv)
Bram Moolenaar0d660222005-01-07 21:51:51 +000019133{
19134 char_u patbuf[NUMBUFLEN];
19135 char_u subbuf[NUMBUFLEN];
19136 char_u flagsbuf[NUMBUFLEN];
19137
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000019138 char_u *str = get_tv_string_chk(&argvars[0]);
19139 char_u *pat = get_tv_string_buf_chk(&argvars[1], patbuf);
19140 char_u *sub = get_tv_string_buf_chk(&argvars[2], subbuf);
19141 char_u *flg = get_tv_string_buf_chk(&argvars[3], flagsbuf);
19142
Bram Moolenaar0d660222005-01-07 21:51:51 +000019143 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000019144 if (str == NULL || pat == NULL || sub == NULL || flg == NULL)
19145 rettv->vval.v_string = NULL;
19146 else
19147 rettv->vval.v_string = do_string_sub(str, pat, sub, flg);
Bram Moolenaar0d660222005-01-07 21:51:51 +000019148}
19149
19150/*
Bram Moolenaar54ff3412005-04-20 19:48:33 +000019151 * "synID(lnum, col, trans)" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000019152 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000019153 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019154f_synID(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019155{
19156 int id = 0;
19157#ifdef FEAT_SYN_HL
Bram Moolenaar54ff3412005-04-20 19:48:33 +000019158 long lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019159 long col;
19160 int trans;
Bram Moolenaar92124a32005-06-17 22:03:40 +000019161 int transerr = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019162
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000019163 lnum = get_tv_lnum(argvars); /* -1 on type error */
19164 col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */
19165 trans = get_tv_number_chk(&argvars[2], &transerr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019166
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000019167 if (!transerr && lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
Bram Moolenaar54ff3412005-04-20 19:48:33 +000019168 && col >= 0 && col < (long)STRLEN(ml_get(lnum)))
Bram Moolenaar56cefaf2008-01-12 15:47:10 +000019169 id = syn_get_id(curwin, lnum, (colnr_T)col, trans, NULL, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019170#endif
19171
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019172 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019173}
19174
19175/*
19176 * "synIDattr(id, what [, mode])" function
19177 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000019178 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019179f_synIDattr(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019180{
19181 char_u *p = NULL;
19182#ifdef FEAT_SYN_HL
19183 int id;
19184 char_u *what;
19185 char_u *mode;
19186 char_u modebuf[NUMBUFLEN];
19187 int modec;
19188
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019189 id = get_tv_number(&argvars[0]);
19190 what = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000019191 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019192 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019193 mode = get_tv_string_buf(&argvars[2], modebuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019194 modec = TOLOWER_ASC(mode[0]);
Bram Moolenaar61623362010-07-14 22:04:22 +020019195 if (modec != 't' && modec != 'c' && modec != 'g')
Bram Moolenaar071d4272004-06-13 20:20:40 +000019196 modec = 0; /* replace invalid with current */
19197 }
19198 else
19199 {
19200#ifdef FEAT_GUI
19201 if (gui.in_use)
19202 modec = 'g';
19203 else
19204#endif
19205 if (t_colors > 1)
19206 modec = 'c';
19207 else
19208 modec = 't';
19209 }
19210
19211
19212 switch (TOLOWER_ASC(what[0]))
19213 {
19214 case 'b':
19215 if (TOLOWER_ASC(what[1]) == 'g') /* bg[#] */
19216 p = highlight_color(id, what, modec);
19217 else /* bold */
19218 p = highlight_has_attr(id, HL_BOLD, modec);
19219 break;
19220
Bram Moolenaar12682fd2010-03-10 13:43:49 +010019221 case 'f': /* fg[#] or font */
Bram Moolenaar071d4272004-06-13 20:20:40 +000019222 p = highlight_color(id, what, modec);
19223 break;
19224
19225 case 'i':
19226 if (TOLOWER_ASC(what[1]) == 'n') /* inverse */
19227 p = highlight_has_attr(id, HL_INVERSE, modec);
19228 else /* italic */
19229 p = highlight_has_attr(id, HL_ITALIC, modec);
19230 break;
19231
19232 case 'n': /* name */
19233 p = get_highlight_name(NULL, id - 1);
19234 break;
19235
19236 case 'r': /* reverse */
19237 p = highlight_has_attr(id, HL_INVERSE, modec);
19238 break;
19239
Bram Moolenaar6f507d62008-11-28 10:16:05 +000019240 case 's':
19241 if (TOLOWER_ASC(what[1]) == 'p') /* sp[#] */
19242 p = highlight_color(id, what, modec);
19243 else /* standout */
19244 p = highlight_has_attr(id, HL_STANDOUT, modec);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019245 break;
19246
Bram Moolenaar5b743bf2005-03-15 22:50:43 +000019247 case 'u':
19248 if (STRLEN(what) <= 5 || TOLOWER_ASC(what[5]) != 'c')
19249 /* underline */
19250 p = highlight_has_attr(id, HL_UNDERLINE, modec);
19251 else
19252 /* undercurl */
19253 p = highlight_has_attr(id, HL_UNDERCURL, modec);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019254 break;
19255 }
19256
19257 if (p != NULL)
19258 p = vim_strsave(p);
19259#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019260 rettv->v_type = VAR_STRING;
19261 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019262}
19263
19264/*
19265 * "synIDtrans(id)" function
19266 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000019267 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019268f_synIDtrans(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019269{
19270 int id;
19271
19272#ifdef FEAT_SYN_HL
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019273 id = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019274
19275 if (id > 0)
19276 id = syn_get_final_id(id);
19277 else
19278#endif
19279 id = 0;
19280
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019281 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019282}
19283
19284/*
Bram Moolenaar7510fe72010-07-25 12:46:44 +020019285 * "synconcealed(lnum, col)" function
19286 */
19287 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019288f_synconcealed(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar7510fe72010-07-25 12:46:44 +020019289{
19290#if defined(FEAT_SYN_HL) && defined(FEAT_CONCEAL)
19291 long lnum;
19292 long col;
19293 int syntax_flags = 0;
19294 int cchar;
19295 int matchid = 0;
19296 char_u str[NUMBUFLEN];
19297#endif
19298
19299 rettv->v_type = VAR_LIST;
19300 rettv->vval.v_list = NULL;
19301
19302#if defined(FEAT_SYN_HL) && defined(FEAT_CONCEAL)
19303 lnum = get_tv_lnum(argvars); /* -1 on type error */
19304 col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */
19305
19306 vim_memset(str, NUL, sizeof(str));
19307
19308 if (rettv_list_alloc(rettv) != FAIL)
19309 {
19310 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
19311 && col >= 0 && col <= (long)STRLEN(ml_get(lnum))
19312 && curwin->w_p_cole > 0)
19313 {
19314 (void)syn_get_id(curwin, lnum, col, FALSE, NULL, FALSE);
19315 syntax_flags = get_syntax_info(&matchid);
19316
19317 /* get the conceal character */
19318 if ((syntax_flags & HL_CONCEAL) && curwin->w_p_cole < 3)
19319 {
19320 cchar = syn_get_sub_char();
19321 if (cchar == NUL && curwin->w_p_cole == 1 && lcs_conceal != NUL)
19322 cchar = lcs_conceal;
19323 if (cchar != NUL)
19324 {
19325# ifdef FEAT_MBYTE
19326 if (has_mbyte)
19327 (*mb_char2bytes)(cchar, str);
19328 else
19329# endif
19330 str[0] = cchar;
19331 }
19332 }
19333 }
19334
19335 list_append_number(rettv->vval.v_list,
19336 (syntax_flags & HL_CONCEAL) != 0);
19337 /* -1 to auto-determine strlen */
19338 list_append_string(rettv->vval.v_list, str, -1);
19339 list_append_number(rettv->vval.v_list, matchid);
19340 }
19341#endif
19342}
19343
19344/*
Bram Moolenaar9d188ab2008-01-10 21:24:39 +000019345 * "synstack(lnum, col)" function
19346 */
Bram Moolenaar9d188ab2008-01-10 21:24:39 +000019347 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019348f_synstack(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar9d188ab2008-01-10 21:24:39 +000019349{
19350#ifdef FEAT_SYN_HL
19351 long lnum;
19352 long col;
19353 int i;
19354 int id;
19355#endif
19356
19357 rettv->v_type = VAR_LIST;
19358 rettv->vval.v_list = NULL;
19359
19360#ifdef FEAT_SYN_HL
19361 lnum = get_tv_lnum(argvars); /* -1 on type error */
19362 col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */
19363
19364 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
Bram Moolenaard04b7502010-07-08 22:27:55 +020019365 && col >= 0 && col <= (long)STRLEN(ml_get(lnum))
Bram Moolenaar9d188ab2008-01-10 21:24:39 +000019366 && rettv_list_alloc(rettv) != FAIL)
19367 {
Bram Moolenaar56cefaf2008-01-12 15:47:10 +000019368 (void)syn_get_id(curwin, lnum, (colnr_T)col, FALSE, NULL, TRUE);
Bram Moolenaar9d188ab2008-01-10 21:24:39 +000019369 for (i = 0; ; ++i)
19370 {
19371 id = syn_get_stack_item(i);
19372 if (id < 0)
19373 break;
19374 if (list_append_number(rettv->vval.v_list, id) == FAIL)
19375 break;
19376 }
19377 }
19378#endif
19379}
19380
Bram Moolenaar071d4272004-06-13 20:20:40 +000019381 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019382get_cmd_output_as_rettv(
19383 typval_T *argvars,
19384 typval_T *rettv,
19385 int retlist)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019386{
Bram Moolenaarc0197e22004-09-13 20:26:32 +000019387 char_u *res = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019388 char_u *p;
Bram Moolenaarc0197e22004-09-13 20:26:32 +000019389 char_u *infile = NULL;
19390 char_u buf[NUMBUFLEN];
19391 int err = FALSE;
19392 FILE *fd;
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019393 list_T *list = NULL;
Bram Moolenaar52a72462014-08-29 15:53:52 +020019394 int flags = SHELL_SILENT;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019395
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019396 rettv->v_type = VAR_STRING;
19397 rettv->vval.v_string = NULL;
Bram Moolenaard9fe7c42007-04-29 11:53:56 +000019398 if (check_restricted() || check_secure())
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019399 goto errret;
Bram Moolenaard9fe7c42007-04-29 11:53:56 +000019400
Bram Moolenaar49cd9572005-01-03 21:06:01 +000019401 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc0197e22004-09-13 20:26:32 +000019402 {
19403 /*
19404 * Write the string to a temp file, to be used for input of the shell
19405 * command.
19406 */
Bram Moolenaare5c421c2015-03-31 13:33:08 +020019407 if ((infile = vim_tempname('i', TRUE)) == NULL)
Bram Moolenaarc0197e22004-09-13 20:26:32 +000019408 {
19409 EMSG(_(e_notmp));
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019410 goto errret;
Bram Moolenaarc0197e22004-09-13 20:26:32 +000019411 }
19412
19413 fd = mch_fopen((char *)infile, WRITEBIN);
19414 if (fd == NULL)
19415 {
19416 EMSG2(_(e_notopen), infile);
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019417 goto errret;
Bram Moolenaarc0197e22004-09-13 20:26:32 +000019418 }
Bram Moolenaar57ebe6e2014-04-05 18:55:46 +020019419 if (argvars[1].v_type == VAR_LIST)
Bram Moolenaareb3593b2006-04-22 22:33:57 +000019420 {
Bram Moolenaar57ebe6e2014-04-05 18:55:46 +020019421 if (write_list(fd, argvars[1].vval.v_list, TRUE) == FAIL)
19422 err = TRUE;
Bram Moolenaareb3593b2006-04-22 22:33:57 +000019423 }
Bram Moolenaar57ebe6e2014-04-05 18:55:46 +020019424 else
19425 {
Bram Moolenaar1ecfd9c2014-09-19 20:45:23 +020019426 size_t len;
19427
Bram Moolenaar57ebe6e2014-04-05 18:55:46 +020019428 p = get_tv_string_buf_chk(&argvars[1], buf);
19429 if (p == NULL)
19430 {
19431 fclose(fd);
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019432 goto errret; /* type error; errmsg already given */
Bram Moolenaar57ebe6e2014-04-05 18:55:46 +020019433 }
Bram Moolenaar1ecfd9c2014-09-19 20:45:23 +020019434 len = STRLEN(p);
19435 if (len > 0 && fwrite(p, len, 1, fd) != 1)
Bram Moolenaar57ebe6e2014-04-05 18:55:46 +020019436 err = TRUE;
19437 }
Bram Moolenaarc0197e22004-09-13 20:26:32 +000019438 if (fclose(fd) != 0)
19439 err = TRUE;
19440 if (err)
19441 {
19442 EMSG(_("E677: Error writing temp file"));
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019443 goto errret;
Bram Moolenaarc0197e22004-09-13 20:26:32 +000019444 }
19445 }
19446
Bram Moolenaar52a72462014-08-29 15:53:52 +020019447 /* Omit SHELL_COOKED when invoked with ":silent". Avoids that the shell
19448 * echoes typeahead, that messes up the display. */
19449 if (!msg_silent)
19450 flags += SHELL_COOKED;
19451
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019452 if (retlist)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019453 {
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019454 int len;
19455 listitem_T *li;
19456 char_u *s = NULL;
19457 char_u *start;
19458 char_u *end;
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019459 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019460
Bram Moolenaar52a72462014-08-29 15:53:52 +020019461 res = get_cmd_output(get_tv_string(&argvars[0]), infile, flags, &len);
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019462 if (res == NULL)
19463 goto errret;
19464
19465 list = list_alloc();
19466 if (list == NULL)
19467 goto errret;
19468
19469 for (i = 0; i < len; ++i)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019470 {
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019471 start = res + i;
Bram Moolenaarb21a29b2014-04-11 10:22:53 +020019472 while (i < len && res[i] != NL)
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019473 ++i;
Bram Moolenaarb21a29b2014-04-11 10:22:53 +020019474 end = res + i;
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019475
Bram Moolenaarb21a29b2014-04-11 10:22:53 +020019476 s = alloc((unsigned)(end - start + 1));
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019477 if (s == NULL)
19478 goto errret;
19479
Bram Moolenaarb21a29b2014-04-11 10:22:53 +020019480 for (p = s; start < end; ++p, ++start)
19481 *p = *start == NUL ? NL : *start;
19482 *p = NUL;
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019483
19484 li = listitem_alloc();
19485 if (li == NULL)
19486 {
19487 vim_free(s);
19488 goto errret;
19489 }
19490 li->li_tv.v_type = VAR_STRING;
Bram Moolenaar9a492d42015-01-27 13:49:31 +010019491 li->li_tv.v_lock = 0;
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019492 li->li_tv.vval.v_string = s;
19493 list_append(list, li);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019494 }
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019495
Bram Moolenaarb21a29b2014-04-11 10:22:53 +020019496 ++list->lv_refcount;
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019497 rettv->v_type = VAR_LIST;
19498 rettv->vval.v_list = list;
19499 list = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019500 }
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019501 else
19502 {
Bram Moolenaar52a72462014-08-29 15:53:52 +020019503 res = get_cmd_output(get_tv_string(&argvars[0]), infile, flags, NULL);
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019504#ifdef USE_CR
19505 /* translate <CR> into <NL> */
19506 if (res != NULL)
19507 {
19508 char_u *s;
19509
19510 for (s = res; *s; ++s)
19511 {
19512 if (*s == CAR)
19513 *s = NL;
19514 }
19515 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000019516#else
19517# ifdef USE_CRNL
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019518 /* translate <CR><NL> into <NL> */
19519 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019520 {
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019521 char_u *s, *d;
19522
19523 d = res;
19524 for (s = res; *s; ++s)
19525 {
19526 if (s[0] == CAR && s[1] == NL)
19527 ++s;
19528 *d++ = *s;
19529 }
19530 *d = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019531 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000019532# endif
19533#endif
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019534 rettv->vval.v_string = res;
19535 res = NULL;
19536 }
Bram Moolenaarc0197e22004-09-13 20:26:32 +000019537
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019538errret:
Bram Moolenaarc0197e22004-09-13 20:26:32 +000019539 if (infile != NULL)
19540 {
19541 mch_remove(infile);
19542 vim_free(infile);
19543 }
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019544 if (res != NULL)
19545 vim_free(res);
19546 if (list != NULL)
19547 list_free(list, TRUE);
19548}
19549
19550/*
19551 * "system()" function
19552 */
19553 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019554f_system(typval_T *argvars, typval_T *rettv)
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019555{
19556 get_cmd_output_as_rettv(argvars, rettv, FALSE);
19557}
19558
19559/*
19560 * "systemlist()" function
19561 */
19562 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019563f_systemlist(typval_T *argvars, typval_T *rettv)
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020019564{
19565 get_cmd_output_as_rettv(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019566}
19567
19568/*
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000019569 * "tabpagebuflist()" function
19570 */
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000019571 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019572f_tabpagebuflist(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000019573{
Bram Moolenaar798b30b2009-04-22 10:56:16 +000019574#ifdef FEAT_WINDOWS
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000019575 tabpage_T *tp;
19576 win_T *wp = NULL;
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000019577
19578 if (argvars[0].v_type == VAR_UNKNOWN)
19579 wp = firstwin;
19580 else
19581 {
19582 tp = find_tabpage((int)get_tv_number(&argvars[0]));
19583 if (tp != NULL)
Bram Moolenaar238a5642006-02-21 22:12:05 +000019584 wp = (tp == curtab) ? firstwin : tp->tp_firstwin;
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000019585 }
Bram Moolenaar798b30b2009-04-22 10:56:16 +000019586 if (wp != NULL && rettv_list_alloc(rettv) != FAIL)
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000019587 {
Bram Moolenaar798b30b2009-04-22 10:56:16 +000019588 for (; wp != NULL; wp = wp->w_next)
19589 if (list_append_number(rettv->vval.v_list,
Bram Moolenaareddf53b2006-02-27 00:11:10 +000019590 wp->w_buffer->b_fnum) == FAIL)
Bram Moolenaar798b30b2009-04-22 10:56:16 +000019591 break;
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000019592 }
19593#endif
19594}
19595
19596
19597/*
Bram Moolenaar7e8fd632006-02-18 22:14:51 +000019598 * "tabpagenr()" function
19599 */
Bram Moolenaar7e8fd632006-02-18 22:14:51 +000019600 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019601f_tabpagenr(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar7e8fd632006-02-18 22:14:51 +000019602{
19603 int nr = 1;
19604#ifdef FEAT_WINDOWS
Bram Moolenaar7e8fd632006-02-18 22:14:51 +000019605 char_u *arg;
19606
19607 if (argvars[0].v_type != VAR_UNKNOWN)
19608 {
19609 arg = get_tv_string_chk(&argvars[0]);
19610 nr = 0;
19611 if (arg != NULL)
19612 {
19613 if (STRCMP(arg, "$") == 0)
Bram Moolenaara5621492006-02-25 21:55:24 +000019614 nr = tabpage_index(NULL) - 1;
Bram Moolenaar7e8fd632006-02-18 22:14:51 +000019615 else
19616 EMSG2(_(e_invexpr2), arg);
19617 }
19618 }
19619 else
Bram Moolenaar32466aa2006-02-24 23:53:04 +000019620 nr = tabpage_index(curtab);
Bram Moolenaar7e8fd632006-02-18 22:14:51 +000019621#endif
19622 rettv->vval.v_number = nr;
19623}
19624
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000019625
19626#ifdef FEAT_WINDOWS
Bram Moolenaar48e697e2016-01-23 22:17:30 +010019627static int get_winnr(tabpage_T *tp, typval_T *argvar);
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000019628
19629/*
19630 * Common code for tabpagewinnr() and winnr().
19631 */
19632 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010019633get_winnr(tabpage_T *tp, typval_T *argvar)
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000019634{
19635 win_T *twin;
19636 int nr = 1;
19637 win_T *wp;
19638 char_u *arg;
19639
19640 twin = (tp == curtab) ? curwin : tp->tp_curwin;
19641 if (argvar->v_type != VAR_UNKNOWN)
19642 {
19643 arg = get_tv_string_chk(argvar);
19644 if (arg == NULL)
19645 nr = 0; /* type error; errmsg already given */
19646 else if (STRCMP(arg, "$") == 0)
19647 twin = (tp == curtab) ? lastwin : tp->tp_lastwin;
19648 else if (STRCMP(arg, "#") == 0)
19649 {
19650 twin = (tp == curtab) ? prevwin : tp->tp_prevwin;
19651 if (twin == NULL)
19652 nr = 0;
19653 }
19654 else
19655 {
19656 EMSG2(_(e_invexpr2), arg);
19657 nr = 0;
19658 }
19659 }
19660
19661 if (nr > 0)
19662 for (wp = (tp == curtab) ? firstwin : tp->tp_firstwin;
19663 wp != twin; wp = wp->w_next)
Bram Moolenaar4940e3f2007-03-25 15:49:08 +000019664 {
19665 if (wp == NULL)
19666 {
19667 /* didn't find it in this tabpage */
19668 nr = 0;
19669 break;
19670 }
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000019671 ++nr;
Bram Moolenaar4940e3f2007-03-25 15:49:08 +000019672 }
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000019673 return nr;
19674}
19675#endif
19676
19677/*
19678 * "tabpagewinnr()" function
19679 */
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000019680 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019681f_tabpagewinnr(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000019682{
19683 int nr = 1;
19684#ifdef FEAT_WINDOWS
19685 tabpage_T *tp;
19686
19687 tp = find_tabpage((int)get_tv_number(&argvars[0]));
19688 if (tp == NULL)
19689 nr = 0;
19690 else
19691 nr = get_winnr(tp, &argvars[1]);
19692#endif
19693 rettv->vval.v_number = nr;
19694}
19695
19696
Bram Moolenaar7e8fd632006-02-18 22:14:51 +000019697/*
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000019698 * "tagfiles()" function
19699 */
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000019700 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019701f_tagfiles(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000019702{
Bram Moolenaard9462e32011-04-11 21:35:11 +020019703 char_u *fname;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000019704 tagname_T tn;
19705 int first;
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000019706
Bram Moolenaareddf53b2006-02-27 00:11:10 +000019707 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000019708 return;
Bram Moolenaard9462e32011-04-11 21:35:11 +020019709 fname = alloc(MAXPATHL);
19710 if (fname == NULL)
19711 return;
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000019712
Bram Moolenaareddf53b2006-02-27 00:11:10 +000019713 for (first = TRUE; ; first = FALSE)
19714 if (get_tagfname(&tn, first, fname) == FAIL
19715 || list_append_string(rettv->vval.v_list, fname, -1) == FAIL)
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000019716 break;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000019717 tagname_free(&tn);
Bram Moolenaard9462e32011-04-11 21:35:11 +020019718 vim_free(fname);
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000019719}
19720
19721/*
Bram Moolenaare2ac10d2005-03-07 23:26:06 +000019722 * "taglist()" function
Bram Moolenaar19a09a12005-03-04 23:39:37 +000019723 */
19724 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019725f_taglist(typval_T *argvars, typval_T *rettv)
Bram Moolenaar19a09a12005-03-04 23:39:37 +000019726{
19727 char_u *tag_pattern;
Bram Moolenaar19a09a12005-03-04 23:39:37 +000019728
19729 tag_pattern = get_tv_string(&argvars[0]);
19730
19731 rettv->vval.v_number = FALSE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000019732 if (*tag_pattern == NUL)
19733 return;
Bram Moolenaar19a09a12005-03-04 23:39:37 +000019734
Bram Moolenaareddf53b2006-02-27 00:11:10 +000019735 if (rettv_list_alloc(rettv) == OK)
19736 (void)get_tags(rettv->vval.v_list, tag_pattern);
Bram Moolenaar19a09a12005-03-04 23:39:37 +000019737}
19738
19739/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000019740 * "tempname()" function
19741 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000019742 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019743f_tempname(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019744{
19745 static int x = 'A';
19746
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019747 rettv->v_type = VAR_STRING;
Bram Moolenaare5c421c2015-03-31 13:33:08 +020019748 rettv->vval.v_string = vim_tempname(x, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019749
19750 /* Advance 'x' to use A-Z and 0-9, so that there are at least 34 different
19751 * names. Skip 'I' and 'O', they are used for shell redirection. */
19752 do
19753 {
19754 if (x == 'Z')
19755 x = '0';
19756 else if (x == '9')
19757 x = 'A';
19758 else
19759 {
19760#ifdef EBCDIC
19761 if (x == 'I')
19762 x = 'J';
19763 else if (x == 'R')
19764 x = 'S';
19765 else
19766#endif
19767 ++x;
19768 }
19769 } while (x == 'I' || x == 'O');
19770}
19771
19772/*
Bram Moolenaard52d9742005-08-21 22:20:28 +000019773 * "test(list)" function: Just checking the walls...
19774 */
Bram Moolenaard52d9742005-08-21 22:20:28 +000019775 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019776f_test(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaard52d9742005-08-21 22:20:28 +000019777{
19778 /* Used for unit testing. Change the code below to your liking. */
19779#if 0
19780 listitem_T *li;
19781 list_T *l;
19782 char_u *bad, *good;
19783
19784 if (argvars[0].v_type != VAR_LIST)
19785 return;
19786 l = argvars[0].vval.v_list;
19787 if (l == NULL)
19788 return;
19789 li = l->lv_first;
19790 if (li == NULL)
19791 return;
19792 bad = get_tv_string(&li->li_tv);
19793 li = li->li_next;
19794 if (li == NULL)
19795 return;
19796 good = get_tv_string(&li->li_tv);
19797 rettv->vval.v_number = test_edit_score(bad, good);
19798#endif
19799}
19800
Bram Moolenaardb7c6862010-05-21 16:33:48 +020019801#ifdef FEAT_FLOAT
19802/*
19803 * "tan()" function
19804 */
19805 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019806f_tan(typval_T *argvars, typval_T *rettv)
Bram Moolenaardb7c6862010-05-21 16:33:48 +020019807{
Bram Moolenaara1e24b92016-02-18 20:18:09 +010019808 float_T f = 0.0;
Bram Moolenaardb7c6862010-05-21 16:33:48 +020019809
19810 rettv->v_type = VAR_FLOAT;
19811 if (get_float_arg(argvars, &f) == OK)
19812 rettv->vval.v_float = tan(f);
19813 else
19814 rettv->vval.v_float = 0.0;
19815}
19816
19817/*
19818 * "tanh()" function
19819 */
19820 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019821f_tanh(typval_T *argvars, typval_T *rettv)
Bram Moolenaardb7c6862010-05-21 16:33:48 +020019822{
Bram Moolenaara1e24b92016-02-18 20:18:09 +010019823 float_T f = 0.0;
Bram Moolenaardb7c6862010-05-21 16:33:48 +020019824
19825 rettv->v_type = VAR_FLOAT;
19826 if (get_float_arg(argvars, &f) == OK)
19827 rettv->vval.v_float = tanh(f);
19828 else
19829 rettv->vval.v_float = 0.0;
19830}
19831#endif
19832
Bram Moolenaard52d9742005-08-21 22:20:28 +000019833/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000019834 * "tolower(string)" function
19835 */
19836 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019837f_tolower(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019838{
19839 char_u *p;
19840
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019841 p = vim_strsave(get_tv_string(&argvars[0]));
19842 rettv->v_type = VAR_STRING;
19843 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019844
19845 if (p != NULL)
19846 while (*p != NUL)
19847 {
19848#ifdef FEAT_MBYTE
19849 int l;
19850
19851 if (enc_utf8)
19852 {
19853 int c, lc;
19854
19855 c = utf_ptr2char(p);
19856 lc = utf_tolower(c);
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000019857 l = utf_ptr2len(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019858 /* TODO: reallocate string when byte count changes. */
19859 if (utf_char2len(lc) == l)
19860 utf_char2bytes(lc, p);
19861 p += l;
19862 }
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000019863 else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019864 p += l; /* skip multi-byte character */
19865 else
19866#endif
19867 {
19868 *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */
19869 ++p;
19870 }
19871 }
19872}
19873
19874/*
19875 * "toupper(string)" function
19876 */
19877 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019878f_toupper(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019879{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019880 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000019881 rettv->vval.v_string = strup_save(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000019882}
19883
19884/*
Bram Moolenaar8299df92004-07-10 09:47:34 +000019885 * "tr(string, fromstr, tostr)" function
19886 */
19887 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010019888f_tr(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8299df92004-07-10 09:47:34 +000019889{
Bram Moolenaar70b2a562012-01-10 22:26:17 +010019890 char_u *in_str;
Bram Moolenaar8299df92004-07-10 09:47:34 +000019891 char_u *fromstr;
19892 char_u *tostr;
19893 char_u *p;
19894#ifdef FEAT_MBYTE
Bram Moolenaar342337a2005-07-21 21:11:17 +000019895 int inlen;
19896 int fromlen;
19897 int tolen;
Bram Moolenaar8299df92004-07-10 09:47:34 +000019898 int idx;
19899 char_u *cpstr;
19900 int cplen;
19901 int first = TRUE;
19902#endif
19903 char_u buf[NUMBUFLEN];
19904 char_u buf2[NUMBUFLEN];
19905 garray_T ga;
19906
Bram Moolenaar70b2a562012-01-10 22:26:17 +010019907 in_str = get_tv_string(&argvars[0]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000019908 fromstr = get_tv_string_buf_chk(&argvars[1], buf);
19909 tostr = get_tv_string_buf_chk(&argvars[2], buf2);
Bram Moolenaar8299df92004-07-10 09:47:34 +000019910
19911 /* Default return value: empty string. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019912 rettv->v_type = VAR_STRING;
19913 rettv->vval.v_string = NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000019914 if (fromstr == NULL || tostr == NULL)
19915 return; /* type error; errmsg already given */
Bram Moolenaar8299df92004-07-10 09:47:34 +000019916 ga_init2(&ga, (int)sizeof(char), 80);
19917
19918#ifdef FEAT_MBYTE
19919 if (!has_mbyte)
19920#endif
19921 /* not multi-byte: fromstr and tostr must be the same length */
19922 if (STRLEN(fromstr) != STRLEN(tostr))
19923 {
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000019924#ifdef FEAT_MBYTE
Bram Moolenaar8299df92004-07-10 09:47:34 +000019925error:
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000019926#endif
Bram Moolenaar8299df92004-07-10 09:47:34 +000019927 EMSG2(_(e_invarg2), fromstr);
19928 ga_clear(&ga);
19929 return;
19930 }
19931
19932 /* fromstr and tostr have to contain the same number of chars */
Bram Moolenaar70b2a562012-01-10 22:26:17 +010019933 while (*in_str != NUL)
Bram Moolenaar8299df92004-07-10 09:47:34 +000019934 {
19935#ifdef FEAT_MBYTE
19936 if (has_mbyte)
19937 {
Bram Moolenaar70b2a562012-01-10 22:26:17 +010019938 inlen = (*mb_ptr2len)(in_str);
19939 cpstr = in_str;
Bram Moolenaar8299df92004-07-10 09:47:34 +000019940 cplen = inlen;
19941 idx = 0;
19942 for (p = fromstr; *p != NUL; p += fromlen)
19943 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000019944 fromlen = (*mb_ptr2len)(p);
Bram Moolenaar70b2a562012-01-10 22:26:17 +010019945 if (fromlen == inlen && STRNCMP(in_str, p, inlen) == 0)
Bram Moolenaar8299df92004-07-10 09:47:34 +000019946 {
19947 for (p = tostr; *p != NUL; p += tolen)
19948 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000019949 tolen = (*mb_ptr2len)(p);
Bram Moolenaar8299df92004-07-10 09:47:34 +000019950 if (idx-- == 0)
19951 {
19952 cplen = tolen;
19953 cpstr = p;
19954 break;
19955 }
19956 }
19957 if (*p == NUL) /* tostr is shorter than fromstr */
19958 goto error;
19959 break;
19960 }
19961 ++idx;
19962 }
19963
Bram Moolenaar70b2a562012-01-10 22:26:17 +010019964 if (first && cpstr == in_str)
Bram Moolenaar8299df92004-07-10 09:47:34 +000019965 {
19966 /* Check that fromstr and tostr have the same number of
19967 * (multi-byte) characters. Done only once when a character
Bram Moolenaar70b2a562012-01-10 22:26:17 +010019968 * of in_str doesn't appear in fromstr. */
Bram Moolenaar8299df92004-07-10 09:47:34 +000019969 first = FALSE;
19970 for (p = tostr; *p != NUL; p += tolen)
19971 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000019972 tolen = (*mb_ptr2len)(p);
Bram Moolenaar8299df92004-07-10 09:47:34 +000019973 --idx;
19974 }
19975 if (idx != 0)
19976 goto error;
19977 }
19978
Bram Moolenaarcde88542015-08-11 19:14:00 +020019979 (void)ga_grow(&ga, cplen);
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +000019980 mch_memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen);
Bram Moolenaar8299df92004-07-10 09:47:34 +000019981 ga.ga_len += cplen;
Bram Moolenaar8299df92004-07-10 09:47:34 +000019982
Bram Moolenaar70b2a562012-01-10 22:26:17 +010019983 in_str += inlen;
Bram Moolenaar8299df92004-07-10 09:47:34 +000019984 }
19985 else
19986#endif
19987 {
19988 /* When not using multi-byte chars we can do it faster. */
Bram Moolenaar70b2a562012-01-10 22:26:17 +010019989 p = vim_strchr(fromstr, *in_str);
Bram Moolenaar8299df92004-07-10 09:47:34 +000019990 if (p != NULL)
19991 ga_append(&ga, tostr[p - fromstr]);
19992 else
Bram Moolenaar70b2a562012-01-10 22:26:17 +010019993 ga_append(&ga, *in_str);
19994 ++in_str;
Bram Moolenaar8299df92004-07-10 09:47:34 +000019995 }
19996 }
19997
Bram Moolenaar61b974b2006-12-05 09:32:29 +000019998 /* add a terminating NUL */
Bram Moolenaarcde88542015-08-11 19:14:00 +020019999 (void)ga_grow(&ga, 1);
Bram Moolenaar61b974b2006-12-05 09:32:29 +000020000 ga_append(&ga, NUL);
20001
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020002 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar8299df92004-07-10 09:47:34 +000020003}
20004
Bram Moolenaar8c8de832008-06-24 22:58:06 +000020005#ifdef FEAT_FLOAT
20006/*
20007 * "trunc({float})" function
20008 */
20009 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020010f_trunc(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8c8de832008-06-24 22:58:06 +000020011{
Bram Moolenaara1e24b92016-02-18 20:18:09 +010020012 float_T f = 0.0;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000020013
20014 rettv->v_type = VAR_FLOAT;
20015 if (get_float_arg(argvars, &f) == OK)
20016 /* trunc() is not in C90, use floor() or ceil() instead. */
20017 rettv->vval.v_float = f > 0 ? floor(f) : ceil(f);
20018 else
20019 rettv->vval.v_float = 0.0;
20020}
20021#endif
20022
Bram Moolenaar8299df92004-07-10 09:47:34 +000020023/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000020024 * "type(expr)" function
20025 */
20026 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020027f_type(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020028{
Bram Moolenaar2fc83fc2016-02-08 22:57:24 +010020029 int n = -1;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000020030
20031 switch (argvars[0].v_type)
20032 {
20033 case VAR_NUMBER: n = 0; break;
20034 case VAR_STRING: n = 1; break;
20035 case VAR_FUNC: n = 2; break;
20036 case VAR_LIST: n = 3; break;
Bram Moolenaar758711c2005-02-02 23:11:38 +000020037 case VAR_DICT: n = 4; break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000020038 case VAR_FLOAT: n = 5; break;
Bram Moolenaarf95534c2016-01-23 21:59:52 +010020039 case VAR_SPECIAL:
Bram Moolenaara03f2332016-02-06 18:09:59 +010020040 if (argvars[0].vval.v_number == VVAL_FALSE
20041 || argvars[0].vval.v_number == VVAL_TRUE)
20042 n = 6;
20043 else
20044 n = 7;
20045 break;
Bram Moolenaar77073442016-02-13 23:23:53 +010020046 case VAR_JOB: n = 8; break;
20047 case VAR_CHANNEL: n = 9; break;
Bram Moolenaara03f2332016-02-06 18:09:59 +010020048 case VAR_UNKNOWN:
20049 EMSG2(_(e_intern2), "f_type(UNKNOWN)");
20050 n = -1;
20051 break;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000020052 }
20053 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020054}
20055
20056/*
Bram Moolenaara17d4c12010-05-30 18:30:36 +020020057 * "undofile(name)" function
20058 */
20059 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020060f_undofile(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaara17d4c12010-05-30 18:30:36 +020020061{
20062 rettv->v_type = VAR_STRING;
20063#ifdef FEAT_PERSISTENT_UNDO
Bram Moolenaar945e2db2010-06-05 17:43:32 +020020064 {
Bram Moolenaarb41d9682012-04-30 17:35:48 +020020065 char_u *fname = get_tv_string(&argvars[0]);
Bram Moolenaar945e2db2010-06-05 17:43:32 +020020066
Bram Moolenaarb41d9682012-04-30 17:35:48 +020020067 if (*fname == NUL)
20068 {
20069 /* If there is no file name there will be no undo file. */
20070 rettv->vval.v_string = NULL;
20071 }
20072 else
20073 {
20074 char_u *ffname = FullName_save(fname, FALSE);
20075
20076 if (ffname != NULL)
20077 rettv->vval.v_string = u_get_undo_file_name(ffname, FALSE);
20078 vim_free(ffname);
20079 }
Bram Moolenaar945e2db2010-06-05 17:43:32 +020020080 }
Bram Moolenaara17d4c12010-05-30 18:30:36 +020020081#else
20082 rettv->vval.v_string = NULL;
20083#endif
20084}
20085
20086/*
Bram Moolenaara800b422010-06-27 01:15:55 +020020087 * "undotree()" function
20088 */
20089 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020090f_undotree(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaara800b422010-06-27 01:15:55 +020020091{
20092 if (rettv_dict_alloc(rettv) == OK)
20093 {
20094 dict_T *dict = rettv->vval.v_dict;
20095 list_T *list;
20096
Bram Moolenaar730cde92010-06-27 05:18:54 +020020097 dict_add_nr_str(dict, "synced", (long)curbuf->b_u_synced, NULL);
Bram Moolenaara800b422010-06-27 01:15:55 +020020098 dict_add_nr_str(dict, "seq_last", curbuf->b_u_seq_last, NULL);
Bram Moolenaar730cde92010-06-27 05:18:54 +020020099 dict_add_nr_str(dict, "save_last",
20100 (long)curbuf->b_u_save_nr_last, NULL);
Bram Moolenaara800b422010-06-27 01:15:55 +020020101 dict_add_nr_str(dict, "seq_cur", curbuf->b_u_seq_cur, NULL);
20102 dict_add_nr_str(dict, "time_cur", (long)curbuf->b_u_time_cur, NULL);
Bram Moolenaar730cde92010-06-27 05:18:54 +020020103 dict_add_nr_str(dict, "save_cur", (long)curbuf->b_u_save_nr_cur, NULL);
Bram Moolenaara800b422010-06-27 01:15:55 +020020104
20105 list = list_alloc();
20106 if (list != NULL)
20107 {
20108 u_eval_tree(curbuf->b_u_oldhead, list);
20109 dict_add_list(dict, "entries", list);
20110 }
20111 }
20112}
20113
20114/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000020115 * "values(dict)" function
20116 */
20117 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020118f_values(typval_T *argvars, typval_T *rettv)
Bram Moolenaar8c711452005-01-14 21:53:12 +000020119{
20120 dict_list(argvars, rettv, 1);
20121}
20122
20123/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000020124 * "virtcol(string)" function
20125 */
20126 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020127f_virtcol(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020128{
20129 colnr_T vcol = 0;
20130 pos_T *fp;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000020131 int fnum = curbuf->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020132
Bram Moolenaar0e34f622006-03-03 23:00:03 +000020133 fp = var2fpos(&argvars[0], FALSE, &fnum);
20134 if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count
20135 && fnum == curbuf->b_fnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020136 {
20137 getvvcol(curwin, fp, NULL, NULL, &vcol);
20138 ++vcol;
20139 }
20140
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020141 rettv->vval.v_number = vcol;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020142}
20143
20144/*
20145 * "visualmode()" function
20146 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000020147 static void
Bram Moolenaarf1d25012016-03-03 12:22:53 +010020148f_visualmode(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020149{
Bram Moolenaar071d4272004-06-13 20:20:40 +000020150 char_u str[2];
20151
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020152 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020153 str[0] = curbuf->b_visual_mode_eval;
20154 str[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020155 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020156
20157 /* A non-zero number or non-empty string argument: reset mode. */
Bram Moolenaar05bb9532008-07-04 09:44:11 +000020158 if (non_zero_arg(&argvars[0]))
Bram Moolenaar071d4272004-06-13 20:20:40 +000020159 curbuf->b_visual_mode_eval = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020160}
20161
20162/*
Bram Moolenaar8738fc12013-02-20 17:59:11 +010020163 * "wildmenumode()" function
20164 */
20165 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020166f_wildmenumode(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
Bram Moolenaar8738fc12013-02-20 17:59:11 +010020167{
20168#ifdef FEAT_WILDMENU
20169 if (wild_menu_showing)
20170 rettv->vval.v_number = 1;
20171#endif
20172}
20173
20174/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000020175 * "winbufnr(nr)" function
20176 */
20177 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020178f_winbufnr(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020179{
20180 win_T *wp;
20181
Bram Moolenaar99ebf042006-04-15 20:28:54 +000020182 wp = find_win_by_nr(&argvars[0], NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020183 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020184 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020185 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020186 rettv->vval.v_number = wp->w_buffer->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020187}
20188
20189/*
20190 * "wincol()" function
20191 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000020192 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020193f_wincol(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020194{
20195 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020196 rettv->vval.v_number = curwin->w_wcol + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020197}
20198
20199/*
20200 * "winheight(nr)" function
20201 */
20202 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020203f_winheight(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020204{
20205 win_T *wp;
20206
Bram Moolenaar99ebf042006-04-15 20:28:54 +000020207 wp = find_win_by_nr(&argvars[0], NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020208 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020209 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020210 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020211 rettv->vval.v_number = wp->w_height;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020212}
20213
20214/*
20215 * "winline()" function
20216 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000020217 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020218f_winline(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020219{
20220 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020221 rettv->vval.v_number = curwin->w_wrow + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020222}
20223
20224/*
20225 * "winnr()" function
20226 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000020227 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020228f_winnr(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020229{
20230 int nr = 1;
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000020231
Bram Moolenaar071d4272004-06-13 20:20:40 +000020232#ifdef FEAT_WINDOWS
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000020233 nr = get_winnr(curtab, &argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020234#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020235 rettv->vval.v_number = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020236}
20237
20238/*
20239 * "winrestcmd()" function
20240 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000020241 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020242f_winrestcmd(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020243{
20244#ifdef FEAT_WINDOWS
20245 win_T *wp;
20246 int winnr = 1;
20247 garray_T ga;
20248 char_u buf[50];
20249
20250 ga_init2(&ga, (int)sizeof(char), 70);
20251 for (wp = firstwin; wp != NULL; wp = wp->w_next)
20252 {
20253 sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height);
20254 ga_concat(&ga, buf);
20255# ifdef FEAT_VERTSPLIT
20256 sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width);
20257 ga_concat(&ga, buf);
20258# endif
20259 ++winnr;
20260 }
Bram Moolenaar269ec652004-07-29 08:43:53 +000020261 ga_append(&ga, NUL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020262
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020263 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020264#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020265 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020266#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020267 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020268}
20269
20270/*
Bram Moolenaar768b8c42006-03-04 21:58:33 +000020271 * "winrestview()" function
20272 */
Bram Moolenaar768b8c42006-03-04 21:58:33 +000020273 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020274f_winrestview(typval_T *argvars, typval_T *rettv UNUSED)
Bram Moolenaar768b8c42006-03-04 21:58:33 +000020275{
20276 dict_T *dict;
20277
20278 if (argvars[0].v_type != VAR_DICT
20279 || (dict = argvars[0].vval.v_dict) == NULL)
20280 EMSG(_(e_invarg));
20281 else
20282 {
Bram Moolenaar82c25852014-05-28 16:47:16 +020020283 if (dict_find(dict, (char_u *)"lnum", -1) != NULL)
20284 curwin->w_cursor.lnum = get_dict_number(dict, (char_u *)"lnum");
20285 if (dict_find(dict, (char_u *)"col", -1) != NULL)
20286 curwin->w_cursor.col = get_dict_number(dict, (char_u *)"col");
Bram Moolenaar768b8c42006-03-04 21:58:33 +000020287#ifdef FEAT_VIRTUALEDIT
Bram Moolenaar82c25852014-05-28 16:47:16 +020020288 if (dict_find(dict, (char_u *)"coladd", -1) != NULL)
20289 curwin->w_cursor.coladd = get_dict_number(dict, (char_u *)"coladd");
Bram Moolenaar768b8c42006-03-04 21:58:33 +000020290#endif
Bram Moolenaar82c25852014-05-28 16:47:16 +020020291 if (dict_find(dict, (char_u *)"curswant", -1) != NULL)
20292 {
20293 curwin->w_curswant = get_dict_number(dict, (char_u *)"curswant");
20294 curwin->w_set_curswant = FALSE;
20295 }
Bram Moolenaar768b8c42006-03-04 21:58:33 +000020296
Bram Moolenaar82c25852014-05-28 16:47:16 +020020297 if (dict_find(dict, (char_u *)"topline", -1) != NULL)
20298 set_topline(curwin, get_dict_number(dict, (char_u *)"topline"));
Bram Moolenaar768b8c42006-03-04 21:58:33 +000020299#ifdef FEAT_DIFF
Bram Moolenaar82c25852014-05-28 16:47:16 +020020300 if (dict_find(dict, (char_u *)"topfill", -1) != NULL)
20301 curwin->w_topfill = get_dict_number(dict, (char_u *)"topfill");
Bram Moolenaar768b8c42006-03-04 21:58:33 +000020302#endif
Bram Moolenaar82c25852014-05-28 16:47:16 +020020303 if (dict_find(dict, (char_u *)"leftcol", -1) != NULL)
20304 curwin->w_leftcol = get_dict_number(dict, (char_u *)"leftcol");
20305 if (dict_find(dict, (char_u *)"skipcol", -1) != NULL)
20306 curwin->w_skipcol = get_dict_number(dict, (char_u *)"skipcol");
Bram Moolenaar768b8c42006-03-04 21:58:33 +000020307
20308 check_cursor();
Bram Moolenaar6763c142012-07-19 18:05:44 +020020309 win_new_height(curwin, curwin->w_height);
20310# ifdef FEAT_VERTSPLIT
20311 win_new_width(curwin, W_WIDTH(curwin));
20312# endif
Bram Moolenaarab984db2012-06-06 16:29:10 +020020313 changed_window_setting();
Bram Moolenaar768b8c42006-03-04 21:58:33 +000020314
Bram Moolenaarb851a962014-10-31 15:45:52 +010020315 if (curwin->w_topline <= 0)
Bram Moolenaar768b8c42006-03-04 21:58:33 +000020316 curwin->w_topline = 1;
20317 if (curwin->w_topline > curbuf->b_ml.ml_line_count)
20318 curwin->w_topline = curbuf->b_ml.ml_line_count;
20319#ifdef FEAT_DIFF
20320 check_topfill(curwin, TRUE);
20321#endif
20322 }
20323}
20324
20325/*
20326 * "winsaveview()" function
20327 */
Bram Moolenaar768b8c42006-03-04 21:58:33 +000020328 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020329f_winsaveview(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaar768b8c42006-03-04 21:58:33 +000020330{
20331 dict_T *dict;
20332
Bram Moolenaara800b422010-06-27 01:15:55 +020020333 if (rettv_dict_alloc(rettv) == FAIL)
Bram Moolenaar768b8c42006-03-04 21:58:33 +000020334 return;
Bram Moolenaara800b422010-06-27 01:15:55 +020020335 dict = rettv->vval.v_dict;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000020336
20337 dict_add_nr_str(dict, "lnum", (long)curwin->w_cursor.lnum, NULL);
20338 dict_add_nr_str(dict, "col", (long)curwin->w_cursor.col, NULL);
20339#ifdef FEAT_VIRTUALEDIT
20340 dict_add_nr_str(dict, "coladd", (long)curwin->w_cursor.coladd, NULL);
20341#endif
Bram Moolenaar9af1ba92006-08-29 19:55:53 +000020342 update_curswant();
Bram Moolenaar768b8c42006-03-04 21:58:33 +000020343 dict_add_nr_str(dict, "curswant", (long)curwin->w_curswant, NULL);
20344
20345 dict_add_nr_str(dict, "topline", (long)curwin->w_topline, NULL);
20346#ifdef FEAT_DIFF
20347 dict_add_nr_str(dict, "topfill", (long)curwin->w_topfill, NULL);
20348#endif
20349 dict_add_nr_str(dict, "leftcol", (long)curwin->w_leftcol, NULL);
20350 dict_add_nr_str(dict, "skipcol", (long)curwin->w_skipcol, NULL);
20351}
20352
20353/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000020354 * "winwidth(nr)" function
20355 */
20356 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020357f_winwidth(typval_T *argvars, typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020358{
20359 win_T *wp;
20360
Bram Moolenaar99ebf042006-04-15 20:28:54 +000020361 wp = find_win_by_nr(&argvars[0], NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020362 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020363 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020364 else
20365#ifdef FEAT_VERTSPLIT
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020366 rettv->vval.v_number = wp->w_width;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020367#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020368 rettv->vval.v_number = Columns;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020369#endif
20370}
20371
Bram Moolenaar071d4272004-06-13 20:20:40 +000020372/*
Bram Moolenaared767a22016-01-03 22:49:16 +010020373 * "wordcount()" function
20374 */
20375 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020376f_wordcount(typval_T *argvars UNUSED, typval_T *rettv)
Bram Moolenaared767a22016-01-03 22:49:16 +010020377{
20378 if (rettv_dict_alloc(rettv) == FAIL)
20379 return;
20380 cursor_pos_info(rettv->vval.v_dict);
20381}
20382
20383/*
Bram Moolenaar57ebe6e2014-04-05 18:55:46 +020020384 * Write list of strings to file
20385 */
20386 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010020387write_list(FILE *fd, list_T *list, int binary)
Bram Moolenaar57ebe6e2014-04-05 18:55:46 +020020388{
20389 listitem_T *li;
20390 int c;
20391 int ret = OK;
20392 char_u *s;
20393
20394 for (li = list->lv_first; li != NULL; li = li->li_next)
20395 {
20396 for (s = get_tv_string(&li->li_tv); *s != NUL; ++s)
20397 {
20398 if (*s == '\n')
20399 c = putc(NUL, fd);
20400 else
20401 c = putc(*s, fd);
20402 if (c == EOF)
20403 {
20404 ret = FAIL;
20405 break;
20406 }
20407 }
20408 if (!binary || li->li_next != NULL)
20409 if (putc('\n', fd) == EOF)
20410 {
20411 ret = FAIL;
20412 break;
20413 }
20414 if (ret == FAIL)
20415 {
20416 EMSG(_(e_write));
20417 break;
20418 }
20419 }
20420 return ret;
20421}
20422
20423/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020424 * "writefile()" function
20425 */
20426 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020427f_writefile(typval_T *argvars, typval_T *rettv)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020428{
20429 int binary = FALSE;
Bram Moolenaar6b2e9382014-11-05 18:06:01 +010020430 int append = FALSE;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020431 char_u *fname;
20432 FILE *fd;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020433 int ret = 0;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020434
Bram Moolenaard9fe7c42007-04-29 11:53:56 +000020435 if (check_restricted() || check_secure())
20436 return;
20437
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020438 if (argvars[0].v_type != VAR_LIST)
20439 {
20440 EMSG2(_(e_listarg), "writefile()");
20441 return;
20442 }
20443 if (argvars[0].vval.v_list == NULL)
20444 return;
20445
Bram Moolenaar6b2e9382014-11-05 18:06:01 +010020446 if (argvars[2].v_type != VAR_UNKNOWN)
20447 {
20448 if (vim_strchr(get_tv_string(&argvars[2]), 'b') != NULL)
20449 binary = TRUE;
20450 if (vim_strchr(get_tv_string(&argvars[2]), 'a') != NULL)
20451 append = TRUE;
20452 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020453
20454 /* Always open the file in binary mode, library functions have a mind of
20455 * their own about CR-LF conversion. */
20456 fname = get_tv_string(&argvars[1]);
Bram Moolenaar6b2e9382014-11-05 18:06:01 +010020457 if (*fname == NUL || (fd = mch_fopen((char *)fname,
20458 append ? APPENDBIN : WRITEBIN)) == NULL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020459 {
20460 EMSG2(_(e_notcreate), *fname == NUL ? (char_u *)_("<empty>") : fname);
20461 ret = -1;
20462 }
20463 else
20464 {
Bram Moolenaar57ebe6e2014-04-05 18:55:46 +020020465 if (write_list(fd, argvars[0].vval.v_list, binary) == FAIL)
20466 ret = -1;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020467 fclose(fd);
20468 }
20469
20470 rettv->vval.v_number = ret;
20471}
20472
20473/*
Bram Moolenaard6e256c2011-12-14 15:32:50 +010020474 * "xor(expr, expr)" function
20475 */
20476 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020477f_xor(typval_T *argvars, typval_T *rettv)
Bram Moolenaard6e256c2011-12-14 15:32:50 +010020478{
20479 rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL)
20480 ^ get_tv_number_chk(&argvars[1], NULL);
20481}
20482
20483
20484/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000020485 * Translate a String variable into a position.
Bram Moolenaar32466aa2006-02-24 23:53:04 +000020486 * Returns NULL when there is an error.
Bram Moolenaar071d4272004-06-13 20:20:40 +000020487 */
20488 static pos_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +010020489var2fpos(
20490 typval_T *varp,
20491 int dollar_lnum, /* TRUE when $ is last line */
20492 int *fnum) /* set to fnum for '0, 'A, etc. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000020493{
Bram Moolenaar261bfea2006-03-01 22:12:31 +000020494 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020495 static pos_T pos;
Bram Moolenaar261bfea2006-03-01 22:12:31 +000020496 pos_T *pp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020497
Bram Moolenaara5525202006-03-02 22:52:09 +000020498 /* Argument can be [lnum, col, coladd]. */
Bram Moolenaar32466aa2006-02-24 23:53:04 +000020499 if (varp->v_type == VAR_LIST)
20500 {
20501 list_T *l;
Bram Moolenaar32466aa2006-02-24 23:53:04 +000020502 int len;
Bram Moolenaara5525202006-03-02 22:52:09 +000020503 int error = FALSE;
Bram Moolenaar477933c2007-07-17 14:32:23 +000020504 listitem_T *li;
Bram Moolenaar32466aa2006-02-24 23:53:04 +000020505
20506 l = varp->vval.v_list;
20507 if (l == NULL)
20508 return NULL;
20509
20510 /* Get the line number */
Bram Moolenaara5525202006-03-02 22:52:09 +000020511 pos.lnum = list_find_nr(l, 0L, &error);
20512 if (error || pos.lnum <= 0 || pos.lnum > curbuf->b_ml.ml_line_count)
Bram Moolenaar32466aa2006-02-24 23:53:04 +000020513 return NULL; /* invalid line number */
20514
20515 /* Get the column number */
Bram Moolenaara5525202006-03-02 22:52:09 +000020516 pos.col = list_find_nr(l, 1L, &error);
20517 if (error)
Bram Moolenaar32466aa2006-02-24 23:53:04 +000020518 return NULL;
Bram Moolenaar32466aa2006-02-24 23:53:04 +000020519 len = (long)STRLEN(ml_get(pos.lnum));
Bram Moolenaar477933c2007-07-17 14:32:23 +000020520
20521 /* We accept "$" for the column number: last column. */
20522 li = list_find(l, 1L);
20523 if (li != NULL && li->li_tv.v_type == VAR_STRING
20524 && li->li_tv.vval.v_string != NULL
20525 && STRCMP(li->li_tv.vval.v_string, "$") == 0)
20526 pos.col = len + 1;
20527
Bram Moolenaara5525202006-03-02 22:52:09 +000020528 /* Accept a position up to the NUL after the line. */
Bram Moolenaar4c3f5362006-04-11 21:38:50 +000020529 if (pos.col == 0 || (int)pos.col > len + 1)
Bram Moolenaar32466aa2006-02-24 23:53:04 +000020530 return NULL; /* invalid column number */
Bram Moolenaara5525202006-03-02 22:52:09 +000020531 --pos.col;
Bram Moolenaar32466aa2006-02-24 23:53:04 +000020532
Bram Moolenaara5525202006-03-02 22:52:09 +000020533#ifdef FEAT_VIRTUALEDIT
20534 /* Get the virtual offset. Defaults to zero. */
20535 pos.coladd = list_find_nr(l, 2L, &error);
20536 if (error)
20537 pos.coladd = 0;
20538#endif
20539
Bram Moolenaar32466aa2006-02-24 23:53:04 +000020540 return &pos;
20541 }
20542
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000020543 name = get_tv_string_chk(varp);
20544 if (name == NULL)
20545 return NULL;
Bram Moolenaar9ecd0232008-06-20 15:31:51 +000020546 if (name[0] == '.') /* cursor */
Bram Moolenaar071d4272004-06-13 20:20:40 +000020547 return &curwin->w_cursor;
Bram Moolenaar9ecd0232008-06-20 15:31:51 +000020548 if (name[0] == 'v' && name[1] == NUL) /* Visual start */
20549 {
20550 if (VIsual_active)
20551 return &VIsual;
20552 return &curwin->w_cursor;
20553 }
Bram Moolenaar9ecd0232008-06-20 15:31:51 +000020554 if (name[0] == '\'') /* mark */
Bram Moolenaar071d4272004-06-13 20:20:40 +000020555 {
Bram Moolenaar9d182dd2013-01-23 15:53:15 +010020556 pp = getmark_buf_fnum(curbuf, name[1], FALSE, fnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020557 if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
20558 return NULL;
20559 return pp;
20560 }
Bram Moolenaara5525202006-03-02 22:52:09 +000020561
20562#ifdef FEAT_VIRTUALEDIT
20563 pos.coladd = 0;
20564#endif
20565
Bram Moolenaar477933c2007-07-17 14:32:23 +000020566 if (name[0] == 'w' && dollar_lnum)
Bram Moolenaarf52c7252006-02-10 23:23:57 +000020567 {
20568 pos.col = 0;
20569 if (name[1] == '0') /* "w0": first visible line */
20570 {
Bram Moolenaarf740b292006-02-16 22:11:02 +000020571 update_topline();
Bram Moolenaarf52c7252006-02-10 23:23:57 +000020572 pos.lnum = curwin->w_topline;
20573 return &pos;
20574 }
20575 else if (name[1] == '$') /* "w$": last visible line */
20576 {
Bram Moolenaarf740b292006-02-16 22:11:02 +000020577 validate_botline();
Bram Moolenaarf52c7252006-02-10 23:23:57 +000020578 pos.lnum = curwin->w_botline - 1;
20579 return &pos;
20580 }
20581 }
20582 else if (name[0] == '$') /* last column or line */
Bram Moolenaar071d4272004-06-13 20:20:40 +000020583 {
Bram Moolenaar477933c2007-07-17 14:32:23 +000020584 if (dollar_lnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020585 {
20586 pos.lnum = curbuf->b_ml.ml_line_count;
20587 pos.col = 0;
20588 }
20589 else
20590 {
20591 pos.lnum = curwin->w_cursor.lnum;
20592 pos.col = (colnr_T)STRLEN(ml_get_curline());
20593 }
20594 return &pos;
20595 }
20596 return NULL;
20597}
20598
20599/*
Bram Moolenaar0e34f622006-03-03 23:00:03 +000020600 * Convert list in "arg" into a position and optional file number.
20601 * When "fnump" is NULL there is no file number, only 3 items.
20602 * Note that the column is passed on as-is, the caller may want to decrement
20603 * it to use 1 for the first column.
20604 * Return FAIL when conversion is not possible, doesn't check the position for
20605 * validity.
20606 */
20607 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010020608list2fpos(
20609 typval_T *arg,
20610 pos_T *posp,
20611 int *fnump,
20612 colnr_T *curswantp)
Bram Moolenaar0e34f622006-03-03 23:00:03 +000020613{
20614 list_T *l = arg->vval.v_list;
20615 long i = 0;
20616 long n;
20617
Bram Moolenaar493c1782014-05-28 14:34:46 +020020618 /* List must be: [fnum, lnum, col, coladd, curswant], where "fnum" is only
20619 * there when "fnump" isn't NULL; "coladd" and "curswant" are optional. */
Bram Moolenaarbde35262006-07-23 20:12:24 +000020620 if (arg->v_type != VAR_LIST
20621 || l == NULL
20622 || l->lv_len < (fnump == NULL ? 2 : 3)
Bram Moolenaar493c1782014-05-28 14:34:46 +020020623 || l->lv_len > (fnump == NULL ? 4 : 5))
Bram Moolenaar0e34f622006-03-03 23:00:03 +000020624 return FAIL;
20625
20626 if (fnump != NULL)
20627 {
20628 n = list_find_nr(l, i++, NULL); /* fnum */
20629 if (n < 0)
20630 return FAIL;
20631 if (n == 0)
20632 n = curbuf->b_fnum; /* current buffer */
20633 *fnump = n;
20634 }
20635
20636 n = list_find_nr(l, i++, NULL); /* lnum */
20637 if (n < 0)
20638 return FAIL;
20639 posp->lnum = n;
20640
20641 n = list_find_nr(l, i++, NULL); /* col */
20642 if (n < 0)
20643 return FAIL;
20644 posp->col = n;
20645
20646#ifdef FEAT_VIRTUALEDIT
Bram Moolenaar493c1782014-05-28 14:34:46 +020020647 n = list_find_nr(l, i, NULL); /* off */
Bram Moolenaar0e34f622006-03-03 23:00:03 +000020648 if (n < 0)
Bram Moolenaarbde35262006-07-23 20:12:24 +000020649 posp->coladd = 0;
20650 else
20651 posp->coladd = n;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000020652#endif
20653
Bram Moolenaar493c1782014-05-28 14:34:46 +020020654 if (curswantp != NULL)
20655 *curswantp = list_find_nr(l, i + 1, NULL); /* curswant */
20656
Bram Moolenaar0e34f622006-03-03 23:00:03 +000020657 return OK;
20658}
20659
20660/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000020661 * Get the length of an environment variable name.
20662 * Advance "arg" to the first character after the name.
20663 * Return 0 for error.
20664 */
20665 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010020666get_env_len(char_u **arg)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020667{
20668 char_u *p;
20669 int len;
20670
20671 for (p = *arg; vim_isIDc(*p); ++p)
20672 ;
20673 if (p == *arg) /* no name found */
20674 return 0;
20675
20676 len = (int)(p - *arg);
20677 *arg = p;
20678 return len;
20679}
20680
20681/*
20682 * Get the length of the name of a function or internal variable.
20683 * "arg" is advanced to the first non-white character after the name.
20684 * Return 0 if something is wrong.
20685 */
20686 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010020687get_id_len(char_u **arg)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020688{
20689 char_u *p;
20690 int len;
20691
20692 /* Find the end of the name. */
20693 for (p = *arg; eval_isnamec(*p); ++p)
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +010020694 {
20695 if (*p == ':')
20696 {
20697 /* "s:" is start of "s:var", but "n:" is not and can be used in
20698 * slice "[n:]". Also "xx:" is not a namespace. */
20699 len = (int)(p - *arg);
20700 if ((len == 1 && vim_strchr(NAMESPACE_CHAR, **arg) == NULL)
20701 || len > 1)
20702 break;
20703 }
20704 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000020705 if (p == *arg) /* no name found */
20706 return 0;
20707
20708 len = (int)(p - *arg);
20709 *arg = skipwhite(p);
20710
20711 return len;
20712}
20713
20714/*
Bram Moolenaara7043832005-01-21 11:56:39 +000020715 * Get the length of the name of a variable or function.
20716 * Only the name is recognized, does not handle ".key" or "[idx]".
Bram Moolenaar071d4272004-06-13 20:20:40 +000020717 * "arg" is advanced to the first non-white character after the name.
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020718 * Return -1 if curly braces expansion failed.
20719 * Return 0 if something else is wrong.
Bram Moolenaar071d4272004-06-13 20:20:40 +000020720 * If the name contains 'magic' {}'s, expand them and return the
20721 * expanded name in an allocated string via 'alias' - caller must free.
20722 */
20723 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010020724get_name_len(
20725 char_u **arg,
20726 char_u **alias,
20727 int evaluate,
20728 int verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020729{
20730 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020731 char_u *p;
20732 char_u *expr_start;
20733 char_u *expr_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020734
20735 *alias = NULL; /* default to no alias */
20736
20737 if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
20738 && (*arg)[2] == (int)KE_SNR)
20739 {
20740 /* hard coded <SNR>, already translated */
20741 *arg += 3;
20742 return get_id_len(arg) + 3;
20743 }
20744 len = eval_fname_script(*arg);
20745 if (len > 0)
20746 {
20747 /* literal "<SID>", "s:" or "<SNR>" */
20748 *arg += len;
20749 }
20750
Bram Moolenaar071d4272004-06-13 20:20:40 +000020751 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020752 * Find the end of the name; check for {} construction.
Bram Moolenaar071d4272004-06-13 20:20:40 +000020753 */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000020754 p = find_name_end(*arg, &expr_start, &expr_end,
20755 len > 0 ? 0 : FNE_CHECK_START);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020756 if (expr_start != NULL)
20757 {
20758 char_u *temp_string;
20759
20760 if (!evaluate)
20761 {
20762 len += (int)(p - *arg);
20763 *arg = skipwhite(p);
20764 return len;
20765 }
20766
20767 /*
20768 * Include any <SID> etc in the expanded string:
20769 * Thus the -len here.
20770 */
20771 temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
20772 if (temp_string == NULL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020773 return -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020774 *alias = temp_string;
20775 *arg = skipwhite(p);
20776 return (int)STRLEN(temp_string);
20777 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000020778
20779 len += get_id_len(arg);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020780 if (len == 0 && verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020781 EMSG2(_(e_invexpr2), *arg);
20782
20783 return len;
20784}
20785
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020786/*
20787 * Find the end of a variable or function name, taking care of magic braces.
20788 * If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the
20789 * start and end of the first magic braces item.
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000020790 * "flags" can have FNE_INCL_BR and FNE_CHECK_START.
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020791 * Return a pointer to just after the name. Equal to "arg" if there is no
20792 * valid name.
20793 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000020794 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010020795find_name_end(
20796 char_u *arg,
20797 char_u **expr_start,
20798 char_u **expr_end,
20799 int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020800{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020801 int mb_nest = 0;
20802 int br_nest = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020803 char_u *p;
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +010020804 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020805
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020806 if (expr_start != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020807 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020808 *expr_start = NULL;
20809 *expr_end = NULL;
20810 }
20811
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000020812 /* Quick check for valid starting character. */
20813 if ((flags & FNE_CHECK_START) && !eval_isnamec1(*arg) && *arg != '{')
20814 return arg;
20815
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020816 for (p = arg; *p != NUL
20817 && (eval_isnamec(*p)
Bram Moolenaare9a41262005-01-15 22:18:47 +000020818 || *p == '{'
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000020819 || ((flags & FNE_INCL_BR) && (*p == '[' || *p == '.'))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020820 || mb_nest != 0
Bram Moolenaar8af24422005-08-08 22:06:28 +000020821 || br_nest != 0); mb_ptr_adv(p))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020822 {
Bram Moolenaar8af24422005-08-08 22:06:28 +000020823 if (*p == '\'')
20824 {
20825 /* skip over 'string' to avoid counting [ and ] inside it. */
20826 for (p = p + 1; *p != NUL && *p != '\''; mb_ptr_adv(p))
20827 ;
20828 if (*p == NUL)
20829 break;
20830 }
20831 else if (*p == '"')
20832 {
20833 /* skip over "str\"ing" to avoid counting [ and ] inside it. */
20834 for (p = p + 1; *p != NUL && *p != '"'; mb_ptr_adv(p))
20835 if (*p == '\\' && p[1] != NUL)
20836 ++p;
20837 if (*p == NUL)
20838 break;
20839 }
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +010020840 else if (br_nest == 0 && mb_nest == 0 && *p == ':')
20841 {
20842 /* "s:" is start of "s:var", but "n:" is not and can be used in
Bram Moolenaar4119cf82016-01-17 14:59:01 +010020843 * slice "[n:]". Also "xx:" is not a namespace. But {ns}: is. */
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +010020844 len = (int)(p - arg);
20845 if ((len == 1 && vim_strchr(NAMESPACE_CHAR, *arg) == NULL)
Bram Moolenaar4119cf82016-01-17 14:59:01 +010020846 || (len > 1 && p[-1] != '}'))
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +010020847 break;
20848 }
Bram Moolenaar8af24422005-08-08 22:06:28 +000020849
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020850 if (mb_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020851 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020852 if (*p == '[')
20853 ++br_nest;
20854 else if (*p == ']')
20855 --br_nest;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020856 }
Bram Moolenaar8af24422005-08-08 22:06:28 +000020857
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020858 if (br_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020859 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020860 if (*p == '{')
20861 {
20862 mb_nest++;
20863 if (expr_start != NULL && *expr_start == NULL)
20864 *expr_start = p;
20865 }
20866 else if (*p == '}')
20867 {
20868 mb_nest--;
20869 if (expr_start != NULL && mb_nest == 0 && *expr_end == NULL)
20870 *expr_end = p;
20871 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000020872 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000020873 }
20874
20875 return p;
20876}
20877
20878/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020879 * Expands out the 'magic' {}'s in a variable/function name.
20880 * Note that this can call itself recursively, to deal with
20881 * constructs like foo{bar}{baz}{bam}
20882 * The four pointer arguments point to "foo{expre}ss{ion}bar"
20883 * "in_start" ^
20884 * "expr_start" ^
20885 * "expr_end" ^
20886 * "in_end" ^
20887 *
20888 * Returns a new allocated string, which the caller must free.
20889 * Returns NULL for failure.
20890 */
20891 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010020892make_expanded_name(
20893 char_u *in_start,
20894 char_u *expr_start,
20895 char_u *expr_end,
20896 char_u *in_end)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020897{
20898 char_u c1;
20899 char_u *retval = NULL;
20900 char_u *temp_result;
20901 char_u *nextcmd = NULL;
20902
20903 if (expr_end == NULL || in_end == NULL)
20904 return NULL;
20905 *expr_start = NUL;
20906 *expr_end = NUL;
20907 c1 = *in_end;
20908 *in_end = NUL;
20909
Bram Moolenaar362e1a32006-03-06 23:29:24 +000020910 temp_result = eval_to_string(expr_start + 1, &nextcmd, FALSE);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020911 if (temp_result != NULL && nextcmd == NULL)
20912 {
20913 retval = alloc((unsigned)(STRLEN(temp_result) + (expr_start - in_start)
20914 + (in_end - expr_end) + 1));
20915 if (retval != NULL)
20916 {
20917 STRCPY(retval, in_start);
20918 STRCAT(retval, temp_result);
20919 STRCAT(retval, expr_end + 1);
20920 }
20921 }
20922 vim_free(temp_result);
20923
20924 *in_end = c1; /* put char back for error messages */
20925 *expr_start = '{';
20926 *expr_end = '}';
20927
20928 if (retval != NULL)
20929 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000020930 temp_result = find_name_end(retval, &expr_start, &expr_end, 0);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020931 if (expr_start != NULL)
20932 {
20933 /* Further expansion! */
20934 temp_result = make_expanded_name(retval, expr_start,
20935 expr_end, temp_result);
20936 vim_free(retval);
20937 retval = temp_result;
20938 }
20939 }
20940
20941 return retval;
20942}
20943
20944/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000020945 * Return TRUE if character "c" can be used in a variable or function name.
Bram Moolenaare9a41262005-01-15 22:18:47 +000020946 * Does not include '{' or '}' for magic braces.
Bram Moolenaar071d4272004-06-13 20:20:40 +000020947 */
20948 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010020949eval_isnamec(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020950{
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000020951 return (ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR);
20952}
20953
20954/*
20955 * Return TRUE if character "c" can be used as the first character in a
20956 * variable or function name (excluding '{' and '}').
20957 */
20958 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010020959eval_isnamec1(int c)
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000020960{
20961 return (ASCII_ISALPHA(c) || c == '_');
Bram Moolenaar071d4272004-06-13 20:20:40 +000020962}
20963
20964/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000020965 * Set number v: variable to "val".
20966 */
20967 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010020968set_vim_var_nr(int idx, long val)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020969{
Bram Moolenaare9a41262005-01-15 22:18:47 +000020970 vimvars[idx].vv_nr = val;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020971}
20972
20973/*
Bram Moolenaar19a09a12005-03-04 23:39:37 +000020974 * Get number v: variable value.
Bram Moolenaar071d4272004-06-13 20:20:40 +000020975 */
20976 long
Bram Moolenaar7454a062016-01-30 15:14:10 +010020977get_vim_var_nr(int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020978{
Bram Moolenaare9a41262005-01-15 22:18:47 +000020979 return vimvars[idx].vv_nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020980}
20981
Bram Moolenaar19a09a12005-03-04 23:39:37 +000020982/*
20983 * Get string v: variable value. Uses a static buffer, can only be used once.
20984 */
20985 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010020986get_vim_var_str(int idx)
Bram Moolenaar19a09a12005-03-04 23:39:37 +000020987{
20988 return get_tv_string(&vimvars[idx].vv_tv);
20989}
Bram Moolenaar19a09a12005-03-04 23:39:37 +000020990
Bram Moolenaar071d4272004-06-13 20:20:40 +000020991/*
Bram Moolenaard812df62008-11-09 12:46:09 +000020992 * Get List v: variable value. Caller must take care of reference count when
20993 * needed.
20994 */
20995 list_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +010020996get_vim_var_list(int idx)
Bram Moolenaard812df62008-11-09 12:46:09 +000020997{
20998 return vimvars[idx].vv_list;
20999}
21000
21001/*
Bram Moolenaarda9591e2009-09-30 13:17:02 +000021002 * Set v:char to character "c".
21003 */
21004 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010021005set_vim_var_char(int c)
Bram Moolenaarda9591e2009-09-30 13:17:02 +000021006{
Bram Moolenaar9a920d82012-06-01 15:21:02 +020021007 char_u buf[MB_MAXBYTES + 1];
Bram Moolenaarda9591e2009-09-30 13:17:02 +000021008
21009#ifdef FEAT_MBYTE
21010 if (has_mbyte)
21011 buf[(*mb_char2bytes)(c, buf)] = NUL;
21012 else
21013#endif
21014 {
21015 buf[0] = c;
21016 buf[1] = NUL;
21017 }
21018 set_vim_var_string(VV_CHAR, buf, -1);
21019}
21020
21021/*
Bram Moolenaar8df74be2008-11-20 15:12:02 +000021022 * Set v:count to "count" and v:count1 to "count1".
21023 * When "set_prevcount" is TRUE first set v:prevcount from v:count.
Bram Moolenaar071d4272004-06-13 20:20:40 +000021024 */
21025 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010021026set_vcount(
21027 long count,
21028 long count1,
21029 int set_prevcount)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021030{
Bram Moolenaar8df74be2008-11-20 15:12:02 +000021031 if (set_prevcount)
21032 vimvars[VV_PREVCOUNT].vv_nr = vimvars[VV_COUNT].vv_nr;
Bram Moolenaare9a41262005-01-15 22:18:47 +000021033 vimvars[VV_COUNT].vv_nr = count;
21034 vimvars[VV_COUNT1].vv_nr = count1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021035}
21036
21037/*
21038 * Set string v: variable to a copy of "val".
21039 */
21040 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010021041set_vim_var_string(
21042 int idx,
21043 char_u *val,
21044 int len) /* length of "val" to use or -1 (whole string) */
Bram Moolenaar071d4272004-06-13 20:20:40 +000021045{
Bram Moolenaara542c682016-01-31 16:28:04 +010021046 clear_tv(&vimvars[idx].vv_di.di_tv);
21047 vimvars[idx].vv_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021048 if (val == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000021049 vimvars[idx].vv_str = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021050 else if (len == -1)
Bram Moolenaare9a41262005-01-15 22:18:47 +000021051 vimvars[idx].vv_str = vim_strsave(val);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021052 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000021053 vimvars[idx].vv_str = vim_strnsave(val, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021054}
21055
21056/*
Bram Moolenaard812df62008-11-09 12:46:09 +000021057 * Set List v: variable to "val".
21058 */
21059 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010021060set_vim_var_list(int idx, list_T *val)
Bram Moolenaard812df62008-11-09 12:46:09 +000021061{
Bram Moolenaara542c682016-01-31 16:28:04 +010021062 clear_tv(&vimvars[idx].vv_di.di_tv);
21063 vimvars[idx].vv_type = VAR_LIST;
Bram Moolenaard812df62008-11-09 12:46:09 +000021064 vimvars[idx].vv_list = val;
21065 if (val != NULL)
21066 ++val->lv_refcount;
21067}
21068
21069/*
Bram Moolenaar42a45122015-07-10 17:56:23 +020021070 * Set Dictionary v: variable to "val".
21071 */
21072 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010021073set_vim_var_dict(int idx, dict_T *val)
Bram Moolenaar42a45122015-07-10 17:56:23 +020021074{
21075 int todo;
21076 hashitem_T *hi;
21077
Bram Moolenaara542c682016-01-31 16:28:04 +010021078 clear_tv(&vimvars[idx].vv_di.di_tv);
21079 vimvars[idx].vv_type = VAR_DICT;
Bram Moolenaar42a45122015-07-10 17:56:23 +020021080 vimvars[idx].vv_dict = val;
21081 if (val != NULL)
21082 {
21083 ++val->dv_refcount;
21084
21085 /* Set readonly */
21086 todo = (int)val->dv_hashtab.ht_used;
21087 for (hi = val->dv_hashtab.ht_array; todo > 0 ; ++hi)
21088 {
21089 if (HASHITEM_EMPTY(hi))
21090 continue;
21091 --todo;
21092 HI2DI(hi)->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
21093 }
21094 }
21095}
21096
21097/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000021098 * Set v:register if needed.
21099 */
21100 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010021101set_reg_var(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021102{
21103 char_u regname;
21104
21105 if (c == 0 || c == ' ')
21106 regname = '"';
21107 else
21108 regname = c;
21109 /* Avoid free/alloc when the value is already right. */
Bram Moolenaare9a41262005-01-15 22:18:47 +000021110 if (vimvars[VV_REG].vv_str == NULL || vimvars[VV_REG].vv_str[0] != c)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021111 set_vim_var_string(VV_REG, &regname, 1);
21112}
21113
21114/*
21115 * Get or set v:exception. If "oldval" == NULL, return the current value.
21116 * Otherwise, restore the value to "oldval" and return NULL.
21117 * Must always be called in pairs to save and restore v:exception! Does not
21118 * take care of memory allocations.
21119 */
21120 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010021121v_exception(char_u *oldval)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021122{
21123 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000021124 return vimvars[VV_EXCEPTION].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021125
Bram Moolenaare9a41262005-01-15 22:18:47 +000021126 vimvars[VV_EXCEPTION].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021127 return NULL;
21128}
21129
21130/*
21131 * Get or set v:throwpoint. If "oldval" == NULL, return the current value.
21132 * Otherwise, restore the value to "oldval" and return NULL.
21133 * Must always be called in pairs to save and restore v:throwpoint! Does not
21134 * take care of memory allocations.
21135 */
21136 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010021137v_throwpoint(char_u *oldval)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021138{
21139 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000021140 return vimvars[VV_THROWPOINT].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021141
Bram Moolenaare9a41262005-01-15 22:18:47 +000021142 vimvars[VV_THROWPOINT].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021143 return NULL;
21144}
21145
21146#if defined(FEAT_AUTOCMD) || defined(PROTO)
21147/*
21148 * Set v:cmdarg.
21149 * If "eap" != NULL, use "eap" to generate the value and return the old value.
21150 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
21151 * Must always be called in pairs!
21152 */
21153 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010021154set_cmdarg(exarg_T *eap, char_u *oldarg)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021155{
21156 char_u *oldval;
21157 char_u *newval;
21158 unsigned len;
21159
Bram Moolenaare9a41262005-01-15 22:18:47 +000021160 oldval = vimvars[VV_CMDARG].vv_str;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000021161 if (eap == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021162 {
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000021163 vim_free(oldval);
Bram Moolenaare9a41262005-01-15 22:18:47 +000021164 vimvars[VV_CMDARG].vv_str = oldarg;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000021165 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021166 }
21167
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000021168 if (eap->force_bin == FORCE_BIN)
21169 len = 6;
21170 else if (eap->force_bin == FORCE_NOBIN)
21171 len = 8;
21172 else
21173 len = 0;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000021174
21175 if (eap->read_edit)
21176 len += 7;
21177
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000021178 if (eap->force_ff != 0)
21179 len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6;
21180# ifdef FEAT_MBYTE
21181 if (eap->force_enc != 0)
21182 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
Bram Moolenaar34b4daf2010-05-16 13:26:25 +020021183 if (eap->bad_char != 0)
21184 len += 7 + 4; /* " ++bad=" + "keep" or "drop" */
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000021185# endif
21186
21187 newval = alloc(len + 1);
21188 if (newval == NULL)
21189 return NULL;
21190
21191 if (eap->force_bin == FORCE_BIN)
21192 sprintf((char *)newval, " ++bin");
21193 else if (eap->force_bin == FORCE_NOBIN)
21194 sprintf((char *)newval, " ++nobin");
21195 else
21196 *newval = NUL;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000021197
21198 if (eap->read_edit)
21199 STRCAT(newval, " ++edit");
21200
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000021201 if (eap->force_ff != 0)
21202 sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
21203 eap->cmd + eap->force_ff);
21204# ifdef FEAT_MBYTE
21205 if (eap->force_enc != 0)
21206 sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
21207 eap->cmd + eap->force_enc);
Bram Moolenaar34b4daf2010-05-16 13:26:25 +020021208 if (eap->bad_char == BAD_KEEP)
21209 STRCPY(newval + STRLEN(newval), " ++bad=keep");
21210 else if (eap->bad_char == BAD_DROP)
21211 STRCPY(newval + STRLEN(newval), " ++bad=drop");
21212 else if (eap->bad_char != 0)
21213 sprintf((char *)newval + STRLEN(newval), " ++bad=%c", eap->bad_char);
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000021214# endif
Bram Moolenaare9a41262005-01-15 22:18:47 +000021215 vimvars[VV_CMDARG].vv_str = newval;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000021216 return oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021217}
21218#endif
21219
21220/*
21221 * Get the value of internal variable "name".
21222 * Return OK or FAIL.
21223 */
21224 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010021225get_var_tv(
21226 char_u *name,
21227 int len, /* length of "name" */
21228 typval_T *rettv, /* NULL when only checking existence */
21229 dictitem_T **dip, /* non-NULL when typval's dict item is needed */
21230 int verbose, /* may give error message */
21231 int no_autoload) /* do not use script autoloading */
Bram Moolenaar071d4272004-06-13 20:20:40 +000021232{
21233 int ret = OK;
Bram Moolenaar33570922005-01-25 22:26:29 +000021234 typval_T *tv = NULL;
21235 typval_T atv;
21236 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021237 int cc;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021238
21239 /* truncate the name, so that we can use strcmp() */
21240 cc = name[len];
21241 name[len] = NUL;
21242
21243 /*
21244 * Check for "b:changedtick".
21245 */
21246 if (STRCMP(name, "b:changedtick") == 0)
21247 {
Bram Moolenaare9a41262005-01-15 22:18:47 +000021248 atv.v_type = VAR_NUMBER;
21249 atv.vval.v_number = curbuf->b_changedtick;
21250 tv = &atv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021251 }
21252
21253 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +000021254 * Check for user-defined variables.
21255 */
21256 else
21257 {
Bram Moolenaar6d977d62014-01-14 15:24:39 +010021258 v = find_var(name, NULL, no_autoload);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021259 if (v != NULL)
Bram Moolenaar1cd5e612015-05-04 11:10:27 +020021260 {
Bram Moolenaar33570922005-01-25 22:26:29 +000021261 tv = &v->di_tv;
Bram Moolenaar1cd5e612015-05-04 11:10:27 +020021262 if (dip != NULL)
21263 *dip = v;
21264 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000021265 }
21266
Bram Moolenaare9a41262005-01-15 22:18:47 +000021267 if (tv == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021268 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000021269 if (rettv != NULL && verbose)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021270 EMSG2(_(e_undefvar), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021271 ret = FAIL;
21272 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021273 else if (rettv != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000021274 copy_tv(tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021275
21276 name[len] = cc;
21277
21278 return ret;
21279}
21280
21281/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000021282 * Handle expr[expr], expr[expr:expr] subscript and .name lookup.
21283 * Also handle function call with Funcref variable: func(expr)
21284 * Can all be combined: dict.func(expr)[idx]['func'](expr)
21285 */
21286 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010021287handle_subscript(
21288 char_u **arg,
21289 typval_T *rettv,
21290 int evaluate, /* do more than finding the end */
21291 int verbose) /* give error messages */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000021292{
21293 int ret = OK;
21294 dict_T *selfdict = NULL;
21295 char_u *s;
21296 int len;
Bram Moolenaard9fba312005-06-26 22:34:35 +000021297 typval_T functv;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000021298
21299 while (ret == OK
21300 && (**arg == '['
21301 || (**arg == '.' && rettv->v_type == VAR_DICT)
Bram Moolenaar0f8de8d2013-11-11 04:25:53 +010021302 || (**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC)))
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000021303 && !vim_iswhite(*(*arg - 1)))
21304 {
21305 if (**arg == '(')
21306 {
Bram Moolenaard9fba312005-06-26 22:34:35 +000021307 /* need to copy the funcref so that we can clear rettv */
Bram Moolenaar0f8de8d2013-11-11 04:25:53 +010021308 if (evaluate)
21309 {
21310 functv = *rettv;
21311 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000021312
Bram Moolenaar0f8de8d2013-11-11 04:25:53 +010021313 /* Invoke the function. Recursive! */
21314 s = functv.vval.v_string;
21315 }
21316 else
21317 s = (char_u *)"";
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000021318 ret = get_func_tv(s, (int)STRLEN(s), rettv, arg,
Bram Moolenaard9fba312005-06-26 22:34:35 +000021319 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
21320 &len, evaluate, selfdict);
21321
21322 /* Clear the funcref afterwards, so that deleting it while
21323 * evaluating the arguments is possible (see test55). */
Bram Moolenaar0f8de8d2013-11-11 04:25:53 +010021324 if (evaluate)
21325 clear_tv(&functv);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000021326
21327 /* Stop the expression evaluation when immediately aborting on
21328 * error, or when an interrupt occurred or an exception was thrown
21329 * but not caught. */
21330 if (aborting())
21331 {
21332 if (ret == OK)
21333 clear_tv(rettv);
21334 ret = FAIL;
21335 }
21336 dict_unref(selfdict);
21337 selfdict = NULL;
21338 }
21339 else /* **arg == '[' || **arg == '.' */
21340 {
21341 dict_unref(selfdict);
21342 if (rettv->v_type == VAR_DICT)
21343 {
21344 selfdict = rettv->vval.v_dict;
21345 if (selfdict != NULL)
21346 ++selfdict->dv_refcount;
21347 }
21348 else
21349 selfdict = NULL;
21350 if (eval_index(arg, rettv, evaluate, verbose) == FAIL)
21351 {
21352 clear_tv(rettv);
21353 ret = FAIL;
21354 }
21355 }
21356 }
21357 dict_unref(selfdict);
21358 return ret;
21359}
21360
21361/*
Bram Moolenaar8c8de832008-06-24 22:58:06 +000021362 * Allocate memory for a variable type-value, and make it empty (0 or NULL
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021363 * value).
21364 */
Bram Moolenaar11e0afa2016-02-01 22:41:00 +010021365 typval_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +010021366alloc_tv(void)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021367{
Bram Moolenaar33570922005-01-25 22:26:29 +000021368 return (typval_T *)alloc_clear((unsigned)sizeof(typval_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021369}
21370
21371/*
21372 * Allocate memory for a variable type-value, and assign a string to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000021373 * The string "s" must have been allocated, it is consumed.
21374 * Return NULL for out of memory, the variable otherwise.
21375 */
Bram Moolenaar33570922005-01-25 22:26:29 +000021376 static typval_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +010021377alloc_string_tv(char_u *s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021378{
Bram Moolenaar33570922005-01-25 22:26:29 +000021379 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021380
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021381 rettv = alloc_tv();
21382 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021383 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021384 rettv->v_type = VAR_STRING;
21385 rettv->vval.v_string = s;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021386 }
21387 else
21388 vim_free(s);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021389 return rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021390}
21391
21392/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021393 * Free the memory for a variable type-value.
Bram Moolenaar071d4272004-06-13 20:20:40 +000021394 */
Bram Moolenaar4770d092006-01-12 23:22:24 +000021395 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010021396free_tv(typval_T *varp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021397{
21398 if (varp != NULL)
21399 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021400 switch (varp->v_type)
21401 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021402 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021403 func_unref(varp->vval.v_string);
21404 /*FALLTHROUGH*/
21405 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021406 vim_free(varp->vval.v_string);
21407 break;
21408 case VAR_LIST:
21409 list_unref(varp->vval.v_list);
21410 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021411 case VAR_DICT:
21412 dict_unref(varp->vval.v_dict);
21413 break;
Bram Moolenaar835dc632016-02-07 14:27:38 +010021414 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +010021415#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +010021416 job_unref(varp->vval.v_job);
21417 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000021418#endif
Bram Moolenaar77073442016-02-13 23:23:53 +010021419 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +010021420#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +010021421 channel_unref(varp->vval.v_channel);
21422 break;
21423#endif
Bram Moolenaar835dc632016-02-07 14:27:38 +010021424 case VAR_NUMBER:
21425 case VAR_FLOAT:
Bram Moolenaar758711c2005-02-02 23:11:38 +000021426 case VAR_UNKNOWN:
Bram Moolenaar6650a692016-01-26 19:59:10 +010021427 case VAR_SPECIAL:
Bram Moolenaar758711c2005-02-02 23:11:38 +000021428 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021429 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000021430 vim_free(varp);
21431 }
21432}
21433
21434/*
21435 * Free the memory for a variable value and set the value to NULL or 0.
21436 */
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000021437 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010021438clear_tv(typval_T *varp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021439{
21440 if (varp != NULL)
21441 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021442 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021443 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021444 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021445 func_unref(varp->vval.v_string);
21446 /*FALLTHROUGH*/
21447 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021448 vim_free(varp->vval.v_string);
21449 varp->vval.v_string = NULL;
21450 break;
21451 case VAR_LIST:
21452 list_unref(varp->vval.v_list);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000021453 varp->vval.v_list = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021454 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000021455 case VAR_DICT:
21456 dict_unref(varp->vval.v_dict);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000021457 varp->vval.v_dict = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +000021458 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021459 case VAR_NUMBER:
Bram Moolenaar520e1e42016-01-23 19:46:28 +010021460 case VAR_SPECIAL:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021461 varp->vval.v_number = 0;
21462 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000021463 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +010021464#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +000021465 varp->vval.v_float = 0.0;
21466 break;
21467#endif
Bram Moolenaar835dc632016-02-07 14:27:38 +010021468 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +010021469#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +010021470 job_unref(varp->vval.v_job);
21471 varp->vval.v_job = NULL;
21472#endif
21473 break;
Bram Moolenaar77073442016-02-13 23:23:53 +010021474 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +010021475#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +010021476 channel_unref(varp->vval.v_channel);
21477 varp->vval.v_channel = NULL;
21478#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021479 case VAR_UNKNOWN:
21480 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021481 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000021482 varp->v_lock = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021483 }
21484}
21485
21486/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021487 * Set the value of a variable to NULL without freeing items.
21488 */
21489 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010021490init_tv(typval_T *varp)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021491{
21492 if (varp != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000021493 vim_memset(varp, 0, sizeof(typval_T));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021494}
21495
21496/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000021497 * Get the number value of a variable.
21498 * If it is a String variable, uses vim_str2nr().
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000021499 * For incompatible types, return 0.
21500 * get_tv_number_chk() is similar to get_tv_number(), but informs the
21501 * caller of incompatible types: it sets *denote to TRUE if "denote"
21502 * is not NULL or returns -1 otherwise.
Bram Moolenaar071d4272004-06-13 20:20:40 +000021503 */
Bram Moolenaar8e2c9422016-03-12 13:43:33 +010021504 long
Bram Moolenaar7454a062016-01-30 15:14:10 +010021505get_tv_number(typval_T *varp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021506{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000021507 int error = FALSE;
21508
21509 return get_tv_number_chk(varp, &error); /* return 0L on error */
21510}
21511
Bram Moolenaar4be06f92005-07-29 22:36:03 +000021512 long
Bram Moolenaar7454a062016-01-30 15:14:10 +010021513get_tv_number_chk(typval_T *varp, int *denote)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000021514{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021515 long n = 0L;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021516
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021517 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021518 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021519 case VAR_NUMBER:
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000021520 return (long)(varp->vval.v_number);
Bram Moolenaar8c8de832008-06-24 22:58:06 +000021521 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +010021522#ifdef FEAT_FLOAT
Bram Moolenaared0e7452008-06-27 19:17:34 +000021523 EMSG(_("E805: Using a Float as a Number"));
Bram Moolenaar8c8de832008-06-24 22:58:06 +000021524 break;
21525#endif
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021526 case VAR_FUNC:
Bram Moolenaared0e7452008-06-27 19:17:34 +000021527 EMSG(_("E703: Using a Funcref as a Number"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021528 break;
21529 case VAR_STRING:
21530 if (varp->vval.v_string != NULL)
21531 vim_str2nr(varp->vval.v_string, NULL, NULL,
Bram Moolenaar887c1fe2016-01-02 17:56:35 +010021532 STR2NR_ALL, &n, NULL, 0);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000021533 return n;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000021534 case VAR_LIST:
Bram Moolenaared0e7452008-06-27 19:17:34 +000021535 EMSG(_("E745: Using a List as a Number"));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000021536 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021537 case VAR_DICT:
Bram Moolenaared0e7452008-06-27 19:17:34 +000021538 EMSG(_("E728: Using a Dictionary as a Number"));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021539 break;
Bram Moolenaar17a13432016-01-24 14:22:10 +010021540 case VAR_SPECIAL:
21541 return varp->vval.v_number == VVAL_TRUE ? 1 : 0;
21542 break;
Bram Moolenaar835dc632016-02-07 14:27:38 +010021543 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +010021544#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +010021545 EMSG(_("E910: Using a Job as a Number"));
21546 break;
21547#endif
Bram Moolenaar77073442016-02-13 23:23:53 +010021548 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +010021549#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +010021550 EMSG(_("E913: Using a Channel as a Number"));
21551 break;
21552#endif
Bram Moolenaara03f2332016-02-06 18:09:59 +010021553 case VAR_UNKNOWN:
21554 EMSG2(_(e_intern2), "get_tv_number(UNKNOWN)");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021555 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021556 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000021557 if (denote == NULL) /* useful for values that must be unsigned */
21558 n = -1;
21559 else
21560 *denote = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021561 return n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021562}
21563
Bram Moolenaarf7edf402016-01-19 23:36:15 +010021564#ifdef FEAT_FLOAT
21565 static float_T
Bram Moolenaar7454a062016-01-30 15:14:10 +010021566get_tv_float(typval_T *varp)
Bram Moolenaarf7edf402016-01-19 23:36:15 +010021567{
21568 switch (varp->v_type)
21569 {
21570 case VAR_NUMBER:
21571 return (float_T)(varp->vval.v_number);
Bram Moolenaarf7edf402016-01-19 23:36:15 +010021572 case VAR_FLOAT:
21573 return varp->vval.v_float;
Bram Moolenaarf7edf402016-01-19 23:36:15 +010021574 case VAR_FUNC:
21575 EMSG(_("E891: Using a Funcref as a Float"));
21576 break;
21577 case VAR_STRING:
21578 EMSG(_("E892: Using a String as a Float"));
21579 break;
21580 case VAR_LIST:
21581 EMSG(_("E893: Using a List as a Float"));
21582 break;
21583 case VAR_DICT:
21584 EMSG(_("E894: Using a Dictionary as a Float"));
21585 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +010021586 case VAR_SPECIAL:
21587 EMSG(_("E907: Using a special value as a Float"));
21588 break;
Bram Moolenaar835dc632016-02-07 14:27:38 +010021589 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +010021590# ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +010021591 EMSG(_("E911: Using a Job as a Float"));
21592 break;
21593# endif
Bram Moolenaar77073442016-02-13 23:23:53 +010021594 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +010021595# ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +010021596 EMSG(_("E914: Using a Channel as a Float"));
21597 break;
21598# endif
Bram Moolenaara03f2332016-02-06 18:09:59 +010021599 case VAR_UNKNOWN:
21600 EMSG2(_(e_intern2), "get_tv_float(UNKNOWN)");
Bram Moolenaarf7edf402016-01-19 23:36:15 +010021601 break;
21602 }
21603 return 0;
21604}
21605#endif
21606
Bram Moolenaar071d4272004-06-13 20:20:40 +000021607/*
Bram Moolenaar661b1822005-07-28 22:36:45 +000021608 * Get the lnum from the first argument.
21609 * Also accepts ".", "$", etc., but that only works for the current buffer.
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000021610 * Returns -1 on error.
Bram Moolenaar071d4272004-06-13 20:20:40 +000021611 */
21612 static linenr_T
Bram Moolenaar7454a062016-01-30 15:14:10 +010021613get_tv_lnum(typval_T *argvars)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021614{
Bram Moolenaar33570922005-01-25 22:26:29 +000021615 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021616 linenr_T lnum;
21617
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000021618 lnum = get_tv_number_chk(&argvars[0], NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021619 if (lnum == 0) /* no valid number, try using line() */
21620 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021621 rettv.v_type = VAR_NUMBER;
21622 f_line(argvars, &rettv);
21623 lnum = rettv.vval.v_number;
21624 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021625 }
21626 return lnum;
21627}
21628
21629/*
Bram Moolenaar661b1822005-07-28 22:36:45 +000021630 * Get the lnum from the first argument.
21631 * Also accepts "$", then "buf" is used.
21632 * Returns 0 on error.
21633 */
21634 static linenr_T
Bram Moolenaar7454a062016-01-30 15:14:10 +010021635get_tv_lnum_buf(typval_T *argvars, buf_T *buf)
Bram Moolenaar661b1822005-07-28 22:36:45 +000021636{
21637 if (argvars[0].v_type == VAR_STRING
21638 && argvars[0].vval.v_string != NULL
21639 && argvars[0].vval.v_string[0] == '$'
21640 && buf != NULL)
21641 return buf->b_ml.ml_line_count;
21642 return get_tv_number_chk(&argvars[0], NULL);
21643}
21644
21645/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000021646 * Get the string value of a variable.
21647 * If it is a Number variable, the number is converted into a string.
Bram Moolenaara7043832005-01-21 11:56:39 +000021648 * get_tv_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
21649 * get_tv_string_buf() uses a given buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +000021650 * If the String variable has never been set, return an empty string.
21651 * Never returns NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000021652 * get_tv_string_chk() and get_tv_string_buf_chk() are similar, but return
21653 * NULL on error.
Bram Moolenaar071d4272004-06-13 20:20:40 +000021654 */
Bram Moolenaar8e2c9422016-03-12 13:43:33 +010021655 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010021656get_tv_string(typval_T *varp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021657{
21658 static char_u mybuf[NUMBUFLEN];
21659
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021660 return get_tv_string_buf(varp, mybuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021661}
21662
Bram Moolenaar8e2c9422016-03-12 13:43:33 +010021663 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010021664get_tv_string_buf(typval_T *varp, char_u *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021665{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000021666 char_u *res = get_tv_string_buf_chk(varp, buf);
21667
21668 return res != NULL ? res : (char_u *)"";
21669}
21670
Bram Moolenaar7d647822014-04-05 21:28:56 +020021671/*
21672 * Careful: This uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
21673 */
Bram Moolenaar4be06f92005-07-29 22:36:03 +000021674 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010021675get_tv_string_chk(typval_T *varp)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000021676{
21677 static char_u mybuf[NUMBUFLEN];
21678
21679 return get_tv_string_buf_chk(varp, mybuf);
21680}
21681
Bram Moolenaar520e1e42016-01-23 19:46:28 +010021682 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010021683get_tv_string_buf_chk(typval_T *varp, char_u *buf)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000021684{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021685 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021686 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021687 case VAR_NUMBER:
21688 sprintf((char *)buf, "%ld", (long)varp->vval.v_number);
21689 return buf;
21690 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021691 EMSG(_("E729: using Funcref as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021692 break;
21693 case VAR_LIST:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021694 EMSG(_("E730: using List as a String"));
Bram Moolenaar8c711452005-01-14 21:53:12 +000021695 break;
21696 case VAR_DICT:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021697 EMSG(_("E731: using Dictionary as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021698 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000021699 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +010021700#ifdef FEAT_FLOAT
Bram Moolenaar2a876e42013-06-12 22:08:58 +020021701 EMSG(_(e_float_as_string));
Bram Moolenaar8c8de832008-06-24 22:58:06 +000021702 break;
21703#endif
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021704 case VAR_STRING:
21705 if (varp->vval.v_string != NULL)
21706 return varp->vval.v_string;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000021707 return (char_u *)"";
Bram Moolenaar17a13432016-01-24 14:22:10 +010021708 case VAR_SPECIAL:
21709 STRCPY(buf, get_var_special_name(varp->vval.v_number));
21710 return buf;
Bram Moolenaar835dc632016-02-07 14:27:38 +010021711 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +010021712#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +010021713 {
21714 job_T *job = varp->vval.v_job;
Bram Moolenaar839fd112016-03-06 21:34:03 +010021715 char *status;
21716
21717 if (job == NULL)
21718 return (char_u *)"no process";
21719 status = job->jv_status == JOB_FAILED ? "fail"
Bram Moolenaar835dc632016-02-07 14:27:38 +010021720 : job->jv_status == JOB_ENDED ? "dead"
21721 : "run";
21722# ifdef UNIX
21723 vim_snprintf((char *)buf, NUMBUFLEN,
21724 "process %ld %s", (long)job->jv_pid, status);
Bram Moolenaar4d8747c2016-02-09 20:39:26 +010021725# elif defined(WIN32)
21726 vim_snprintf((char *)buf, NUMBUFLEN,
Bram Moolenaar76467df2016-02-12 19:30:26 +010021727 "process %ld %s",
21728 (long)job->jv_proc_info.dwProcessId,
Bram Moolenaar4d8747c2016-02-09 20:39:26 +010021729 status);
Bram Moolenaar835dc632016-02-07 14:27:38 +010021730# else
Bram Moolenaar4d8747c2016-02-09 20:39:26 +010021731 /* fall-back */
Bram Moolenaar835dc632016-02-07 14:27:38 +010021732 vim_snprintf((char *)buf, NUMBUFLEN, "process ? %s", status);
21733# endif
21734 return buf;
21735 }
21736#endif
21737 break;
Bram Moolenaar77073442016-02-13 23:23:53 +010021738 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +010021739#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +010021740 {
21741 channel_T *channel = varp->vval.v_channel;
21742 char *status = channel_status(channel);
21743
Bram Moolenaar5cefd402016-02-16 12:44:26 +010021744 if (channel == NULL)
21745 vim_snprintf((char *)buf, NUMBUFLEN, "channel %s", status);
21746 else
21747 vim_snprintf((char *)buf, NUMBUFLEN,
Bram Moolenaar77073442016-02-13 23:23:53 +010021748 "channel %d %s", channel->ch_id, status);
21749 return buf;
21750 }
21751#endif
21752 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +010021753 case VAR_UNKNOWN:
21754 EMSG(_("E908: using an invalid value as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021755 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021756 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000021757 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021758}
21759
21760/*
21761 * Find variable "name" in the list of variables.
21762 * Return a pointer to it if found, NULL if not found.
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021763 * Careful: "a:0" variables don't have a name.
Bram Moolenaara7043832005-01-21 11:56:39 +000021764 * When "htp" is not NULL we are writing to the variable, set "htp" to the
Bram Moolenaar33570922005-01-25 22:26:29 +000021765 * hashtab_T used.
Bram Moolenaar071d4272004-06-13 20:20:40 +000021766 */
Bram Moolenaar33570922005-01-25 22:26:29 +000021767 static dictitem_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +010021768find_var(char_u *name, hashtab_T **htp, int no_autoload)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021769{
Bram Moolenaar071d4272004-06-13 20:20:40 +000021770 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000021771 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021772
Bram Moolenaara7043832005-01-21 11:56:39 +000021773 ht = find_var_ht(name, &varname);
21774 if (htp != NULL)
21775 *htp = ht;
21776 if (ht == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021777 return NULL;
Bram Moolenaar6d977d62014-01-14 15:24:39 +010021778 return find_var_in_ht(ht, *name, varname, no_autoload || htp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021779}
21780
21781/*
Bram Moolenaar332ac062013-04-15 13:06:21 +020021782 * Find variable "varname" in hashtab "ht" with name "htname".
Bram Moolenaara7043832005-01-21 11:56:39 +000021783 * Returns NULL if not found.
Bram Moolenaar071d4272004-06-13 20:20:40 +000021784 */
Bram Moolenaar33570922005-01-25 22:26:29 +000021785 static dictitem_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +010021786find_var_in_ht(
21787 hashtab_T *ht,
21788 int htname,
21789 char_u *varname,
21790 int no_autoload)
Bram Moolenaara7043832005-01-21 11:56:39 +000021791{
Bram Moolenaar33570922005-01-25 22:26:29 +000021792 hashitem_T *hi;
21793
21794 if (*varname == NUL)
21795 {
21796 /* Must be something like "s:", otherwise "ht" would be NULL. */
Bram Moolenaar332ac062013-04-15 13:06:21 +020021797 switch (htname)
Bram Moolenaar33570922005-01-25 22:26:29 +000021798 {
Bram Moolenaar9577c3e2010-05-14 12:16:25 +020021799 case 's': return &SCRIPT_SV(current_SID)->sv_var;
Bram Moolenaar33570922005-01-25 22:26:29 +000021800 case 'g': return &globvars_var;
21801 case 'v': return &vimvars_var;
21802 case 'b': return &curbuf->b_bufvar;
21803 case 'w': return &curwin->w_winvar;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000021804#ifdef FEAT_WINDOWS
21805 case 't': return &curtab->tp_winvar;
21806#endif
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000021807 case 'l': return current_funccal == NULL
21808 ? NULL : &current_funccal->l_vars_var;
21809 case 'a': return current_funccal == NULL
21810 ? NULL : &current_funccal->l_avars_var;
Bram Moolenaar33570922005-01-25 22:26:29 +000021811 }
21812 return NULL;
21813 }
Bram Moolenaara7043832005-01-21 11:56:39 +000021814
21815 hi = hash_find(ht, varname);
21816 if (HASHITEM_EMPTY(hi))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000021817 {
21818 /* For global variables we may try auto-loading the script. If it
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000021819 * worked find the variable again. Don't auto-load a script if it was
21820 * loaded already, otherwise it would be loaded every time when
21821 * checking if a function name is a Funcref variable. */
Bram Moolenaar6d977d62014-01-14 15:24:39 +010021822 if (ht == &globvarht && !no_autoload)
Bram Moolenaar8000baf2011-11-30 15:19:28 +010021823 {
21824 /* Note: script_autoload() may make "hi" invalid. It must either
21825 * be obtained again or not used. */
21826 if (!script_autoload(varname, FALSE) || aborting())
21827 return NULL;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000021828 hi = hash_find(ht, varname);
Bram Moolenaar8000baf2011-11-30 15:19:28 +010021829 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000021830 if (HASHITEM_EMPTY(hi))
21831 return NULL;
21832 }
Bram Moolenaar33570922005-01-25 22:26:29 +000021833 return HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +000021834}
21835
21836/*
Bram Moolenaar33570922005-01-25 22:26:29 +000021837 * Find the hashtab used for a variable name.
Bram Moolenaar73627d02015-08-11 15:46:09 +020021838 * Return NULL if the name is not valid.
Bram Moolenaara7043832005-01-21 11:56:39 +000021839 * Set "varname" to the start of name without ':'.
21840 */
Bram Moolenaar33570922005-01-25 22:26:29 +000021841 static hashtab_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +010021842find_var_ht(char_u *name, char_u **varname)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021843{
Bram Moolenaar75c50c42005-06-04 22:06:24 +000021844 hashitem_T *hi;
21845
Bram Moolenaar73627d02015-08-11 15:46:09 +020021846 if (name[0] == NUL)
21847 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021848 if (name[1] != ':')
21849 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000021850 /* The name must not start with a colon or #. */
21851 if (name[0] == ':' || name[0] == AUTOLOAD_CHAR)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021852 return NULL;
21853 *varname = name;
Bram Moolenaar532c7802005-01-27 14:44:31 +000021854
21855 /* "version" is "v:version" in all scopes */
Bram Moolenaar75c50c42005-06-04 22:06:24 +000021856 hi = hash_find(&compat_hashtab, name);
21857 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar532c7802005-01-27 14:44:31 +000021858 return &compat_hashtab;
21859
Bram Moolenaar071d4272004-06-13 20:20:40 +000021860 if (current_funccal == NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000021861 return &globvarht; /* global variable */
Bram Moolenaarf1f60f82016-01-16 15:40:53 +010021862 return &get_funccal()->l_vars.dv_hashtab; /* l: variable */
Bram Moolenaar071d4272004-06-13 20:20:40 +000021863 }
21864 *varname = name + 2;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000021865 if (*name == 'g') /* global variable */
21866 return &globvarht;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000021867 /* There must be no ':' or '#' in the rest of the name, unless g: is used
21868 */
21869 if (vim_strchr(name + 2, ':') != NULL
21870 || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000021871 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021872 if (*name == 'b') /* buffer variable */
Bram Moolenaar429fa852013-04-15 12:27:36 +020021873 return &curbuf->b_vars->dv_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021874 if (*name == 'w') /* window variable */
Bram Moolenaar429fa852013-04-15 12:27:36 +020021875 return &curwin->w_vars->dv_hashtab;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000021876#ifdef FEAT_WINDOWS
21877 if (*name == 't') /* tab page variable */
Bram Moolenaar429fa852013-04-15 12:27:36 +020021878 return &curtab->tp_vars->dv_hashtab;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000021879#endif
Bram Moolenaar33570922005-01-25 22:26:29 +000021880 if (*name == 'v') /* v: variable */
21881 return &vimvarht;
21882 if (*name == 'a' && current_funccal != NULL) /* function argument */
Bram Moolenaarf1f60f82016-01-16 15:40:53 +010021883 return &get_funccal()->l_avars.dv_hashtab;
Bram Moolenaar33570922005-01-25 22:26:29 +000021884 if (*name == 'l' && current_funccal != NULL) /* local function variable */
Bram Moolenaarf1f60f82016-01-16 15:40:53 +010021885 return &get_funccal()->l_vars.dv_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021886 if (*name == 's' /* script variable */
21887 && current_SID > 0 && current_SID <= ga_scripts.ga_len)
21888 return &SCRIPT_VARS(current_SID);
21889 return NULL;
21890}
21891
21892/*
Bram Moolenaarf1f60f82016-01-16 15:40:53 +010021893 * Get function call environment based on bactrace debug level
21894 */
21895 static funccall_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +010021896get_funccal(void)
Bram Moolenaarf1f60f82016-01-16 15:40:53 +010021897{
21898 int i;
21899 funccall_T *funccal;
21900 funccall_T *temp_funccal;
21901
21902 funccal = current_funccal;
21903 if (debug_backtrace_level > 0)
21904 {
Bram Moolenaarc9703302016-01-17 21:49:33 +010021905 for (i = 0; i < debug_backtrace_level; i++)
21906 {
21907 temp_funccal = funccal->caller;
21908 if (temp_funccal)
21909 funccal = temp_funccal;
Bram Moolenaarf1f60f82016-01-16 15:40:53 +010021910 else
Bram Moolenaarc9703302016-01-17 21:49:33 +010021911 /* backtrace level overflow. reset to max */
21912 debug_backtrace_level = i;
21913 }
Bram Moolenaarf1f60f82016-01-16 15:40:53 +010021914 }
21915 return funccal;
21916}
21917
21918/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000021919 * Get the string value of a (global/local) variable.
Bram Moolenaar1950c352010-06-06 15:21:10 +020021920 * Note: see get_tv_string() for how long the pointer remains valid.
Bram Moolenaar071d4272004-06-13 20:20:40 +000021921 * Returns NULL when it doesn't exist.
21922 */
21923 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010021924get_var_value(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021925{
Bram Moolenaar33570922005-01-25 22:26:29 +000021926 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021927
Bram Moolenaar6d977d62014-01-14 15:24:39 +010021928 v = find_var(name, NULL, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021929 if (v == NULL)
21930 return NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +000021931 return get_tv_string(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021932}
21933
21934/*
Bram Moolenaar33570922005-01-25 22:26:29 +000021935 * Allocate a new hashtab for a sourced script. It will be used while
Bram Moolenaar071d4272004-06-13 20:20:40 +000021936 * sourcing this script and when executing functions defined in the script.
21937 */
21938 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010021939new_script_vars(scid_T id)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021940{
Bram Moolenaara7043832005-01-21 11:56:39 +000021941 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +000021942 hashtab_T *ht;
21943 scriptvar_T *sv;
Bram Moolenaara7043832005-01-21 11:56:39 +000021944
Bram Moolenaar071d4272004-06-13 20:20:40 +000021945 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
21946 {
Bram Moolenaara7043832005-01-21 11:56:39 +000021947 /* Re-allocating ga_data means that an ht_array pointing to
21948 * ht_smallarray becomes invalid. We can recognize this: ht_mask is
Bram Moolenaar33570922005-01-25 22:26:29 +000021949 * at its init value. Also reset "v_dict", it's always the same. */
Bram Moolenaara7043832005-01-21 11:56:39 +000021950 for (i = 1; i <= ga_scripts.ga_len; ++i)
21951 {
21952 ht = &SCRIPT_VARS(i);
21953 if (ht->ht_mask == HT_INIT_SIZE - 1)
21954 ht->ht_array = ht->ht_smallarray;
Bram Moolenaar9577c3e2010-05-14 12:16:25 +020021955 sv = SCRIPT_SV(i);
Bram Moolenaar33570922005-01-25 22:26:29 +000021956 sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict;
Bram Moolenaara7043832005-01-21 11:56:39 +000021957 }
21958
Bram Moolenaar071d4272004-06-13 20:20:40 +000021959 while (ga_scripts.ga_len < id)
21960 {
Bram Moolenaar2c704a72010-06-03 21:17:25 +020021961 sv = SCRIPT_SV(ga_scripts.ga_len + 1) =
Bram Moolenaar9577c3e2010-05-14 12:16:25 +020021962 (scriptvar_T *)alloc_clear(sizeof(scriptvar_T));
Bram Moolenaarbdb62052012-07-16 17:31:53 +020021963 init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021964 ++ga_scripts.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021965 }
21966 }
21967}
21968
21969/*
Bram Moolenaar33570922005-01-25 22:26:29 +000021970 * Initialize dictionary "dict" as a scope and set variable "dict_var" to
21971 * point to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000021972 */
21973 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010021974init_var_dict(dict_T *dict, dictitem_T *dict_var, int scope)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021975{
Bram Moolenaar33570922005-01-25 22:26:29 +000021976 hash_init(&dict->dv_hashtab);
Bram Moolenaared465602012-06-20 14:13:06 +020021977 dict->dv_lock = 0;
Bram Moolenaarbdb62052012-07-16 17:31:53 +020021978 dict->dv_scope = scope;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000021979 dict->dv_refcount = DO_NOT_FREE_CNT;
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +000021980 dict->dv_copyID = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000021981 dict_var->di_tv.vval.v_dict = dict;
21982 dict_var->di_tv.v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000021983 dict_var->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000021984 dict_var->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
21985 dict_var->di_key[0] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021986}
21987
21988/*
Bram Moolenaar429fa852013-04-15 12:27:36 +020021989 * Unreference a dictionary initialized by init_var_dict().
21990 */
21991 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010021992unref_var_dict(dict_T *dict)
Bram Moolenaar429fa852013-04-15 12:27:36 +020021993{
21994 /* Now the dict needs to be freed if no one else is using it, go back to
21995 * normal reference counting. */
21996 dict->dv_refcount -= DO_NOT_FREE_CNT - 1;
21997 dict_unref(dict);
21998}
21999
22000/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000022001 * Clean up a list of internal variables.
Bram Moolenaar33570922005-01-25 22:26:29 +000022002 * Frees all allocated variables and the value they contain.
22003 * Clears hashtab "ht", does not free it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000022004 */
22005 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010022006vars_clear(hashtab_T *ht)
Bram Moolenaar33570922005-01-25 22:26:29 +000022007{
22008 vars_clear_ext(ht, TRUE);
22009}
22010
22011/*
22012 * Like vars_clear(), but only free the value if "free_val" is TRUE.
22013 */
22014 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010022015vars_clear_ext(hashtab_T *ht, int free_val)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022016{
Bram Moolenaara7043832005-01-21 11:56:39 +000022017 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000022018 hashitem_T *hi;
22019 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022020
Bram Moolenaar33570922005-01-25 22:26:29 +000022021 hash_lock(ht);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000022022 todo = (int)ht->ht_used;
Bram Moolenaara7043832005-01-21 11:56:39 +000022023 for (hi = ht->ht_array; todo > 0; ++hi)
22024 {
22025 if (!HASHITEM_EMPTY(hi))
22026 {
22027 --todo;
22028
Bram Moolenaar33570922005-01-25 22:26:29 +000022029 /* Free the variable. Don't remove it from the hashtab,
Bram Moolenaara7043832005-01-21 11:56:39 +000022030 * ht_array might change then. hash_clear() takes care of it
22031 * later. */
Bram Moolenaar33570922005-01-25 22:26:29 +000022032 v = HI2DI(hi);
22033 if (free_val)
22034 clear_tv(&v->di_tv);
Bram Moolenaar9bc174b2015-04-13 16:16:38 +020022035 if (v->di_flags & DI_FLAGS_ALLOC)
Bram Moolenaar33570922005-01-25 22:26:29 +000022036 vim_free(v);
Bram Moolenaara7043832005-01-21 11:56:39 +000022037 }
22038 }
22039 hash_clear(ht);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000022040 ht->ht_used = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022041}
22042
Bram Moolenaara7043832005-01-21 11:56:39 +000022043/*
Bram Moolenaar33570922005-01-25 22:26:29 +000022044 * Delete a variable from hashtab "ht" at item "hi".
22045 * Clear the variable value and free the dictitem.
Bram Moolenaara7043832005-01-21 11:56:39 +000022046 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000022047 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010022048delete_var(hashtab_T *ht, hashitem_T *hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022049{
Bram Moolenaar33570922005-01-25 22:26:29 +000022050 dictitem_T *di = HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +000022051
22052 hash_remove(ht, hi);
Bram Moolenaar33570922005-01-25 22:26:29 +000022053 clear_tv(&di->di_tv);
22054 vim_free(di);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022055}
22056
22057/*
22058 * List the value of one internal variable.
22059 */
22060 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010022061list_one_var(dictitem_T *v, char_u *prefix, int *first)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022062{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022063 char_u *tofree;
22064 char_u *s;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000022065 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022066
Bram Moolenaar520e1e42016-01-23 19:46:28 +010022067 s = echo_string(&v->di_tv, &tofree, numbuf, get_copyID());
Bram Moolenaar33570922005-01-25 22:26:29 +000022068 list_one_var_a(prefix, v->di_key, v->di_tv.v_type,
Bram Moolenaar7d61a922007-08-30 09:12:23 +000022069 s == NULL ? (char_u *)"" : s, first);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022070 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022071}
22072
Bram Moolenaar071d4272004-06-13 20:20:40 +000022073 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010022074list_one_var_a(
22075 char_u *prefix,
22076 char_u *name,
22077 int type,
22078 char_u *string,
22079 int *first) /* when TRUE clear rest of screen and set to FALSE */
Bram Moolenaar071d4272004-06-13 20:20:40 +000022080{
Bram Moolenaar31859182007-08-14 20:41:13 +000022081 /* don't use msg() or msg_attr() to avoid overwriting "v:statusmsg" */
22082 msg_start();
22083 msg_puts(prefix);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022084 if (name != NULL) /* "a:" vars don't have a name stored */
22085 msg_puts(name);
22086 msg_putchar(' ');
22087 msg_advance(22);
22088 if (type == VAR_NUMBER)
22089 msg_putchar('#');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022090 else if (type == VAR_FUNC)
22091 msg_putchar('*');
22092 else if (type == VAR_LIST)
22093 {
22094 msg_putchar('[');
22095 if (*string == '[')
22096 ++string;
22097 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000022098 else if (type == VAR_DICT)
22099 {
22100 msg_putchar('{');
22101 if (*string == '{')
22102 ++string;
22103 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000022104 else
22105 msg_putchar(' ');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022106
Bram Moolenaar071d4272004-06-13 20:20:40 +000022107 msg_outtrans(string);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022108
22109 if (type == VAR_FUNC)
22110 msg_puts((char_u *)"()");
Bram Moolenaar7d61a922007-08-30 09:12:23 +000022111 if (*first)
22112 {
22113 msg_clr_eos();
22114 *first = FALSE;
22115 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000022116}
22117
22118/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000022119 * Set variable "name" to value in "tv".
Bram Moolenaar071d4272004-06-13 20:20:40 +000022120 * If the variable already exists, the value is updated.
22121 * Otherwise the variable is created.
22122 */
22123 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010022124set_var(
22125 char_u *name,
22126 typval_T *tv,
22127 int copy) /* make copy of value in "tv" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000022128{
Bram Moolenaar33570922005-01-25 22:26:29 +000022129 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022130 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000022131 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022132
Bram Moolenaarbaff0fe2010-03-17 19:53:49 +010022133 ht = find_var_ht(name, &varname);
22134 if (ht == NULL || *varname == NUL)
22135 {
22136 EMSG2(_(e_illvar), name);
22137 return;
22138 }
Bram Moolenaar332ac062013-04-15 13:06:21 +020022139 v = find_var_in_ht(ht, 0, varname, TRUE);
Bram Moolenaarbaff0fe2010-03-17 19:53:49 +010022140
Bram Moolenaar4228bec2011-03-27 16:03:15 +020022141 if (tv->v_type == VAR_FUNC && var_check_func_name(name, v == NULL))
22142 return;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022143
Bram Moolenaar33570922005-01-25 22:26:29 +000022144 if (v != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022145 {
Bram Moolenaar33570922005-01-25 22:26:29 +000022146 /* existing variable, need to clear the value */
Bram Moolenaar77354e72015-04-21 16:49:05 +020022147 if (var_check_ro(v->di_flags, name, FALSE)
22148 || tv_check_lock(v->di_tv.v_lock, name, FALSE))
Bram Moolenaar33570922005-01-25 22:26:29 +000022149 return;
Bram Moolenaar33570922005-01-25 22:26:29 +000022150
22151 /*
Bram Moolenaar1cd5e612015-05-04 11:10:27 +020022152 * Handle setting internal v: variables separately where needed to
22153 * prevent changing the type.
Bram Moolenaar33570922005-01-25 22:26:29 +000022154 */
22155 if (ht == &vimvarht)
22156 {
22157 if (v->di_tv.v_type == VAR_STRING)
22158 {
22159 vim_free(v->di_tv.vval.v_string);
22160 if (copy || tv->v_type != VAR_STRING)
22161 v->di_tv.vval.v_string = vim_strsave(get_tv_string(tv));
22162 else
22163 {
22164 /* Take over the string to avoid an extra alloc/free. */
22165 v->di_tv.vval.v_string = tv->vval.v_string;
22166 tv->vval.v_string = NULL;
22167 }
Bram Moolenaar1cd5e612015-05-04 11:10:27 +020022168 return;
Bram Moolenaar33570922005-01-25 22:26:29 +000022169 }
Bram Moolenaar1cd5e612015-05-04 11:10:27 +020022170 else if (v->di_tv.v_type == VAR_NUMBER)
Bram Moolenaar8c8de832008-06-24 22:58:06 +000022171 {
Bram Moolenaar33570922005-01-25 22:26:29 +000022172 v->di_tv.vval.v_number = get_tv_number(tv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +000022173 if (STRCMP(varname, "searchforward") == 0)
22174 set_search_direction(v->di_tv.vval.v_number ? '/' : '?');
Bram Moolenaar8050efa2013-11-08 04:30:20 +010022175#ifdef FEAT_SEARCH_EXTRA
22176 else if (STRCMP(varname, "hlsearch") == 0)
22177 {
22178 no_hlsearch = !v->di_tv.vval.v_number;
22179 redraw_all_later(SOME_VALID);
22180 }
22181#endif
Bram Moolenaar1cd5e612015-05-04 11:10:27 +020022182 return;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000022183 }
Bram Moolenaar1cd5e612015-05-04 11:10:27 +020022184 else if (v->di_tv.v_type != tv->v_type)
22185 EMSG2(_(e_intern2), "set_var()");
Bram Moolenaar33570922005-01-25 22:26:29 +000022186 }
22187
22188 clear_tv(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022189 }
22190 else /* add a new variable */
22191 {
Bram Moolenaar5fcc3fe2006-06-22 15:35:14 +000022192 /* Can't add "v:" variable. */
22193 if (ht == &vimvarht)
22194 {
22195 EMSG2(_(e_illvar), name);
22196 return;
22197 }
22198
Bram Moolenaar92124a32005-06-17 22:03:40 +000022199 /* Make sure the variable name is valid. */
Bram Moolenaar4228bec2011-03-27 16:03:15 +020022200 if (!valid_varname(varname))
22201 return;
Bram Moolenaar92124a32005-06-17 22:03:40 +000022202
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000022203 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
22204 + STRLEN(varname)));
Bram Moolenaara7043832005-01-21 11:56:39 +000022205 if (v == NULL)
22206 return;
Bram Moolenaar33570922005-01-25 22:26:29 +000022207 STRCPY(v->di_key, varname);
Bram Moolenaar33570922005-01-25 22:26:29 +000022208 if (hash_add(ht, DI2HIKEY(v)) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022209 {
Bram Moolenaara7043832005-01-21 11:56:39 +000022210 vim_free(v);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022211 return;
22212 }
Bram Moolenaar9bc174b2015-04-13 16:16:38 +020022213 v->di_flags = DI_FLAGS_ALLOC;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022214 }
Bram Moolenaara7043832005-01-21 11:56:39 +000022215
Bram Moolenaar8c8de832008-06-24 22:58:06 +000022216 if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT)
Bram Moolenaar33570922005-01-25 22:26:29 +000022217 copy_tv(tv, &v->di_tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000022218 else
22219 {
Bram Moolenaar33570922005-01-25 22:26:29 +000022220 v->di_tv = *tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000022221 v->di_tv.v_lock = 0;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000022222 init_tv(tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000022223 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000022224}
22225
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022226/*
Bram Moolenaar4e957af2006-09-02 11:41:07 +000022227 * Return TRUE if di_flags "flags" indicates variable "name" is read-only.
Bram Moolenaar33570922005-01-25 22:26:29 +000022228 * Also give an error message.
22229 */
22230 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010022231var_check_ro(int flags, char_u *name, int use_gettext)
Bram Moolenaar33570922005-01-25 22:26:29 +000022232{
22233 if (flags & DI_FLAGS_RO)
22234 {
Bram Moolenaar77354e72015-04-21 16:49:05 +020022235 EMSG2(_(e_readonlyvar), use_gettext ? (char_u *)_(name) : name);
Bram Moolenaar33570922005-01-25 22:26:29 +000022236 return TRUE;
22237 }
22238 if ((flags & DI_FLAGS_RO_SBX) && sandbox)
22239 {
Bram Moolenaar77354e72015-04-21 16:49:05 +020022240 EMSG2(_(e_readonlysbx), use_gettext ? (char_u *)_(name) : name);
Bram Moolenaar33570922005-01-25 22:26:29 +000022241 return TRUE;
22242 }
22243 return FALSE;
22244}
22245
22246/*
Bram Moolenaar4e957af2006-09-02 11:41:07 +000022247 * Return TRUE if di_flags "flags" indicates variable "name" is fixed.
22248 * Also give an error message.
22249 */
22250 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010022251var_check_fixed(int flags, char_u *name, int use_gettext)
Bram Moolenaar4e957af2006-09-02 11:41:07 +000022252{
22253 if (flags & DI_FLAGS_FIX)
22254 {
Bram Moolenaar77354e72015-04-21 16:49:05 +020022255 EMSG2(_("E795: Cannot delete variable %s"),
22256 use_gettext ? (char_u *)_(name) : name);
Bram Moolenaar4e957af2006-09-02 11:41:07 +000022257 return TRUE;
22258 }
22259 return FALSE;
22260}
22261
22262/*
Bram Moolenaar4228bec2011-03-27 16:03:15 +020022263 * Check if a funcref is assigned to a valid variable name.
22264 * Return TRUE and give an error if not.
22265 */
22266 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010022267var_check_func_name(
22268 char_u *name, /* points to start of variable name */
22269 int new_var) /* TRUE when creating the variable */
Bram Moolenaar4228bec2011-03-27 16:03:15 +020022270{
Bram Moolenaarcbc67722014-05-22 14:19:56 +020022271 /* Allow for w: b: s: and t:. */
22272 if (!(vim_strchr((char_u *)"wbst", name[0]) != NULL && name[1] == ':')
Bram Moolenaar4228bec2011-03-27 16:03:15 +020022273 && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
22274 ? name[2] : name[0]))
22275 {
22276 EMSG2(_("E704: Funcref variable name must start with a capital: %s"),
22277 name);
22278 return TRUE;
22279 }
22280 /* Don't allow hiding a function. When "v" is not NULL we might be
22281 * assigning another function to the same var, the type is checked
22282 * below. */
22283 if (new_var && function_exists(name))
22284 {
22285 EMSG2(_("E705: Variable name conflicts with existing function: %s"),
22286 name);
22287 return TRUE;
22288 }
22289 return FALSE;
22290}
22291
22292/*
22293 * Check if a variable name is valid.
22294 * Return FALSE and give an error if not.
22295 */
22296 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010022297valid_varname(char_u *varname)
Bram Moolenaar4228bec2011-03-27 16:03:15 +020022298{
22299 char_u *p;
22300
22301 for (p = varname; *p != NUL; ++p)
22302 if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p))
22303 && *p != AUTOLOAD_CHAR)
22304 {
22305 EMSG2(_(e_illvar), varname);
22306 return FALSE;
22307 }
22308 return TRUE;
22309}
22310
22311/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000022312 * Return TRUE if typeval "tv" is set to be locked (immutable).
Bram Moolenaar77354e72015-04-21 16:49:05 +020022313 * Also give an error message, using "name" or _("name") when use_gettext is
22314 * TRUE.
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000022315 */
22316 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010022317tv_check_lock(int lock, char_u *name, int use_gettext)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000022318{
22319 if (lock & VAR_LOCKED)
22320 {
22321 EMSG2(_("E741: Value is locked: %s"),
Bram Moolenaar77354e72015-04-21 16:49:05 +020022322 name == NULL ? (char_u *)_("Unknown")
22323 : use_gettext ? (char_u *)_(name)
22324 : name);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000022325 return TRUE;
22326 }
22327 if (lock & VAR_FIXED)
22328 {
22329 EMSG2(_("E742: Cannot change value of %s"),
Bram Moolenaar77354e72015-04-21 16:49:05 +020022330 name == NULL ? (char_u *)_("Unknown")
22331 : use_gettext ? (char_u *)_(name)
22332 : name);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000022333 return TRUE;
22334 }
22335 return FALSE;
22336}
22337
22338/*
Bram Moolenaar33570922005-01-25 22:26:29 +000022339 * Copy the values from typval_T "from" to typval_T "to".
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022340 * When needed allocates string or increases reference count.
Bram Moolenaare9a41262005-01-15 22:18:47 +000022341 * Does not make a copy of a list or dict but copies the reference!
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000022342 * It is OK for "from" and "to" to point to the same item. This is used to
22343 * make a copy later.
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022344 */
Bram Moolenaar7e506b62010-01-19 15:55:06 +010022345 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010022346copy_tv(typval_T *from, typval_T *to)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022347{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022348 to->v_type = from->v_type;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000022349 to->v_lock = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022350 switch (from->v_type)
22351 {
22352 case VAR_NUMBER:
Bram Moolenaar520e1e42016-01-23 19:46:28 +010022353 case VAR_SPECIAL:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022354 to->vval.v_number = from->vval.v_number;
22355 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000022356 case VAR_FLOAT:
Bram Moolenaar835dc632016-02-07 14:27:38 +010022357#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +000022358 to->vval.v_float = from->vval.v_float;
22359 break;
22360#endif
Bram Moolenaar835dc632016-02-07 14:27:38 +010022361 case VAR_JOB:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +010022362#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar835dc632016-02-07 14:27:38 +010022363 to->vval.v_job = from->vval.v_job;
Bram Moolenaaree1cffc2016-02-21 19:14:41 +010022364 if (to->vval.v_job != NULL)
22365 ++to->vval.v_job->jv_refcount;
Bram Moolenaar835dc632016-02-07 14:27:38 +010022366 break;
22367#endif
Bram Moolenaar77073442016-02-13 23:23:53 +010022368 case VAR_CHANNEL:
Bram Moolenaar509ce2a2016-03-11 22:52:15 +010022369#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar77073442016-02-13 23:23:53 +010022370 to->vval.v_channel = from->vval.v_channel;
Bram Moolenaar5cefd402016-02-16 12:44:26 +010022371 if (to->vval.v_channel != NULL)
22372 ++to->vval.v_channel->ch_refcount;
Bram Moolenaar77073442016-02-13 23:23:53 +010022373 break;
22374#endif
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022375 case VAR_STRING:
22376 case VAR_FUNC:
22377 if (from->vval.v_string == NULL)
22378 to->vval.v_string = NULL;
22379 else
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022380 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022381 to->vval.v_string = vim_strsave(from->vval.v_string);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022382 if (from->v_type == VAR_FUNC)
22383 func_ref(to->vval.v_string);
22384 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022385 break;
22386 case VAR_LIST:
22387 if (from->vval.v_list == NULL)
22388 to->vval.v_list = NULL;
22389 else
22390 {
22391 to->vval.v_list = from->vval.v_list;
22392 ++to->vval.v_list->lv_refcount;
22393 }
22394 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000022395 case VAR_DICT:
22396 if (from->vval.v_dict == NULL)
22397 to->vval.v_dict = NULL;
22398 else
22399 {
22400 to->vval.v_dict = from->vval.v_dict;
22401 ++to->vval.v_dict->dv_refcount;
22402 }
22403 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +010022404 case VAR_UNKNOWN:
22405 EMSG2(_(e_intern2), "copy_tv(UNKNOWN)");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022406 break;
22407 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000022408}
22409
22410/*
Bram Moolenaare9a41262005-01-15 22:18:47 +000022411 * Make a copy of an item.
22412 * Lists and Dictionaries are also copied. A deep copy if "deep" is set.
Bram Moolenaar81bf7082005-02-12 14:31:42 +000022413 * For deepcopy() "copyID" is zero for a full copy or the ID for when a
22414 * reference to an already copied list/dict can be used.
22415 * Returns FAIL or OK.
Bram Moolenaare9a41262005-01-15 22:18:47 +000022416 */
Bram Moolenaar81bf7082005-02-12 14:31:42 +000022417 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010022418item_copy(
22419 typval_T *from,
22420 typval_T *to,
22421 int deep,
22422 int copyID)
Bram Moolenaare9a41262005-01-15 22:18:47 +000022423{
22424 static int recurse = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000022425 int ret = OK;
Bram Moolenaare9a41262005-01-15 22:18:47 +000022426
Bram Moolenaar33570922005-01-25 22:26:29 +000022427 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +000022428 {
22429 EMSG(_("E698: variable nested too deep for making a copy"));
Bram Moolenaar81bf7082005-02-12 14:31:42 +000022430 return FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000022431 }
22432 ++recurse;
22433
22434 switch (from->v_type)
22435 {
22436 case VAR_NUMBER:
Bram Moolenaar8c8de832008-06-24 22:58:06 +000022437 case VAR_FLOAT:
Bram Moolenaare9a41262005-01-15 22:18:47 +000022438 case VAR_STRING:
22439 case VAR_FUNC:
Bram Moolenaar15550002016-01-31 18:45:24 +010022440 case VAR_SPECIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +010022441 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +010022442 case VAR_CHANNEL:
Bram Moolenaare9a41262005-01-15 22:18:47 +000022443 copy_tv(from, to);
22444 break;
22445 case VAR_LIST:
22446 to->v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000022447 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000022448 if (from->vval.v_list == NULL)
22449 to->vval.v_list = NULL;
22450 else if (copyID != 0 && from->vval.v_list->lv_copyID == copyID)
22451 {
22452 /* use the copy made earlier */
22453 to->vval.v_list = from->vval.v_list->lv_copylist;
22454 ++to->vval.v_list->lv_refcount;
22455 }
22456 else
22457 to->vval.v_list = list_copy(from->vval.v_list, deep, copyID);
22458 if (to->vval.v_list == NULL)
22459 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000022460 break;
22461 case VAR_DICT:
22462 to->v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000022463 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000022464 if (from->vval.v_dict == NULL)
22465 to->vval.v_dict = NULL;
22466 else if (copyID != 0 && from->vval.v_dict->dv_copyID == copyID)
22467 {
22468 /* use the copy made earlier */
22469 to->vval.v_dict = from->vval.v_dict->dv_copydict;
22470 ++to->vval.v_dict->dv_refcount;
22471 }
22472 else
22473 to->vval.v_dict = dict_copy(from->vval.v_dict, deep, copyID);
22474 if (to->vval.v_dict == NULL)
22475 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000022476 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +010022477 case VAR_UNKNOWN:
22478 EMSG2(_(e_intern2), "item_copy(UNKNOWN)");
Bram Moolenaar81bf7082005-02-12 14:31:42 +000022479 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000022480 }
22481 --recurse;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000022482 return ret;
Bram Moolenaare9a41262005-01-15 22:18:47 +000022483}
22484
22485/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000022486 * ":echo expr1 ..." print each argument separated with a space, add a
22487 * newline at the end.
22488 * ":echon expr1 ..." print each argument plain.
22489 */
22490 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010022491ex_echo(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022492{
22493 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000022494 typval_T rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022495 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022496 char_u *p;
22497 int needclr = TRUE;
22498 int atstart = TRUE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000022499 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000022500
22501 if (eap->skip)
22502 ++emsg_skip;
22503 while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int)
22504 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +000022505 /* If eval1() causes an error message the text from the command may
22506 * still need to be cleared. E.g., "echo 22,44". */
22507 need_clr_eos = needclr;
22508
Bram Moolenaar071d4272004-06-13 20:20:40 +000022509 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000022510 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022511 {
22512 /*
22513 * Report the invalid expression unless the expression evaluation
22514 * has been cancelled due to an aborting error, an interrupt, or an
22515 * exception.
22516 */
22517 if (!aborting())
22518 EMSG2(_(e_invexpr2), p);
Bram Moolenaar8c8de832008-06-24 22:58:06 +000022519 need_clr_eos = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022520 break;
22521 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +000022522 need_clr_eos = FALSE;
22523
Bram Moolenaar071d4272004-06-13 20:20:40 +000022524 if (!eap->skip)
22525 {
22526 if (atstart)
22527 {
22528 atstart = FALSE;
22529 /* Call msg_start() after eval1(), evaluating the expression
22530 * may cause a message to appear. */
22531 if (eap->cmdidx == CMD_echo)
Bram Moolenaar12b02902012-03-23 15:18:24 +010022532 {
Bram Moolenaar6df5e5a2012-03-28 16:49:29 +020022533 /* Mark the saved text as finishing the line, so that what
22534 * follows is displayed on a new line when scrolling back
22535 * at the more prompt. */
22536 msg_sb_eol();
Bram Moolenaar071d4272004-06-13 20:20:40 +000022537 msg_start();
Bram Moolenaar12b02902012-03-23 15:18:24 +010022538 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000022539 }
22540 else if (eap->cmdidx == CMD_echo)
22541 msg_puts_attr((char_u *)" ", echo_attr);
Bram Moolenaar520e1e42016-01-23 19:46:28 +010022542 p = echo_string(&rettv, &tofree, numbuf, get_copyID());
Bram Moolenaar81bf7082005-02-12 14:31:42 +000022543 if (p != NULL)
22544 for ( ; *p != NUL && !got_int; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022545 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000022546 if (*p == '\n' || *p == '\r' || *p == TAB)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022547 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000022548 if (*p != TAB && needclr)
22549 {
22550 /* remove any text still there from the command */
22551 msg_clr_eos();
22552 needclr = FALSE;
22553 }
22554 msg_putchar_attr(*p, echo_attr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022555 }
22556 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +000022557 {
22558#ifdef FEAT_MBYTE
22559 if (has_mbyte)
22560 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000022561 int i = (*mb_ptr2len)(p);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000022562
22563 (void)msg_outtrans_len_attr(p, i, echo_attr);
22564 p += i - 1;
22565 }
22566 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000022567#endif
Bram Moolenaar81bf7082005-02-12 14:31:42 +000022568 (void)msg_outtrans_len_attr(p, 1, echo_attr);
22569 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000022570 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022571 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022572 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000022573 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022574 arg = skipwhite(arg);
22575 }
22576 eap->nextcmd = check_nextcmd(arg);
22577
22578 if (eap->skip)
22579 --emsg_skip;
22580 else
22581 {
22582 /* remove text that may still be there from the command */
22583 if (needclr)
22584 msg_clr_eos();
22585 if (eap->cmdidx == CMD_echo)
22586 msg_end();
22587 }
22588}
22589
22590/*
22591 * ":echohl {name}".
22592 */
22593 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010022594ex_echohl(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022595{
22596 int id;
22597
22598 id = syn_name2id(eap->arg);
22599 if (id == 0)
22600 echo_attr = 0;
22601 else
22602 echo_attr = syn_id2attr(id);
22603}
22604
22605/*
22606 * ":execute expr1 ..." execute the result of an expression.
22607 * ":echomsg expr1 ..." Print a message
22608 * ":echoerr expr1 ..." Print an error
22609 * Each gets spaces around each argument and a newline at the end for
22610 * echo commands
22611 */
22612 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010022613ex_execute(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022614{
22615 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000022616 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022617 int ret = OK;
22618 char_u *p;
22619 garray_T ga;
22620 int len;
22621 int save_did_emsg;
22622
22623 ga_init2(&ga, 1, 80);
22624
22625 if (eap->skip)
22626 ++emsg_skip;
22627 while (*arg != NUL && *arg != '|' && *arg != '\n')
22628 {
22629 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000022630 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022631 {
22632 /*
22633 * Report the invalid expression unless the expression evaluation
22634 * has been cancelled due to an aborting error, an interrupt, or an
22635 * exception.
22636 */
22637 if (!aborting())
22638 EMSG2(_(e_invexpr2), p);
22639 ret = FAIL;
22640 break;
22641 }
22642
22643 if (!eap->skip)
22644 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000022645 p = get_tv_string(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022646 len = (int)STRLEN(p);
22647 if (ga_grow(&ga, len + 2) == FAIL)
22648 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000022649 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022650 ret = FAIL;
22651 break;
22652 }
22653 if (ga.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022654 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
Bram Moolenaar071d4272004-06-13 20:20:40 +000022655 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022656 ga.ga_len += len;
22657 }
22658
Bram Moolenaarc70646c2005-01-04 21:52:38 +000022659 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022660 arg = skipwhite(arg);
22661 }
22662
22663 if (ret != FAIL && ga.ga_data != NULL)
22664 {
22665 if (eap->cmdidx == CMD_echomsg)
Bram Moolenaar4770d092006-01-12 23:22:24 +000022666 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000022667 MSG_ATTR(ga.ga_data, echo_attr);
Bram Moolenaar4770d092006-01-12 23:22:24 +000022668 out_flush();
22669 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000022670 else if (eap->cmdidx == CMD_echoerr)
22671 {
22672 /* We don't want to abort following commands, restore did_emsg. */
22673 save_did_emsg = did_emsg;
22674 EMSG((char_u *)ga.ga_data);
22675 if (!force_abort)
22676 did_emsg = save_did_emsg;
22677 }
22678 else if (eap->cmdidx == CMD_execute)
22679 do_cmdline((char_u *)ga.ga_data,
22680 eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE);
22681 }
22682
22683 ga_clear(&ga);
22684
22685 if (eap->skip)
22686 --emsg_skip;
22687
22688 eap->nextcmd = check_nextcmd(arg);
22689}
22690
22691/*
22692 * Skip over the name of an option: "&option", "&g:option" or "&l:option".
22693 * "arg" points to the "&" or '+' when called, to "option" when returning.
22694 * Returns NULL when no option name found. Otherwise pointer to the char
22695 * after the option name.
22696 */
22697 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010022698find_option_end(char_u **arg, int *opt_flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022699{
22700 char_u *p = *arg;
22701
22702 ++p;
22703 if (*p == 'g' && p[1] == ':')
22704 {
22705 *opt_flags = OPT_GLOBAL;
22706 p += 2;
22707 }
22708 else if (*p == 'l' && p[1] == ':')
22709 {
22710 *opt_flags = OPT_LOCAL;
22711 p += 2;
22712 }
22713 else
22714 *opt_flags = 0;
22715
22716 if (!ASCII_ISALPHA(*p))
22717 return NULL;
22718 *arg = p;
22719
22720 if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL)
22721 p += 4; /* termcap option */
22722 else
22723 while (ASCII_ISALPHA(*p))
22724 ++p;
22725 return p;
22726}
22727
22728/*
22729 * ":function"
22730 */
22731 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010022732ex_function(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022733{
22734 char_u *theline;
Bram Moolenaaracd6a042011-09-30 16:39:48 +020022735 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022736 int j;
22737 int c;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022738 int saved_did_emsg;
Bram Moolenaarccf623f2013-07-05 18:29:48 +020022739 int saved_wait_return = need_wait_return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022740 char_u *name = NULL;
22741 char_u *p;
22742 char_u *arg;
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000022743 char_u *line_arg = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022744 garray_T newargs;
22745 garray_T newlines;
22746 int varargs = FALSE;
22747 int mustend = FALSE;
22748 int flags = 0;
22749 ufunc_T *fp;
22750 int indent;
22751 int nesting;
22752 char_u *skip_until = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +000022753 dictitem_T *v;
22754 funcdict_T fudi;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022755 static int func_nr = 0; /* number for nameless function */
22756 int paren;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022757 hashtab_T *ht;
22758 int todo;
22759 hashitem_T *hi;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000022760 int sourcing_lnum_off;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022761
22762 /*
22763 * ":function" without argument: list functions.
22764 */
22765 if (ends_excmd(*eap->arg))
22766 {
22767 if (!eap->skip)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022768 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000022769 todo = (int)func_hashtab.ht_used;
Bram Moolenaar038eb0e2005-02-27 22:43:26 +000022770 for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022771 {
22772 if (!HASHITEM_EMPTY(hi))
22773 {
22774 --todo;
22775 fp = HI2UF(hi);
22776 if (!isdigit(*fp->uf_name))
22777 list_func_head(fp, FALSE);
22778 }
22779 }
22780 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000022781 eap->nextcmd = check_nextcmd(eap->arg);
22782 return;
22783 }
22784
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022785 /*
Bram Moolenaardd2436f2005-09-05 22:14:46 +000022786 * ":function /pat": list functions matching pattern.
22787 */
22788 if (*eap->arg == '/')
22789 {
22790 p = skip_regexp(eap->arg + 1, '/', TRUE, NULL);
22791 if (!eap->skip)
22792 {
22793 regmatch_T regmatch;
22794
22795 c = *p;
22796 *p = NUL;
22797 regmatch.regprog = vim_regcomp(eap->arg + 1, RE_MAGIC);
22798 *p = c;
22799 if (regmatch.regprog != NULL)
22800 {
22801 regmatch.rm_ic = p_ic;
22802
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000022803 todo = (int)func_hashtab.ht_used;
Bram Moolenaardd2436f2005-09-05 22:14:46 +000022804 for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
22805 {
22806 if (!HASHITEM_EMPTY(hi))
22807 {
22808 --todo;
22809 fp = HI2UF(hi);
22810 if (!isdigit(*fp->uf_name)
22811 && vim_regexec(&regmatch, fp->uf_name, 0))
22812 list_func_head(fp, FALSE);
22813 }
22814 }
Bram Moolenaar473de612013-06-08 18:19:48 +020022815 vim_regfree(regmatch.regprog);
Bram Moolenaardd2436f2005-09-05 22:14:46 +000022816 }
22817 }
22818 if (*p == '/')
22819 ++p;
22820 eap->nextcmd = check_nextcmd(p);
22821 return;
22822 }
22823
22824 /*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022825 * Get the function name. There are these situations:
22826 * func normal function name
22827 * "name" == func, "fudi.fd_dict" == NULL
22828 * dict.func new dictionary entry
22829 * "name" == NULL, "fudi.fd_dict" set,
22830 * "fudi.fd_di" == NULL, "fudi.fd_newkey" == func
22831 * dict.func existing dict entry with a Funcref
Bram Moolenaard857f0e2005-06-21 22:37:39 +000022832 * "name" == func, "fudi.fd_dict" set,
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022833 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL
22834 * dict.func existing dict entry that's not a Funcref
22835 * "name" == NULL, "fudi.fd_dict" set,
22836 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL
Bram Moolenaareccb7fc2014-04-23 20:43:41 +020022837 * s:func script-local function name
22838 * g:func global function name, same as "func"
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022839 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000022840 p = eap->arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022841 name = trans_function_name(&p, eap->skip, 0, &fudi);
22842 paren = (vim_strchr(p, '(') != NULL);
22843 if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022844 {
22845 /*
22846 * Return on an invalid expression in braces, unless the expression
22847 * evaluation has been cancelled due to an aborting error, an
22848 * interrupt, or an exception.
22849 */
22850 if (!aborting())
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022851 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000022852 if (!eap->skip && fudi.fd_newkey != NULL)
22853 EMSG2(_(e_dictkey), fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022854 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022855 return;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022856 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000022857 else
22858 eap->skip = TRUE;
22859 }
Bram Moolenaar1f35bf92006-03-07 22:38:47 +000022860
Bram Moolenaar071d4272004-06-13 20:20:40 +000022861 /* An error in a function call during evaluation of an expression in magic
22862 * braces should not cause the function not to be defined. */
22863 saved_did_emsg = did_emsg;
22864 did_emsg = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022865
22866 /*
22867 * ":function func" with only function name: list function.
22868 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022869 if (!paren)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022870 {
22871 if (!ends_excmd(*skipwhite(p)))
22872 {
22873 EMSG(_(e_trailing));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022874 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022875 }
22876 eap->nextcmd = check_nextcmd(p);
22877 if (eap->nextcmd != NULL)
22878 *p = NUL;
22879 if (!eap->skip && !got_int)
22880 {
22881 fp = find_func(name);
22882 if (fp != NULL)
22883 {
22884 list_func_head(fp, TRUE);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022885 for (j = 0; j < fp->uf_lines.ga_len && !got_int; ++j)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022886 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000022887 if (FUNCLINE(fp, j) == NULL)
22888 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022889 msg_putchar('\n');
22890 msg_outnum((long)(j + 1));
22891 if (j < 9)
22892 msg_putchar(' ');
22893 if (j < 99)
22894 msg_putchar(' ');
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022895 msg_prt_line(FUNCLINE(fp, j), FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022896 out_flush(); /* show a line at a time */
22897 ui_breakcheck();
22898 }
22899 if (!got_int)
22900 {
22901 msg_putchar('\n');
22902 msg_puts((char_u *)" endfunction");
22903 }
22904 }
22905 else
Bram Moolenaar7b76b0a2009-01-28 18:09:38 +000022906 emsg_funcname(N_("E123: Undefined function: %s"), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022907 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022908 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022909 }
22910
22911 /*
22912 * ":function name(arg1, arg2)" Define function.
22913 */
22914 p = skipwhite(p);
22915 if (*p != '(')
22916 {
22917 if (!eap->skip)
22918 {
22919 EMSG2(_("E124: Missing '(': %s"), eap->arg);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022920 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022921 }
22922 /* attempt to continue by skipping some text */
22923 if (vim_strchr(p, '(') != NULL)
22924 p = vim_strchr(p, '(');
22925 }
22926 p = skipwhite(p + 1);
22927
22928 ga_init2(&newargs, (int)sizeof(char_u *), 3);
22929 ga_init2(&newlines, (int)sizeof(char_u *), 3);
22930
Bram Moolenaard857f0e2005-06-21 22:37:39 +000022931 if (!eap->skip)
22932 {
Bram Moolenaarb42dc232006-11-21 18:36:05 +000022933 /* Check the name of the function. Unless it's a dictionary function
22934 * (that we are overwriting). */
Bram Moolenaard857f0e2005-06-21 22:37:39 +000022935 if (name != NULL)
22936 arg = name;
22937 else
22938 arg = fudi.fd_newkey;
Bram Moolenaarb42dc232006-11-21 18:36:05 +000022939 if (arg != NULL && (fudi.fd_di == NULL
22940 || fudi.fd_di->di_tv.v_type != VAR_FUNC))
Bram Moolenaard857f0e2005-06-21 22:37:39 +000022941 {
22942 if (*arg == K_SPECIAL)
22943 j = 3;
22944 else
22945 j = 0;
22946 while (arg[j] != NUL && (j == 0 ? eval_isnamec1(arg[j])
22947 : eval_isnamec(arg[j])))
22948 ++j;
22949 if (arg[j] != NUL)
Bram Moolenaarb67cc162009-02-04 15:27:06 +000022950 emsg_funcname((char *)e_invarg2, arg);
Bram Moolenaard857f0e2005-06-21 22:37:39 +000022951 }
Bram Moolenaar2142e5d2013-02-20 15:19:43 +010022952 /* Disallow using the g: dict. */
22953 if (fudi.fd_dict != NULL && fudi.fd_dict->dv_scope == VAR_DEF_SCOPE)
22954 EMSG(_("E862: Cannot use g: here"));
Bram Moolenaard857f0e2005-06-21 22:37:39 +000022955 }
22956
Bram Moolenaar071d4272004-06-13 20:20:40 +000022957 /*
22958 * Isolate the arguments: "arg1, arg2, ...)"
22959 */
22960 while (*p != ')')
22961 {
22962 if (p[0] == '.' && p[1] == '.' && p[2] == '.')
22963 {
22964 varargs = TRUE;
22965 p += 3;
22966 mustend = TRUE;
22967 }
22968 else
22969 {
22970 arg = p;
22971 while (ASCII_ISALNUM(*p) || *p == '_')
22972 ++p;
22973 if (arg == p || isdigit(*arg)
22974 || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0)
22975 || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0))
22976 {
22977 if (!eap->skip)
22978 EMSG2(_("E125: Illegal argument: %s"), arg);
22979 break;
22980 }
22981 if (ga_grow(&newargs, 1) == FAIL)
22982 goto erret;
22983 c = *p;
22984 *p = NUL;
22985 arg = vim_strsave(arg);
22986 if (arg == NULL)
22987 goto erret;
Bram Moolenaaracd6a042011-09-30 16:39:48 +020022988
22989 /* Check for duplicate argument name. */
22990 for (i = 0; i < newargs.ga_len; ++i)
22991 if (STRCMP(((char_u **)(newargs.ga_data))[i], arg) == 0)
22992 {
22993 EMSG2(_("E853: Duplicate argument name: %s"), arg);
Bram Moolenaar47b83422014-02-24 03:32:00 +010022994 vim_free(arg);
Bram Moolenaaracd6a042011-09-30 16:39:48 +020022995 goto erret;
22996 }
22997
Bram Moolenaar071d4272004-06-13 20:20:40 +000022998 ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg;
22999 *p = c;
23000 newargs.ga_len++;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023001 if (*p == ',')
23002 ++p;
23003 else
23004 mustend = TRUE;
23005 }
23006 p = skipwhite(p);
23007 if (mustend && *p != ')')
23008 {
23009 if (!eap->skip)
23010 EMSG2(_(e_invarg2), eap->arg);
23011 break;
23012 }
23013 }
Bram Moolenaardd8a5282015-08-11 15:54:52 +020023014 if (*p != ')')
23015 goto erret;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023016 ++p; /* skip the ')' */
23017
Bram Moolenaare9a41262005-01-15 22:18:47 +000023018 /* find extra arguments "range", "dict" and "abort" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000023019 for (;;)
23020 {
23021 p = skipwhite(p);
23022 if (STRNCMP(p, "range", 5) == 0)
23023 {
23024 flags |= FC_RANGE;
23025 p += 5;
23026 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000023027 else if (STRNCMP(p, "dict", 4) == 0)
23028 {
23029 flags |= FC_DICT;
23030 p += 4;
23031 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000023032 else if (STRNCMP(p, "abort", 5) == 0)
23033 {
23034 flags |= FC_ABORT;
23035 p += 5;
23036 }
23037 else
23038 break;
23039 }
23040
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000023041 /* When there is a line break use what follows for the function body.
23042 * Makes 'exe "func Test()\n...\nendfunc"' work. */
23043 if (*p == '\n')
23044 line_arg = p + 1;
23045 else if (*p != NUL && *p != '"' && !eap->skip && !did_emsg)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023046 EMSG(_(e_trailing));
23047
23048 /*
23049 * Read the body of the function, until ":endfunction" is found.
23050 */
23051 if (KeyTyped)
23052 {
23053 /* Check if the function already exists, don't let the user type the
23054 * whole function before telling him it doesn't work! For a script we
23055 * need to skip the body to be able to find what follows. */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023056 if (!eap->skip && !eap->forceit)
23057 {
23058 if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL)
23059 EMSG(_(e_funcdict));
23060 else if (name != NULL && find_func(name) != NULL)
Bram Moolenaar81bf7082005-02-12 14:31:42 +000023061 emsg_funcname(e_funcexts, name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023062 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000023063
Bram Moolenaard857f0e2005-06-21 22:37:39 +000023064 if (!eap->skip && did_emsg)
23065 goto erret;
23066
Bram Moolenaar071d4272004-06-13 20:20:40 +000023067 msg_putchar('\n'); /* don't overwrite the function name */
23068 cmdline_row = msg_row;
23069 }
23070
23071 indent = 2;
23072 nesting = 0;
23073 for (;;)
23074 {
Bram Moolenaar52af9652011-09-14 14:33:51 +020023075 if (KeyTyped)
Bram Moolenaarccf623f2013-07-05 18:29:48 +020023076 {
Bram Moolenaar52af9652011-09-14 14:33:51 +020023077 msg_scroll = TRUE;
Bram Moolenaarccf623f2013-07-05 18:29:48 +020023078 saved_wait_return = FALSE;
23079 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000023080 need_wait_return = FALSE;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000023081 sourcing_lnum_off = sourcing_lnum;
23082
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000023083 if (line_arg != NULL)
23084 {
23085 /* Use eap->arg, split up in parts by line breaks. */
23086 theline = line_arg;
23087 p = vim_strchr(theline, '\n');
23088 if (p == NULL)
23089 line_arg += STRLEN(line_arg);
23090 else
23091 {
23092 *p = NUL;
23093 line_arg = p + 1;
23094 }
23095 }
23096 else if (eap->getline == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023097 theline = getcmdline(':', 0L, indent);
23098 else
23099 theline = eap->getline(':', eap->cookie, indent);
23100 if (KeyTyped)
23101 lines_left = Rows - 1;
23102 if (theline == NULL)
23103 {
23104 EMSG(_("E126: Missing :endfunction"));
23105 goto erret;
23106 }
23107
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000023108 /* Detect line continuation: sourcing_lnum increased more than one. */
23109 if (sourcing_lnum > sourcing_lnum_off + 1)
23110 sourcing_lnum_off = sourcing_lnum - sourcing_lnum_off - 1;
23111 else
23112 sourcing_lnum_off = 0;
23113
Bram Moolenaar071d4272004-06-13 20:20:40 +000023114 if (skip_until != NULL)
23115 {
23116 /* between ":append" and "." and between ":python <<EOF" and "EOF"
23117 * don't check for ":endfunc". */
23118 if (STRCMP(theline, skip_until) == 0)
23119 {
23120 vim_free(skip_until);
23121 skip_until = NULL;
23122 }
23123 }
23124 else
23125 {
23126 /* skip ':' and blanks*/
23127 for (p = theline; vim_iswhite(*p) || *p == ':'; ++p)
23128 ;
23129
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000023130 /* Check for "endfunction". */
23131 if (checkforcmd(&p, "endfunction", 4) && nesting-- == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023132 {
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000023133 if (line_arg == NULL)
23134 vim_free(theline);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023135 break;
23136 }
23137
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000023138 /* Increase indent inside "if", "while", "for" and "try", decrease
Bram Moolenaar071d4272004-06-13 20:20:40 +000023139 * at "end". */
23140 if (indent > 2 && STRNCMP(p, "end", 3) == 0)
23141 indent -= 2;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000023142 else if (STRNCMP(p, "if", 2) == 0
23143 || STRNCMP(p, "wh", 2) == 0
23144 || STRNCMP(p, "for", 3) == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +000023145 || STRNCMP(p, "try", 3) == 0)
23146 indent += 2;
23147
23148 /* Check for defining a function inside this function. */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000023149 if (checkforcmd(&p, "function", 2))
Bram Moolenaar071d4272004-06-13 20:20:40 +000023150 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000023151 if (*p == '!')
23152 p = skipwhite(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023153 p += eval_fname_script(p);
Bram Moolenaaref923902014-12-13 21:00:55 +010023154 vim_free(trans_function_name(&p, TRUE, 0, NULL));
23155 if (*skipwhite(p) == '(')
Bram Moolenaar071d4272004-06-13 20:20:40 +000023156 {
Bram Moolenaaref923902014-12-13 21:00:55 +010023157 ++nesting;
23158 indent += 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023159 }
23160 }
23161
23162 /* Check for ":append" or ":insert". */
23163 p = skip_range(p, NULL);
23164 if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
23165 || (p[0] == 'i'
23166 && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
23167 && (!ASCII_ISALPHA(p[2]) || (p[2] == 's'))))))
23168 skip_until = vim_strsave((char_u *)".");
23169
23170 /* Check for ":python <<EOF", ":tcl <<EOF", etc. */
23171 arg = skipwhite(skiptowhite(p));
23172 if (arg[0] == '<' && arg[1] =='<'
23173 && ((p[0] == 'p' && p[1] == 'y'
23174 && (!ASCII_ISALPHA(p[2]) || p[2] == 't'))
23175 || (p[0] == 'p' && p[1] == 'e'
23176 && (!ASCII_ISALPHA(p[2]) || p[2] == 'r'))
23177 || (p[0] == 't' && p[1] == 'c'
23178 && (!ASCII_ISALPHA(p[2]) || p[2] == 'l'))
Bram Moolenaar50bfb322011-10-26 13:19:27 +020023179 || (p[0] == 'l' && p[1] == 'u' && p[2] == 'a'
23180 && !ASCII_ISALPHA(p[3]))
Bram Moolenaar071d4272004-06-13 20:20:40 +000023181 || (p[0] == 'r' && p[1] == 'u' && p[2] == 'b'
23182 && (!ASCII_ISALPHA(p[3]) || p[3] == 'y'))
Bram Moolenaar325b7a22004-07-05 15:58:32 +000023183 || (p[0] == 'm' && p[1] == 'z'
23184 && (!ASCII_ISALPHA(p[2]) || p[2] == 's'))
Bram Moolenaar071d4272004-06-13 20:20:40 +000023185 ))
23186 {
23187 /* ":python <<" continues until a dot, like ":append" */
23188 p = skipwhite(arg + 2);
23189 if (*p == NUL)
23190 skip_until = vim_strsave((char_u *)".");
23191 else
23192 skip_until = vim_strsave(p);
23193 }
23194 }
23195
23196 /* Add the line to the function. */
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000023197 if (ga_grow(&newlines, 1 + sourcing_lnum_off) == FAIL)
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000023198 {
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000023199 if (line_arg == NULL)
23200 vim_free(theline);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023201 goto erret;
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000023202 }
23203
23204 /* Copy the line to newly allocated memory. get_one_sourceline()
23205 * allocates 250 bytes per line, this saves 80% on average. The cost
23206 * is an extra alloc/free. */
23207 p = vim_strsave(theline);
23208 if (p != NULL)
23209 {
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000023210 if (line_arg == NULL)
23211 vim_free(theline);
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000023212 theline = p;
23213 }
23214
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000023215 ((char_u **)(newlines.ga_data))[newlines.ga_len++] = theline;
23216
23217 /* Add NULL lines for continuation lines, so that the line count is
23218 * equal to the index in the growarray. */
23219 while (sourcing_lnum_off-- > 0)
23220 ((char_u **)(newlines.ga_data))[newlines.ga_len++] = NULL;
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000023221
23222 /* Check for end of eap->arg. */
23223 if (line_arg != NULL && *line_arg == NUL)
23224 line_arg = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023225 }
23226
23227 /* Don't define the function when skipping commands or when an error was
23228 * detected. */
23229 if (eap->skip || did_emsg)
23230 goto erret;
23231
23232 /*
23233 * If there are no errors, add the function
23234 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023235 if (fudi.fd_dict == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000023236 {
Bram Moolenaar6d977d62014-01-14 15:24:39 +010023237 v = find_var(name, &ht, FALSE);
Bram Moolenaar33570922005-01-25 22:26:29 +000023238 if (v != NULL && v->di_tv.v_type == VAR_FUNC)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023239 {
Bram Moolenaar7b76b0a2009-01-28 18:09:38 +000023240 emsg_funcname(N_("E707: Function name conflicts with variable: %s"),
Bram Moolenaar81bf7082005-02-12 14:31:42 +000023241 name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023242 goto erret;
23243 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000023244
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023245 fp = find_func(name);
23246 if (fp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023247 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023248 if (!eap->forceit)
23249 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000023250 emsg_funcname(e_funcexts, name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023251 goto erret;
23252 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023253 if (fp->uf_calls > 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023254 {
Bram Moolenaar7b76b0a2009-01-28 18:09:38 +000023255 emsg_funcname(N_("E127: Cannot redefine function %s: It is in use"),
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023256 name);
23257 goto erret;
23258 }
23259 /* redefine existing function */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023260 ga_clear_strings(&(fp->uf_args));
23261 ga_clear_strings(&(fp->uf_lines));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023262 vim_free(name);
23263 name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023264 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000023265 }
23266 else
23267 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023268 char numbuf[20];
23269
23270 fp = NULL;
23271 if (fudi.fd_newkey == NULL && !eap->forceit)
23272 {
23273 EMSG(_(e_funcdict));
23274 goto erret;
23275 }
Bram Moolenaar758711c2005-02-02 23:11:38 +000023276 if (fudi.fd_di == NULL)
23277 {
23278 /* Can't add a function to a locked dictionary */
Bram Moolenaar77354e72015-04-21 16:49:05 +020023279 if (tv_check_lock(fudi.fd_dict->dv_lock, eap->arg, FALSE))
Bram Moolenaar758711c2005-02-02 23:11:38 +000023280 goto erret;
23281 }
23282 /* Can't change an existing function if it is locked */
Bram Moolenaar77354e72015-04-21 16:49:05 +020023283 else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg, FALSE))
Bram Moolenaar758711c2005-02-02 23:11:38 +000023284 goto erret;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023285
23286 /* Give the function a sequential number. Can only be used with a
23287 * Funcref! */
23288 vim_free(name);
23289 sprintf(numbuf, "%d", ++func_nr);
23290 name = vim_strsave((char_u *)numbuf);
23291 if (name == NULL)
23292 goto erret;
23293 }
23294
23295 if (fp == NULL)
23296 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000023297 if (fudi.fd_dict == NULL && vim_strchr(name, AUTOLOAD_CHAR) != NULL)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023298 {
23299 int slen, plen;
23300 char_u *scriptname;
23301
23302 /* Check that the autoload name matches the script name. */
23303 j = FAIL;
23304 if (sourcing_name != NULL)
23305 {
23306 scriptname = autoload_name(name);
23307 if (scriptname != NULL)
23308 {
23309 p = vim_strchr(scriptname, '/');
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000023310 plen = (int)STRLEN(p);
23311 slen = (int)STRLEN(sourcing_name);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023312 if (slen > plen && fnamecmp(p,
23313 sourcing_name + slen - plen) == 0)
23314 j = OK;
23315 vim_free(scriptname);
23316 }
23317 }
23318 if (j == FAIL)
23319 {
23320 EMSG2(_("E746: Function name does not match script file name: %s"), name);
23321 goto erret;
23322 }
23323 }
23324
23325 fp = (ufunc_T *)alloc((unsigned)(sizeof(ufunc_T) + STRLEN(name)));
Bram Moolenaar071d4272004-06-13 20:20:40 +000023326 if (fp == NULL)
23327 goto erret;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023328
23329 if (fudi.fd_dict != NULL)
23330 {
23331 if (fudi.fd_di == NULL)
23332 {
23333 /* add new dict entry */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000023334 fudi.fd_di = dictitem_alloc(fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023335 if (fudi.fd_di == NULL)
23336 {
23337 vim_free(fp);
23338 goto erret;
23339 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000023340 if (dict_add(fudi.fd_dict, fudi.fd_di) == FAIL)
23341 {
23342 vim_free(fudi.fd_di);
Bram Moolenaar0a5fd8b2006-08-16 20:02:22 +000023343 vim_free(fp);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000023344 goto erret;
23345 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023346 }
23347 else
23348 /* overwrite existing dict entry */
23349 clear_tv(&fudi.fd_di->di_tv);
23350 fudi.fd_di->di_tv.v_type = VAR_FUNC;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000023351 fudi.fd_di->di_tv.v_lock = 0;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023352 fudi.fd_di->di_tv.vval.v_string = vim_strsave(name);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023353 fp->uf_refcount = 1;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000023354
23355 /* behave like "dict" was used */
23356 flags |= FC_DICT;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023357 }
23358
Bram Moolenaar071d4272004-06-13 20:20:40 +000023359 /* insert the new function in the function list */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023360 STRCPY(fp->uf_name, name);
Bram Moolenaar0107f5b2015-12-28 22:51:20 +010023361 if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL)
23362 {
23363 vim_free(fp);
23364 goto erret;
23365 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000023366 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023367 fp->uf_args = newargs;
23368 fp->uf_lines = newlines;
Bram Moolenaar05159a02005-02-26 23:04:13 +000023369#ifdef FEAT_PROFILE
23370 fp->uf_tml_count = NULL;
23371 fp->uf_tml_total = NULL;
23372 fp->uf_tml_self = NULL;
23373 fp->uf_profiling = FALSE;
23374 if (prof_def_func())
23375 func_do_profile(fp);
23376#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023377 fp->uf_varargs = varargs;
23378 fp->uf_flags = flags;
23379 fp->uf_calls = 0;
23380 fp->uf_script_ID = current_SID;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023381 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023382
23383erret:
Bram Moolenaar071d4272004-06-13 20:20:40 +000023384 ga_clear_strings(&newargs);
23385 ga_clear_strings(&newlines);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023386ret_free:
23387 vim_free(skip_until);
23388 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023389 vim_free(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023390 did_emsg |= saved_did_emsg;
Bram Moolenaarccf623f2013-07-05 18:29:48 +020023391 need_wait_return |= saved_wait_return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023392}
23393
23394/*
23395 * Get a function name, translating "<SID>" and "<SNR>".
Bram Moolenaara7043832005-01-21 11:56:39 +000023396 * Also handles a Funcref in a List or Dictionary.
Bram Moolenaar071d4272004-06-13 20:20:40 +000023397 * Returns the function name in allocated memory, or NULL for failure.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023398 * flags:
Bram Moolenaarc9703302016-01-17 21:49:33 +010023399 * TFN_INT: internal function name OK
23400 * TFN_QUIET: be quiet
Bram Moolenaar6d977d62014-01-14 15:24:39 +010023401 * TFN_NO_AUTOLOAD: do not use script autoloading
Bram Moolenaar071d4272004-06-13 20:20:40 +000023402 * Advances "pp" to just after the function name (if no error).
23403 */
23404 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010023405trans_function_name(
23406 char_u **pp,
23407 int skip, /* only find the end, don't evaluate */
23408 int flags,
23409 funcdict_T *fdp) /* return: info about dictionary used */
Bram Moolenaar071d4272004-06-13 20:20:40 +000023410{
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000023411 char_u *name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023412 char_u *start;
23413 char_u *end;
23414 int lead;
23415 char_u sid_buf[20];
Bram Moolenaar071d4272004-06-13 20:20:40 +000023416 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +000023417 lval_T lv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023418
23419 if (fdp != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000023420 vim_memset(fdp, 0, sizeof(funcdict_T));
Bram Moolenaar071d4272004-06-13 20:20:40 +000023421 start = *pp;
Bram Moolenaara7043832005-01-21 11:56:39 +000023422
23423 /* Check for hard coded <SNR>: already translated function ID (from a user
23424 * command). */
23425 if ((*pp)[0] == K_SPECIAL && (*pp)[1] == KS_EXTRA
23426 && (*pp)[2] == (int)KE_SNR)
23427 {
23428 *pp += 3;
23429 len = get_id_len(pp) + 3;
23430 return vim_strnsave(start, len);
23431 }
23432
23433 /* A name starting with "<SID>" or "<SNR>" is local to a script. But
23434 * don't skip over "s:", get_lval() needs it for "s:dict.func". */
Bram Moolenaar071d4272004-06-13 20:20:40 +000023435 lead = eval_fname_script(start);
Bram Moolenaara7043832005-01-21 11:56:39 +000023436 if (lead > 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023437 start += lead;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000023438
Bram Moolenaar6d977d62014-01-14 15:24:39 +010023439 /* Note that TFN_ flags use the same values as GLV_ flags. */
23440 end = get_lval(start, NULL, &lv, FALSE, skip, flags,
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000023441 lead > 2 ? 0 : FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000023442 if (end == start)
23443 {
23444 if (!skip)
23445 EMSG(_("E129: Function name required"));
23446 goto theend;
23447 }
Bram Moolenaara7043832005-01-21 11:56:39 +000023448 if (end == NULL || (lv.ll_tv != NULL && (lead > 2 || lv.ll_range)))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000023449 {
23450 /*
23451 * Report an invalid expression in braces, unless the expression
23452 * evaluation has been cancelled due to an aborting error, an
23453 * interrupt, or an exception.
23454 */
23455 if (!aborting())
23456 {
23457 if (end != NULL)
23458 EMSG2(_(e_invarg2), start);
23459 }
23460 else
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000023461 *pp = find_name_end(start, NULL, NULL, FNE_INCL_BR);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000023462 goto theend;
23463 }
23464
23465 if (lv.ll_tv != NULL)
23466 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023467 if (fdp != NULL)
23468 {
23469 fdp->fd_dict = lv.ll_dict;
23470 fdp->fd_newkey = lv.ll_newkey;
23471 lv.ll_newkey = NULL;
23472 fdp->fd_di = lv.ll_di;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023473 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000023474 if (lv.ll_tv->v_type == VAR_FUNC && lv.ll_tv->vval.v_string != NULL)
23475 {
23476 name = vim_strsave(lv.ll_tv->vval.v_string);
23477 *pp = end;
23478 }
23479 else
23480 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000023481 if (!skip && !(flags & TFN_QUIET) && (fdp == NULL
23482 || lv.ll_dict == NULL || fdp->fd_newkey == NULL))
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023483 EMSG(_(e_funcref));
23484 else
23485 *pp = end;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000023486 name = NULL;
23487 }
23488 goto theend;
23489 }
23490
23491 if (lv.ll_name == NULL)
23492 {
23493 /* Error found, but continue after the function name. */
23494 *pp = end;
23495 goto theend;
23496 }
23497
Bram Moolenaar33e1a802007-09-06 12:26:44 +000023498 /* Check if the name is a Funcref. If so, use the value. */
23499 if (lv.ll_exp_name != NULL)
23500 {
23501 len = (int)STRLEN(lv.ll_exp_name);
Bram Moolenaar8822a9c2014-01-14 19:44:34 +010023502 name = deref_func_name(lv.ll_exp_name, &len, flags & TFN_NO_AUTOLOAD);
Bram Moolenaar33e1a802007-09-06 12:26:44 +000023503 if (name == lv.ll_exp_name)
23504 name = NULL;
23505 }
23506 else
23507 {
23508 len = (int)(end - *pp);
Bram Moolenaar8822a9c2014-01-14 19:44:34 +010023509 name = deref_func_name(*pp, &len, flags & TFN_NO_AUTOLOAD);
Bram Moolenaar33e1a802007-09-06 12:26:44 +000023510 if (name == *pp)
23511 name = NULL;
23512 }
23513 if (name != NULL)
23514 {
23515 name = vim_strsave(name);
23516 *pp = end;
Bram Moolenaar355a95a2014-04-29 14:03:02 +020023517 if (STRNCMP(name, "<SNR>", 5) == 0)
23518 {
23519 /* Change "<SNR>" to the byte sequence. */
23520 name[0] = K_SPECIAL;
23521 name[1] = KS_EXTRA;
23522 name[2] = (int)KE_SNR;
23523 mch_memmove(name + 3, name + 5, STRLEN(name + 5) + 1);
23524 }
Bram Moolenaar33e1a802007-09-06 12:26:44 +000023525 goto theend;
23526 }
23527
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000023528 if (lv.ll_exp_name != NULL)
Bram Moolenaarc32840f2006-01-14 21:23:38 +000023529 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000023530 len = (int)STRLEN(lv.ll_exp_name);
Bram Moolenaarc32840f2006-01-14 21:23:38 +000023531 if (lead <= 2 && lv.ll_name == lv.ll_exp_name
23532 && STRNCMP(lv.ll_name, "s:", 2) == 0)
23533 {
23534 /* When there was "s:" already or the name expanded to get a
23535 * leading "s:" then remove it. */
23536 lv.ll_name += 2;
23537 len -= 2;
23538 lead = 2;
23539 }
23540 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000023541 else
Bram Moolenaara7043832005-01-21 11:56:39 +000023542 {
Bram Moolenaareccb7fc2014-04-23 20:43:41 +020023543 /* skip over "s:" and "g:" */
23544 if (lead == 2 || (lv.ll_name[0] == 'g' && lv.ll_name[1] == ':'))
Bram Moolenaara7043832005-01-21 11:56:39 +000023545 lv.ll_name += 2;
23546 len = (int)(end - lv.ll_name);
23547 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000023548
23549 /*
23550 * Copy the function name to allocated memory.
23551 * Accept <SID>name() inside a script, translate into <SNR>123_name().
23552 * Accept <SNR>123_name() outside a script.
23553 */
23554 if (skip)
23555 lead = 0; /* do nothing */
23556 else if (lead > 0)
23557 {
23558 lead = 3;
Bram Moolenaar86c9ee22006-05-13 11:33:27 +000023559 if ((lv.ll_exp_name != NULL && eval_fname_sid(lv.ll_exp_name))
23560 || eval_fname_sid(*pp))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000023561 {
Bram Moolenaar899dddf2006-03-26 21:06:50 +000023562 /* It's "s:" or "<SID>" */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000023563 if (current_SID <= 0)
23564 {
23565 EMSG(_(e_usingsid));
23566 goto theend;
23567 }
23568 sprintf((char *)sid_buf, "%ld_", (long)current_SID);
23569 lead += (int)STRLEN(sid_buf);
23570 }
23571 }
Bram Moolenaar9bdfb002014-04-23 17:43:42 +020023572 else if (!(flags & TFN_INT) && builtin_function(lv.ll_name, len))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000023573 {
Bram Moolenaar9bdfb002014-04-23 17:43:42 +020023574 EMSG2(_("E128: Function name must start with a capital or \"s:\": %s"),
Bram Moolenaareccb7fc2014-04-23 20:43:41 +020023575 start);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000023576 goto theend;
23577 }
Bram Moolenaareccb7fc2014-04-23 20:43:41 +020023578 if (!skip && !(flags & TFN_QUIET))
Bram Moolenaar9bdfb002014-04-23 17:43:42 +020023579 {
23580 char_u *cp = vim_strchr(lv.ll_name, ':');
23581
23582 if (cp != NULL && cp < end)
23583 {
Bram Moolenaareccb7fc2014-04-23 20:43:41 +020023584 EMSG2(_("E884: Function name cannot contain a colon: %s"), start);
Bram Moolenaar9bdfb002014-04-23 17:43:42 +020023585 goto theend;
23586 }
23587 }
23588
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000023589 name = alloc((unsigned)(len + lead + 1));
23590 if (name != NULL)
23591 {
23592 if (lead > 0)
23593 {
23594 name[0] = K_SPECIAL;
23595 name[1] = KS_EXTRA;
23596 name[2] = (int)KE_SNR;
Bram Moolenaara7043832005-01-21 11:56:39 +000023597 if (lead > 3) /* If it's "<SID>" */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000023598 STRCPY(name + 3, sid_buf);
23599 }
23600 mch_memmove(name + lead, lv.ll_name, (size_t)len);
Bram Moolenaar9bdfb002014-04-23 17:43:42 +020023601 name[lead + len] = NUL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000023602 }
23603 *pp = end;
23604
23605theend:
23606 clear_lval(&lv);
23607 return name;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023608}
23609
23610/*
23611 * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case).
23612 * Return 2 if "p" starts with "s:".
23613 * Return 0 otherwise.
23614 */
23615 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010023616eval_fname_script(char_u *p)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023617{
Bram Moolenaare266d6d2016-01-19 20:51:32 +010023618 /* Use MB_STRICMP() because in Turkish comparing the "I" may not work with
23619 * the standard library function. */
23620 if (p[0] == '<' && (MB_STRNICMP(p + 1, "SID>", 4) == 0
23621 || MB_STRNICMP(p + 1, "SNR>", 4) == 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +000023622 return 5;
23623 if (p[0] == 's' && p[1] == ':')
23624 return 2;
23625 return 0;
23626}
23627
23628/*
23629 * Return TRUE if "p" starts with "<SID>" or "s:".
23630 * Only works if eval_fname_script() returned non-zero for "p"!
23631 */
23632 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010023633eval_fname_sid(char_u *p)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023634{
23635 return (*p == 's' || TOUPPER_ASC(p[2]) == 'I');
23636}
23637
23638/*
23639 * List the head of the function: "name(arg1, arg2)".
23640 */
23641 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010023642list_func_head(ufunc_T *fp, int indent)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023643{
23644 int j;
23645
23646 msg_start();
23647 if (indent)
23648 MSG_PUTS(" ");
23649 MSG_PUTS("function ");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023650 if (fp->uf_name[0] == K_SPECIAL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023651 {
23652 MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023653 msg_puts(fp->uf_name + 3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023654 }
23655 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023656 msg_puts(fp->uf_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023657 msg_putchar('(');
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023658 for (j = 0; j < fp->uf_args.ga_len; ++j)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023659 {
23660 if (j)
23661 MSG_PUTS(", ");
23662 msg_puts(FUNCARG(fp, j));
23663 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023664 if (fp->uf_varargs)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023665 {
23666 if (j)
23667 MSG_PUTS(", ");
23668 MSG_PUTS("...");
23669 }
23670 msg_putchar(')');
Bram Moolenaar4cd92d52013-06-06 21:31:06 +020023671 if (fp->uf_flags & FC_ABORT)
23672 MSG_PUTS(" abort");
23673 if (fp->uf_flags & FC_RANGE)
23674 MSG_PUTS(" range");
23675 if (fp->uf_flags & FC_DICT)
23676 MSG_PUTS(" dict");
Bram Moolenaarcafda4f2005-09-06 19:25:11 +000023677 msg_clr_eos();
Bram Moolenaar5b8d8fd2005-08-16 23:01:50 +000023678 if (p_verbose > 0)
23679 last_set_msg(fp->uf_script_ID);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023680}
23681
23682/*
23683 * Find a function by name, return pointer to it in ufuncs.
23684 * Return NULL for unknown function.
23685 */
23686 static ufunc_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +010023687find_func(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023688{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023689 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023690
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023691 hi = hash_find(&func_hashtab, name);
23692 if (!HASHITEM_EMPTY(hi))
23693 return HI2UF(hi);
23694 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023695}
23696
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000023697#if defined(EXITFREE) || defined(PROTO)
23698 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010023699free_all_functions(void)
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000023700{
23701 hashitem_T *hi;
23702
23703 /* Need to start all over every time, because func_free() may change the
23704 * hash table. */
23705 while (func_hashtab.ht_used > 0)
23706 for (hi = func_hashtab.ht_array; ; ++hi)
23707 if (!HASHITEM_EMPTY(hi))
23708 {
23709 func_free(HI2UF(hi));
23710 break;
23711 }
23712}
23713#endif
23714
Bram Moolenaar355fd9b2013-05-30 13:14:13 +020023715 int
Bram Moolenaar7454a062016-01-30 15:14:10 +010023716translated_function_exists(char_u *name)
Bram Moolenaar355fd9b2013-05-30 13:14:13 +020023717{
Bram Moolenaar9bdfb002014-04-23 17:43:42 +020023718 if (builtin_function(name, -1))
Bram Moolenaar355fd9b2013-05-30 13:14:13 +020023719 return find_internal_func(name) >= 0;
23720 return find_func(name) != NULL;
23721}
23722
Bram Moolenaar49cd9572005-01-03 21:06:01 +000023723/*
23724 * Return TRUE if a function "name" exists.
23725 */
23726 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010023727function_exists(char_u *name)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000023728{
Bram Moolenaaraa35dd12006-04-29 22:03:41 +000023729 char_u *nm = name;
23730 char_u *p;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000023731 int n = FALSE;
23732
Bram Moolenaar6d977d62014-01-14 15:24:39 +010023733 p = trans_function_name(&nm, FALSE, TFN_INT|TFN_QUIET|TFN_NO_AUTOLOAD,
23734 NULL);
Bram Moolenaar79783442006-05-05 21:18:03 +000023735 nm = skipwhite(nm);
23736
23737 /* Only accept "funcname", "funcname ", "funcname (..." and
23738 * "funcname(...", not "funcname!...". */
23739 if (p != NULL && (*nm == NUL || *nm == '('))
Bram Moolenaar355fd9b2013-05-30 13:14:13 +020023740 n = translated_function_exists(p);
Bram Moolenaar79783442006-05-05 21:18:03 +000023741 vim_free(p);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000023742 return n;
23743}
23744
Bram Moolenaara1544c02013-05-30 12:35:52 +020023745 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010023746get_expanded_name(char_u *name, int check)
Bram Moolenaara1544c02013-05-30 12:35:52 +020023747{
23748 char_u *nm = name;
23749 char_u *p;
23750
23751 p = trans_function_name(&nm, FALSE, TFN_INT|TFN_QUIET, NULL);
23752
23753 if (p != NULL && *nm == NUL)
Bram Moolenaar355fd9b2013-05-30 13:14:13 +020023754 if (!check || translated_function_exists(p))
Bram Moolenaara1544c02013-05-30 12:35:52 +020023755 return p;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +020023756
Bram Moolenaara1544c02013-05-30 12:35:52 +020023757 vim_free(p);
23758 return NULL;
23759}
23760
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000023761/*
23762 * Return TRUE if "name" looks like a builtin function name: starts with a
Bram Moolenaar9bdfb002014-04-23 17:43:42 +020023763 * lower case letter and doesn't contain AUTOLOAD_CHAR.
23764 * "len" is the length of "name", or -1 for NUL terminated.
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000023765 */
23766 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010023767builtin_function(char_u *name, int len)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000023768{
Bram Moolenaar9bdfb002014-04-23 17:43:42 +020023769 char_u *p;
23770
23771 if (!ASCII_ISLOWER(name[0]))
23772 return FALSE;
23773 p = vim_strchr(name, AUTOLOAD_CHAR);
23774 return p == NULL || (len > 0 && p > name + len);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000023775}
23776
Bram Moolenaar05159a02005-02-26 23:04:13 +000023777#if defined(FEAT_PROFILE) || defined(PROTO)
23778/*
23779 * Start profiling function "fp".
23780 */
23781 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010023782func_do_profile(ufunc_T *fp)
Bram Moolenaar05159a02005-02-26 23:04:13 +000023783{
Bram Moolenaar904c6222010-07-24 16:57:39 +020023784 int len = fp->uf_lines.ga_len;
23785
23786 if (len == 0)
23787 len = 1; /* avoid getting error for allocating zero bytes */
Bram Moolenaar05159a02005-02-26 23:04:13 +000023788 fp->uf_tm_count = 0;
23789 profile_zero(&fp->uf_tm_self);
23790 profile_zero(&fp->uf_tm_total);
23791 if (fp->uf_tml_count == NULL)
Bram Moolenaar904c6222010-07-24 16:57:39 +020023792 fp->uf_tml_count = (int *)alloc_clear((unsigned) (sizeof(int) * len));
Bram Moolenaar05159a02005-02-26 23:04:13 +000023793 if (fp->uf_tml_total == NULL)
23794 fp->uf_tml_total = (proftime_T *)alloc_clear((unsigned)
Bram Moolenaar904c6222010-07-24 16:57:39 +020023795 (sizeof(proftime_T) * len));
Bram Moolenaar05159a02005-02-26 23:04:13 +000023796 if (fp->uf_tml_self == NULL)
23797 fp->uf_tml_self = (proftime_T *)alloc_clear((unsigned)
Bram Moolenaar904c6222010-07-24 16:57:39 +020023798 (sizeof(proftime_T) * len));
Bram Moolenaar05159a02005-02-26 23:04:13 +000023799 fp->uf_tml_idx = -1;
23800 if (fp->uf_tml_count == NULL || fp->uf_tml_total == NULL
23801 || fp->uf_tml_self == NULL)
23802 return; /* out of memory */
23803
23804 fp->uf_profiling = TRUE;
23805}
23806
23807/*
23808 * Dump the profiling results for all functions in file "fd".
23809 */
23810 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010023811func_dump_profile(FILE *fd)
Bram Moolenaar05159a02005-02-26 23:04:13 +000023812{
23813 hashitem_T *hi;
23814 int todo;
23815 ufunc_T *fp;
23816 int i;
Bram Moolenaar73830342005-02-28 22:48:19 +000023817 ufunc_T **sorttab;
23818 int st_len = 0;
Bram Moolenaar05159a02005-02-26 23:04:13 +000023819
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000023820 todo = (int)func_hashtab.ht_used;
Bram Moolenaar61c4e2c2008-08-25 02:49:18 +000023821 if (todo == 0)
23822 return; /* nothing to dump */
23823
Bram Moolenaare2e4b982015-06-09 20:30:51 +020023824 sorttab = (ufunc_T **)alloc((unsigned)(sizeof(ufunc_T *) * todo));
Bram Moolenaar73830342005-02-28 22:48:19 +000023825
Bram Moolenaar05159a02005-02-26 23:04:13 +000023826 for (hi = func_hashtab.ht_array; todo > 0; ++hi)
23827 {
23828 if (!HASHITEM_EMPTY(hi))
23829 {
23830 --todo;
23831 fp = HI2UF(hi);
23832 if (fp->uf_profiling)
23833 {
Bram Moolenaar73830342005-02-28 22:48:19 +000023834 if (sorttab != NULL)
23835 sorttab[st_len++] = fp;
23836
Bram Moolenaar05159a02005-02-26 23:04:13 +000023837 if (fp->uf_name[0] == K_SPECIAL)
23838 fprintf(fd, "FUNCTION <SNR>%s()\n", fp->uf_name + 3);
23839 else
23840 fprintf(fd, "FUNCTION %s()\n", fp->uf_name);
23841 if (fp->uf_tm_count == 1)
23842 fprintf(fd, "Called 1 time\n");
23843 else
23844 fprintf(fd, "Called %d times\n", fp->uf_tm_count);
23845 fprintf(fd, "Total time: %s\n", profile_msg(&fp->uf_tm_total));
23846 fprintf(fd, " Self time: %s\n", profile_msg(&fp->uf_tm_self));
23847 fprintf(fd, "\n");
23848 fprintf(fd, "count total (s) self (s)\n");
23849
23850 for (i = 0; i < fp->uf_lines.ga_len; ++i)
23851 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000023852 if (FUNCLINE(fp, i) == NULL)
23853 continue;
Bram Moolenaar73830342005-02-28 22:48:19 +000023854 prof_func_line(fd, fp->uf_tml_count[i],
23855 &fp->uf_tml_total[i], &fp->uf_tml_self[i], TRUE);
Bram Moolenaar05159a02005-02-26 23:04:13 +000023856 fprintf(fd, "%s\n", FUNCLINE(fp, i));
23857 }
23858 fprintf(fd, "\n");
23859 }
23860 }
23861 }
Bram Moolenaar73830342005-02-28 22:48:19 +000023862
23863 if (sorttab != NULL && st_len > 0)
23864 {
23865 qsort((void *)sorttab, (size_t)st_len, sizeof(ufunc_T *),
23866 prof_total_cmp);
23867 prof_sort_list(fd, sorttab, st_len, "TOTAL", FALSE);
23868 qsort((void *)sorttab, (size_t)st_len, sizeof(ufunc_T *),
23869 prof_self_cmp);
23870 prof_sort_list(fd, sorttab, st_len, "SELF", TRUE);
23871 }
Bram Moolenaar61c4e2c2008-08-25 02:49:18 +000023872
23873 vim_free(sorttab);
Bram Moolenaar05159a02005-02-26 23:04:13 +000023874}
Bram Moolenaar73830342005-02-28 22:48:19 +000023875
23876 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010023877prof_sort_list(
23878 FILE *fd,
23879 ufunc_T **sorttab,
23880 int st_len,
23881 char *title,
23882 int prefer_self) /* when equal print only self time */
Bram Moolenaar73830342005-02-28 22:48:19 +000023883{
23884 int i;
23885 ufunc_T *fp;
23886
23887 fprintf(fd, "FUNCTIONS SORTED ON %s TIME\n", title);
23888 fprintf(fd, "count total (s) self (s) function\n");
23889 for (i = 0; i < 20 && i < st_len; ++i)
23890 {
23891 fp = sorttab[i];
23892 prof_func_line(fd, fp->uf_tm_count, &fp->uf_tm_total, &fp->uf_tm_self,
23893 prefer_self);
23894 if (fp->uf_name[0] == K_SPECIAL)
23895 fprintf(fd, " <SNR>%s()\n", fp->uf_name + 3);
23896 else
23897 fprintf(fd, " %s()\n", fp->uf_name);
23898 }
23899 fprintf(fd, "\n");
23900}
23901
23902/*
23903 * Print the count and times for one function or function line.
23904 */
23905 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010023906prof_func_line(
23907 FILE *fd,
23908 int count,
23909 proftime_T *total,
23910 proftime_T *self,
23911 int prefer_self) /* when equal print only self time */
Bram Moolenaar73830342005-02-28 22:48:19 +000023912{
23913 if (count > 0)
23914 {
23915 fprintf(fd, "%5d ", count);
23916 if (prefer_self && profile_equal(total, self))
23917 fprintf(fd, " ");
23918 else
23919 fprintf(fd, "%s ", profile_msg(total));
23920 if (!prefer_self && profile_equal(total, self))
23921 fprintf(fd, " ");
23922 else
23923 fprintf(fd, "%s ", profile_msg(self));
23924 }
23925 else
23926 fprintf(fd, " ");
23927}
23928
23929/*
23930 * Compare function for total time sorting.
23931 */
23932 static int
23933#ifdef __BORLANDC__
23934_RTLENTRYF
23935#endif
Bram Moolenaar7454a062016-01-30 15:14:10 +010023936prof_total_cmp(const void *s1, const void *s2)
Bram Moolenaar73830342005-02-28 22:48:19 +000023937{
23938 ufunc_T *p1, *p2;
23939
23940 p1 = *(ufunc_T **)s1;
23941 p2 = *(ufunc_T **)s2;
23942 return profile_cmp(&p1->uf_tm_total, &p2->uf_tm_total);
23943}
23944
23945/*
23946 * Compare function for self time sorting.
23947 */
23948 static int
23949#ifdef __BORLANDC__
23950_RTLENTRYF
23951#endif
Bram Moolenaar7454a062016-01-30 15:14:10 +010023952prof_self_cmp(const void *s1, const void *s2)
Bram Moolenaar73830342005-02-28 22:48:19 +000023953{
23954 ufunc_T *p1, *p2;
23955
23956 p1 = *(ufunc_T **)s1;
23957 p2 = *(ufunc_T **)s2;
23958 return profile_cmp(&p1->uf_tm_self, &p2->uf_tm_self);
23959}
23960
Bram Moolenaar05159a02005-02-26 23:04:13 +000023961#endif
23962
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000023963/*
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023964 * If "name" has a package name try autoloading the script for it.
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000023965 * Return TRUE if a package was loaded.
23966 */
Bram Moolenaar018acca2013-05-30 13:37:28 +020023967 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010023968script_autoload(
23969 char_u *name,
23970 int reload) /* load script again when already loaded */
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000023971{
23972 char_u *p;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000023973 char_u *scriptname, *tofree;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000023974 int ret = FALSE;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000023975 int i;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000023976
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000023977 /* If there is no '#' after name[0] there is no package name. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000023978 p = vim_strchr(name, AUTOLOAD_CHAR);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000023979 if (p == NULL || p == name)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000023980 return FALSE;
23981
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000023982 tofree = scriptname = autoload_name(name);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023983
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000023984 /* Find the name in the list of previously loaded package names. Skip
23985 * "autoload/", it's always the same. */
23986 for (i = 0; i < ga_loaded.ga_len; ++i)
23987 if (STRCMP(((char_u **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0)
23988 break;
23989 if (!reload && i < ga_loaded.ga_len)
23990 ret = FALSE; /* was loaded already */
23991 else
23992 {
23993 /* Remember the name if it wasn't loaded already. */
23994 if (i == ga_loaded.ga_len && ga_grow(&ga_loaded, 1) == OK)
23995 {
23996 ((char_u **)ga_loaded.ga_data)[ga_loaded.ga_len++] = scriptname;
23997 tofree = NULL;
23998 }
23999
24000 /* Try loading the package from $VIMRUNTIME/autoload/<name>.vim */
Bram Moolenaar7f8989d2016-03-12 22:11:39 +010024001 if (source_runtime(scriptname, 0) == OK)
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000024002 ret = TRUE;
24003 }
24004
24005 vim_free(tofree);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024006 return ret;
24007}
24008
24009/*
24010 * Return the autoload script name for a function or variable name.
24011 * Returns NULL when out of memory.
24012 */
24013 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010024014autoload_name(char_u *name)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024015{
24016 char_u *p;
24017 char_u *scriptname;
24018
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000024019 /* Get the script file name: replace '#' with '/', append ".vim". */
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000024020 scriptname = alloc((unsigned)(STRLEN(name) + 14));
24021 if (scriptname == NULL)
24022 return FALSE;
24023 STRCPY(scriptname, "autoload/");
24024 STRCAT(scriptname, name);
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000024025 *vim_strrchr(scriptname, AUTOLOAD_CHAR) = NUL;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000024026 STRCAT(scriptname, ".vim");
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000024027 while ((p = vim_strchr(scriptname, AUTOLOAD_CHAR)) != NULL)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000024028 *p = '/';
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024029 return scriptname;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000024030}
24031
Bram Moolenaar071d4272004-06-13 20:20:40 +000024032#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
24033
24034/*
24035 * Function given to ExpandGeneric() to obtain the list of user defined
24036 * function names.
24037 */
24038 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010024039get_user_func_name(expand_T *xp, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024040{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024041 static long_u done;
24042 static hashitem_T *hi;
24043 ufunc_T *fp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024044
24045 if (idx == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024046 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024047 done = 0;
24048 hi = func_hashtab.ht_array;
24049 }
24050 if (done < func_hashtab.ht_used)
24051 {
24052 if (done++ > 0)
24053 ++hi;
24054 while (HASHITEM_EMPTY(hi))
24055 ++hi;
24056 fp = HI2UF(hi);
24057
Bram Moolenaar195ea0f2011-11-30 14:57:31 +010024058 if (fp->uf_flags & FC_DICT)
Bram Moolenaar975261e2012-01-26 18:52:06 +010024059 return (char_u *)""; /* don't show dict functions */
Bram Moolenaar195ea0f2011-11-30 14:57:31 +010024060
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024061 if (STRLEN(fp->uf_name) + 4 >= IOSIZE)
24062 return fp->uf_name; /* prevents overflow */
Bram Moolenaar071d4272004-06-13 20:20:40 +000024063
24064 cat_func_name(IObuff, fp);
24065 if (xp->xp_context != EXPAND_USER_FUNC)
24066 {
24067 STRCAT(IObuff, "(");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024068 if (!fp->uf_varargs && fp->uf_args.ga_len == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024069 STRCAT(IObuff, ")");
24070 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000024071 return IObuff;
24072 }
24073 return NULL;
24074}
24075
24076#endif /* FEAT_CMDL_COMPL */
24077
24078/*
24079 * Copy the function name of "fp" to buffer "buf".
24080 * "buf" must be able to hold the function name plus three bytes.
24081 * Takes care of script-local function names.
24082 */
24083 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010024084cat_func_name(char_u *buf, ufunc_T *fp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024085{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024086 if (fp->uf_name[0] == K_SPECIAL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024087 {
24088 STRCPY(buf, "<SNR>");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024089 STRCAT(buf, fp->uf_name + 3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024090 }
24091 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024092 STRCPY(buf, fp->uf_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024093}
24094
24095/*
24096 * ":delfunction {name}"
24097 */
24098 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010024099ex_delfunction(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024100{
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000024101 ufunc_T *fp = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024102 char_u *p;
24103 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000024104 funcdict_T fudi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024105
24106 p = eap->arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000024107 name = trans_function_name(&p, eap->skip, 0, &fudi);
24108 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024109 if (name == NULL)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000024110 {
24111 if (fudi.fd_dict != NULL && !eap->skip)
24112 EMSG(_(e_funcref));
Bram Moolenaar071d4272004-06-13 20:20:40 +000024113 return;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000024114 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000024115 if (!ends_excmd(*skipwhite(p)))
24116 {
24117 vim_free(name);
24118 EMSG(_(e_trailing));
24119 return;
24120 }
24121 eap->nextcmd = check_nextcmd(p);
24122 if (eap->nextcmd != NULL)
24123 *p = NUL;
24124
24125 if (!eap->skip)
24126 fp = find_func(name);
24127 vim_free(name);
24128
24129 if (!eap->skip)
24130 {
24131 if (fp == NULL)
24132 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000024133 EMSG2(_(e_nofunc), eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024134 return;
24135 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024136 if (fp->uf_calls > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024137 {
24138 EMSG2(_("E131: Cannot delete function %s: It is in use"), eap->arg);
24139 return;
24140 }
24141
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000024142 if (fudi.fd_dict != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024143 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000024144 /* Delete the dict item that refers to the function, it will
24145 * invoke func_unref() and possibly delete the function. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000024146 dictitem_remove(fudi.fd_dict, fudi.fd_di);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024147 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000024148 else
24149 func_free(fp);
24150 }
24151}
24152
24153/*
24154 * Free a function and remove it from the list of functions.
24155 */
24156 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010024157func_free(ufunc_T *fp)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000024158{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024159 hashitem_T *hi;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000024160
24161 /* clear this function */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024162 ga_clear_strings(&(fp->uf_args));
24163 ga_clear_strings(&(fp->uf_lines));
Bram Moolenaar05159a02005-02-26 23:04:13 +000024164#ifdef FEAT_PROFILE
24165 vim_free(fp->uf_tml_count);
24166 vim_free(fp->uf_tml_total);
24167 vim_free(fp->uf_tml_self);
24168#endif
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000024169
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024170 /* remove the function from the function hashtable */
24171 hi = hash_find(&func_hashtab, UF2HIKEY(fp));
24172 if (HASHITEM_EMPTY(hi))
24173 EMSG2(_(e_intern2), "func_free()");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000024174 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024175 hash_remove(&func_hashtab, hi);
24176
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000024177 vim_free(fp);
24178}
24179
24180/*
24181 * Unreference a Function: decrement the reference count and free it when it
24182 * becomes zero. Only for numbered functions.
24183 */
Bram Moolenaardb913952012-06-29 12:54:53 +020024184 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010024185func_unref(char_u *name)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000024186{
24187 ufunc_T *fp;
24188
24189 if (name != NULL && isdigit(*name))
24190 {
24191 fp = find_func(name);
24192 if (fp == NULL)
24193 EMSG2(_(e_intern2), "func_unref()");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024194 else if (--fp->uf_refcount <= 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000024195 {
24196 /* Only delete it when it's not being used. Otherwise it's done
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024197 * when "uf_calls" becomes zero. */
24198 if (fp->uf_calls == 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000024199 func_free(fp);
24200 }
24201 }
24202}
24203
24204/*
24205 * Count a reference to a Function.
24206 */
Bram Moolenaardb913952012-06-29 12:54:53 +020024207 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010024208func_ref(char_u *name)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000024209{
24210 ufunc_T *fp;
24211
24212 if (name != NULL && isdigit(*name))
24213 {
24214 fp = find_func(name);
24215 if (fp == NULL)
24216 EMSG2(_(e_intern2), "func_ref()");
24217 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024218 ++fp->uf_refcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024219 }
24220}
24221
24222/*
24223 * Call a user function.
24224 */
24225 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010024226call_user_func(
24227 ufunc_T *fp, /* pointer to function */
24228 int argcount, /* nr of args */
24229 typval_T *argvars, /* arguments */
24230 typval_T *rettv, /* return value */
24231 linenr_T firstline, /* first line of range */
24232 linenr_T lastline, /* last line of range */
24233 dict_T *selfdict) /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000024234{
Bram Moolenaar33570922005-01-25 22:26:29 +000024235 char_u *save_sourcing_name;
24236 linenr_T save_sourcing_lnum;
24237 scid_T save_current_SID;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024238 funccall_T *fc;
Bram Moolenaar33570922005-01-25 22:26:29 +000024239 int save_did_emsg;
24240 static int depth = 0;
24241 dictitem_T *v;
24242 int fixvar_idx = 0; /* index in fixvar[] */
24243 int i;
24244 int ai;
24245 char_u numbuf[NUMBUFLEN];
24246 char_u *name;
Bram Moolenaar1d6328c2015-09-25 17:37:16 +020024247 size_t len;
Bram Moolenaar05159a02005-02-26 23:04:13 +000024248#ifdef FEAT_PROFILE
24249 proftime_T wait_start;
Bram Moolenaare9da72e2006-11-01 17:34:40 +000024250 proftime_T call_start;
Bram Moolenaar05159a02005-02-26 23:04:13 +000024251#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000024252
24253 /* If depth of calling is getting too high, don't execute the function */
24254 if (depth >= p_mfd)
24255 {
24256 EMSG(_("E132: Function call depth is higher than 'maxfuncdepth'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024257 rettv->v_type = VAR_NUMBER;
24258 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024259 return;
24260 }
24261 ++depth;
24262
24263 line_breakcheck(); /* check for CTRL-C hit */
24264
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024265 fc = (funccall_T *)alloc(sizeof(funccall_T));
24266 fc->caller = current_funccal;
24267 current_funccal = fc;
24268 fc->func = fp;
24269 fc->rettv = rettv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024270 rettv->vval.v_number = 0;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024271 fc->linenr = 0;
24272 fc->returned = FALSE;
24273 fc->level = ex_nesting_level;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024274 /* Check if this function has a breakpoint. */
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024275 fc->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0);
24276 fc->dbg_tick = debug_tick;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024277
Bram Moolenaar33570922005-01-25 22:26:29 +000024278 /*
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024279 * Note about using fc->fixvar[]: This is an array of FIXVAR_CNT variables
Bram Moolenaar33570922005-01-25 22:26:29 +000024280 * with names up to VAR_SHORT_LEN long. This avoids having to alloc/free
24281 * each argument variable and saves a lot of time.
24282 */
24283 /*
24284 * Init l: variables.
24285 */
Bram Moolenaarbdb62052012-07-16 17:31:53 +020024286 init_var_dict(&fc->l_vars, &fc->l_vars_var, VAR_DEF_SCOPE);
Bram Moolenaara7043832005-01-21 11:56:39 +000024287 if (selfdict != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000024288 {
Bram Moolenaar76b92b22006-03-24 22:46:53 +000024289 /* Set l:self to "selfdict". Use "name" to avoid a warning from
24290 * some compiler that checks the destination size. */
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024291 v = &fc->fixvar[fixvar_idx++].var;
Bram Moolenaar76b92b22006-03-24 22:46:53 +000024292 name = v->di_key;
24293 STRCPY(name, "self");
Bram Moolenaar33570922005-01-25 22:26:29 +000024294 v->di_flags = DI_FLAGS_RO + DI_FLAGS_FIX;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024295 hash_add(&fc->l_vars.dv_hashtab, DI2HIKEY(v));
Bram Moolenaar33570922005-01-25 22:26:29 +000024296 v->di_tv.v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000024297 v->di_tv.v_lock = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000024298 v->di_tv.vval.v_dict = selfdict;
24299 ++selfdict->dv_refcount;
24300 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000024301
Bram Moolenaar33570922005-01-25 22:26:29 +000024302 /*
24303 * Init a: variables.
24304 * Set a:0 to "argcount".
24305 * Set a:000 to a list with room for the "..." arguments.
24306 */
Bram Moolenaarbdb62052012-07-16 17:31:53 +020024307 init_var_dict(&fc->l_avars, &fc->l_avars_var, VAR_SCOPE);
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024308 add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "0",
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024309 (varnumber_T)(argcount - fp->uf_args.ga_len));
Bram Moolenaar0cd49302008-11-20 09:37:01 +000024310 /* Use "name" to avoid a warning from some compiler that checks the
24311 * destination size. */
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024312 v = &fc->fixvar[fixvar_idx++].var;
Bram Moolenaar0cd49302008-11-20 09:37:01 +000024313 name = v->di_key;
24314 STRCPY(name, "000");
Bram Moolenaar33570922005-01-25 22:26:29 +000024315 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024316 hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v));
Bram Moolenaar33570922005-01-25 22:26:29 +000024317 v->di_tv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000024318 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024319 v->di_tv.vval.v_list = &fc->l_varlist;
24320 vim_memset(&fc->l_varlist, 0, sizeof(list_T));
24321 fc->l_varlist.lv_refcount = DO_NOT_FREE_CNT;
24322 fc->l_varlist.lv_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000024323
24324 /*
24325 * Set a:firstline to "firstline" and a:lastline to "lastline".
24326 * Set a:name to named arguments.
24327 * Set a:N to the "..." arguments.
24328 */
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024329 add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "firstline",
Bram Moolenaar33570922005-01-25 22:26:29 +000024330 (varnumber_T)firstline);
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024331 add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "lastline",
Bram Moolenaar33570922005-01-25 22:26:29 +000024332 (varnumber_T)lastline);
24333 for (i = 0; i < argcount; ++i)
24334 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024335 ai = i - fp->uf_args.ga_len;
Bram Moolenaar33570922005-01-25 22:26:29 +000024336 if (ai < 0)
24337 /* named argument a:name */
24338 name = FUNCARG(fp, i);
24339 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000024340 {
Bram Moolenaar33570922005-01-25 22:26:29 +000024341 /* "..." argument a:1, a:2, etc. */
24342 sprintf((char *)numbuf, "%d", ai + 1);
24343 name = numbuf;
24344 }
24345 if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN)
24346 {
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024347 v = &fc->fixvar[fixvar_idx++].var;
Bram Moolenaar33570922005-01-25 22:26:29 +000024348 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
24349 }
24350 else
24351 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000024352 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
24353 + STRLEN(name)));
Bram Moolenaar33570922005-01-25 22:26:29 +000024354 if (v == NULL)
24355 break;
Bram Moolenaar9bc174b2015-04-13 16:16:38 +020024356 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX | DI_FLAGS_ALLOC;
Bram Moolenaar33570922005-01-25 22:26:29 +000024357 }
24358 STRCPY(v->di_key, name);
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024359 hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v));
Bram Moolenaar33570922005-01-25 22:26:29 +000024360
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000024361 /* Note: the values are copied directly to avoid alloc/free.
24362 * "argvars" must have VAR_FIXED for v_lock. */
Bram Moolenaar33570922005-01-25 22:26:29 +000024363 v->di_tv = argvars[i];
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000024364 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000024365
24366 if (ai >= 0 && ai < MAX_FUNC_ARGS)
24367 {
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024368 list_append(&fc->l_varlist, &fc->l_listitems[ai]);
24369 fc->l_listitems[ai].li_tv = argvars[i];
24370 fc->l_listitems[ai].li_tv.v_lock = VAR_FIXED;
Bram Moolenaare9a41262005-01-15 22:18:47 +000024371 }
24372 }
24373
Bram Moolenaar071d4272004-06-13 20:20:40 +000024374 /* Don't redraw while executing the function. */
24375 ++RedrawingDisabled;
24376 save_sourcing_name = sourcing_name;
24377 save_sourcing_lnum = sourcing_lnum;
24378 sourcing_lnum = 1;
Bram Moolenaar1d6328c2015-09-25 17:37:16 +020024379 /* need space for function name + ("function " + 3) or "[number]" */
24380 len = (save_sourcing_name == NULL ? 0 : STRLEN(save_sourcing_name))
24381 + STRLEN(fp->uf_name) + 20;
24382 sourcing_name = alloc((unsigned)len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024383 if (sourcing_name != NULL)
24384 {
24385 if (save_sourcing_name != NULL
24386 && STRNCMP(save_sourcing_name, "function ", 9) == 0)
Bram Moolenaar1d6328c2015-09-25 17:37:16 +020024387 sprintf((char *)sourcing_name, "%s[%d]..",
24388 save_sourcing_name, (int)save_sourcing_lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024389 else
24390 STRCPY(sourcing_name, "function ");
24391 cat_func_name(sourcing_name + STRLEN(sourcing_name), fp);
24392
24393 if (p_verbose >= 12)
24394 {
24395 ++no_wait_return;
Bram Moolenaar54ee7752005-05-31 22:22:17 +000024396 verbose_enter_scroll();
24397
Bram Moolenaar555b2802005-05-19 21:08:39 +000024398 smsg((char_u *)_("calling %s"), sourcing_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024399 if (p_verbose >= 14)
24400 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000024401 char_u buf[MSG_BUF_LEN];
Bram Moolenaar89d40322006-08-29 15:30:07 +000024402 char_u numbuf2[NUMBUFLEN];
Bram Moolenaar758711c2005-02-02 23:11:38 +000024403 char_u *tofree;
Bram Moolenaar92c5aba2007-08-14 20:29:31 +000024404 char_u *s;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024405
24406 msg_puts((char_u *)"(");
24407 for (i = 0; i < argcount; ++i)
24408 {
24409 if (i > 0)
24410 msg_puts((char_u *)", ");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000024411 if (argvars[i].v_type == VAR_NUMBER)
24412 msg_outnum((long)argvars[i].vval.v_number);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024413 else
24414 {
Bram Moolenaar8502c702014-06-17 12:51:16 +020024415 /* Do not want errors such as E724 here. */
24416 ++emsg_off;
Bram Moolenaar92c5aba2007-08-14 20:29:31 +000024417 s = tv2string(&argvars[i], &tofree, numbuf2, 0);
Bram Moolenaar8502c702014-06-17 12:51:16 +020024418 --emsg_off;
Bram Moolenaar92c5aba2007-08-14 20:29:31 +000024419 if (s != NULL)
24420 {
Bram Moolenaarf31b7642012-01-20 20:44:43 +010024421 if (vim_strsize(s) > MSG_BUF_CLEN)
24422 {
24423 trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN);
24424 s = buf;
24425 }
24426 msg_puts(s);
Bram Moolenaar92c5aba2007-08-14 20:29:31 +000024427 vim_free(tofree);
24428 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000024429 }
24430 }
24431 msg_puts((char_u *)")");
24432 }
24433 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaar54ee7752005-05-31 22:22:17 +000024434
24435 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000024436 --no_wait_return;
24437 }
24438 }
Bram Moolenaar05159a02005-02-26 23:04:13 +000024439#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +000024440 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +000024441 {
24442 if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL))
24443 func_do_profile(fp);
24444 if (fp->uf_profiling
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024445 || (fc->caller != NULL && fc->caller->func->uf_profiling))
Bram Moolenaar05159a02005-02-26 23:04:13 +000024446 {
24447 ++fp->uf_tm_count;
Bram Moolenaare9da72e2006-11-01 17:34:40 +000024448 profile_start(&call_start);
Bram Moolenaar05159a02005-02-26 23:04:13 +000024449 profile_zero(&fp->uf_tm_children);
24450 }
24451 script_prof_save(&wait_start);
24452 }
24453#endif
24454
Bram Moolenaar071d4272004-06-13 20:20:40 +000024455 save_current_SID = current_SID;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024456 current_SID = fp->uf_script_ID;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024457 save_did_emsg = did_emsg;
24458 did_emsg = FALSE;
24459
24460 /* call do_cmdline() to execute the lines */
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024461 do_cmdline(NULL, get_func_line, (void *)fc,
Bram Moolenaar071d4272004-06-13 20:20:40 +000024462 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
24463
24464 --RedrawingDisabled;
24465
24466 /* when the function was aborted because of an error, return -1 */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024467 if ((did_emsg && (fp->uf_flags & FC_ABORT)) || rettv->v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024468 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024469 clear_tv(rettv);
24470 rettv->v_type = VAR_NUMBER;
24471 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024472 }
24473
Bram Moolenaar05159a02005-02-26 23:04:13 +000024474#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +000024475 if (do_profiling == PROF_YES && (fp->uf_profiling
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024476 || (fc->caller != NULL && fc->caller->func->uf_profiling)))
Bram Moolenaar05159a02005-02-26 23:04:13 +000024477 {
Bram Moolenaare9da72e2006-11-01 17:34:40 +000024478 profile_end(&call_start);
24479 profile_sub_wait(&wait_start, &call_start);
24480 profile_add(&fp->uf_tm_total, &call_start);
24481 profile_self(&fp->uf_tm_self, &call_start, &fp->uf_tm_children);
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024482 if (fc->caller != NULL && fc->caller->func->uf_profiling)
Bram Moolenaar05159a02005-02-26 23:04:13 +000024483 {
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024484 profile_add(&fc->caller->func->uf_tm_children, &call_start);
24485 profile_add(&fc->caller->func->uf_tml_children, &call_start);
Bram Moolenaar05159a02005-02-26 23:04:13 +000024486 }
24487 }
24488#endif
24489
Bram Moolenaar071d4272004-06-13 20:20:40 +000024490 /* when being verbose, mention the return value */
24491 if (p_verbose >= 12)
24492 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000024493 ++no_wait_return;
Bram Moolenaar54ee7752005-05-31 22:22:17 +000024494 verbose_enter_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000024495
Bram Moolenaar071d4272004-06-13 20:20:40 +000024496 if (aborting())
Bram Moolenaar555b2802005-05-19 21:08:39 +000024497 smsg((char_u *)_("%s aborted"), sourcing_name);
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024498 else if (fc->rettv->v_type == VAR_NUMBER)
Bram Moolenaar555b2802005-05-19 21:08:39 +000024499 smsg((char_u *)_("%s returning #%ld"), sourcing_name,
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024500 (long)fc->rettv->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +000024501 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000024502 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000024503 char_u buf[MSG_BUF_LEN];
Bram Moolenaar89d40322006-08-29 15:30:07 +000024504 char_u numbuf2[NUMBUFLEN];
Bram Moolenaar758711c2005-02-02 23:11:38 +000024505 char_u *tofree;
Bram Moolenaar92c5aba2007-08-14 20:29:31 +000024506 char_u *s;
Bram Moolenaar758711c2005-02-02 23:11:38 +000024507
Bram Moolenaar555b2802005-05-19 21:08:39 +000024508 /* The value may be very long. Skip the middle part, so that we
24509 * have some idea how it starts and ends. smsg() would always
Bram Moolenaar8502c702014-06-17 12:51:16 +020024510 * truncate it at the end. Don't want errors such as E724 here. */
24511 ++emsg_off;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024512 s = tv2string(fc->rettv, &tofree, numbuf2, 0);
Bram Moolenaar8502c702014-06-17 12:51:16 +020024513 --emsg_off;
Bram Moolenaar92c5aba2007-08-14 20:29:31 +000024514 if (s != NULL)
24515 {
Bram Moolenaarf31b7642012-01-20 20:44:43 +010024516 if (vim_strsize(s) > MSG_BUF_CLEN)
24517 {
24518 trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN);
24519 s = buf;
24520 }
24521 smsg((char_u *)_("%s returning %s"), sourcing_name, s);
Bram Moolenaar92c5aba2007-08-14 20:29:31 +000024522 vim_free(tofree);
24523 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000024524 }
24525 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaar54ee7752005-05-31 22:22:17 +000024526
24527 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000024528 --no_wait_return;
24529 }
24530
24531 vim_free(sourcing_name);
24532 sourcing_name = save_sourcing_name;
24533 sourcing_lnum = save_sourcing_lnum;
24534 current_SID = save_current_SID;
Bram Moolenaar05159a02005-02-26 23:04:13 +000024535#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +000024536 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +000024537 script_prof_restore(&wait_start);
24538#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000024539
24540 if (p_verbose >= 12 && sourcing_name != NULL)
24541 {
24542 ++no_wait_return;
Bram Moolenaar54ee7752005-05-31 22:22:17 +000024543 verbose_enter_scroll();
24544
Bram Moolenaar555b2802005-05-19 21:08:39 +000024545 smsg((char_u *)_("continuing in %s"), sourcing_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024546 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaar54ee7752005-05-31 22:22:17 +000024547
24548 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000024549 --no_wait_return;
24550 }
24551
24552 did_emsg |= save_did_emsg;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024553 current_funccal = fc->caller;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024554 --depth;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024555
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +000024556 /* If the a:000 list and the l: and a: dicts are not referenced we can
24557 * free the funccall_T and what's in it. */
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024558 if (fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT
24559 && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT
24560 && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT)
24561 {
24562 free_funccal(fc, FALSE);
24563 }
24564 else
24565 {
24566 hashitem_T *hi;
24567 listitem_T *li;
24568 int todo;
24569
24570 /* "fc" is still in use. This can happen when returning "a:000" or
24571 * assigning "l:" to a global variable.
24572 * Link "fc" in the list for garbage collection later. */
24573 fc->caller = previous_funccal;
24574 previous_funccal = fc;
24575
24576 /* Make a copy of the a: variables, since we didn't do that above. */
24577 todo = (int)fc->l_avars.dv_hashtab.ht_used;
24578 for (hi = fc->l_avars.dv_hashtab.ht_array; todo > 0; ++hi)
24579 {
24580 if (!HASHITEM_EMPTY(hi))
24581 {
24582 --todo;
24583 v = HI2DI(hi);
24584 copy_tv(&v->di_tv, &v->di_tv);
24585 }
24586 }
24587
24588 /* Make a copy of the a:000 items, since we didn't do that above. */
24589 for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next)
24590 copy_tv(&li->li_tv, &li->li_tv);
24591 }
24592}
24593
24594/*
24595 * Return TRUE if items in "fc" do not have "copyID". That means they are not
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +000024596 * referenced from anywhere that is in use.
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024597 */
24598 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010024599can_free_funccal(funccall_T *fc, int copyID)
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024600{
24601 return (fc->l_varlist.lv_copyID != copyID
24602 && fc->l_vars.dv_copyID != copyID
24603 && fc->l_avars.dv_copyID != copyID);
24604}
24605
24606/*
24607 * Free "fc" and what it contains.
24608 */
24609 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010024610free_funccal(
24611 funccall_T *fc,
24612 int free_val) /* a: vars were allocated */
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000024613{
24614 listitem_T *li;
24615
24616 /* The a: variables typevals may not have been allocated, only free the
24617 * allocated variables. */
24618 vars_clear_ext(&fc->l_avars.dv_hashtab, free_val);
24619
24620 /* free all l: variables */
24621 vars_clear(&fc->l_vars.dv_hashtab);
24622
24623 /* Free the a:000 variables if they were allocated. */
24624 if (free_val)
24625 for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next)
24626 clear_tv(&li->li_tv);
24627
24628 vim_free(fc);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024629}
24630
24631/*
Bram Moolenaar33570922005-01-25 22:26:29 +000024632 * Add a number variable "name" to dict "dp" with value "nr".
24633 */
24634 static void
Bram Moolenaar7454a062016-01-30 15:14:10 +010024635add_nr_var(
24636 dict_T *dp,
24637 dictitem_T *v,
24638 char *name,
24639 varnumber_T nr)
Bram Moolenaar33570922005-01-25 22:26:29 +000024640{
24641 STRCPY(v->di_key, name);
24642 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
24643 hash_add(&dp->dv_hashtab, DI2HIKEY(v));
24644 v->di_tv.v_type = VAR_NUMBER;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000024645 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000024646 v->di_tv.vval.v_number = nr;
24647}
24648
24649/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000024650 * ":return [expr]"
24651 */
24652 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010024653ex_return(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024654{
24655 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000024656 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024657 int returning = FALSE;
24658
24659 if (current_funccal == NULL)
24660 {
24661 EMSG(_("E133: :return not inside a function"));
24662 return;
24663 }
24664
24665 if (eap->skip)
24666 ++emsg_skip;
24667
24668 eap->nextcmd = NULL;
24669 if ((*arg != NUL && *arg != '|' && *arg != '\n')
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024670 && eval0(arg, &rettv, &eap->nextcmd, !eap->skip) != FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024671 {
24672 if (!eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024673 returning = do_return(eap, FALSE, TRUE, &rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024674 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024675 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024676 }
24677 /* It's safer to return also on error. */
24678 else if (!eap->skip)
24679 {
24680 /*
24681 * Return unless the expression evaluation has been cancelled due to an
24682 * aborting error, an interrupt, or an exception.
24683 */
24684 if (!aborting())
24685 returning = do_return(eap, FALSE, TRUE, NULL);
24686 }
24687
24688 /* When skipping or the return gets pending, advance to the next command
24689 * in this line (!returning). Otherwise, ignore the rest of the line.
24690 * Following lines will be ignored by get_func_line(). */
24691 if (returning)
24692 eap->nextcmd = NULL;
24693 else if (eap->nextcmd == NULL) /* no argument */
24694 eap->nextcmd = check_nextcmd(arg);
24695
24696 if (eap->skip)
24697 --emsg_skip;
24698}
24699
24700/*
24701 * Return from a function. Possibly makes the return pending. Also called
24702 * for a pending return at the ":endtry" or after returning from an extra
24703 * do_cmdline(). "reanimate" is used in the latter case. "is_cmd" is set
Bram Moolenaar33570922005-01-25 22:26:29 +000024704 * when called due to a ":return" command. "rettv" may point to a typval_T
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024705 * with the return rettv. Returns TRUE when the return can be carried out,
Bram Moolenaar071d4272004-06-13 20:20:40 +000024706 * FALSE when the return gets pending.
24707 */
24708 int
Bram Moolenaar7454a062016-01-30 15:14:10 +010024709do_return(
24710 exarg_T *eap,
24711 int reanimate,
24712 int is_cmd,
24713 void *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024714{
24715 int idx;
24716 struct condstack *cstack = eap->cstack;
24717
24718 if (reanimate)
24719 /* Undo the return. */
24720 current_funccal->returned = FALSE;
24721
24722 /*
24723 * Cleanup (and inactivate) conditionals, but stop when a try conditional
24724 * not in its finally clause (which then is to be executed next) is found.
24725 * In this case, make the ":return" pending for execution at the ":endtry".
24726 * Otherwise, return normally.
24727 */
24728 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
24729 if (idx >= 0)
24730 {
24731 cstack->cs_pending[idx] = CSTP_RETURN;
24732
24733 if (!is_cmd && !reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024734 /* A pending return again gets pending. "rettv" points to an
24735 * allocated variable with the rettv of the original ":return"'s
Bram Moolenaar071d4272004-06-13 20:20:40 +000024736 * argument if present or is NULL else. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024737 cstack->cs_rettv[idx] = rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024738 else
24739 {
24740 /* When undoing a return in order to make it pending, get the stored
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024741 * return rettv. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000024742 if (reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024743 rettv = current_funccal->rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024744
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024745 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024746 {
24747 /* Store the value of the pending return. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024748 if ((cstack->cs_rettv[idx] = alloc_tv()) != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000024749 *(typval_T *)cstack->cs_rettv[idx] = *(typval_T *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024750 else
24751 EMSG(_(e_outofmem));
24752 }
24753 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024754 cstack->cs_rettv[idx] = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024755
24756 if (reanimate)
24757 {
24758 /* The pending return value could be overwritten by a ":return"
24759 * without argument in a finally clause; reset the default
24760 * return value. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024761 current_funccal->rettv->v_type = VAR_NUMBER;
24762 current_funccal->rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024763 }
24764 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024765 report_make_pending(CSTP_RETURN, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024766 }
24767 else
24768 {
24769 current_funccal->returned = TRUE;
24770
24771 /* If the return is carried out now, store the return value. For
24772 * a return immediately after reanimation, the value is already
24773 * there. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024774 if (!reanimate && rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024775 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024776 clear_tv(current_funccal->rettv);
Bram Moolenaar33570922005-01-25 22:26:29 +000024777 *current_funccal->rettv = *(typval_T *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024778 if (!is_cmd)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024779 vim_free(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024780 }
24781 }
24782
24783 return idx < 0;
24784}
24785
24786/*
24787 * Free the variable with a pending return value.
24788 */
24789 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010024790discard_pending_return(void *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024791{
Bram Moolenaar33570922005-01-25 22:26:29 +000024792 free_tv((typval_T *)rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024793}
24794
24795/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024796 * Generate a return command for producing the value of "rettv". The result
Bram Moolenaar071d4272004-06-13 20:20:40 +000024797 * is an allocated string. Used by report_pending() for verbose messages.
24798 */
24799 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010024800get_return_cmd(void *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024801{
Bram Moolenaar81bf7082005-02-12 14:31:42 +000024802 char_u *s = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024803 char_u *tofree = NULL;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000024804 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000024805
Bram Moolenaar81bf7082005-02-12 14:31:42 +000024806 if (rettv != NULL)
Bram Moolenaarb71eaae2006-01-20 23:10:18 +000024807 s = echo_string((typval_T *)rettv, &tofree, numbuf, 0);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000024808 if (s == NULL)
24809 s = (char_u *)"";
Bram Moolenaarc70646c2005-01-04 21:52:38 +000024810
24811 STRCPY(IObuff, ":return ");
24812 STRNCPY(IObuff + 8, s, IOSIZE - 8);
24813 if (STRLEN(s) + 8 >= IOSIZE)
24814 STRCPY(IObuff + IOSIZE - 4, "...");
24815 vim_free(tofree);
24816 return vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024817}
24818
24819/*
24820 * Get next function line.
24821 * Called by do_cmdline() to get the next line.
24822 * Returns allocated string, or NULL for end of function.
24823 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000024824 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010024825get_func_line(
24826 int c UNUSED,
24827 void *cookie,
24828 int indent UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024829{
Bram Moolenaar33570922005-01-25 22:26:29 +000024830 funccall_T *fcp = (funccall_T *)cookie;
Bram Moolenaar05159a02005-02-26 23:04:13 +000024831 ufunc_T *fp = fcp->func;
24832 char_u *retval;
24833 garray_T *gap; /* growarray with function lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +000024834
24835 /* If breakpoints have been added/deleted need to check for it. */
24836 if (fcp->dbg_tick != debug_tick)
24837 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000024838 fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
Bram Moolenaar071d4272004-06-13 20:20:40 +000024839 sourcing_lnum);
24840 fcp->dbg_tick = debug_tick;
24841 }
Bram Moolenaar05159a02005-02-26 23:04:13 +000024842#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +000024843 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +000024844 func_line_end(cookie);
24845#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000024846
Bram Moolenaar05159a02005-02-26 23:04:13 +000024847 gap = &fp->uf_lines;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000024848 if (((fp->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
24849 || fcp->returned)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024850 retval = NULL;
24851 else
24852 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000024853 /* Skip NULL lines (continuation lines). */
24854 while (fcp->linenr < gap->ga_len
24855 && ((char_u **)(gap->ga_data))[fcp->linenr] == NULL)
24856 ++fcp->linenr;
24857 if (fcp->linenr >= gap->ga_len)
24858 retval = NULL;
24859 else
24860 {
24861 retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]);
24862 sourcing_lnum = fcp->linenr;
Bram Moolenaar05159a02005-02-26 23:04:13 +000024863#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +000024864 if (do_profiling == PROF_YES)
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000024865 func_line_start(cookie);
Bram Moolenaar05159a02005-02-26 23:04:13 +000024866#endif
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000024867 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000024868 }
24869
24870 /* Did we encounter a breakpoint? */
24871 if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum)
24872 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000024873 dbg_breakpoint(fp->uf_name, sourcing_lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024874 /* Find next breakpoint. */
Bram Moolenaar05159a02005-02-26 23:04:13 +000024875 fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
Bram Moolenaar071d4272004-06-13 20:20:40 +000024876 sourcing_lnum);
24877 fcp->dbg_tick = debug_tick;
24878 }
24879
24880 return retval;
24881}
24882
Bram Moolenaar05159a02005-02-26 23:04:13 +000024883#if defined(FEAT_PROFILE) || defined(PROTO)
24884/*
24885 * Called when starting to read a function line.
24886 * "sourcing_lnum" must be correct!
24887 * When skipping lines it may not actually be executed, but we won't find out
24888 * until later and we need to store the time now.
24889 */
24890 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010024891func_line_start(void *cookie)
Bram Moolenaar05159a02005-02-26 23:04:13 +000024892{
24893 funccall_T *fcp = (funccall_T *)cookie;
24894 ufunc_T *fp = fcp->func;
24895
24896 if (fp->uf_profiling && sourcing_lnum >= 1
24897 && sourcing_lnum <= fp->uf_lines.ga_len)
24898 {
24899 fp->uf_tml_idx = sourcing_lnum - 1;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000024900 /* Skip continuation lines. */
24901 while (fp->uf_tml_idx > 0 && FUNCLINE(fp, fp->uf_tml_idx) == NULL)
24902 --fp->uf_tml_idx;
Bram Moolenaar05159a02005-02-26 23:04:13 +000024903 fp->uf_tml_execed = FALSE;
24904 profile_start(&fp->uf_tml_start);
24905 profile_zero(&fp->uf_tml_children);
24906 profile_get_wait(&fp->uf_tml_wait);
24907 }
24908}
24909
24910/*
24911 * Called when actually executing a function line.
24912 */
24913 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010024914func_line_exec(void *cookie)
Bram Moolenaar05159a02005-02-26 23:04:13 +000024915{
24916 funccall_T *fcp = (funccall_T *)cookie;
24917 ufunc_T *fp = fcp->func;
24918
24919 if (fp->uf_profiling && fp->uf_tml_idx >= 0)
24920 fp->uf_tml_execed = TRUE;
24921}
24922
24923/*
24924 * Called when done with a function line.
24925 */
24926 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010024927func_line_end(void *cookie)
Bram Moolenaar05159a02005-02-26 23:04:13 +000024928{
24929 funccall_T *fcp = (funccall_T *)cookie;
24930 ufunc_T *fp = fcp->func;
24931
24932 if (fp->uf_profiling && fp->uf_tml_idx >= 0)
24933 {
24934 if (fp->uf_tml_execed)
24935 {
24936 ++fp->uf_tml_count[fp->uf_tml_idx];
24937 profile_end(&fp->uf_tml_start);
24938 profile_sub_wait(&fp->uf_tml_wait, &fp->uf_tml_start);
Bram Moolenaar05159a02005-02-26 23:04:13 +000024939 profile_add(&fp->uf_tml_total[fp->uf_tml_idx], &fp->uf_tml_start);
Bram Moolenaar1056d982006-03-09 22:37:52 +000024940 profile_self(&fp->uf_tml_self[fp->uf_tml_idx], &fp->uf_tml_start,
24941 &fp->uf_tml_children);
Bram Moolenaar05159a02005-02-26 23:04:13 +000024942 }
24943 fp->uf_tml_idx = -1;
24944 }
24945}
24946#endif
24947
Bram Moolenaar071d4272004-06-13 20:20:40 +000024948/*
24949 * Return TRUE if the currently active function should be ended, because a
Bram Moolenaar8c8de832008-06-24 22:58:06 +000024950 * return was encountered or an error occurred. Used inside a ":while".
Bram Moolenaar071d4272004-06-13 20:20:40 +000024951 */
24952 int
Bram Moolenaar7454a062016-01-30 15:14:10 +010024953func_has_ended(void *cookie)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024954{
Bram Moolenaar33570922005-01-25 22:26:29 +000024955 funccall_T *fcp = (funccall_T *)cookie;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024956
24957 /* Ignore the "abort" flag if the abortion behavior has been changed due to
24958 * an error inside a try conditional. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024959 return (((fcp->func->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
Bram Moolenaar071d4272004-06-13 20:20:40 +000024960 || fcp->returned);
24961}
24962
24963/*
24964 * return TRUE if cookie indicates a function which "abort"s on errors.
24965 */
24966 int
Bram Moolenaar7454a062016-01-30 15:14:10 +010024967func_has_abort(
24968 void *cookie)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024969{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000024970 return ((funccall_T *)cookie)->func->uf_flags & FC_ABORT;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024971}
24972
24973#if defined(FEAT_VIMINFO) || defined(FEAT_SESSION)
24974typedef enum
24975{
Bram Moolenaar8c8de832008-06-24 22:58:06 +000024976 VAR_FLAVOUR_DEFAULT, /* doesn't start with uppercase */
24977 VAR_FLAVOUR_SESSION, /* starts with uppercase, some lower */
24978 VAR_FLAVOUR_VIMINFO /* all uppercase */
Bram Moolenaar071d4272004-06-13 20:20:40 +000024979} var_flavour_T;
24980
Bram Moolenaar48e697e2016-01-23 22:17:30 +010024981static var_flavour_T var_flavour(char_u *varname);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024982
24983 static var_flavour_T
Bram Moolenaar7454a062016-01-30 15:14:10 +010024984var_flavour(char_u *varname)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024985{
24986 char_u *p = varname;
24987
24988 if (ASCII_ISUPPER(*p))
24989 {
24990 while (*(++p))
24991 if (ASCII_ISLOWER(*p))
24992 return VAR_FLAVOUR_SESSION;
24993 return VAR_FLAVOUR_VIMINFO;
24994 }
24995 else
24996 return VAR_FLAVOUR_DEFAULT;
24997}
24998#endif
24999
25000#if defined(FEAT_VIMINFO) || defined(PROTO)
25001/*
25002 * Restore global vars that start with a capital from the viminfo file
25003 */
25004 int
Bram Moolenaar7454a062016-01-30 15:14:10 +010025005read_viminfo_varlist(vir_T *virp, int writing)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025006{
25007 char_u *tab;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000025008 int type = VAR_NUMBER;
Bram Moolenaar33570922005-01-25 22:26:29 +000025009 typval_T tv;
Bram Moolenaarb20e3342016-01-18 23:29:01 +010025010 funccall_T *save_funccal;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025011
25012 if (!writing && (find_viminfo_parameter('!') != NULL))
25013 {
25014 tab = vim_strchr(virp->vir_line + 1, '\t');
25015 if (tab != NULL)
25016 {
25017 *tab++ = '\0'; /* isolate the variable name */
Bram Moolenaar680eeca2010-10-20 17:44:42 +020025018 switch (*tab)
25019 {
25020 case 'S': type = VAR_STRING; break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000025021#ifdef FEAT_FLOAT
Bram Moolenaar680eeca2010-10-20 17:44:42 +020025022 case 'F': type = VAR_FLOAT; break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000025023#endif
Bram Moolenaar680eeca2010-10-20 17:44:42 +020025024 case 'D': type = VAR_DICT; break;
25025 case 'L': type = VAR_LIST; break;
Bram Moolenaara03f2332016-02-06 18:09:59 +010025026 case 'X': type = VAR_SPECIAL; break;
Bram Moolenaar680eeca2010-10-20 17:44:42 +020025027 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000025028
25029 tab = vim_strchr(tab, '\t');
25030 if (tab != NULL)
25031 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +000025032 tv.v_type = type;
Bram Moolenaar680eeca2010-10-20 17:44:42 +020025033 if (type == VAR_STRING || type == VAR_DICT || type == VAR_LIST)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000025034 tv.vval.v_string = viminfo_readstring(virp,
Bram Moolenaar071d4272004-06-13 20:20:40 +000025035 (int)(tab - virp->vir_line + 1), TRUE);
Bram Moolenaar8c8de832008-06-24 22:58:06 +000025036#ifdef FEAT_FLOAT
25037 else if (type == VAR_FLOAT)
25038 (void)string2float(tab + 1, &tv.vval.v_float);
25039#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000025040 else
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000025041 tv.vval.v_number = atol((char *)tab + 1);
Bram Moolenaar680eeca2010-10-20 17:44:42 +020025042 if (type == VAR_DICT || type == VAR_LIST)
25043 {
25044 typval_T *etv = eval_expr(tv.vval.v_string, NULL);
25045
25046 if (etv == NULL)
25047 /* Failed to parse back the dict or list, use it as a
25048 * string. */
25049 tv.v_type = VAR_STRING;
25050 else
25051 {
25052 vim_free(tv.vval.v_string);
25053 tv = *etv;
Bram Moolenaar507cc8a2012-03-23 15:37:02 +010025054 vim_free(etv);
Bram Moolenaar680eeca2010-10-20 17:44:42 +020025055 }
25056 }
25057
Bram Moolenaarb20e3342016-01-18 23:29:01 +010025058 /* when in a function use global variables */
25059 save_funccal = current_funccal;
25060 current_funccal = NULL;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000025061 set_var(virp->vir_line + 1, &tv, FALSE);
Bram Moolenaarb20e3342016-01-18 23:29:01 +010025062 current_funccal = save_funccal;
Bram Moolenaar680eeca2010-10-20 17:44:42 +020025063
25064 if (tv.v_type == VAR_STRING)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000025065 vim_free(tv.vval.v_string);
Bram Moolenaar680eeca2010-10-20 17:44:42 +020025066 else if (tv.v_type == VAR_DICT || tv.v_type == VAR_LIST)
25067 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000025068 }
25069 }
25070 }
25071
25072 return viminfo_readline(virp);
25073}
25074
25075/*
25076 * Write global vars that start with a capital to the viminfo file
25077 */
25078 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010025079write_viminfo_varlist(FILE *fp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025080{
Bram Moolenaar33570922005-01-25 22:26:29 +000025081 hashitem_T *hi;
25082 dictitem_T *this_var;
Bram Moolenaara7043832005-01-21 11:56:39 +000025083 int todo;
Bram Moolenaar2fc83fc2016-02-08 22:57:24 +010025084 char *s = "";
Bram Moolenaar81bf7082005-02-12 14:31:42 +000025085 char_u *p;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000025086 char_u *tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000025087 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000025088
25089 if (find_viminfo_parameter('!') == NULL)
25090 return;
25091
Bram Moolenaar9577c3e2010-05-14 12:16:25 +020025092 fputs(_("\n# global variables:\n"), fp);
Bram Moolenaara7043832005-01-21 11:56:39 +000025093
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000025094 todo = (int)globvarht.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +000025095 for (hi = globvarht.ht_array; todo > 0; ++hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025096 {
Bram Moolenaara7043832005-01-21 11:56:39 +000025097 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar071d4272004-06-13 20:20:40 +000025098 {
Bram Moolenaara7043832005-01-21 11:56:39 +000025099 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000025100 this_var = HI2DI(hi);
25101 if (var_flavour(this_var->di_key) == VAR_FLAVOUR_VIMINFO)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000025102 {
Bram Moolenaar33570922005-01-25 22:26:29 +000025103 switch (this_var->di_tv.v_type)
Bram Moolenaara7043832005-01-21 11:56:39 +000025104 {
25105 case VAR_STRING: s = "STR"; break;
25106 case VAR_NUMBER: s = "NUM"; break;
Bram Moolenaar680eeca2010-10-20 17:44:42 +020025107 case VAR_FLOAT: s = "FLO"; break;
Bram Moolenaar680eeca2010-10-20 17:44:42 +020025108 case VAR_DICT: s = "DIC"; break;
25109 case VAR_LIST: s = "LIS"; break;
Bram Moolenaara03f2332016-02-06 18:09:59 +010025110 case VAR_SPECIAL: s = "XPL"; break;
25111
25112 case VAR_UNKNOWN:
25113 case VAR_FUNC:
Bram Moolenaar835dc632016-02-07 14:27:38 +010025114 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +010025115 case VAR_CHANNEL:
Bram Moolenaara03f2332016-02-06 18:09:59 +010025116 continue;
Bram Moolenaara7043832005-01-21 11:56:39 +000025117 }
Bram Moolenaar33570922005-01-25 22:26:29 +000025118 fprintf(fp, "!%s\t%s\t", this_var->di_key, s);
Bram Moolenaarb71eaae2006-01-20 23:10:18 +000025119 p = echo_string(&this_var->di_tv, &tofree, numbuf, 0);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000025120 if (p != NULL)
25121 viminfo_writestring(fp, p);
Bram Moolenaara7043832005-01-21 11:56:39 +000025122 vim_free(tofree);
25123 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000025124 }
25125 }
25126}
25127#endif
25128
25129#if defined(FEAT_SESSION) || defined(PROTO)
25130 int
Bram Moolenaar7454a062016-01-30 15:14:10 +010025131store_session_globals(FILE *fd)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025132{
Bram Moolenaar33570922005-01-25 22:26:29 +000025133 hashitem_T *hi;
25134 dictitem_T *this_var;
Bram Moolenaara7043832005-01-21 11:56:39 +000025135 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025136 char_u *p, *t;
25137
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000025138 todo = (int)globvarht.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +000025139 for (hi = globvarht.ht_array; todo > 0; ++hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025140 {
Bram Moolenaara7043832005-01-21 11:56:39 +000025141 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar071d4272004-06-13 20:20:40 +000025142 {
Bram Moolenaara7043832005-01-21 11:56:39 +000025143 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000025144 this_var = HI2DI(hi);
25145 if ((this_var->di_tv.v_type == VAR_NUMBER
25146 || this_var->di_tv.v_type == VAR_STRING)
25147 && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000025148 {
Bram Moolenaara7043832005-01-21 11:56:39 +000025149 /* Escape special characters with a backslash. Turn a LF and
25150 * CR into \n and \r. */
Bram Moolenaar33570922005-01-25 22:26:29 +000025151 p = vim_strsave_escaped(get_tv_string(&this_var->di_tv),
Bram Moolenaara7043832005-01-21 11:56:39 +000025152 (char_u *)"\\\"\n\r");
25153 if (p == NULL) /* out of memory */
25154 break;
25155 for (t = p; *t != NUL; ++t)
25156 if (*t == '\n')
25157 *t = 'n';
25158 else if (*t == '\r')
25159 *t = 'r';
25160 if ((fprintf(fd, "let %s = %c%s%c",
Bram Moolenaar33570922005-01-25 22:26:29 +000025161 this_var->di_key,
25162 (this_var->di_tv.v_type == VAR_STRING) ? '"'
25163 : ' ',
25164 p,
25165 (this_var->di_tv.v_type == VAR_STRING) ? '"'
25166 : ' ') < 0)
Bram Moolenaara7043832005-01-21 11:56:39 +000025167 || put_eol(fd) == FAIL)
25168 {
25169 vim_free(p);
25170 return FAIL;
25171 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000025172 vim_free(p);
25173 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +000025174#ifdef FEAT_FLOAT
25175 else if (this_var->di_tv.v_type == VAR_FLOAT
25176 && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION)
25177 {
25178 float_T f = this_var->di_tv.vval.v_float;
25179 int sign = ' ';
25180
25181 if (f < 0)
25182 {
25183 f = -f;
25184 sign = '-';
25185 }
Bram Moolenaar2b04b192012-01-26 11:45:30 +010025186 if ((fprintf(fd, "let %s = %c%f",
Bram Moolenaar8c8de832008-06-24 22:58:06 +000025187 this_var->di_key, sign, f) < 0)
25188 || put_eol(fd) == FAIL)
25189 return FAIL;
25190 }
25191#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000025192 }
25193 }
25194 return OK;
25195}
25196#endif
25197
Bram Moolenaar661b1822005-07-28 22:36:45 +000025198/*
25199 * Display script name where an item was last set.
25200 * Should only be invoked when 'verbose' is non-zero.
25201 */
25202 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010025203last_set_msg(scid_T scriptID)
Bram Moolenaar661b1822005-07-28 22:36:45 +000025204{
Bram Moolenaarcafda4f2005-09-06 19:25:11 +000025205 char_u *p;
25206
Bram Moolenaar661b1822005-07-28 22:36:45 +000025207 if (scriptID != 0)
25208 {
Bram Moolenaarcafda4f2005-09-06 19:25:11 +000025209 p = home_replace_save(NULL, get_scriptname(scriptID));
25210 if (p != NULL)
25211 {
25212 verbose_enter();
25213 MSG_PUTS(_("\n\tLast set from "));
25214 MSG_PUTS(p);
25215 vim_free(p);
25216 verbose_leave();
25217 }
Bram Moolenaar661b1822005-07-28 22:36:45 +000025218 }
25219}
25220
Bram Moolenaard812df62008-11-09 12:46:09 +000025221/*
25222 * List v:oldfiles in a nice way.
25223 */
Bram Moolenaard812df62008-11-09 12:46:09 +000025224 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010025225ex_oldfiles(exarg_T *eap UNUSED)
Bram Moolenaard812df62008-11-09 12:46:09 +000025226{
25227 list_T *l = vimvars[VV_OLDFILES].vv_list;
25228 listitem_T *li;
25229 int nr = 0;
25230
25231 if (l == NULL)
25232 msg((char_u *)_("No old files"));
25233 else
25234 {
25235 msg_start();
25236 msg_scroll = TRUE;
25237 for (li = l->lv_first; li != NULL && !got_int; li = li->li_next)
25238 {
25239 msg_outnum((long)++nr);
25240 MSG_PUTS(": ");
25241 msg_outtrans(get_tv_string(&li->li_tv));
25242 msg_putchar('\n');
25243 out_flush(); /* output one line at a time */
25244 ui_breakcheck();
25245 }
25246 /* Assume "got_int" was set to truncate the listing. */
25247 got_int = FALSE;
25248
25249#ifdef FEAT_BROWSE_CMD
25250 if (cmdmod.browse)
25251 {
25252 quit_more = FALSE;
25253 nr = prompt_for_number(FALSE);
25254 msg_starthere();
25255 if (nr > 0)
25256 {
25257 char_u *p = list_find_str(get_vim_var_list(VV_OLDFILES),
25258 (long)nr);
25259
25260 if (p != NULL)
25261 {
25262 p = expand_env_save(p);
25263 eap->arg = p;
25264 eap->cmdidx = CMD_edit;
25265 cmdmod.browse = FALSE;
25266 do_exedit(eap, NULL);
25267 vim_free(p);
25268 }
25269 }
25270 }
25271#endif
25272 }
25273}
25274
Bram Moolenaar53744302015-07-17 17:38:22 +020025275/* reset v:option_new, v:option_old and v:option_type */
25276 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010025277reset_v_option_vars(void)
Bram Moolenaar53744302015-07-17 17:38:22 +020025278{
25279 set_vim_var_string(VV_OPTION_NEW, NULL, -1);
25280 set_vim_var_string(VV_OPTION_OLD, NULL, -1);
25281 set_vim_var_string(VV_OPTION_TYPE, NULL, -1);
25282}
25283
25284
Bram Moolenaar071d4272004-06-13 20:20:40 +000025285#endif /* FEAT_EVAL */
25286
Bram Moolenaar071d4272004-06-13 20:20:40 +000025287
Bram Moolenaar8c8de832008-06-24 22:58:06 +000025288#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025289
25290#ifdef WIN3264
25291/*
25292 * Functions for ":8" filename modifier: get 8.3 version of a filename.
25293 */
Bram Moolenaar48e697e2016-01-23 22:17:30 +010025294static int get_short_pathname(char_u **fnamep, char_u **bufp, int *fnamelen);
25295static int shortpath_for_invalid_fname(char_u **fname, char_u **bufp, int *fnamelen);
25296static int shortpath_for_partial(char_u **fnamep, char_u **bufp, int *fnamelen);
Bram Moolenaar071d4272004-06-13 20:20:40 +000025297
25298/*
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025299 * Get the short path (8.3) for the filename in "fnamep".
25300 * Only works for a valid file name.
25301 * When the path gets longer "fnamep" is changed and the allocated buffer
25302 * is put in "bufp".
25303 * *fnamelen is the length of "fnamep" and set to 0 for a nonexistent path.
25304 * Returns OK on success, FAIL on failure.
Bram Moolenaar071d4272004-06-13 20:20:40 +000025305 */
25306 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010025307get_short_pathname(char_u **fnamep, char_u **bufp, int *fnamelen)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025308{
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025309 int l, len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025310 char_u *newbuf;
25311
25312 len = *fnamelen;
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +010025313 l = GetShortPathName((LPSTR)*fnamep, (LPSTR)*fnamep, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000025314 if (l > len - 1)
25315 {
25316 /* If that doesn't work (not enough space), then save the string
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025317 * and try again with a new buffer big enough. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000025318 newbuf = vim_strnsave(*fnamep, l);
25319 if (newbuf == NULL)
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025320 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025321
25322 vim_free(*bufp);
25323 *fnamep = *bufp = newbuf;
25324
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025325 /* Really should always succeed, as the buffer is big enough. */
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +010025326 l = GetShortPathName((LPSTR)*fnamep, (LPSTR)*fnamep, l+1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000025327 }
25328
25329 *fnamelen = l;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025330 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025331}
25332
25333/*
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025334 * Get the short path (8.3) for the filename in "fname". The converted
25335 * path is returned in "bufp".
25336 *
25337 * Some of the directories specified in "fname" may not exist. This function
25338 * will shorten the existing directories at the beginning of the path and then
25339 * append the remaining non-existing path.
25340 *
25341 * fname - Pointer to the filename to shorten. On return, contains the
Bram Moolenaar2c704a72010-06-03 21:17:25 +020025342 * pointer to the shortened pathname
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025343 * bufp - Pointer to an allocated buffer for the filename.
25344 * fnamelen - Length of the filename pointed to by fname
25345 *
25346 * Returns OK on success (or nothing done) and FAIL on failure (out of memory).
Bram Moolenaar071d4272004-06-13 20:20:40 +000025347 */
25348 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010025349shortpath_for_invalid_fname(
25350 char_u **fname,
25351 char_u **bufp,
25352 int *fnamelen)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025353{
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025354 char_u *short_fname, *save_fname, *pbuf_unused;
25355 char_u *endp, *save_endp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025356 char_u ch;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025357 int old_len, len;
25358 int new_len, sfx_len;
25359 int retval = OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025360
25361 /* Make a copy */
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025362 old_len = *fnamelen;
25363 save_fname = vim_strnsave(*fname, old_len);
25364 pbuf_unused = NULL;
25365 short_fname = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025366
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025367 endp = save_fname + old_len - 1; /* Find the end of the copy */
25368 save_endp = endp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025369
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025370 /*
25371 * Try shortening the supplied path till it succeeds by removing one
25372 * directory at a time from the tail of the path.
25373 */
25374 len = 0;
25375 for (;;)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025376 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025377 /* go back one path-separator */
25378 while (endp > save_fname && !after_pathsep(save_fname, endp + 1))
25379 --endp;
25380 if (endp <= save_fname)
25381 break; /* processed the complete path */
25382
25383 /*
25384 * Replace the path separator with a NUL and try to shorten the
25385 * resulting path.
25386 */
25387 ch = *endp;
25388 *endp = 0;
25389 short_fname = save_fname;
Bram Moolenaarc236c162008-07-13 17:41:49 +000025390 len = (int)STRLEN(short_fname) + 1;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025391 if (get_short_pathname(&short_fname, &pbuf_unused, &len) == FAIL)
25392 {
25393 retval = FAIL;
25394 goto theend;
25395 }
25396 *endp = ch; /* preserve the string */
25397
25398 if (len > 0)
25399 break; /* successfully shortened the path */
25400
25401 /* failed to shorten the path. Skip the path separator */
25402 --endp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025403 }
25404
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025405 if (len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025406 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025407 /*
25408 * Succeeded in shortening the path. Now concatenate the shortened
25409 * path with the remaining path at the tail.
25410 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000025411
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025412 /* Compute the length of the new path. */
25413 sfx_len = (int)(save_endp - endp) + 1;
25414 new_len = len + sfx_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025415
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025416 *fnamelen = new_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025417 vim_free(*bufp);
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025418 if (new_len > old_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025419 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025420 /* There is not enough space in the currently allocated string,
25421 * copy it to a buffer big enough. */
25422 *fname = *bufp = vim_strnsave(short_fname, new_len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000025423 if (*fname == NULL)
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025424 {
25425 retval = FAIL;
25426 goto theend;
25427 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000025428 }
25429 else
25430 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025431 /* Transfer short_fname to the main buffer (it's big enough),
25432 * unless get_short_pathname() did its work in-place. */
25433 *fname = *bufp = save_fname;
25434 if (short_fname != save_fname)
25435 vim_strncpy(save_fname, short_fname, len);
25436 save_fname = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025437 }
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025438
25439 /* concat the not-shortened part of the path */
25440 vim_strncpy(*fname + len, endp, sfx_len);
25441 (*fname)[new_len] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025442 }
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025443
25444theend:
25445 vim_free(pbuf_unused);
25446 vim_free(save_fname);
25447
25448 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025449}
25450
25451/*
25452 * Get a pathname for a partial path.
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025453 * Returns OK for success, FAIL for failure.
Bram Moolenaar071d4272004-06-13 20:20:40 +000025454 */
25455 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +010025456shortpath_for_partial(
25457 char_u **fnamep,
25458 char_u **bufp,
25459 int *fnamelen)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025460{
25461 int sepcount, len, tflen;
25462 char_u *p;
25463 char_u *pbuf, *tfname;
25464 int hasTilde;
25465
Bram Moolenaar8c8de832008-06-24 22:58:06 +000025466 /* Count up the path separators from the RHS.. so we know which part
25467 * of the path to return. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000025468 sepcount = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000025469 for (p = *fnamep; p < *fnamep + *fnamelen; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000025470 if (vim_ispathsep(*p))
25471 ++sepcount;
25472
25473 /* Need full path first (use expand_env() to remove a "~/") */
25474 hasTilde = (**fnamep == '~');
25475 if (hasTilde)
25476 pbuf = tfname = expand_env_save(*fnamep);
25477 else
25478 pbuf = tfname = FullName_save(*fnamep, FALSE);
25479
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000025480 len = tflen = (int)STRLEN(tfname);
Bram Moolenaar071d4272004-06-13 20:20:40 +000025481
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025482 if (get_short_pathname(&tfname, &pbuf, &len) == FAIL)
25483 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025484
25485 if (len == 0)
25486 {
25487 /* Don't have a valid filename, so shorten the rest of the
25488 * path if we can. This CAN give us invalid 8.3 filenames, but
25489 * there's not a lot of point in guessing what it might be.
25490 */
25491 len = tflen;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025492 if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == FAIL)
25493 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025494 }
25495
25496 /* Count the paths backward to find the beginning of the desired string. */
25497 for (p = tfname + len - 1; p >= tfname; --p)
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000025498 {
25499#ifdef FEAT_MBYTE
25500 if (has_mbyte)
25501 p -= mb_head_off(tfname, p);
25502#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000025503 if (vim_ispathsep(*p))
25504 {
25505 if (sepcount == 0 || (hasTilde && sepcount == 1))
25506 break;
25507 else
25508 sepcount --;
25509 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000025510 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000025511 if (hasTilde)
25512 {
25513 --p;
25514 if (p >= tfname)
25515 *p = '~';
25516 else
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025517 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025518 }
25519 else
25520 ++p;
25521
25522 /* Copy in the string - p indexes into tfname - allocated at pbuf */
25523 vim_free(*bufp);
25524 *fnamelen = (int)STRLEN(p);
25525 *bufp = pbuf;
25526 *fnamep = p;
25527
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025528 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025529}
25530#endif /* WIN3264 */
25531
25532/*
25533 * Adjust a filename, according to a string of modifiers.
25534 * *fnamep must be NUL terminated when called. When returning, the length is
25535 * determined by *fnamelen.
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025536 * Returns VALID_ flags or -1 for failure.
Bram Moolenaar071d4272004-06-13 20:20:40 +000025537 * When there is an error, *fnamep is set to NULL.
25538 */
25539 int
Bram Moolenaar7454a062016-01-30 15:14:10 +010025540modify_fname(
25541 char_u *src, /* string with modifiers */
25542 int *usedlen, /* characters after src that are used */
25543 char_u **fnamep, /* file name so far */
25544 char_u **bufp, /* buffer for allocated file name or NULL */
25545 int *fnamelen) /* length of fnamep */
Bram Moolenaar071d4272004-06-13 20:20:40 +000025546{
25547 int valid = 0;
25548 char_u *tail;
25549 char_u *s, *p, *pbuf;
25550 char_u dirname[MAXPATHL];
25551 int c;
25552 int has_fullname = 0;
25553#ifdef WIN3264
Bram Moolenaardc935552011-08-17 15:23:23 +020025554 char_u *fname_start = *fnamep;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025555 int has_shortname = 0;
25556#endif
25557
25558repeat:
25559 /* ":p" - full path/file_name */
25560 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p')
25561 {
25562 has_fullname = 1;
25563
25564 valid |= VALID_PATH;
25565 *usedlen += 2;
25566
25567 /* Expand "~/path" for all systems and "~user/path" for Unix and VMS */
25568 if ((*fnamep)[0] == '~'
25569#if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME))
25570 && ((*fnamep)[1] == '/'
25571# ifdef BACKSLASH_IN_FILENAME
25572 || (*fnamep)[1] == '\\'
25573# endif
25574 || (*fnamep)[1] == NUL)
25575
25576#endif
25577 )
25578 {
25579 *fnamep = expand_env_save(*fnamep);
25580 vim_free(*bufp); /* free any allocated file name */
25581 *bufp = *fnamep;
25582 if (*fnamep == NULL)
25583 return -1;
25584 }
25585
25586 /* When "/." or "/.." is used: force expansion to get rid of it. */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000025587 for (p = *fnamep; *p != NUL; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000025588 {
25589 if (vim_ispathsep(*p)
25590 && p[1] == '.'
25591 && (p[2] == NUL
25592 || vim_ispathsep(p[2])
25593 || (p[2] == '.'
25594 && (p[3] == NUL || vim_ispathsep(p[3])))))
25595 break;
25596 }
25597
25598 /* FullName_save() is slow, don't use it when not needed. */
25599 if (*p != NUL || !vim_isAbsName(*fnamep))
25600 {
25601 *fnamep = FullName_save(*fnamep, *p != NUL);
25602 vim_free(*bufp); /* free any allocated file name */
25603 *bufp = *fnamep;
25604 if (*fnamep == NULL)
25605 return -1;
25606 }
25607
Bram Moolenaar9158f9e2012-06-20 14:02:27 +020025608#ifdef WIN3264
25609# if _WIN32_WINNT >= 0x0500
25610 if (vim_strchr(*fnamep, '~') != NULL)
25611 {
25612 /* Expand 8.3 filename to full path. Needed to make sure the same
25613 * file does not have two different names.
25614 * Note: problem does not occur if _WIN32_WINNT < 0x0500. */
25615 p = alloc(_MAX_PATH + 1);
25616 if (p != NULL)
25617 {
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +010025618 if (GetLongPathName((LPSTR)*fnamep, (LPSTR)p, _MAX_PATH))
Bram Moolenaar9158f9e2012-06-20 14:02:27 +020025619 {
25620 vim_free(*bufp);
25621 *bufp = *fnamep = p;
25622 }
25623 else
25624 vim_free(p);
25625 }
25626 }
25627# endif
25628#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000025629 /* Append a path separator to a directory. */
25630 if (mch_isdir(*fnamep))
25631 {
25632 /* Make room for one or two extra characters. */
25633 *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2);
25634 vim_free(*bufp); /* free any allocated file name */
25635 *bufp = *fnamep;
25636 if (*fnamep == NULL)
25637 return -1;
25638 add_pathsep(*fnamep);
25639 }
25640 }
25641
25642 /* ":." - path relative to the current directory */
25643 /* ":~" - path relative to the home directory */
25644 /* ":8" - shortname path - postponed till after */
25645 while (src[*usedlen] == ':'
25646 && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8'))
25647 {
25648 *usedlen += 2;
25649 if (c == '8')
25650 {
25651#ifdef WIN3264
25652 has_shortname = 1; /* Postpone this. */
25653#endif
25654 continue;
25655 }
25656 pbuf = NULL;
25657 /* Need full path first (use expand_env() to remove a "~/") */
25658 if (!has_fullname)
25659 {
25660 if (c == '.' && **fnamep == '~')
25661 p = pbuf = expand_env_save(*fnamep);
25662 else
25663 p = pbuf = FullName_save(*fnamep, FALSE);
25664 }
25665 else
25666 p = *fnamep;
25667
25668 has_fullname = 0;
25669
25670 if (p != NULL)
25671 {
25672 if (c == '.')
25673 {
25674 mch_dirname(dirname, MAXPATHL);
25675 s = shorten_fname(p, dirname);
25676 if (s != NULL)
25677 {
25678 *fnamep = s;
25679 if (pbuf != NULL)
25680 {
25681 vim_free(*bufp); /* free any allocated file name */
25682 *bufp = pbuf;
25683 pbuf = NULL;
25684 }
25685 }
25686 }
25687 else
25688 {
25689 home_replace(NULL, p, dirname, MAXPATHL, TRUE);
25690 /* Only replace it when it starts with '~' */
25691 if (*dirname == '~')
25692 {
25693 s = vim_strsave(dirname);
25694 if (s != NULL)
25695 {
25696 *fnamep = s;
25697 vim_free(*bufp);
25698 *bufp = s;
25699 }
25700 }
25701 }
25702 vim_free(pbuf);
25703 }
25704 }
25705
25706 tail = gettail(*fnamep);
25707 *fnamelen = (int)STRLEN(*fnamep);
25708
25709 /* ":h" - head, remove "/file_name", can be repeated */
25710 /* Don't remove the first "/" or "c:\" */
25711 while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h')
25712 {
25713 valid |= VALID_HEAD;
25714 *usedlen += 2;
25715 s = get_past_head(*fnamep);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000025716 while (tail > s && after_pathsep(s, tail))
Bram Moolenaar5461cfe2007-09-25 18:40:14 +000025717 mb_ptr_back(*fnamep, tail);
Bram Moolenaar071d4272004-06-13 20:20:40 +000025718 *fnamelen = (int)(tail - *fnamep);
25719#ifdef VMS
25720 if (*fnamelen > 0)
25721 *fnamelen += 1; /* the path separator is part of the path */
25722#endif
Bram Moolenaar5461cfe2007-09-25 18:40:14 +000025723 if (*fnamelen == 0)
25724 {
25725 /* Result is empty. Turn it into "." to make ":cd %:h" work. */
25726 p = vim_strsave((char_u *)".");
25727 if (p == NULL)
25728 return -1;
25729 vim_free(*bufp);
25730 *bufp = *fnamep = tail = p;
25731 *fnamelen = 1;
25732 }
25733 else
25734 {
25735 while (tail > s && !after_pathsep(s, tail))
25736 mb_ptr_back(*fnamep, tail);
25737 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000025738 }
25739
25740 /* ":8" - shortname */
25741 if (src[*usedlen] == ':' && src[*usedlen + 1] == '8')
25742 {
25743 *usedlen += 2;
25744#ifdef WIN3264
25745 has_shortname = 1;
25746#endif
25747 }
25748
25749#ifdef WIN3264
Bram Moolenaardc935552011-08-17 15:23:23 +020025750 /*
25751 * Handle ":8" after we have done 'heads' and before we do 'tails'.
Bram Moolenaar071d4272004-06-13 20:20:40 +000025752 */
25753 if (has_shortname)
25754 {
Bram Moolenaardc935552011-08-17 15:23:23 +020025755 /* Copy the string if it is shortened by :h and when it wasn't copied
25756 * yet, because we are going to change it in place. Avoids changing
25757 * the buffer name for "%:8". */
25758 if (*fnamelen < (int)STRLEN(*fnamep) || *fnamep == fname_start)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025759 {
25760 p = vim_strnsave(*fnamep, *fnamelen);
Bram Moolenaardc935552011-08-17 15:23:23 +020025761 if (p == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025762 return -1;
25763 vim_free(*bufp);
25764 *bufp = *fnamep = p;
25765 }
25766
25767 /* Split into two implementations - makes it easier. First is where
Bram Moolenaardc935552011-08-17 15:23:23 +020025768 * there isn't a full name already, second is where there is. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000025769 if (!has_fullname && !vim_isAbsName(*fnamep))
25770 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025771 if (shortpath_for_partial(fnamep, bufp, fnamelen) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025772 return -1;
25773 }
25774 else
25775 {
Bram Moolenaardc935552011-08-17 15:23:23 +020025776 int l = *fnamelen;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025777
Bram Moolenaardc935552011-08-17 15:23:23 +020025778 /* Simple case, already have the full-name.
Bram Moolenaar071d4272004-06-13 20:20:40 +000025779 * Nearly always shorter, so try first time. */
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025780 if (get_short_pathname(fnamep, bufp, &l) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025781 return -1;
25782
25783 if (l == 0)
25784 {
Bram Moolenaardc935552011-08-17 15:23:23 +020025785 /* Couldn't find the filename, search the paths. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000025786 l = *fnamelen;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000025787 if (shortpath_for_invalid_fname(fnamep, bufp, &l) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025788 return -1;
25789 }
25790 *fnamelen = l;
25791 }
25792 }
25793#endif /* WIN3264 */
25794
25795 /* ":t" - tail, just the basename */
25796 if (src[*usedlen] == ':' && src[*usedlen + 1] == 't')
25797 {
25798 *usedlen += 2;
25799 *fnamelen -= (int)(tail - *fnamep);
25800 *fnamep = tail;
25801 }
25802
25803 /* ":e" - extension, can be repeated */
25804 /* ":r" - root, without extension, can be repeated */
25805 while (src[*usedlen] == ':'
25806 && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r'))
25807 {
25808 /* find a '.' in the tail:
25809 * - for second :e: before the current fname
25810 * - otherwise: The last '.'
25811 */
25812 if (src[*usedlen + 1] == 'e' && *fnamep > tail)
25813 s = *fnamep - 2;
25814 else
25815 s = *fnamep + *fnamelen - 1;
25816 for ( ; s > tail; --s)
25817 if (s[0] == '.')
25818 break;
25819 if (src[*usedlen + 1] == 'e') /* :e */
25820 {
25821 if (s > tail)
25822 {
25823 *fnamelen += (int)(*fnamep - (s + 1));
25824 *fnamep = s + 1;
25825#ifdef VMS
25826 /* cut version from the extension */
25827 s = *fnamep + *fnamelen - 1;
25828 for ( ; s > *fnamep; --s)
25829 if (s[0] == ';')
25830 break;
25831 if (s > *fnamep)
25832 *fnamelen = s - *fnamep;
25833#endif
25834 }
25835 else if (*fnamep <= tail)
25836 *fnamelen = 0;
25837 }
25838 else /* :r */
25839 {
25840 if (s > tail) /* remove one extension */
25841 *fnamelen = (int)(s - *fnamep);
25842 }
25843 *usedlen += 2;
25844 }
25845
25846 /* ":s?pat?foo?" - substitute */
25847 /* ":gs?pat?foo?" - global substitute */
25848 if (src[*usedlen] == ':'
25849 && (src[*usedlen + 1] == 's'
25850 || (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's')))
25851 {
25852 char_u *str;
25853 char_u *pat;
25854 char_u *sub;
25855 int sep;
25856 char_u *flags;
25857 int didit = FALSE;
25858
25859 flags = (char_u *)"";
25860 s = src + *usedlen + 2;
25861 if (src[*usedlen + 1] == 'g')
25862 {
25863 flags = (char_u *)"g";
25864 ++s;
25865 }
25866
25867 sep = *s++;
25868 if (sep)
25869 {
25870 /* find end of pattern */
25871 p = vim_strchr(s, sep);
25872 if (p != NULL)
25873 {
25874 pat = vim_strnsave(s, (int)(p - s));
25875 if (pat != NULL)
25876 {
25877 s = p + 1;
25878 /* find end of substitution */
25879 p = vim_strchr(s, sep);
25880 if (p != NULL)
25881 {
25882 sub = vim_strnsave(s, (int)(p - s));
25883 str = vim_strnsave(*fnamep, *fnamelen);
25884 if (sub != NULL && str != NULL)
25885 {
25886 *usedlen = (int)(p + 1 - src);
25887 s = do_string_sub(str, pat, sub, flags);
25888 if (s != NULL)
25889 {
25890 *fnamep = s;
25891 *fnamelen = (int)STRLEN(s);
25892 vim_free(*bufp);
25893 *bufp = s;
25894 didit = TRUE;
25895 }
25896 }
25897 vim_free(sub);
25898 vim_free(str);
25899 }
25900 vim_free(pat);
25901 }
25902 }
25903 /* after using ":s", repeat all the modifiers */
25904 if (didit)
25905 goto repeat;
25906 }
25907 }
25908
Bram Moolenaar26df0922014-02-23 23:39:13 +010025909 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'S')
25910 {
25911 p = vim_strsave_shellescape(*fnamep, FALSE, FALSE);
25912 if (p == NULL)
25913 return -1;
25914 vim_free(*bufp);
25915 *bufp = *fnamep = p;
25916 *fnamelen = (int)STRLEN(p);
25917 *usedlen += 2;
25918 }
25919
Bram Moolenaar071d4272004-06-13 20:20:40 +000025920 return valid;
25921}
25922
25923/*
25924 * Perform a substitution on "str" with pattern "pat" and substitute "sub".
25925 * "flags" can be "g" to do a global substitute.
25926 * Returns an allocated string, NULL for error.
25927 */
25928 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +010025929do_string_sub(
25930 char_u *str,
25931 char_u *pat,
25932 char_u *sub,
25933 char_u *flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +000025934{
25935 int sublen;
25936 regmatch_T regmatch;
25937 int i;
25938 int do_all;
25939 char_u *tail;
Bram Moolenaare90c8532014-11-05 16:03:44 +010025940 char_u *end;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025941 garray_T ga;
25942 char_u *ret;
25943 char_u *save_cpo;
Bram Moolenaar8af26912014-01-23 20:09:34 +010025944 char_u *zero_width = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025945
25946 /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */
25947 save_cpo = p_cpo;
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +000025948 p_cpo = empty_option;
Bram Moolenaar071d4272004-06-13 20:20:40 +000025949
25950 ga_init2(&ga, 1, 200);
25951
25952 do_all = (flags[0] == 'g');
25953
25954 regmatch.rm_ic = p_ic;
25955 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
25956 if (regmatch.regprog != NULL)
25957 {
25958 tail = str;
Bram Moolenaare90c8532014-11-05 16:03:44 +010025959 end = str + STRLEN(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000025960 while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
25961 {
Bram Moolenaar8af26912014-01-23 20:09:34 +010025962 /* Skip empty match except for first match. */
25963 if (regmatch.startp[0] == regmatch.endp[0])
25964 {
25965 if (zero_width == regmatch.startp[0])
25966 {
25967 /* avoid getting stuck on a match with an empty string */
Bram Moolenaar8e7048c2014-06-12 18:39:22 +020025968 i = MB_PTR2LEN(tail);
25969 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail,
25970 (size_t)i);
25971 ga.ga_len += i;
25972 tail += i;
Bram Moolenaar8af26912014-01-23 20:09:34 +010025973 continue;
25974 }
25975 zero_width = regmatch.startp[0];
25976 }
25977
Bram Moolenaar071d4272004-06-13 20:20:40 +000025978 /*
25979 * Get some space for a temporary buffer to do the substitution
25980 * into. It will contain:
25981 * - The text up to where the match is.
25982 * - The substituted text.
25983 * - The text after the match.
25984 */
25985 sublen = vim_regsub(&regmatch, sub, tail, FALSE, TRUE, FALSE);
Bram Moolenaare90c8532014-11-05 16:03:44 +010025986 if (ga_grow(&ga, (int)((end - tail) + sublen -
Bram Moolenaar071d4272004-06-13 20:20:40 +000025987 (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
25988 {
25989 ga_clear(&ga);
25990 break;
25991 }
25992
25993 /* copy the text up to where the match is */
25994 i = (int)(regmatch.startp[0] - tail);
25995 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
25996 /* add the substituted text */
25997 (void)vim_regsub(&regmatch, sub, (char_u *)ga.ga_data
25998 + ga.ga_len + i, TRUE, TRUE, FALSE);
25999 ga.ga_len += i + sublen - 1;
Bram Moolenaarceb84af2013-09-29 21:11:05 +020026000 tail = regmatch.endp[0];
26001 if (*tail == NUL)
26002 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000026003 if (!do_all)
26004 break;
26005 }
26006
26007 if (ga.ga_data != NULL)
26008 STRCPY((char *)ga.ga_data + ga.ga_len, tail);
26009
Bram Moolenaar473de612013-06-08 18:19:48 +020026010 vim_regfree(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000026011 }
26012
26013 ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data);
26014 ga_clear(&ga);
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +000026015 if (p_cpo == empty_option)
26016 p_cpo = save_cpo;
26017 else
26018 /* Darn, evaluating {sub} expression changed the value. */
26019 free_string_option(save_cpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +000026020
26021 return ret;
26022}
26023
26024#endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */