blob: 51ec0b8b969ec9e855d9ea93174ca0c47e8c80bb [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 Moolenaar071d4272004-06-13 20:20:40 +000013
14#include "vim.h"
15
Bram Moolenaar8c8de832008-06-24 22:58:06 +000016#if defined(FEAT_EVAL) || defined(PROTO)
17
Bram Moolenaar071d4272004-06-13 20:20:40 +000018#ifdef AMIGA
19# include <time.h> /* for strftime() */
20#endif
21
Bram Moolenaar314f11d2010-08-09 22:07:08 +020022#ifdef VMS
23# include <float.h>
24#endif
25
Bram Moolenaar071d4272004-06-13 20:20:40 +000026#ifdef MACOS
27# include <time.h> /* for time_t */
28#endif
29
Bram Moolenaar8c8de832008-06-24 22:58:06 +000030#if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
31# include <math.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000032#endif
33
Bram Moolenaar33570922005-01-25 22:26:29 +000034#define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */
Bram Moolenaar071d4272004-06-13 20:20:40 +000035
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000036#define DO_NOT_FREE_CNT 99999 /* refcount for dict or list that should not
37 be freed. */
38
Bram Moolenaar071d4272004-06-13 20:20:40 +000039/*
Bram Moolenaar33570922005-01-25 22:26:29 +000040 * In a hashtab item "hi_key" points to "di_key" in a dictitem.
41 * This avoids adding a pointer to the hashtab item.
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000042 * DI2HIKEY() converts a dictitem pointer to a hashitem key pointer.
43 * HIKEY2DI() converts a hashitem key pointer to a dictitem pointer.
44 * HI2DI() converts a hashitem pointer to a dictitem pointer.
45 */
Bram Moolenaar33570922005-01-25 22:26:29 +000046static dictitem_T dumdi;
Bram Moolenaara7043832005-01-21 11:56:39 +000047#define DI2HIKEY(di) ((di)->di_key)
Bram Moolenaar33570922005-01-25 22:26:29 +000048#define HIKEY2DI(p) ((dictitem_T *)(p - (dumdi.di_key - (char_u *)&dumdi)))
Bram Moolenaara7043832005-01-21 11:56:39 +000049#define HI2DI(hi) HIKEY2DI((hi)->hi_key)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000050
51/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000052 * Structure returned by get_lval() and used by set_var_lval().
53 * For a plain name:
54 * "name" points to the variable name.
55 * "exp_name" is NULL.
56 * "tv" is NULL
57 * For a magic braces name:
58 * "name" points to the expanded variable name.
59 * "exp_name" is non-NULL, to be freed later.
60 * "tv" is NULL
61 * For an index in a list:
62 * "name" points to the (expanded) variable name.
63 * "exp_name" NULL or non-NULL, to be freed later.
64 * "tv" points to the (first) list item value
65 * "li" points to the (first) list item
66 * "range", "n1", "n2" and "empty2" indicate what items are used.
67 * For an existing Dict item:
68 * "name" points to the (expanded) variable name.
69 * "exp_name" NULL or non-NULL, to be freed later.
70 * "tv" points to the dict item value
71 * "newkey" is NULL
72 * For a non-existing Dict item:
73 * "name" points to the (expanded) variable name.
74 * "exp_name" NULL or non-NULL, to be freed later.
Bram Moolenaar33570922005-01-25 22:26:29 +000075 * "tv" points to the Dictionary typval_T
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000076 * "newkey" is the key for the new item.
77 */
78typedef struct lval_S
79{
80 char_u *ll_name; /* start of variable name (can be NULL) */
81 char_u *ll_exp_name; /* NULL or expanded name in allocated memory. */
Bram Moolenaar33570922005-01-25 22:26:29 +000082 typval_T *ll_tv; /* Typeval of item being used. If "newkey"
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000083 isn't NULL it's the Dict to which to add
84 the item. */
Bram Moolenaar33570922005-01-25 22:26:29 +000085 listitem_T *ll_li; /* The list item or NULL. */
86 list_T *ll_list; /* The list or NULL. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000087 int ll_range; /* TRUE when a [i:j] range was used */
88 long ll_n1; /* First index for list */
89 long ll_n2; /* Second index for list range */
90 int ll_empty2; /* Second index is empty: [i:] */
Bram Moolenaar33570922005-01-25 22:26:29 +000091 dict_T *ll_dict; /* The Dictionary or NULL */
92 dictitem_T *ll_di; /* The dictitem or NULL */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000093 char_u *ll_newkey; /* New key for Dict in alloc. mem or NULL. */
Bram Moolenaar33570922005-01-25 22:26:29 +000094} lval_T;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000095
Bram Moolenaar8c711452005-01-14 21:53:12 +000096
Bram Moolenaarc70646c2005-01-04 21:52:38 +000097static char *e_letunexp = N_("E18: Unexpected characters in :let");
Bram Moolenaare49b69a2005-01-08 16:11:57 +000098static char *e_listidx = N_("E684: list index out of range: %ld");
Bram Moolenaarc70646c2005-01-04 21:52:38 +000099static char *e_undefvar = N_("E121: Undefined variable: %s");
100static char *e_missbrac = N_("E111: Missing ']'");
Bram Moolenaar8c711452005-01-14 21:53:12 +0000101static char *e_listarg = N_("E686: Argument of %s must be a List");
Bram Moolenaar13fcaaf2005-04-15 21:13:42 +0000102static char *e_listdictarg = N_("E712: Argument of %s must be a List or Dictionary");
Bram Moolenaarce5e58e2005-01-19 22:24:34 +0000103static char *e_emptykey = N_("E713: Cannot use empty key for Dictionary");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000104static char *e_listreq = N_("E714: List required");
105static char *e_dictreq = N_("E715: Dictionary required");
Bram Moolenaar8c711452005-01-14 21:53:12 +0000106static char *e_toomanyarg = N_("E118: Too many arguments for function: %s");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000107static char *e_dictkey = N_("E716: Key not present in Dictionary: %s");
108static char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it");
109static char *e_funcdict = N_("E717: Dictionary entry already exists");
110static char *e_funcref = N_("E718: Funcref required");
111static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary");
112static char *e_letwrong = N_("E734: Wrong variable type for %s=");
Bram Moolenaar05159a02005-02-26 23:04:13 +0000113static char *e_nofunc = N_("E130: Unknown function: %s");
Bram Moolenaar92124a32005-06-17 22:03:40 +0000114static char *e_illvar = N_("E461: Illegal variable name: %s");
Bram Moolenaar8c0e3222013-06-16 17:32:40 +0200115#ifdef FEAT_FLOAT
Bram Moolenaar2a876e42013-06-12 22:08:58 +0200116static char *e_float_as_string = N_("E806: using Float as a String");
Bram Moolenaar8c0e3222013-06-16 17:32:40 +0200117#endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000118
Bram Moolenaar230bb3f2013-04-24 14:07:45 +0200119static dictitem_T globvars_var; /* variable used for g: */
Bram Moolenaar33570922005-01-25 22:26:29 +0000120#define globvarht globvardict.dv_hashtab
Bram Moolenaar071d4272004-06-13 20:20:40 +0000121
122/*
Bram Moolenaar532c7802005-01-27 14:44:31 +0000123 * Old Vim variables such as "v:version" are also available without the "v:".
124 * Also in functions. We need a special hashtable for them.
125 */
Bram Moolenaar4debb442005-06-01 21:57:40 +0000126static hashtab_T compat_hashtab;
Bram Moolenaar532c7802005-01-27 14:44:31 +0000127
128/*
Bram Moolenaard9fba312005-06-26 22:34:35 +0000129 * When recursively copying lists and dicts we need to remember which ones we
130 * have done to avoid endless recursiveness. This unique ID is used for that.
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +0000131 * The last bit is used for previous_funccal, ignored when comparing.
Bram Moolenaard9fba312005-06-26 22:34:35 +0000132 */
133static int current_copyID = 0;
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +0000134#define COPYID_INC 2
135#define COPYID_MASK (~0x1)
Bram Moolenaard9fba312005-06-26 22:34:35 +0000136
137/*
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 Moolenaar33570922005-01-25 22:26:29 +0000365};
366
367/* shorthand */
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000368#define vv_type vv_di.di_tv.v_type
369#define vv_nr vv_di.di_tv.vval.v_number
370#define vv_float vv_di.di_tv.vval.v_float
371#define vv_str vv_di.di_tv.vval.v_string
Bram Moolenaard812df62008-11-09 12:46:09 +0000372#define vv_list vv_di.di_tv.vval.v_list
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000373#define vv_tv vv_di.di_tv
Bram Moolenaar33570922005-01-25 22:26:29 +0000374
Bram Moolenaar230bb3f2013-04-24 14:07:45 +0200375static dictitem_T vimvars_var; /* variable used for v: */
Bram Moolenaar33570922005-01-25 22:26:29 +0000376#define vimvarht vimvardict.dv_hashtab
377
Bram Moolenaara40058a2005-07-11 22:42:07 +0000378static void prepare_vimvar __ARGS((int idx, typval_T *save_tv));
379static void restore_vimvar __ARGS((int idx, typval_T *save_tv));
Bram Moolenaara40058a2005-07-11 22:42:07 +0000380static int ex_let_vars __ARGS((char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, char_u *nextchars));
381static char_u *skip_var_list __ARGS((char_u *arg, int *var_count, int *semicolon));
382static char_u *skip_var_one __ARGS((char_u *arg));
Bram Moolenaar7d61a922007-08-30 09:12:23 +0000383static void list_hashtable_vars __ARGS((hashtab_T *ht, char_u *prefix, int empty, int *first));
384static void list_glob_vars __ARGS((int *first));
385static void list_buf_vars __ARGS((int *first));
386static void list_win_vars __ARGS((int *first));
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000387#ifdef FEAT_WINDOWS
Bram Moolenaar7d61a922007-08-30 09:12:23 +0000388static void list_tab_vars __ARGS((int *first));
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000389#endif
Bram Moolenaar7d61a922007-08-30 09:12:23 +0000390static void list_vim_vars __ARGS((int *first));
391static void list_script_vars __ARGS((int *first));
392static void list_func_vars __ARGS((int *first));
393static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg, int *first));
Bram Moolenaara40058a2005-07-11 22:42:07 +0000394static char_u *ex_let_one __ARGS((char_u *arg, typval_T *tv, int copy, char_u *endchars, char_u *op));
395static int check_changedtick __ARGS((char_u *arg));
Bram Moolenaar6d977d62014-01-14 15:24:39 +0100396static char_u *get_lval __ARGS((char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int flags, int fne_flags));
Bram Moolenaara40058a2005-07-11 22:42:07 +0000397static void clear_lval __ARGS((lval_T *lp));
398static void set_var_lval __ARGS((lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op));
399static int tv_op __ARGS((typval_T *tv1, typval_T *tv2, char_u *op));
Bram Moolenaara40058a2005-07-11 22:42:07 +0000400static void list_fix_watch __ARGS((list_T *l, listitem_T *item));
401static void ex_unletlock __ARGS((exarg_T *eap, char_u *argstart, int deep));
402static int do_unlet_var __ARGS((lval_T *lp, char_u *name_end, int forceit));
403static int do_lock_var __ARGS((lval_T *lp, char_u *name_end, int deep, int lock));
404static void item_lock __ARGS((typval_T *tv, int deep, int lock));
405static int tv_islocked __ARGS((typval_T *tv));
406
Bram Moolenaar33570922005-01-25 22:26:29 +0000407static int eval0 __ARGS((char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate));
408static int eval1 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
409static int eval2 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
410static int eval3 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
411static int eval4 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
412static int eval5 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +0000413static int eval6 __ARGS((char_u **arg, typval_T *rettv, int evaluate, int want_string));
414static int eval7 __ARGS((char_u **arg, typval_T *rettv, int evaluate, int want_string));
Bram Moolenaara40058a2005-07-11 22:42:07 +0000415
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000416static int eval_index __ARGS((char_u **arg, typval_T *rettv, int evaluate, int verbose));
Bram Moolenaar33570922005-01-25 22:26:29 +0000417static int get_option_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
418static int get_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
419static int get_lit_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
420static int get_list_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
Bram Moolenaareddf53b2006-02-27 00:11:10 +0000421static int rettv_list_alloc __ARGS((typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000422static long list_len __ARGS((list_T *l));
Bram Moolenaar67b3f992010-11-10 20:41:57 +0100423static int list_equal __ARGS((list_T *l1, list_T *l2, int ic, int recursive));
424static int dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic, int recursive));
425static int tv_equal __ARGS((typval_T *tv1, typval_T *tv2, int ic, int recursive));
Bram Moolenaara5525202006-03-02 22:52:09 +0000426static long list_find_nr __ARGS((list_T *l, long idx, int *errorp));
Bram Moolenaar33570922005-01-25 22:26:29 +0000427static long list_idx_of_item __ARGS((list_T *l, listitem_T *item));
Bram Moolenaar4463f292005-09-25 22:20:24 +0000428static int list_append_number __ARGS((list_T *l, varnumber_T n));
Bram Moolenaar33570922005-01-25 22:26:29 +0000429static int list_extend __ARGS((list_T *l1, list_T *l2, listitem_T *bef));
430static int list_concat __ARGS((list_T *l1, list_T *l2, typval_T *tv));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000431static list_T *list_copy __ARGS((list_T *orig, int deep, int copyID));
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000432static char_u *list2string __ARGS((typval_T *tv, int copyID));
Bram Moolenaar3fe37d62012-02-06 00:13:22 +0100433static int list_join_inner __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo_style, int copyID, garray_T *join_gap));
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000434static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo, int copyID));
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +0000435static int free_unref_items __ARGS((int copyID));
Bram Moolenaara800b422010-06-27 01:15:55 +0200436static int rettv_dict_alloc __ARGS((typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000437static dictitem_T *dictitem_copy __ARGS((dictitem_T *org));
438static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000439static dict_T *dict_copy __ARGS((dict_T *orig, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000440static long dict_len __ARGS((dict_T *d));
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000441static char_u *dict2string __ARGS((typval_T *tv, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000442static int get_dict_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000443static char_u *echo_string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID));
444static char_u *tv2string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000445static char_u *string_quote __ARGS((char_u *str, int function));
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000446#ifdef FEAT_FLOAT
447static int string2float __ARGS((char_u *text, float_T *value));
448#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000449static int get_env_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
450static int find_internal_func __ARGS((char_u *name));
Bram Moolenaar8822a9c2014-01-14 19:44:34 +0100451static char_u *deref_func_name __ARGS((char_u *name, int *lenp, int no_autoload));
Bram Moolenaar33570922005-01-25 22:26:29 +0000452static int get_func_tv __ARGS((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 Moolenaarf506c5b2010-06-22 06:28:58 +0200453static int call_func __ARGS((char_u *funcname, int len, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
Bram Moolenaar89d40322006-08-29 15:30:07 +0000454static void emsg_funcname __ARGS((char *ermsg, char_u *name));
Bram Moolenaar05bb9532008-07-04 09:44:11 +0000455static int non_zero_arg __ARGS((typval_T *argvars));
Bram Moolenaar33570922005-01-25 22:26:29 +0000456
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000457#ifdef FEAT_FLOAT
458static void f_abs __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaardb7c6862010-05-21 16:33:48 +0200459static void f_acos __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000460#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000461static void f_add __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaard6e256c2011-12-14 15:32:50 +0100462static void f_and __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000463static void f_append __ARGS((typval_T *argvars, typval_T *rettv));
464static void f_argc __ARGS((typval_T *argvars, typval_T *rettv));
465static void f_argidx __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2d1fe052014-05-28 18:22:57 +0200466static void f_arglistid __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000467static void f_argv __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000468#ifdef FEAT_FLOAT
Bram Moolenaardb7c6862010-05-21 16:33:48 +0200469static void f_asin __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000470static void f_atan __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaardb7c6862010-05-21 16:33:48 +0200471static void f_atan2 __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000472#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000473static void f_browse __ARGS((typval_T *argvars, typval_T *rettv));
474static void f_browsedir __ARGS((typval_T *argvars, typval_T *rettv));
475static void f_bufexists __ARGS((typval_T *argvars, typval_T *rettv));
476static void f_buflisted __ARGS((typval_T *argvars, typval_T *rettv));
477static void f_bufloaded __ARGS((typval_T *argvars, typval_T *rettv));
478static void f_bufname __ARGS((typval_T *argvars, typval_T *rettv));
479static void f_bufnr __ARGS((typval_T *argvars, typval_T *rettv));
480static void f_bufwinnr __ARGS((typval_T *argvars, typval_T *rettv));
481static void f_byte2line __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar0ffbbf92013-11-02 23:29:26 +0100482static void byteidx __ARGS((typval_T *argvars, typval_T *rettv, int comp));
Bram Moolenaar33570922005-01-25 22:26:29 +0000483static void f_byteidx __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar0ffbbf92013-11-02 23:29:26 +0100484static void f_byteidxcomp __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000485static void f_call __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000486#ifdef FEAT_FLOAT
487static void f_ceil __ARGS((typval_T *argvars, typval_T *rettv));
488#endif
Bram Moolenaarf0acfce2006-03-17 23:21:19 +0000489static void f_changenr __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000490static void f_char2nr __ARGS((typval_T *argvars, typval_T *rettv));
491static void f_cindent __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar6ee10162007-07-26 20:58:42 +0000492static void f_clearmatches __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000493static void f_col __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar572cb562005-08-05 21:35:02 +0000494#if defined(FEAT_INS_EXPAND)
Bram Moolenaarade00832006-03-10 21:46:58 +0000495static void f_complete __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar572cb562005-08-05 21:35:02 +0000496static void f_complete_add __ARGS((typval_T *argvars, typval_T *rettv));
497static void f_complete_check __ARGS((typval_T *argvars, typval_T *rettv));
498#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000499static void f_confirm __ARGS((typval_T *argvars, typval_T *rettv));
500static void f_copy __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000501#ifdef FEAT_FLOAT
502static void f_cos __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaardb7c6862010-05-21 16:33:48 +0200503static void f_cosh __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000504#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000505static void f_count __ARGS((typval_T *argvars, typval_T *rettv));
506static void f_cscope_connection __ARGS((typval_T *argvars, typval_T *rettv));
507static void f_cursor __ARGS((typval_T *argsvars, typval_T *rettv));
508static void f_deepcopy __ARGS((typval_T *argvars, typval_T *rettv));
509static void f_delete __ARGS((typval_T *argvars, typval_T *rettv));
510static void f_did_filetype __ARGS((typval_T *argvars, typval_T *rettv));
511static void f_diff_filler __ARGS((typval_T *argvars, typval_T *rettv));
512static void f_diff_hlID __ARGS((typval_T *argvars, typval_T *rettv));
513static void f_empty __ARGS((typval_T *argvars, typval_T *rettv));
514static void f_escape __ARGS((typval_T *argvars, typval_T *rettv));
515static void f_eval __ARGS((typval_T *argvars, typval_T *rettv));
516static void f_eventhandler __ARGS((typval_T *argvars, typval_T *rettv));
517static void f_executable __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaarc7f02552014-04-01 21:00:59 +0200518static void f_exepath __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000519static void f_exists __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaardb7c6862010-05-21 16:33:48 +0200520#ifdef FEAT_FLOAT
521static void f_exp __ARGS((typval_T *argvars, typval_T *rettv));
522#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000523static void f_expand __ARGS((typval_T *argvars, typval_T *rettv));
524static void f_extend __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaarf9393ef2006-04-24 19:47:27 +0000525static void f_feedkeys __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000526static void f_filereadable __ARGS((typval_T *argvars, typval_T *rettv));
527static void f_filewritable __ARGS((typval_T *argvars, typval_T *rettv));
528static void f_filter __ARGS((typval_T *argvars, typval_T *rettv));
529static void f_finddir __ARGS((typval_T *argvars, typval_T *rettv));
530static void f_findfile __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000531#ifdef FEAT_FLOAT
532static void f_float2nr __ARGS((typval_T *argvars, typval_T *rettv));
533static void f_floor __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaardb7c6862010-05-21 16:33:48 +0200534static void f_fmod __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000535#endif
Bram Moolenaaraebaf892008-05-28 14:49:58 +0000536static void f_fnameescape __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000537static void f_fnamemodify __ARGS((typval_T *argvars, typval_T *rettv));
538static void f_foldclosed __ARGS((typval_T *argvars, typval_T *rettv));
539static void f_foldclosedend __ARGS((typval_T *argvars, typval_T *rettv));
540static void f_foldlevel __ARGS((typval_T *argvars, typval_T *rettv));
541static void f_foldtext __ARGS((typval_T *argvars, typval_T *rettv));
542static void f_foldtextresult __ARGS((typval_T *argvars, typval_T *rettv));
543static void f_foreground __ARGS((typval_T *argvars, typval_T *rettv));
544static void f_function __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000545static void f_garbagecollect __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000546static void f_get __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar80fc0432005-07-20 22:06:07 +0000547static void f_getbufline __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000548static void f_getbufvar __ARGS((typval_T *argvars, typval_T *rettv));
549static void f_getchar __ARGS((typval_T *argvars, typval_T *rettv));
550static void f_getcharmod __ARGS((typval_T *argvars, typval_T *rettv));
551static void f_getcmdline __ARGS((typval_T *argvars, typval_T *rettv));
552static void f_getcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000553static void f_getcmdtype __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000554static void f_getcwd __ARGS((typval_T *argvars, typval_T *rettv));
555static void f_getfontname __ARGS((typval_T *argvars, typval_T *rettv));
556static void f_getfperm __ARGS((typval_T *argvars, typval_T *rettv));
557static void f_getfsize __ARGS((typval_T *argvars, typval_T *rettv));
558static void f_getftime __ARGS((typval_T *argvars, typval_T *rettv));
559static void f_getftype __ARGS((typval_T *argvars, typval_T *rettv));
560static void f_getline __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar6ee10162007-07-26 20:58:42 +0000561static void f_getmatches __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar18081e32008-02-20 19:11:07 +0000562static void f_getpid __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar6f6c0f82014-05-28 20:31:42 +0200563static void f_getcurpos __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaara5525202006-03-02 22:52:09 +0000564static void f_getpos __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2641f772005-03-25 21:58:17 +0000565static void f_getqflist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000566static void f_getreg __ARGS((typval_T *argvars, typval_T *rettv));
567static void f_getregtype __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar06b5d512010-05-22 15:37:44 +0200568static void f_gettabvar __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar99ebf042006-04-15 20:28:54 +0000569static void f_gettabwinvar __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000570static void f_getwinposx __ARGS((typval_T *argvars, typval_T *rettv));
571static void f_getwinposy __ARGS((typval_T *argvars, typval_T *rettv));
572static void f_getwinvar __ARGS((typval_T *argvars, typval_T *rettv));
573static void f_glob __ARGS((typval_T *argvars, typval_T *rettv));
574static void f_globpath __ARGS((typval_T *argvars, typval_T *rettv));
575static void f_has __ARGS((typval_T *argvars, typval_T *rettv));
576static void f_has_key __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaard267b9c2007-04-26 15:06:45 +0000577static void f_haslocaldir __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000578static void f_hasmapto __ARGS((typval_T *argvars, typval_T *rettv));
579static void f_histadd __ARGS((typval_T *argvars, typval_T *rettv));
580static void f_histdel __ARGS((typval_T *argvars, typval_T *rettv));
581static void f_histget __ARGS((typval_T *argvars, typval_T *rettv));
582static void f_histnr __ARGS((typval_T *argvars, typval_T *rettv));
583static void f_hlID __ARGS((typval_T *argvars, typval_T *rettv));
584static void f_hlexists __ARGS((typval_T *argvars, typval_T *rettv));
585static void f_hostname __ARGS((typval_T *argvars, typval_T *rettv));
586static void f_iconv __ARGS((typval_T *argvars, typval_T *rettv));
587static void f_indent __ARGS((typval_T *argvars, typval_T *rettv));
588static void f_index __ARGS((typval_T *argvars, typval_T *rettv));
589static void f_input __ARGS((typval_T *argvars, typval_T *rettv));
590static void f_inputdialog __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar6efa2b32005-09-10 19:26:26 +0000591static void f_inputlist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000592static void f_inputrestore __ARGS((typval_T *argvars, typval_T *rettv));
593static void f_inputsave __ARGS((typval_T *argvars, typval_T *rettv));
594static void f_inputsecret __ARGS((typval_T *argvars, typval_T *rettv));
595static void f_insert __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaard6e256c2011-12-14 15:32:50 +0100596static void f_invert __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000597static void f_isdirectory __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000598static void f_islocked __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000599static void f_items __ARGS((typval_T *argvars, typval_T *rettv));
600static void f_join __ARGS((typval_T *argvars, typval_T *rettv));
601static void f_keys __ARGS((typval_T *argvars, typval_T *rettv));
602static void f_last_buffer_nr __ARGS((typval_T *argvars, typval_T *rettv));
603static void f_len __ARGS((typval_T *argvars, typval_T *rettv));
604static void f_libcall __ARGS((typval_T *argvars, typval_T *rettv));
605static void f_libcallnr __ARGS((typval_T *argvars, typval_T *rettv));
606static void f_line __ARGS((typval_T *argvars, typval_T *rettv));
607static void f_line2byte __ARGS((typval_T *argvars, typval_T *rettv));
608static void f_lispindent __ARGS((typval_T *argvars, typval_T *rettv));
609static void f_localtime __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000610#ifdef FEAT_FLOAT
Bram Moolenaardb7c6862010-05-21 16:33:48 +0200611static void f_log __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000612static void f_log10 __ARGS((typval_T *argvars, typval_T *rettv));
613#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +0200614#ifdef FEAT_LUA
615static void f_luaeval __ARGS((typval_T *argvars, typval_T *rettv));
616#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000617static void f_map __ARGS((typval_T *argvars, typval_T *rettv));
618static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv));
619static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv));
620static void f_match __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar6ee10162007-07-26 20:58:42 +0000621static void f_matchadd __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000622static void f_matcharg __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar6ee10162007-07-26 20:58:42 +0000623static void f_matchdelete __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000624static void f_matchend __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000625static void f_matchlist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000626static void f_matchstr __ARGS((typval_T *argvars, typval_T *rettv));
627static void f_max __ARGS((typval_T *argvars, typval_T *rettv));
628static void f_min __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000629#ifdef vim_mkdir
630static void f_mkdir __ARGS((typval_T *argvars, typval_T *rettv));
631#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000632static void f_mode __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar7e506b62010-01-19 15:55:06 +0100633#ifdef FEAT_MZSCHEME
634static void f_mzeval __ARGS((typval_T *argvars, typval_T *rettv));
635#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000636static void f_nextnonblank __ARGS((typval_T *argvars, typval_T *rettv));
637static void f_nr2char __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaard6e256c2011-12-14 15:32:50 +0100638static void f_or __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000639static void f_pathshorten __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000640#ifdef FEAT_FLOAT
641static void f_pow __ARGS((typval_T *argvars, typval_T *rettv));
642#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000643static void f_prevnonblank __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar4be06f92005-07-29 22:36:03 +0000644static void f_printf __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000645static void f_pumvisible __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaardb913952012-06-29 12:54:53 +0200646#ifdef FEAT_PYTHON3
647static void f_py3eval __ARGS((typval_T *argvars, typval_T *rettv));
648#endif
649#ifdef FEAT_PYTHON
650static void f_pyeval __ARGS((typval_T *argvars, typval_T *rettv));
651#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000652static void f_range __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000653static void f_readfile __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaare580b0c2006-03-21 21:33:03 +0000654static void f_reltime __ARGS((typval_T *argvars, typval_T *rettv));
655static void f_reltimestr __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000656static void f_remote_expr __ARGS((typval_T *argvars, typval_T *rettv));
657static void f_remote_foreground __ARGS((typval_T *argvars, typval_T *rettv));
658static void f_remote_peek __ARGS((typval_T *argvars, typval_T *rettv));
659static void f_remote_read __ARGS((typval_T *argvars, typval_T *rettv));
660static void f_remote_send __ARGS((typval_T *argvars, typval_T *rettv));
661static void f_remove __ARGS((typval_T *argvars, typval_T *rettv));
662static void f_rename __ARGS((typval_T *argvars, typval_T *rettv));
663static void f_repeat __ARGS((typval_T *argvars, typval_T *rettv));
664static void f_resolve __ARGS((typval_T *argvars, typval_T *rettv));
665static void f_reverse __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000666#ifdef FEAT_FLOAT
667static void f_round __ARGS((typval_T *argvars, typval_T *rettv));
668#endif
Bram Moolenaar9a773482013-06-11 18:40:13 +0200669static void f_screenattr __ARGS((typval_T *argvars, typval_T *rettv));
670static void f_screenchar __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar9750bb12012-12-05 16:10:42 +0100671static void f_screencol __ARGS((typval_T *argvars, typval_T *rettv));
672static void f_screenrow __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000673static void f_search __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaardd2436f2005-09-05 22:14:46 +0000674static void f_searchdecl __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000675static void f_searchpair __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000676static void f_searchpairpos __ARGS((typval_T *argvars, typval_T *rettv));
677static void f_searchpos __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000678static void f_server2client __ARGS((typval_T *argvars, typval_T *rettv));
679static void f_serverlist __ARGS((typval_T *argvars, typval_T *rettv));
680static void f_setbufvar __ARGS((typval_T *argvars, typval_T *rettv));
681static void f_setcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
682static void f_setline __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar17c7c012006-01-26 22:25:15 +0000683static void f_setloclist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar6ee10162007-07-26 20:58:42 +0000684static void f_setmatches __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar0e34f622006-03-03 23:00:03 +0000685static void f_setpos __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2641f772005-03-25 21:58:17 +0000686static void f_setqflist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000687static void f_setreg __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar06b5d512010-05-22 15:37:44 +0200688static void f_settabvar __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar99ebf042006-04-15 20:28:54 +0000689static void f_settabwinvar __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000690static void f_setwinvar __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaaraf9aeb92013-02-13 17:35:04 +0100691#ifdef FEAT_CRYPT
692static void f_sha256 __ARGS((typval_T *argvars, typval_T *rettv));
693#endif /* FEAT_CRYPT */
Bram Moolenaar60a495f2006-10-03 12:44:42 +0000694static void f_shellescape __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2d17fa32012-10-21 00:45:18 +0200695static void f_shiftwidth __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000696static void f_simplify __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000697#ifdef FEAT_FLOAT
698static void f_sin __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaardb7c6862010-05-21 16:33:48 +0200699static void f_sinh __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000700#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000701static void f_sort __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +0000702static void f_soundfold __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaard857f0e2005-06-21 22:37:39 +0000703static void f_spellbadword __ARGS((typval_T *argvars, typval_T *rettv));
704static void f_spellsuggest __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000705static void f_split __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000706#ifdef FEAT_FLOAT
707static void f_sqrt __ARGS((typval_T *argvars, typval_T *rettv));
708static void f_str2float __ARGS((typval_T *argvars, typval_T *rettv));
709#endif
Bram Moolenaar2c932302006-03-18 21:42:09 +0000710static void f_str2nr __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar72597a52010-07-18 15:31:08 +0200711static void f_strchars __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000712#ifdef HAVE_STRFTIME
713static void f_strftime __ARGS((typval_T *argvars, typval_T *rettv));
714#endif
715static void f_stridx __ARGS((typval_T *argvars, typval_T *rettv));
716static void f_string __ARGS((typval_T *argvars, typval_T *rettv));
717static void f_strlen __ARGS((typval_T *argvars, typval_T *rettv));
718static void f_strpart __ARGS((typval_T *argvars, typval_T *rettv));
719static void f_strridx __ARGS((typval_T *argvars, typval_T *rettv));
720static void f_strtrans __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaardc536092010-07-18 15:45:49 +0200721static void f_strdisplaywidth __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar72597a52010-07-18 15:31:08 +0200722static void f_strwidth __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000723static void f_submatch __ARGS((typval_T *argvars, typval_T *rettv));
724static void f_substitute __ARGS((typval_T *argvars, typval_T *rettv));
725static void f_synID __ARGS((typval_T *argvars, typval_T *rettv));
726static void f_synIDattr __ARGS((typval_T *argvars, typval_T *rettv));
727static void f_synIDtrans __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar9d188ab2008-01-10 21:24:39 +0000728static void f_synstack __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar7510fe72010-07-25 12:46:44 +0200729static void f_synconcealed __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000730static void f_system __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar39c29ed2014-04-05 19:44:40 +0200731static void f_systemlist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaarfaa959a2006-02-20 21:37:40 +0000732static void f_tabpagebuflist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar7e8fd632006-02-18 22:14:51 +0000733static void f_tabpagenr __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaarfaa959a2006-02-20 21:37:40 +0000734static void f_tabpagewinnr __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar19a09a12005-03-04 23:39:37 +0000735static void f_taglist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaard43b6cf2005-09-09 19:53:42 +0000736static void f_tagfiles __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000737static void f_tempname __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaard52d9742005-08-21 22:20:28 +0000738static void f_test __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaardb7c6862010-05-21 16:33:48 +0200739#ifdef FEAT_FLOAT
740static void f_tan __ARGS((typval_T *argvars, typval_T *rettv));
741static void f_tanh __ARGS((typval_T *argvars, typval_T *rettv));
742#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000743static void f_tolower __ARGS((typval_T *argvars, typval_T *rettv));
744static void f_toupper __ARGS((typval_T *argvars, typval_T *rettv));
745static void f_tr __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000746#ifdef FEAT_FLOAT
747static void f_trunc __ARGS((typval_T *argvars, typval_T *rettv));
748#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000749static void f_type __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaara17d4c12010-05-30 18:30:36 +0200750static void f_undofile __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaara800b422010-06-27 01:15:55 +0200751static void f_undotree __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar327aa022014-03-25 18:24:23 +0100752static void f_uniq __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000753static void f_values __ARGS((typval_T *argvars, typval_T *rettv));
754static void f_virtcol __ARGS((typval_T *argvars, typval_T *rettv));
755static void f_visualmode __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar8738fc12013-02-20 17:59:11 +0100756static void f_wildmenumode __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000757static void f_winbufnr __ARGS((typval_T *argvars, typval_T *rettv));
758static void f_wincol __ARGS((typval_T *argvars, typval_T *rettv));
759static void f_winheight __ARGS((typval_T *argvars, typval_T *rettv));
760static void f_winline __ARGS((typval_T *argvars, typval_T *rettv));
761static void f_winnr __ARGS((typval_T *argvars, typval_T *rettv));
762static void f_winrestcmd __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar768b8c42006-03-04 21:58:33 +0000763static void f_winrestview __ARGS((typval_T *argvars, typval_T *rettv));
764static void f_winsaveview __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000765static void f_winwidth __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000766static void f_writefile __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaard6e256c2011-12-14 15:32:50 +0100767static void f_xor __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000768
Bram Moolenaar493c1782014-05-28 14:34:46 +0200769static int list2fpos __ARGS((typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp));
Bram Moolenaar477933c2007-07-17 14:32:23 +0000770static pos_T *var2fpos __ARGS((typval_T *varp, int dollar_lnum, int *fnum));
Bram Moolenaar33570922005-01-25 22:26:29 +0000771static int get_env_len __ARGS((char_u **arg));
772static int get_id_len __ARGS((char_u **arg));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000773static int get_name_len __ARGS((char_u **arg, char_u **alias, int evaluate, int verbose));
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000774static char_u *find_name_end __ARGS((char_u *arg, char_u **expr_start, char_u **expr_end, int flags));
775#define FNE_INCL_BR 1 /* find_name_end(): include [] in name */
776#define FNE_CHECK_START 2 /* find_name_end(): check name starts with
777 valid character */
Bram Moolenaara40058a2005-07-11 22:42:07 +0000778static char_u * make_expanded_name __ARGS((char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end));
Bram Moolenaar33570922005-01-25 22:26:29 +0000779static int eval_isnamec __ARGS((int c));
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000780static int eval_isnamec1 __ARGS((int c));
Bram Moolenaar6d977d62014-01-14 15:24:39 +0100781static int get_var_tv __ARGS((char_u *name, int len, typval_T *rettv, int verbose, int no_autoload));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000782static int handle_subscript __ARGS((char_u **arg, typval_T *rettv, int evaluate, int verbose));
Bram Moolenaar33570922005-01-25 22:26:29 +0000783static typval_T *alloc_tv __ARGS((void));
784static typval_T *alloc_string_tv __ARGS((char_u *string));
Bram Moolenaar33570922005-01-25 22:26:29 +0000785static void init_tv __ARGS((typval_T *varp));
786static long get_tv_number __ARGS((typval_T *varp));
787static linenr_T get_tv_lnum __ARGS((typval_T *argvars));
Bram Moolenaar661b1822005-07-28 22:36:45 +0000788static linenr_T get_tv_lnum_buf __ARGS((typval_T *argvars, buf_T *buf));
Bram Moolenaar33570922005-01-25 22:26:29 +0000789static char_u *get_tv_string __ARGS((typval_T *varp));
790static char_u *get_tv_string_buf __ARGS((typval_T *varp, char_u *buf));
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +0000791static char_u *get_tv_string_buf_chk __ARGS((typval_T *varp, char_u *buf));
Bram Moolenaar6d977d62014-01-14 15:24:39 +0100792static dictitem_T *find_var __ARGS((char_u *name, hashtab_T **htp, int no_autoload));
793static dictitem_T *find_var_in_ht __ARGS((hashtab_T *ht, int htname, char_u *varname, int no_autoload));
Bram Moolenaar33570922005-01-25 22:26:29 +0000794static hashtab_T *find_var_ht __ARGS((char_u *name, char_u **varname));
795static void vars_clear_ext __ARGS((hashtab_T *ht, int free_val));
796static void delete_var __ARGS((hashtab_T *ht, hashitem_T *hi));
Bram Moolenaar7d61a922007-08-30 09:12:23 +0000797static void list_one_var __ARGS((dictitem_T *v, char_u *prefix, int *first));
798static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string, int *first));
Bram Moolenaar33570922005-01-25 22:26:29 +0000799static void set_var __ARGS((char_u *name, typval_T *varp, int copy));
800static int var_check_ro __ARGS((int flags, char_u *name));
Bram Moolenaar4e957af2006-09-02 11:41:07 +0000801static int var_check_fixed __ARGS((int flags, char_u *name));
Bram Moolenaar4228bec2011-03-27 16:03:15 +0200802static int var_check_func_name __ARGS((char_u *name, int new_var));
803static int valid_varname __ARGS((char_u *varname));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000804static int tv_check_lock __ARGS((int lock, char_u *name));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000805static int item_copy __ARGS((typval_T *from, typval_T *to, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000806static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags));
807static char_u *trans_function_name __ARGS((char_u **pp, int skip, int flags, funcdict_T *fd));
808static int eval_fname_script __ARGS((char_u *p));
809static int eval_fname_sid __ARGS((char_u *p));
810static void list_func_head __ARGS((ufunc_T *fp, int indent));
Bram Moolenaar33570922005-01-25 22:26:29 +0000811static ufunc_T *find_func __ARGS((char_u *name));
812static int function_exists __ARGS((char_u *name));
Bram Moolenaar9bdfb002014-04-23 17:43:42 +0200813static int builtin_function __ARGS((char_u *name, int len));
Bram Moolenaar05159a02005-02-26 23:04:13 +0000814#ifdef FEAT_PROFILE
815static void func_do_profile __ARGS((ufunc_T *fp));
Bram Moolenaar73830342005-02-28 22:48:19 +0000816static void prof_sort_list __ARGS((FILE *fd, ufunc_T **sorttab, int st_len, char *title, int prefer_self));
817static void prof_func_line __ARGS((FILE *fd, int count, proftime_T *total, proftime_T *self, int prefer_self));
818static int
819# ifdef __BORLANDC__
820 _RTLENTRYF
821# endif
822 prof_total_cmp __ARGS((const void *s1, const void *s2));
823static int
824# ifdef __BORLANDC__
825 _RTLENTRYF
826# endif
827 prof_self_cmp __ARGS((const void *s1, const void *s2));
Bram Moolenaar05159a02005-02-26 23:04:13 +0000828#endif
Bram Moolenaar018acca2013-05-30 13:37:28 +0200829static int script_autoload __ARGS((char_u *name, int reload));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000830static char_u *autoload_name __ARGS((char_u *name));
Bram Moolenaara40058a2005-07-11 22:42:07 +0000831static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp));
Bram Moolenaar33570922005-01-25 22:26:29 +0000832static void func_free __ARGS((ufunc_T *fp));
Bram Moolenaar33570922005-01-25 22:26:29 +0000833static void call_user_func __ARGS((ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, linenr_T firstline, linenr_T lastline, dict_T *selfdict));
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +0000834static int can_free_funccal __ARGS((funccall_T *fc, int copyID)) ;
835static void free_funccal __ARGS((funccall_T *fc, int free_val));
Bram Moolenaar33570922005-01-25 22:26:29 +0000836static void add_nr_var __ARGS((dict_T *dp, dictitem_T *v, char *name, varnumber_T nr));
Bram Moolenaar99ebf042006-04-15 20:28:54 +0000837static win_T *find_win_by_nr __ARGS((typval_T *vp, tabpage_T *tp));
838static void getwinvar __ARGS((typval_T *argvars, typval_T *rettv, int off));
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000839static int searchpair_cmn __ARGS((typval_T *argvars, pos_T *match_pos));
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000840static int search_cmn __ARGS((typval_T *argvars, pos_T *match_pos, int *flagsp));
Bram Moolenaar99ebf042006-04-15 20:28:54 +0000841static void setwinvar __ARGS((typval_T *argvars, typval_T *rettv, int off));
Bram Moolenaar57ebe6e2014-04-05 18:55:46 +0200842static int write_list __ARGS((FILE *fd, list_T *list, int binary));
Bram Moolenaar39c29ed2014-04-05 19:44:40 +0200843static void get_cmd_output_as_rettv __ARGS((typval_T *argvars, typval_T *rettv, int retlist));
Bram Moolenaar33570922005-01-25 22:26:29 +0000844
Bram Moolenaar2c704a72010-06-03 21:17:25 +0200845
846#ifdef EBCDIC
847static int compare_func_name __ARGS((const void *s1, const void *s2));
848static void sortFunctions __ARGS(());
849#endif
850
Bram Moolenaar33570922005-01-25 22:26:29 +0000851/*
852 * Initialize the global and v: variables.
Bram Moolenaara7043832005-01-21 11:56:39 +0000853 */
854 void
855eval_init()
856{
Bram Moolenaar33570922005-01-25 22:26:29 +0000857 int i;
858 struct vimvar *p;
859
Bram Moolenaarbdb62052012-07-16 17:31:53 +0200860 init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE);
861 init_var_dict(&vimvardict, &vimvars_var, VAR_SCOPE);
Bram Moolenaar32f649e2011-04-11 13:46:13 +0200862 vimvardict.dv_lock = VAR_FIXED;
Bram Moolenaar532c7802005-01-27 14:44:31 +0000863 hash_init(&compat_hashtab);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000864 hash_init(&func_hashtab);
Bram Moolenaar33570922005-01-25 22:26:29 +0000865
866 for (i = 0; i < VV_LEN; ++i)
867 {
868 p = &vimvars[i];
869 STRCPY(p->vv_di.di_key, p->vv_name);
870 if (p->vv_flags & VV_RO)
871 p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
872 else if (p->vv_flags & VV_RO_SBX)
873 p->vv_di.di_flags = DI_FLAGS_RO_SBX | DI_FLAGS_FIX;
874 else
875 p->vv_di.di_flags = DI_FLAGS_FIX;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000876
877 /* add to v: scope dict, unless the value is not always available */
878 if (p->vv_type != VAR_UNKNOWN)
879 hash_add(&vimvarht, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000880 if (p->vv_flags & VV_COMPAT)
Bram Moolenaar532c7802005-01-27 14:44:31 +0000881 /* add to compat scope dict */
882 hash_add(&compat_hashtab, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000883 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000884 set_vim_var_nr(VV_SEARCHFORWARD, 1L);
Bram Moolenaar8050efa2013-11-08 04:30:20 +0100885 set_vim_var_nr(VV_HLSEARCH, 1L);
Bram Moolenaarb429cde2012-04-25 18:24:29 +0200886 set_reg_var(0); /* default for v:register is not 0 but '"' */
Bram Moolenaar2c704a72010-06-03 21:17:25 +0200887
888#ifdef EBCDIC
889 /*
Bram Moolenaar195ea0f2011-11-30 14:57:31 +0100890 * Sort the function table, to enable binary search.
Bram Moolenaar2c704a72010-06-03 21:17:25 +0200891 */
892 sortFunctions();
893#endif
Bram Moolenaara7043832005-01-21 11:56:39 +0000894}
895
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000896#if defined(EXITFREE) || defined(PROTO)
897 void
898eval_clear()
899{
900 int i;
901 struct vimvar *p;
902
903 for (i = 0; i < VV_LEN; ++i)
904 {
905 p = &vimvars[i];
906 if (p->vv_di.di_tv.v_type == VAR_STRING)
Bram Moolenaard9fba312005-06-26 22:34:35 +0000907 {
Bram Moolenaar12193212008-11-09 16:22:01 +0000908 vim_free(p->vv_str);
909 p->vv_str = NULL;
Bram Moolenaard812df62008-11-09 12:46:09 +0000910 }
911 else if (p->vv_di.di_tv.v_type == VAR_LIST)
912 {
913 list_unref(p->vv_list);
914 p->vv_list = NULL;
Bram Moolenaard9fba312005-06-26 22:34:35 +0000915 }
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000916 }
917 hash_clear(&vimvarht);
Bram Moolenaar0f71c6d2008-11-12 14:29:28 +0000918 hash_init(&vimvarht); /* garbage_collect() will access it */
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000919 hash_clear(&compat_hashtab);
920
Bram Moolenaard9fba312005-06-26 22:34:35 +0000921 free_scriptnames();
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +0100922# if defined(FEAT_CMDL_COMPL)
Bram Moolenaar9b486ca2011-05-19 18:26:40 +0200923 free_locales();
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +0100924# endif
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000925
926 /* global variables */
927 vars_clear(&globvarht);
Bram Moolenaard9fba312005-06-26 22:34:35 +0000928
Bram Moolenaaraa35dd12006-04-29 22:03:41 +0000929 /* autoloaded script names */
930 ga_clear_strings(&ga_loaded);
931
Bram Moolenaarcca74132013-09-25 21:00:28 +0200932 /* Script-local variables. First clear all the variables and in a second
933 * loop free the scriptvar_T, because a variable in one script might hold
934 * a reference to the whole scope of another script. */
Bram Moolenaar9577c3e2010-05-14 12:16:25 +0200935 for (i = 1; i <= ga_scripts.ga_len; ++i)
Bram Moolenaar9577c3e2010-05-14 12:16:25 +0200936 vars_clear(&SCRIPT_VARS(i));
Bram Moolenaarcca74132013-09-25 21:00:28 +0200937 for (i = 1; i <= ga_scripts.ga_len; ++i)
Bram Moolenaar9577c3e2010-05-14 12:16:25 +0200938 vim_free(SCRIPT_SV(i));
Bram Moolenaar9577c3e2010-05-14 12:16:25 +0200939 ga_clear(&ga_scripts);
940
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000941 /* unreferenced lists and dicts */
942 (void)garbage_collect();
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000943
944 /* functions */
945 free_all_functions();
946 hash_clear(&func_hashtab);
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000947}
948#endif
949
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000950/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000951 * Return the name of the executed function.
952 */
953 char_u *
954func_name(cookie)
955 void *cookie;
956{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000957 return ((funccall_T *)cookie)->func->uf_name;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000958}
959
960/*
961 * Return the address holding the next breakpoint line for a funccall cookie.
962 */
963 linenr_T *
964func_breakpoint(cookie)
965 void *cookie;
966{
Bram Moolenaar33570922005-01-25 22:26:29 +0000967 return &((funccall_T *)cookie)->breakpoint;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000968}
969
970/*
971 * Return the address holding the debug tick for a funccall cookie.
972 */
973 int *
974func_dbg_tick(cookie)
975 void *cookie;
976{
Bram Moolenaar33570922005-01-25 22:26:29 +0000977 return &((funccall_T *)cookie)->dbg_tick;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000978}
979
980/*
981 * Return the nesting level for a funccall cookie.
982 */
983 int
984func_level(cookie)
985 void *cookie;
986{
Bram Moolenaar33570922005-01-25 22:26:29 +0000987 return ((funccall_T *)cookie)->level;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000988}
989
990/* pointer to funccal for currently active function */
Bram Moolenaar33570922005-01-25 22:26:29 +0000991funccall_T *current_funccal = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000992
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +0000993/* pointer to list of previously used funccal, still around because some
994 * item in it is still being used. */
995funccall_T *previous_funccal = NULL;
996
Bram Moolenaar071d4272004-06-13 20:20:40 +0000997/*
998 * Return TRUE when a function was ended by a ":return" command.
999 */
1000 int
1001current_func_returned()
1002{
1003 return current_funccal->returned;
1004}
1005
1006
1007/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00001008 * Set an internal variable to a string value. Creates the variable if it does
1009 * not already exist.
1010 */
1011 void
1012set_internal_string_var(name, value)
1013 char_u *name;
1014 char_u *value;
1015{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001016 char_u *val;
Bram Moolenaar33570922005-01-25 22:26:29 +00001017 typval_T *tvp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001018
1019 val = vim_strsave(value);
1020 if (val != NULL)
1021 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001022 tvp = alloc_string_tv(val);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001023 if (tvp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001024 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001025 set_var(name, tvp, FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001026 free_tv(tvp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001027 }
1028 }
1029}
1030
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001031static lval_T *redir_lval = NULL;
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001032static garray_T redir_ga; /* only valid when redir_lval is not NULL */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001033static char_u *redir_endp = NULL;
1034static char_u *redir_varname = NULL;
1035
1036/*
1037 * Start recording command output to a variable
1038 * Returns OK if successfully completed the setup. FAIL otherwise.
1039 */
1040 int
1041var_redir_start(name, append)
1042 char_u *name;
1043 int append; /* append to an existing variable */
1044{
1045 int save_emsg;
1046 int err;
1047 typval_T tv;
1048
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +00001049 /* Catch a bad name early. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001050 if (!eval_isnamec1(*name))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001051 {
1052 EMSG(_(e_invarg));
1053 return FAIL;
1054 }
1055
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +00001056 /* Make a copy of the name, it is used in redir_lval until redir ends. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001057 redir_varname = vim_strsave(name);
1058 if (redir_varname == NULL)
1059 return FAIL;
1060
1061 redir_lval = (lval_T *)alloc_clear((unsigned)sizeof(lval_T));
1062 if (redir_lval == NULL)
1063 {
1064 var_redir_stop();
1065 return FAIL;
1066 }
1067
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001068 /* The output is stored in growarray "redir_ga" until redirection ends. */
1069 ga_init2(&redir_ga, (int)sizeof(char), 500);
1070
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001071 /* Parse the variable name (can be a dict or list entry). */
Bram Moolenaar6d977d62014-01-14 15:24:39 +01001072 redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, 0,
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001073 FNE_CHECK_START);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001074 if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != NUL)
1075 {
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +02001076 clear_lval(redir_lval);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001077 if (redir_endp != NULL && *redir_endp != NUL)
1078 /* Trailing characters are present after the variable name */
1079 EMSG(_(e_trailing));
1080 else
1081 EMSG(_(e_invarg));
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +00001082 redir_endp = NULL; /* don't store a value, only cleanup */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001083 var_redir_stop();
1084 return FAIL;
1085 }
1086
1087 /* check if we can write to the variable: set it to or append an empty
1088 * string */
1089 save_emsg = did_emsg;
1090 did_emsg = FALSE;
1091 tv.v_type = VAR_STRING;
1092 tv.vval.v_string = (char_u *)"";
1093 if (append)
1094 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)".");
1095 else
1096 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)"=");
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +02001097 clear_lval(redir_lval);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001098 err = did_emsg;
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00001099 did_emsg |= save_emsg;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001100 if (err)
1101 {
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +00001102 redir_endp = NULL; /* don't store a value, only cleanup */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001103 var_redir_stop();
1104 return FAIL;
1105 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001106
1107 return OK;
1108}
1109
1110/*
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001111 * Append "value[value_len]" to the variable set by var_redir_start().
1112 * The actual appending is postponed until redirection ends, because the value
1113 * appended may in fact be the string we write to, changing it may cause freed
1114 * memory to be used:
1115 * :redir => foo
1116 * :let foo
1117 * :redir END
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001118 */
1119 void
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001120var_redir_str(value, value_len)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001121 char_u *value;
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001122 int value_len;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001123{
Bram Moolenaar5fdec472007-07-24 08:45:13 +00001124 int len;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001125
1126 if (redir_lval == NULL)
1127 return;
1128
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001129 if (value_len == -1)
Bram Moolenaar5fdec472007-07-24 08:45:13 +00001130 len = (int)STRLEN(value); /* Append the entire string */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001131 else
Bram Moolenaar5fdec472007-07-24 08:45:13 +00001132 len = value_len; /* Append only "value_len" characters */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001133
Bram Moolenaar5fdec472007-07-24 08:45:13 +00001134 if (ga_grow(&redir_ga, len) == OK)
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001135 {
1136 mch_memmove((char *)redir_ga.ga_data + redir_ga.ga_len, value, len);
Bram Moolenaar5fdec472007-07-24 08:45:13 +00001137 redir_ga.ga_len += len;
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001138 }
1139 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001140 var_redir_stop();
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001141}
1142
1143/*
1144 * Stop redirecting command output to a variable.
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +00001145 * Frees the allocated memory.
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001146 */
1147 void
1148var_redir_stop()
1149{
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001150 typval_T tv;
1151
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001152 if (redir_lval != NULL)
1153 {
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +00001154 /* If there was no error: assign the text to the variable. */
1155 if (redir_endp != NULL)
1156 {
1157 ga_append(&redir_ga, NUL); /* Append the trailing NUL. */
1158 tv.v_type = VAR_STRING;
1159 tv.vval.v_string = redir_ga.ga_data;
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +02001160 /* Call get_lval() again, if it's inside a Dict or List it may
1161 * have changed. */
1162 redir_endp = get_lval(redir_varname, NULL, redir_lval,
Bram Moolenaar6d977d62014-01-14 15:24:39 +01001163 FALSE, FALSE, 0, FNE_CHECK_START);
Bram Moolenaar1dba0fb2010-07-28 18:55:02 +02001164 if (redir_endp != NULL && redir_lval->ll_name != NULL)
1165 set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)".");
1166 clear_lval(redir_lval);
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +00001167 }
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001168
Bram Moolenaar2f59b5c2009-11-03 13:26:55 +00001169 /* free the collected output */
1170 vim_free(redir_ga.ga_data);
1171 redir_ga.ga_data = NULL;
Bram Moolenaar863b53b2007-01-14 14:28:34 +00001172
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001173 vim_free(redir_lval);
1174 redir_lval = NULL;
1175 }
1176 vim_free(redir_varname);
1177 redir_varname = NULL;
1178}
1179
Bram Moolenaar071d4272004-06-13 20:20:40 +00001180# if defined(FEAT_MBYTE) || defined(PROTO)
1181 int
1182eval_charconvert(enc_from, enc_to, fname_from, fname_to)
1183 char_u *enc_from;
1184 char_u *enc_to;
1185 char_u *fname_from;
1186 char_u *fname_to;
1187{
1188 int err = FALSE;
1189
1190 set_vim_var_string(VV_CC_FROM, enc_from, -1);
1191 set_vim_var_string(VV_CC_TO, enc_to, -1);
1192 set_vim_var_string(VV_FNAME_IN, fname_from, -1);
1193 set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
1194 if (eval_to_bool(p_ccv, &err, NULL, FALSE))
1195 err = TRUE;
1196 set_vim_var_string(VV_CC_FROM, NULL, -1);
1197 set_vim_var_string(VV_CC_TO, NULL, -1);
1198 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1199 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
1200
1201 if (err)
1202 return FAIL;
1203 return OK;
1204}
1205# endif
1206
1207# if defined(FEAT_POSTSCRIPT) || defined(PROTO)
1208 int
1209eval_printexpr(fname, args)
1210 char_u *fname;
1211 char_u *args;
1212{
1213 int err = FALSE;
1214
1215 set_vim_var_string(VV_FNAME_IN, fname, -1);
1216 set_vim_var_string(VV_CMDARG, args, -1);
1217 if (eval_to_bool(p_pexpr, &err, NULL, FALSE))
1218 err = TRUE;
1219 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1220 set_vim_var_string(VV_CMDARG, NULL, -1);
1221
1222 if (err)
1223 {
1224 mch_remove(fname);
1225 return FAIL;
1226 }
1227 return OK;
1228}
1229# endif
1230
1231# if defined(FEAT_DIFF) || defined(PROTO)
1232 void
1233eval_diff(origfile, newfile, outfile)
1234 char_u *origfile;
1235 char_u *newfile;
1236 char_u *outfile;
1237{
1238 int err = FALSE;
1239
1240 set_vim_var_string(VV_FNAME_IN, origfile, -1);
1241 set_vim_var_string(VV_FNAME_NEW, newfile, -1);
1242 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
1243 (void)eval_to_bool(p_dex, &err, NULL, FALSE);
1244 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1245 set_vim_var_string(VV_FNAME_NEW, NULL, -1);
1246 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
1247}
1248
1249 void
1250eval_patch(origfile, difffile, outfile)
1251 char_u *origfile;
1252 char_u *difffile;
1253 char_u *outfile;
1254{
1255 int err;
1256
1257 set_vim_var_string(VV_FNAME_IN, origfile, -1);
1258 set_vim_var_string(VV_FNAME_DIFF, difffile, -1);
1259 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
1260 (void)eval_to_bool(p_pex, &err, NULL, FALSE);
1261 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1262 set_vim_var_string(VV_FNAME_DIFF, NULL, -1);
1263 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
1264}
1265# endif
1266
1267/*
1268 * Top level evaluation function, returning a boolean.
1269 * Sets "error" to TRUE if there was an error.
1270 * Return TRUE or FALSE.
1271 */
1272 int
1273eval_to_bool(arg, error, nextcmd, skip)
1274 char_u *arg;
1275 int *error;
1276 char_u **nextcmd;
1277 int skip; /* only parse, don't execute */
1278{
Bram Moolenaar33570922005-01-25 22:26:29 +00001279 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001280 int retval = FALSE;
1281
1282 if (skip)
1283 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001284 if (eval0(arg, &tv, nextcmd, !skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001285 *error = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001286 else
1287 {
1288 *error = FALSE;
1289 if (!skip)
1290 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001291 retval = (get_tv_number_chk(&tv, error) != 0);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001292 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001293 }
1294 }
1295 if (skip)
1296 --emsg_skip;
1297
1298 return retval;
1299}
1300
1301/*
1302 * Top level evaluation function, returning a string. If "skip" is TRUE,
1303 * only parsing to "nextcmd" is done, without reporting errors. Return
1304 * pointer to allocated memory, or NULL for failure or when "skip" is TRUE.
1305 */
1306 char_u *
1307eval_to_string_skip(arg, nextcmd, skip)
1308 char_u *arg;
1309 char_u **nextcmd;
1310 int skip; /* only parse, don't execute */
1311{
Bram Moolenaar33570922005-01-25 22:26:29 +00001312 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001313 char_u *retval;
1314
1315 if (skip)
1316 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001317 if (eval0(arg, &tv, nextcmd, !skip) == FAIL || skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001318 retval = NULL;
1319 else
1320 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001321 retval = vim_strsave(get_tv_string(&tv));
1322 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001323 }
1324 if (skip)
1325 --emsg_skip;
1326
1327 return retval;
1328}
1329
1330/*
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001331 * Skip over an expression at "*pp".
1332 * Return FAIL for an error, OK otherwise.
1333 */
1334 int
1335skip_expr(pp)
1336 char_u **pp;
1337{
Bram Moolenaar33570922005-01-25 22:26:29 +00001338 typval_T rettv;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001339
1340 *pp = skipwhite(*pp);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001341 return eval1(pp, &rettv, FALSE);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001342}
1343
1344/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00001345 * Top level evaluation function, returning a string.
Bram Moolenaara85fb752008-09-07 11:55:43 +00001346 * When "convert" is TRUE convert a List into a sequence of lines and convert
1347 * a Float to a String.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001348 * Return pointer to allocated memory, or NULL for failure.
1349 */
1350 char_u *
Bram Moolenaara85fb752008-09-07 11:55:43 +00001351eval_to_string(arg, nextcmd, convert)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001352 char_u *arg;
1353 char_u **nextcmd;
Bram Moolenaara85fb752008-09-07 11:55:43 +00001354 int convert;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001355{
Bram Moolenaar33570922005-01-25 22:26:29 +00001356 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001357 char_u *retval;
Bram Moolenaar362e1a32006-03-06 23:29:24 +00001358 garray_T ga;
Bram Moolenaar798b30b2009-04-22 10:56:16 +00001359#ifdef FEAT_FLOAT
Bram Moolenaara85fb752008-09-07 11:55:43 +00001360 char_u numbuf[NUMBUFLEN];
Bram Moolenaar798b30b2009-04-22 10:56:16 +00001361#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001362
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001363 if (eval0(arg, &tv, nextcmd, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001364 retval = NULL;
1365 else
1366 {
Bram Moolenaara85fb752008-09-07 11:55:43 +00001367 if (convert && tv.v_type == VAR_LIST)
Bram Moolenaar362e1a32006-03-06 23:29:24 +00001368 {
1369 ga_init2(&ga, (int)sizeof(char), 80);
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00001370 if (tv.vval.v_list != NULL)
Bram Moolenaar213b10a2011-08-10 12:38:08 +02001371 {
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00001372 list_join(&ga, tv.vval.v_list, (char_u *)"\n", TRUE, 0);
Bram Moolenaar213b10a2011-08-10 12:38:08 +02001373 if (tv.vval.v_list->lv_len > 0)
1374 ga_append(&ga, NL);
1375 }
Bram Moolenaar362e1a32006-03-06 23:29:24 +00001376 ga_append(&ga, NUL);
1377 retval = (char_u *)ga.ga_data;
1378 }
Bram Moolenaara85fb752008-09-07 11:55:43 +00001379#ifdef FEAT_FLOAT
1380 else if (convert && tv.v_type == VAR_FLOAT)
1381 {
1382 vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv.vval.v_float);
1383 retval = vim_strsave(numbuf);
1384 }
1385#endif
Bram Moolenaar362e1a32006-03-06 23:29:24 +00001386 else
1387 retval = vim_strsave(get_tv_string(&tv));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001388 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001389 }
1390
1391 return retval;
1392}
1393
1394/*
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001395 * Call eval_to_string() without using current local variables and using
1396 * textlock. When "use_sandbox" is TRUE use the sandbox.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001397 */
1398 char_u *
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001399eval_to_string_safe(arg, nextcmd, use_sandbox)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001400 char_u *arg;
1401 char_u **nextcmd;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001402 int use_sandbox;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001403{
1404 char_u *retval;
1405 void *save_funccalp;
1406
1407 save_funccalp = save_funccal();
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001408 if (use_sandbox)
1409 ++sandbox;
1410 ++textlock;
Bram Moolenaar362e1a32006-03-06 23:29:24 +00001411 retval = eval_to_string(arg, nextcmd, FALSE);
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001412 if (use_sandbox)
1413 --sandbox;
1414 --textlock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001415 restore_funccal(save_funccalp);
1416 return retval;
1417}
1418
Bram Moolenaar071d4272004-06-13 20:20:40 +00001419/*
1420 * Top level evaluation function, returning a number.
1421 * Evaluates "expr" silently.
1422 * Returns -1 for an error.
1423 */
1424 int
1425eval_to_number(expr)
1426 char_u *expr;
1427{
Bram Moolenaar33570922005-01-25 22:26:29 +00001428 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001429 int retval;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00001430 char_u *p = skipwhite(expr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001431
1432 ++emsg_off;
1433
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001434 if (eval1(&p, &rettv, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001435 retval = -1;
1436 else
1437 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001438 retval = get_tv_number_chk(&rettv, NULL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001439 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001440 }
1441 --emsg_off;
1442
1443 return retval;
1444}
1445
Bram Moolenaara40058a2005-07-11 22:42:07 +00001446/*
1447 * Prepare v: variable "idx" to be used.
1448 * Save the current typeval in "save_tv".
1449 * When not used yet add the variable to the v: hashtable.
1450 */
1451 static void
1452prepare_vimvar(idx, save_tv)
1453 int idx;
1454 typval_T *save_tv;
1455{
1456 *save_tv = vimvars[idx].vv_tv;
1457 if (vimvars[idx].vv_type == VAR_UNKNOWN)
1458 hash_add(&vimvarht, vimvars[idx].vv_di.di_key);
1459}
1460
1461/*
1462 * Restore v: variable "idx" to typeval "save_tv".
1463 * When no longer defined, remove the variable from the v: hashtable.
1464 */
1465 static void
1466restore_vimvar(idx, save_tv)
1467 int idx;
1468 typval_T *save_tv;
1469{
1470 hashitem_T *hi;
1471
Bram Moolenaara40058a2005-07-11 22:42:07 +00001472 vimvars[idx].vv_tv = *save_tv;
1473 if (vimvars[idx].vv_type == VAR_UNKNOWN)
1474 {
1475 hi = hash_find(&vimvarht, vimvars[idx].vv_di.di_key);
1476 if (HASHITEM_EMPTY(hi))
1477 EMSG2(_(e_intern2), "restore_vimvar()");
1478 else
1479 hash_remove(&vimvarht, hi);
1480 }
1481}
1482
Bram Moolenaar3c56a962006-03-12 22:19:04 +00001483#if defined(FEAT_SPELL) || defined(PROTO)
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001484/*
1485 * Evaluate an expression to a list with suggestions.
1486 * For the "expr:" part of 'spellsuggest'.
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00001487 * Returns NULL when there is an error.
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001488 */
1489 list_T *
1490eval_spell_expr(badword, expr)
1491 char_u *badword;
1492 char_u *expr;
1493{
1494 typval_T save_val;
1495 typval_T rettv;
1496 list_T *list = NULL;
1497 char_u *p = skipwhite(expr);
1498
1499 /* Set "v:val" to the bad word. */
1500 prepare_vimvar(VV_VAL, &save_val);
1501 vimvars[VV_VAL].vv_type = VAR_STRING;
1502 vimvars[VV_VAL].vv_str = badword;
1503 if (p_verbose == 0)
1504 ++emsg_off;
1505
1506 if (eval1(&p, &rettv, TRUE) == OK)
1507 {
1508 if (rettv.v_type != VAR_LIST)
1509 clear_tv(&rettv);
1510 else
1511 list = rettv.vval.v_list;
1512 }
1513
1514 if (p_verbose == 0)
1515 --emsg_off;
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001516 restore_vimvar(VV_VAL, &save_val);
1517
1518 return list;
1519}
1520
1521/*
1522 * "list" is supposed to contain two items: a word and a number. Return the
1523 * word in "pp" and the number as the return value.
1524 * Return -1 if anything isn't right.
1525 * Used to get the good word and score from the eval_spell_expr() result.
1526 */
1527 int
1528get_spellword(list, pp)
1529 list_T *list;
1530 char_u **pp;
1531{
1532 listitem_T *li;
1533
1534 li = list->lv_first;
1535 if (li == NULL)
1536 return -1;
1537 *pp = get_tv_string(&li->li_tv);
1538
1539 li = li->li_next;
1540 if (li == NULL)
1541 return -1;
1542 return get_tv_number(&li->li_tv);
1543}
1544#endif
1545
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001546/*
Bram Moolenaar4770d092006-01-12 23:22:24 +00001547 * Top level evaluation function.
1548 * Returns an allocated typval_T with the result.
1549 * Returns NULL when there is an error.
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001550 */
1551 typval_T *
1552eval_expr(arg, nextcmd)
1553 char_u *arg;
1554 char_u **nextcmd;
1555{
1556 typval_T *tv;
1557
1558 tv = (typval_T *)alloc(sizeof(typval_T));
Bram Moolenaar4770d092006-01-12 23:22:24 +00001559 if (tv != NULL && eval0(arg, tv, nextcmd, TRUE) == FAIL)
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001560 {
1561 vim_free(tv);
Bram Moolenaar4770d092006-01-12 23:22:24 +00001562 tv = NULL;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001563 }
1564
1565 return tv;
1566}
1567
1568
Bram Moolenaar071d4272004-06-13 20:20:40 +00001569/*
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001570 * Call some vimL function and return the result in "*rettv".
Bram Moolenaar8c8de832008-06-24 22:58:06 +00001571 * Uses argv[argc] for the function arguments. Only Number and String
1572 * arguments are currently supported.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001573 * Returns OK or FAIL.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001574 */
Bram Moolenaar82139082011-09-14 16:52:09 +02001575 int
Bram Moolenaar0cbba942012-07-25 16:47:03 +02001576call_vim_function(func, argc, argv, safe, str_arg_only, rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001577 char_u *func;
1578 int argc;
1579 char_u **argv;
1580 int safe; /* use the sandbox */
Bram Moolenaar0cbba942012-07-25 16:47:03 +02001581 int str_arg_only; /* all arguments are strings */
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001582 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001583{
Bram Moolenaar33570922005-01-25 22:26:29 +00001584 typval_T *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001585 long n;
1586 int len;
1587 int i;
1588 int doesrange;
1589 void *save_funccalp = NULL;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001590 int ret;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001591
Bram Moolenaareb3593b2006-04-22 22:33:57 +00001592 argvars = (typval_T *)alloc((unsigned)((argc + 1) * sizeof(typval_T)));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001593 if (argvars == NULL)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001594 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001595
1596 for (i = 0; i < argc; i++)
1597 {
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00001598 /* Pass a NULL or empty argument as an empty string */
1599 if (argv[i] == NULL || *argv[i] == NUL)
1600 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001601 argvars[i].v_type = VAR_STRING;
1602 argvars[i].vval.v_string = (char_u *)"";
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00001603 continue;
1604 }
1605
Bram Moolenaar0cbba942012-07-25 16:47:03 +02001606 if (str_arg_only)
1607 len = 0;
1608 else
1609 /* Recognize a number argument, the others must be strings. */
1610 vim_str2nr(argv[i], NULL, &len, TRUE, TRUE, &n, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001611 if (len != 0 && len == (int)STRLEN(argv[i]))
1612 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001613 argvars[i].v_type = VAR_NUMBER;
1614 argvars[i].vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001615 }
1616 else
1617 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001618 argvars[i].v_type = VAR_STRING;
1619 argvars[i].vval.v_string = argv[i];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001620 }
1621 }
1622
1623 if (safe)
1624 {
1625 save_funccalp = save_funccal();
1626 ++sandbox;
1627 }
1628
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001629 rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */
1630 ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001631 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001632 &doesrange, TRUE, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001633 if (safe)
1634 {
1635 --sandbox;
1636 restore_funccal(save_funccalp);
1637 }
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001638 vim_free(argvars);
1639
1640 if (ret == FAIL)
1641 clear_tv(rettv);
1642
1643 return ret;
1644}
1645
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01001646/*
1647 * Call vimL function "func" and return the result as a number.
1648 * Returns -1 when calling the function fails.
1649 * Uses argv[argc] for the function arguments.
1650 */
1651 long
1652call_func_retnr(func, argc, argv, safe)
1653 char_u *func;
1654 int argc;
1655 char_u **argv;
1656 int safe; /* use the sandbox */
1657{
1658 typval_T rettv;
1659 long retval;
1660
1661 /* All arguments are passed as strings, no conversion to number. */
1662 if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL)
1663 return -1;
1664
1665 retval = get_tv_number_chk(&rettv, NULL);
1666 clear_tv(&rettv);
1667 return retval;
1668}
1669
1670#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) \
1671 || defined(FEAT_COMPL_FUNC) || defined(PROTO)
1672
Bram Moolenaar4f688582007-07-24 12:34:30 +00001673# if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001674/*
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001675 * Call vimL function "func" and return the result as a string.
1676 * Returns NULL when calling the function fails.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001677 * Uses argv[argc] for the function arguments.
1678 */
1679 void *
1680call_func_retstr(func, argc, argv, safe)
1681 char_u *func;
1682 int argc;
1683 char_u **argv;
1684 int safe; /* use the sandbox */
1685{
1686 typval_T rettv;
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001687 char_u *retval;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001688
Bram Moolenaar0cbba942012-07-25 16:47:03 +02001689 /* All arguments are passed as strings, no conversion to number. */
1690 if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001691 return NULL;
1692
1693 retval = vim_strsave(get_tv_string(&rettv));
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001694 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001695 return retval;
1696}
Bram Moolenaar4f688582007-07-24 12:34:30 +00001697# endif
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001698
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001699/*
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00001700 * Call vimL function "func" and return the result as a List.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001701 * Uses argv[argc] for the function arguments.
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00001702 * Returns NULL when there is something wrong.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001703 */
1704 void *
1705call_func_retlist(func, argc, argv, safe)
1706 char_u *func;
1707 int argc;
1708 char_u **argv;
1709 int safe; /* use the sandbox */
1710{
1711 typval_T rettv;
1712
Bram Moolenaar0cbba942012-07-25 16:47:03 +02001713 /* All arguments are passed as strings, no conversion to number. */
1714 if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001715 return NULL;
1716
1717 if (rettv.v_type != VAR_LIST)
1718 {
1719 clear_tv(&rettv);
1720 return NULL;
1721 }
1722
1723 return rettv.vval.v_list;
1724}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001725#endif
1726
1727/*
1728 * Save the current function call pointer, and set it to NULL.
1729 * Used when executing autocommands and for ":source".
1730 */
1731 void *
1732save_funccal()
1733{
Bram Moolenaar05159a02005-02-26 23:04:13 +00001734 funccall_T *fc = current_funccal;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001735
Bram Moolenaar071d4272004-06-13 20:20:40 +00001736 current_funccal = NULL;
1737 return (void *)fc;
1738}
1739
1740 void
Bram Moolenaar05159a02005-02-26 23:04:13 +00001741restore_funccal(vfc)
1742 void *vfc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001743{
Bram Moolenaar05159a02005-02-26 23:04:13 +00001744 funccall_T *fc = (funccall_T *)vfc;
1745
1746 current_funccal = fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001747}
1748
Bram Moolenaar05159a02005-02-26 23:04:13 +00001749#if defined(FEAT_PROFILE) || defined(PROTO)
1750/*
1751 * Prepare profiling for entering a child or something else that is not
1752 * counted for the script/function itself.
1753 * Should always be called in pair with prof_child_exit().
1754 */
1755 void
1756prof_child_enter(tm)
1757 proftime_T *tm; /* place to store waittime */
1758{
1759 funccall_T *fc = current_funccal;
1760
1761 if (fc != NULL && fc->func->uf_profiling)
1762 profile_start(&fc->prof_child);
1763 script_prof_save(tm);
1764}
1765
1766/*
1767 * Take care of time spent in a child.
1768 * Should always be called after prof_child_enter().
1769 */
1770 void
1771prof_child_exit(tm)
1772 proftime_T *tm; /* where waittime was stored */
1773{
1774 funccall_T *fc = current_funccal;
1775
1776 if (fc != NULL && fc->func->uf_profiling)
1777 {
1778 profile_end(&fc->prof_child);
1779 profile_sub_wait(tm, &fc->prof_child); /* don't count waiting time */
1780 profile_add(&fc->func->uf_tm_children, &fc->prof_child);
1781 profile_add(&fc->func->uf_tml_children, &fc->prof_child);
1782 }
1783 script_prof_restore(tm);
1784}
1785#endif
1786
1787
Bram Moolenaar071d4272004-06-13 20:20:40 +00001788#ifdef FEAT_FOLDING
1789/*
1790 * Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding
1791 * it in "*cp". Doesn't give error messages.
1792 */
1793 int
1794eval_foldexpr(arg, cp)
1795 char_u *arg;
1796 int *cp;
1797{
Bram Moolenaar33570922005-01-25 22:26:29 +00001798 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001799 int retval;
1800 char_u *s;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00001801 int use_sandbox = was_set_insecurely((char_u *)"foldexpr",
1802 OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001803
1804 ++emsg_off;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001805 if (use_sandbox)
1806 ++sandbox;
1807 ++textlock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001808 *cp = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001809 if (eval0(arg, &tv, NULL, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001810 retval = 0;
1811 else
1812 {
1813 /* If the result is a number, just return the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001814 if (tv.v_type == VAR_NUMBER)
1815 retval = tv.vval.v_number;
Bram Moolenaar758711c2005-02-02 23:11:38 +00001816 else if (tv.v_type != VAR_STRING || tv.vval.v_string == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001817 retval = 0;
1818 else
1819 {
1820 /* If the result is a string, check if there is a non-digit before
1821 * the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001822 s = tv.vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001823 if (!VIM_ISDIGIT(*s) && *s != '-')
1824 *cp = *s++;
1825 retval = atol((char *)s);
1826 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001827 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001828 }
1829 --emsg_off;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001830 if (use_sandbox)
1831 --sandbox;
1832 --textlock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001833
1834 return retval;
1835}
1836#endif
1837
Bram Moolenaar071d4272004-06-13 20:20:40 +00001838/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001839 * ":let" list all variable values
1840 * ":let var1 var2" list variable values
1841 * ":let var = expr" assignment command.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001842 * ":let var += expr" assignment command.
1843 * ":let var -= expr" assignment command.
1844 * ":let var .= expr" assignment command.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001845 * ":let [var1, var2] = expr" unpack list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001846 */
1847 void
1848ex_let(eap)
1849 exarg_T *eap;
1850{
1851 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001852 char_u *expr = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00001853 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001854 int i;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001855 int var_count = 0;
1856 int semicolon = 0;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001857 char_u op[2];
Bram Moolenaardb552d602006-03-23 22:59:57 +00001858 char_u *argend;
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001859 int first = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001860
Bram Moolenaardb552d602006-03-23 22:59:57 +00001861 argend = skip_var_list(arg, &var_count, &semicolon);
1862 if (argend == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001863 return;
Bram Moolenaar76b92b22006-03-24 22:46:53 +00001864 if (argend > arg && argend[-1] == '.') /* for var.='str' */
1865 --argend;
Bram Moolenaara3920382014-03-30 16:49:09 +02001866 expr = skipwhite(argend);
1867 if (*expr != '=' && !(vim_strchr((char_u *)"+-.", *expr) != NULL
1868 && expr[1] == '='))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001869 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001870 /*
1871 * ":let" without "=": list variables
1872 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001873 if (*arg == '[')
1874 EMSG(_(e_invarg));
1875 else if (!ends_excmd(*arg))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001876 /* ":let var1 var2" */
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001877 arg = list_arg_vars(eap, arg, &first);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001878 else if (!eap->skip)
Bram Moolenaara7043832005-01-21 11:56:39 +00001879 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001880 /* ":let" */
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001881 list_glob_vars(&first);
1882 list_buf_vars(&first);
1883 list_win_vars(&first);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001884#ifdef FEAT_WINDOWS
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001885 list_tab_vars(&first);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001886#endif
Bram Moolenaar7d61a922007-08-30 09:12:23 +00001887 list_script_vars(&first);
1888 list_func_vars(&first);
1889 list_vim_vars(&first);
Bram Moolenaara7043832005-01-21 11:56:39 +00001890 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001891 eap->nextcmd = check_nextcmd(arg);
1892 }
1893 else
1894 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001895 op[0] = '=';
1896 op[1] = NUL;
Bram Moolenaara3920382014-03-30 16:49:09 +02001897 if (*expr != '=')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001898 {
Bram Moolenaara3920382014-03-30 16:49:09 +02001899 if (vim_strchr((char_u *)"+-.", *expr) != NULL)
1900 op[0] = *expr; /* +=, -= or .= */
1901 expr = skipwhite(expr + 2);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001902 }
Bram Moolenaara3920382014-03-30 16:49:09 +02001903 else
1904 expr = skipwhite(expr + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001905
Bram Moolenaar071d4272004-06-13 20:20:40 +00001906 if (eap->skip)
1907 ++emsg_skip;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001908 i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001909 if (eap->skip)
1910 {
1911 if (i != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001912 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001913 --emsg_skip;
1914 }
1915 else if (i != FAIL)
1916 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001917 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001918 op);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001919 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001920 }
1921 }
1922}
1923
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001924/*
1925 * Assign the typevalue "tv" to the variable or variables at "arg_start".
1926 * Handles both "var" with any type and "[var, var; var]" with a list type.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001927 * When "nextchars" is not NULL it points to a string with characters that
1928 * must appear after the variable(s). Use "+", "-" or "." for add, subtract
1929 * or concatenate.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001930 * Returns OK or FAIL;
1931 */
1932 static int
1933ex_let_vars(arg_start, tv, copy, semicolon, var_count, nextchars)
1934 char_u *arg_start;
Bram Moolenaar33570922005-01-25 22:26:29 +00001935 typval_T *tv;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001936 int copy; /* copy values from "tv", don't move */
1937 int semicolon; /* from skip_var_list() */
1938 int var_count; /* from skip_var_list() */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001939 char_u *nextchars;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001940{
1941 char_u *arg = arg_start;
Bram Moolenaar33570922005-01-25 22:26:29 +00001942 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001943 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00001944 listitem_T *item;
1945 typval_T ltv;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001946
1947 if (*arg != '[')
1948 {
1949 /*
1950 * ":let var = expr" or ":for var in list"
1951 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001952 if (ex_let_one(arg, tv, copy, nextchars, nextchars) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001953 return FAIL;
1954 return OK;
1955 }
1956
1957 /*
1958 * ":let [v1, v2] = list" or ":for [v1, v2] in listlist"
1959 */
Bram Moolenaar758711c2005-02-02 23:11:38 +00001960 if (tv->v_type != VAR_LIST || (l = tv->vval.v_list) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001961 {
1962 EMSG(_(e_listreq));
1963 return FAIL;
1964 }
1965
1966 i = list_len(l);
1967 if (semicolon == 0 && var_count < i)
1968 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00001969 EMSG(_("E687: Less targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001970 return FAIL;
1971 }
1972 if (var_count - semicolon > i)
1973 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00001974 EMSG(_("E688: More targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001975 return FAIL;
1976 }
1977
1978 item = l->lv_first;
1979 while (*arg != ']')
1980 {
1981 arg = skipwhite(arg + 1);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001982 arg = ex_let_one(arg, &item->li_tv, TRUE, (char_u *)",;]", nextchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001983 item = item->li_next;
1984 if (arg == NULL)
1985 return FAIL;
1986
1987 arg = skipwhite(arg);
1988 if (*arg == ';')
1989 {
1990 /* Put the rest of the list (may be empty) in the var after ';'.
1991 * Create a new list for this. */
1992 l = list_alloc();
1993 if (l == NULL)
1994 return FAIL;
1995 while (item != NULL)
1996 {
1997 list_append_tv(l, &item->li_tv);
1998 item = item->li_next;
1999 }
2000
2001 ltv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002002 ltv.v_lock = 0;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002003 ltv.vval.v_list = l;
2004 l->lv_refcount = 1;
2005
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002006 arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE,
2007 (char_u *)"]", nextchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002008 clear_tv(&ltv);
2009 if (arg == NULL)
2010 return FAIL;
2011 break;
2012 }
2013 else if (*arg != ',' && *arg != ']')
2014 {
2015 EMSG2(_(e_intern2), "ex_let_vars()");
2016 return FAIL;
2017 }
2018 }
2019
2020 return OK;
2021}
2022
2023/*
2024 * Skip over assignable variable "var" or list of variables "[var, var]".
2025 * Used for ":let varvar = expr" and ":for varvar in expr".
2026 * For "[var, var]" increment "*var_count" for each variable.
2027 * for "[var, var; var]" set "semicolon".
2028 * Return NULL for an error.
2029 */
2030 static char_u *
2031skip_var_list(arg, var_count, semicolon)
2032 char_u *arg;
2033 int *var_count;
2034 int *semicolon;
2035{
2036 char_u *p, *s;
2037
2038 if (*arg == '[')
2039 {
2040 /* "[var, var]": find the matching ']'. */
2041 p = arg;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00002042 for (;;)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002043 {
2044 p = skipwhite(p + 1); /* skip whites after '[', ';' or ',' */
2045 s = skip_var_one(p);
2046 if (s == p)
2047 {
2048 EMSG2(_(e_invarg2), p);
2049 return NULL;
2050 }
2051 ++*var_count;
2052
2053 p = skipwhite(s);
2054 if (*p == ']')
2055 break;
2056 else if (*p == ';')
2057 {
2058 if (*semicolon == 1)
2059 {
2060 EMSG(_("Double ; in list of variables"));
2061 return NULL;
2062 }
2063 *semicolon = 1;
2064 }
2065 else if (*p != ',')
2066 {
2067 EMSG2(_(e_invarg2), p);
2068 return NULL;
2069 }
2070 }
2071 return p + 1;
2072 }
2073 else
2074 return skip_var_one(arg);
2075}
2076
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002077/*
Bram Moolenaarbae0c162007-05-10 19:30:25 +00002078 * Skip one (assignable) variable name, including @r, $VAR, &option, d.key,
Bram Moolenaar92124a32005-06-17 22:03:40 +00002079 * l[idx].
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002080 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002081 static char_u *
2082skip_var_one(arg)
2083 char_u *arg;
2084{
Bram Moolenaar92124a32005-06-17 22:03:40 +00002085 if (*arg == '@' && arg[1] != NUL)
2086 return arg + 2;
2087 return find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg,
2088 NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002089}
2090
Bram Moolenaara7043832005-01-21 11:56:39 +00002091/*
Bram Moolenaar33570922005-01-25 22:26:29 +00002092 * List variables for hashtab "ht" with prefix "prefix".
2093 * If "empty" is TRUE also list NULL strings as empty strings.
Bram Moolenaara7043832005-01-21 11:56:39 +00002094 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002095 static void
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002096list_hashtable_vars(ht, prefix, empty, first)
Bram Moolenaar33570922005-01-25 22:26:29 +00002097 hashtab_T *ht;
Bram Moolenaara7043832005-01-21 11:56:39 +00002098 char_u *prefix;
Bram Moolenaar33570922005-01-25 22:26:29 +00002099 int empty;
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002100 int *first;
Bram Moolenaara7043832005-01-21 11:56:39 +00002101{
Bram Moolenaar33570922005-01-25 22:26:29 +00002102 hashitem_T *hi;
2103 dictitem_T *di;
Bram Moolenaara7043832005-01-21 11:56:39 +00002104 int todo;
2105
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00002106 todo = (int)ht->ht_used;
Bram Moolenaara7043832005-01-21 11:56:39 +00002107 for (hi = ht->ht_array; todo > 0 && !got_int; ++hi)
2108 {
2109 if (!HASHITEM_EMPTY(hi))
2110 {
2111 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00002112 di = HI2DI(hi);
2113 if (empty || di->di_tv.v_type != VAR_STRING
2114 || di->di_tv.vval.v_string != NULL)
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002115 list_one_var(di, prefix, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00002116 }
2117 }
2118}
2119
2120/*
2121 * List global variables.
2122 */
2123 static void
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002124list_glob_vars(first)
2125 int *first;
Bram Moolenaara7043832005-01-21 11:56:39 +00002126{
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002127 list_hashtable_vars(&globvarht, (char_u *)"", TRUE, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00002128}
2129
2130/*
2131 * List buffer variables.
2132 */
2133 static void
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002134list_buf_vars(first)
2135 int *first;
Bram Moolenaara7043832005-01-21 11:56:39 +00002136{
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002137 char_u numbuf[NUMBUFLEN];
2138
Bram Moolenaar429fa852013-04-15 12:27:36 +02002139 list_hashtable_vars(&curbuf->b_vars->dv_hashtab, (char_u *)"b:",
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002140 TRUE, first);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002141
2142 sprintf((char *)numbuf, "%ld", (long)curbuf->b_changedtick);
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002143 list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER,
2144 numbuf, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00002145}
2146
2147/*
2148 * List window variables.
2149 */
2150 static void
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002151list_win_vars(first)
2152 int *first;
Bram Moolenaara7043832005-01-21 11:56:39 +00002153{
Bram Moolenaar429fa852013-04-15 12:27:36 +02002154 list_hashtable_vars(&curwin->w_vars->dv_hashtab,
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002155 (char_u *)"w:", TRUE, first);
Bram Moolenaara7043832005-01-21 11:56:39 +00002156}
2157
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002158#ifdef FEAT_WINDOWS
2159/*
2160 * List tab page variables.
2161 */
2162 static void
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002163list_tab_vars(first)
2164 int *first;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002165{
Bram Moolenaar429fa852013-04-15 12:27:36 +02002166 list_hashtable_vars(&curtab->tp_vars->dv_hashtab,
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002167 (char_u *)"t:", TRUE, first);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002168}
2169#endif
2170
Bram Moolenaara7043832005-01-21 11:56:39 +00002171/*
2172 * List Vim variables.
2173 */
2174 static void
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002175list_vim_vars(first)
2176 int *first;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002177{
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002178 list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE, first);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002179}
2180
2181/*
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00002182 * List script-local variables, if there is a script.
2183 */
2184 static void
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002185list_script_vars(first)
2186 int *first;
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00002187{
2188 if (current_SID > 0 && current_SID <= ga_scripts.ga_len)
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002189 list_hashtable_vars(&SCRIPT_VARS(current_SID),
2190 (char_u *)"s:", FALSE, first);
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00002191}
2192
2193/*
2194 * List function variables, if there is a function.
2195 */
2196 static void
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002197list_func_vars(first)
2198 int *first;
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00002199{
2200 if (current_funccal != NULL)
2201 list_hashtable_vars(&current_funccal->l_vars.dv_hashtab,
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002202 (char_u *)"l:", FALSE, first);
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00002203}
2204
2205/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002206 * List variables in "arg".
2207 */
2208 static char_u *
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002209list_arg_vars(eap, arg, first)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002210 exarg_T *eap;
2211 char_u *arg;
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002212 int *first;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002213{
2214 int error = FALSE;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002215 int len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002216 char_u *name;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002217 char_u *name_start;
2218 char_u *arg_subsc;
2219 char_u *tofree;
2220 typval_T tv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002221
2222 while (!ends_excmd(*arg) && !got_int)
2223 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002224 if (error || eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002225 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002226 arg = find_name_end(arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002227 if (!vim_iswhite(*arg) && !ends_excmd(*arg))
2228 {
2229 emsg_severe = TRUE;
2230 EMSG(_(e_trailing));
2231 break;
2232 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002233 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002234 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002235 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002236 /* get_name_len() takes care of expanding curly braces */
2237 name_start = name = arg;
2238 len = get_name_len(&arg, &tofree, TRUE, TRUE);
2239 if (len <= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002240 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002241 /* This is mainly to keep test 49 working: when expanding
2242 * curly braces fails overrule the exception error message. */
2243 if (len < 0 && !aborting())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002244 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002245 emsg_severe = TRUE;
2246 EMSG2(_(e_invarg2), arg);
2247 break;
2248 }
2249 error = TRUE;
2250 }
2251 else
2252 {
2253 if (tofree != NULL)
2254 name = tofree;
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002255 if (get_var_tv(name, len, &tv, TRUE, FALSE) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002256 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002257 else
2258 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002259 /* handle d.key, l[idx], f(expr) */
2260 arg_subsc = arg;
2261 if (handle_subscript(&arg, &tv, TRUE, TRUE) == FAIL)
Bram Moolenaara7043832005-01-21 11:56:39 +00002262 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002263 else
Bram Moolenaara7043832005-01-21 11:56:39 +00002264 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002265 if (arg == arg_subsc && len == 2 && name[1] == ':')
Bram Moolenaara7043832005-01-21 11:56:39 +00002266 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002267 switch (*name)
Bram Moolenaara7043832005-01-21 11:56:39 +00002268 {
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002269 case 'g': list_glob_vars(first); break;
2270 case 'b': list_buf_vars(first); break;
2271 case 'w': list_win_vars(first); break;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002272#ifdef FEAT_WINDOWS
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002273 case 't': list_tab_vars(first); break;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002274#endif
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002275 case 'v': list_vim_vars(first); break;
2276 case 's': list_script_vars(first); break;
2277 case 'l': list_func_vars(first); break;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002278 default:
2279 EMSG2(_("E738: Can't list variables for %s"), name);
Bram Moolenaara7043832005-01-21 11:56:39 +00002280 }
Bram Moolenaara7043832005-01-21 11:56:39 +00002281 }
2282 else
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002283 {
2284 char_u numbuf[NUMBUFLEN];
2285 char_u *tf;
2286 int c;
2287 char_u *s;
2288
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002289 s = echo_string(&tv, &tf, numbuf, 0);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002290 c = *arg;
2291 *arg = NUL;
2292 list_one_var_a((char_u *)"",
2293 arg == arg_subsc ? name : name_start,
Bram Moolenaar7d61a922007-08-30 09:12:23 +00002294 tv.v_type,
2295 s == NULL ? (char_u *)"" : s,
2296 first);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002297 *arg = c;
2298 vim_free(tf);
2299 }
2300 clear_tv(&tv);
Bram Moolenaara7043832005-01-21 11:56:39 +00002301 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002302 }
2303 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002304
2305 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002306 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002307
2308 arg = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002309 }
2310
2311 return arg;
2312}
2313
2314/*
2315 * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value.
2316 * Returns a pointer to the char just after the var name.
2317 * Returns NULL if there is an error.
2318 */
2319 static char_u *
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002320ex_let_one(arg, tv, copy, endchars, op)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002321 char_u *arg; /* points to variable name */
Bram Moolenaar33570922005-01-25 22:26:29 +00002322 typval_T *tv; /* value to assign to variable */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002323 int copy; /* copy value from "tv" */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002324 char_u *endchars; /* valid chars after variable name or NULL */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002325 char_u *op; /* "+", "-", "." or NULL*/
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002326{
2327 int c1;
2328 char_u *name;
2329 char_u *p;
2330 char_u *arg_end = NULL;
2331 int len;
2332 int opt_flags;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002333 char_u *tofree = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002334
2335 /*
2336 * ":let $VAR = expr": Set environment variable.
2337 */
2338 if (*arg == '$')
2339 {
2340 /* Find the end of the name. */
2341 ++arg;
2342 name = arg;
2343 len = get_env_len(&arg);
2344 if (len == 0)
2345 EMSG2(_(e_invarg2), name - 1);
2346 else
2347 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002348 if (op != NULL && (*op == '+' || *op == '-'))
2349 EMSG2(_(e_letwrong), op);
2350 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002351 && vim_strchr(endchars, *skipwhite(arg)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002352 EMSG(_(e_letunexp));
Bram Moolenaard4ddfaf2010-12-02 14:48:14 +01002353 else if (!check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002354 {
2355 c1 = name[len];
2356 name[len] = NUL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002357 p = get_tv_string_chk(tv);
2358 if (p != NULL && op != NULL && *op == '.')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002359 {
2360 int mustfree = FALSE;
2361 char_u *s = vim_getenv(name, &mustfree);
2362
2363 if (s != NULL)
2364 {
2365 p = tofree = concat_str(s, p);
2366 if (mustfree)
2367 vim_free(s);
2368 }
2369 }
2370 if (p != NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002371 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002372 vim_setenv(name, p);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002373 if (STRICMP(name, "HOME") == 0)
2374 init_homedir();
2375 else if (didset_vim && STRICMP(name, "VIM") == 0)
2376 didset_vim = FALSE;
2377 else if (didset_vimruntime
2378 && STRICMP(name, "VIMRUNTIME") == 0)
2379 didset_vimruntime = FALSE;
2380 arg_end = arg;
2381 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002382 name[len] = c1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002383 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002384 }
2385 }
2386 }
2387
2388 /*
2389 * ":let &option = expr": Set option value.
2390 * ":let &l:option = expr": Set local option value.
2391 * ":let &g:option = expr": Set global option value.
2392 */
2393 else if (*arg == '&')
2394 {
2395 /* Find the end of the name. */
2396 p = find_option_end(&arg, &opt_flags);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002397 if (p == NULL || (endchars != NULL
2398 && vim_strchr(endchars, *skipwhite(p)) == NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002399 EMSG(_(e_letunexp));
2400 else
2401 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002402 long n;
2403 int opt_type;
2404 long numval;
2405 char_u *stringval = NULL;
2406 char_u *s;
2407
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002408 c1 = *p;
2409 *p = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002410
2411 n = get_tv_number(tv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002412 s = get_tv_string_chk(tv); /* != NULL if number or string */
2413 if (s != NULL && op != NULL && *op != '=')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002414 {
2415 opt_type = get_option_value(arg, &numval,
2416 &stringval, opt_flags);
2417 if ((opt_type == 1 && *op == '.')
2418 || (opt_type == 0 && *op != '.'))
2419 EMSG2(_(e_letwrong), op);
2420 else
2421 {
2422 if (opt_type == 1) /* number */
2423 {
2424 if (*op == '+')
2425 n = numval + n;
2426 else
2427 n = numval - n;
2428 }
2429 else if (opt_type == 0 && stringval != NULL) /* string */
2430 {
2431 s = concat_str(stringval, s);
2432 vim_free(stringval);
2433 stringval = s;
2434 }
2435 }
2436 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002437 if (s != NULL)
2438 {
2439 set_option_value(arg, n, s, opt_flags);
2440 arg_end = p;
2441 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002442 *p = c1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002443 vim_free(stringval);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002444 }
2445 }
2446
2447 /*
2448 * ":let @r = expr": Set register contents.
2449 */
2450 else if (*arg == '@')
2451 {
2452 ++arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002453 if (op != NULL && (*op == '+' || *op == '-'))
2454 EMSG2(_(e_letwrong), op);
2455 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002456 && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002457 EMSG(_(e_letunexp));
2458 else
2459 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00002460 char_u *ptofree = NULL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002461 char_u *s;
2462
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002463 p = get_tv_string_chk(tv);
2464 if (p != NULL && op != NULL && *op == '.')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002465 {
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +02002466 s = get_reg_contents(*arg == '@' ? '"' : *arg, GREG_EXPR_SRC);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002467 if (s != NULL)
2468 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00002469 p = ptofree = concat_str(s, p);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002470 vim_free(s);
2471 }
2472 }
2473 if (p != NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002474 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002475 write_reg_contents(*arg == '@' ? '"' : *arg, p, -1, FALSE);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002476 arg_end = arg + 1;
2477 }
Bram Moolenaar89d40322006-08-29 15:30:07 +00002478 vim_free(ptofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002479 }
2480 }
2481
2482 /*
2483 * ":let var = expr": Set internal variable.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002484 * ":let {expr} = expr": Idem, name made with curly braces
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002485 */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002486 else if (eval_isnamec1(*arg) || *arg == '{')
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002487 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002488 lval_T lv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002489
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002490 p = get_lval(arg, tv, &lv, FALSE, FALSE, 0, FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002491 if (p != NULL && lv.ll_name != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002492 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002493 if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL)
2494 EMSG(_(e_letunexp));
2495 else
2496 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002497 set_var_lval(&lv, p, tv, copy, op);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002498 arg_end = p;
2499 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002500 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002501 clear_lval(&lv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002502 }
2503
2504 else
2505 EMSG2(_(e_invarg2), arg);
2506
2507 return arg_end;
2508}
2509
2510/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00002511 * If "arg" is equal to "b:changedtick" give an error and return TRUE.
2512 */
2513 static int
2514check_changedtick(arg)
2515 char_u *arg;
2516{
2517 if (STRNCMP(arg, "b:changedtick", 13) == 0 && !eval_isnamec(arg[13]))
2518 {
2519 EMSG2(_(e_readonlyvar), arg);
2520 return TRUE;
2521 }
2522 return FALSE;
2523}
2524
2525/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002526 * Get an lval: variable, Dict item or List item that can be assigned a value
2527 * to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]",
2528 * "name.key", "name.key[expr]" etc.
2529 * Indexing only works if "name" is an existing List or Dictionary.
2530 * "name" points to the start of the name.
2531 * If "rettv" is not NULL it points to the value to be assigned.
2532 * "unlet" is TRUE for ":unlet": slightly different behavior when something is
2533 * wrong; must end in space or cmd separator.
2534 *
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002535 * flags:
2536 * GLV_QUIET: do not give error messages
2537 * GLV_NO_AUTOLOAD: do not use script autoloading
2538 *
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002539 * Returns a pointer to just after the name, including indexes.
Bram Moolenaara7043832005-01-21 11:56:39 +00002540 * When an evaluation error occurs "lp->ll_name" is NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002541 * Returns NULL for a parsing error. Still need to free items in "lp"!
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002542 */
2543 static char_u *
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002544get_lval(name, rettv, lp, unlet, skip, flags, fne_flags)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002545 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +00002546 typval_T *rettv;
2547 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002548 int unlet;
2549 int skip;
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002550 int flags; /* GLV_ values */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002551 int fne_flags; /* flags for find_name_end() */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002552{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002553 char_u *p;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002554 char_u *expr_start, *expr_end;
2555 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00002556 dictitem_T *v;
2557 typval_T var1;
2558 typval_T var2;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002559 int empty1 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00002560 listitem_T *ni;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002561 char_u *key = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002562 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +00002563 hashtab_T *ht;
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002564 int quiet = flags & GLV_QUIET;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002565
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002566 /* Clear everything in "lp". */
Bram Moolenaar33570922005-01-25 22:26:29 +00002567 vim_memset(lp, 0, sizeof(lval_T));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002568
2569 if (skip)
2570 {
2571 /* When skipping just find the end of the name. */
2572 lp->ll_name = name;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002573 return find_name_end(name, NULL, NULL, FNE_INCL_BR | fne_flags);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002574 }
2575
2576 /* Find the end of the name. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002577 p = find_name_end(name, &expr_start, &expr_end, fne_flags);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002578 if (expr_start != NULL)
2579 {
2580 /* Don't expand the name when we already know there is an error. */
2581 if (unlet && !vim_iswhite(*p) && !ends_excmd(*p)
2582 && *p != '[' && *p != '.')
2583 {
2584 EMSG(_(e_trailing));
2585 return NULL;
2586 }
2587
2588 lp->ll_exp_name = make_expanded_name(name, expr_start, expr_end, p);
2589 if (lp->ll_exp_name == NULL)
2590 {
2591 /* Report an invalid expression in braces, unless the
2592 * expression evaluation has been cancelled due to an
2593 * aborting error, an interrupt, or an exception. */
2594 if (!aborting() && !quiet)
2595 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002596 emsg_severe = TRUE;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002597 EMSG2(_(e_invarg2), name);
2598 return NULL;
2599 }
2600 }
2601 lp->ll_name = lp->ll_exp_name;
2602 }
2603 else
2604 lp->ll_name = name;
2605
2606 /* Without [idx] or .key we are done. */
2607 if ((*p != '[' && *p != '.') || lp->ll_name == NULL)
2608 return p;
2609
2610 cc = *p;
2611 *p = NUL;
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002612 v = find_var(lp->ll_name, &ht, flags & GLV_NO_AUTOLOAD);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002613 if (v == NULL && !quiet)
2614 EMSG2(_(e_undefvar), lp->ll_name);
2615 *p = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002616 if (v == NULL)
2617 return NULL;
2618
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002619 /*
2620 * Loop until no more [idx] or .key is following.
2621 */
Bram Moolenaar33570922005-01-25 22:26:29 +00002622 lp->ll_tv = &v->di_tv;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002623 while (*p == '[' || (*p == '.' && lp->ll_tv->v_type == VAR_DICT))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002624 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002625 if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL)
2626 && !(lp->ll_tv->v_type == VAR_DICT
2627 && lp->ll_tv->vval.v_dict != NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002628 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002629 if (!quiet)
2630 EMSG(_("E689: Can only index a List or Dictionary"));
2631 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002632 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002633 if (lp->ll_range)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002634 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002635 if (!quiet)
2636 EMSG(_("E708: [:] must come last"));
2637 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002638 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002639
Bram Moolenaar8c711452005-01-14 21:53:12 +00002640 len = -1;
2641 if (*p == '.')
2642 {
2643 key = p + 1;
2644 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
2645 ;
2646 if (len == 0)
2647 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002648 if (!quiet)
2649 EMSG(_(e_emptykey));
2650 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002651 }
2652 p = key + len;
2653 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002654 else
2655 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002656 /* Get the index [expr] or the first index [expr: ]. */
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002657 p = skipwhite(p + 1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002658 if (*p == ':')
2659 empty1 = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002660 else
2661 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002662 empty1 = FALSE;
2663 if (eval1(&p, &var1, TRUE) == FAIL) /* recursive! */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002664 return NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002665 if (get_tv_string_chk(&var1) == NULL)
2666 {
2667 /* not a number or string */
2668 clear_tv(&var1);
2669 return NULL;
2670 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002671 }
2672
2673 /* Optionally get the second index [ :expr]. */
2674 if (*p == ':')
2675 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002676 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002677 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002678 if (!quiet)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002679 EMSG(_(e_dictrange));
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002680 if (!empty1)
2681 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002682 return NULL;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002683 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002684 if (rettv != NULL && (rettv->v_type != VAR_LIST
2685 || rettv->vval.v_list == NULL))
Bram Moolenaar8c711452005-01-14 21:53:12 +00002686 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002687 if (!quiet)
2688 EMSG(_("E709: [:] requires a List value"));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002689 if (!empty1)
2690 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002691 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002692 }
2693 p = skipwhite(p + 1);
2694 if (*p == ']')
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002695 lp->ll_empty2 = TRUE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002696 else
2697 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002698 lp->ll_empty2 = FALSE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002699 if (eval1(&p, &var2, TRUE) == FAIL) /* recursive! */
2700 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002701 if (!empty1)
2702 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002703 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002704 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002705 if (get_tv_string_chk(&var2) == NULL)
2706 {
2707 /* not a number or string */
2708 if (!empty1)
2709 clear_tv(&var1);
2710 clear_tv(&var2);
2711 return NULL;
2712 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002713 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002714 lp->ll_range = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002715 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002716 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002717 lp->ll_range = FALSE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002718
Bram Moolenaar8c711452005-01-14 21:53:12 +00002719 if (*p != ']')
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002720 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002721 if (!quiet)
2722 EMSG(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002723 if (!empty1)
2724 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002725 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002726 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002727 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002728 }
2729
2730 /* Skip to past ']'. */
2731 ++p;
2732 }
2733
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002734 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002735 {
2736 if (len == -1)
2737 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002738 /* "[key]": get key from "var1" */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002739 key = get_tv_string(&var1); /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002740 if (*key == NUL)
2741 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002742 if (!quiet)
2743 EMSG(_(e_emptykey));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002744 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002745 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002746 }
2747 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002748 lp->ll_list = NULL;
2749 lp->ll_dict = lp->ll_tv->vval.v_dict;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002750 lp->ll_di = dict_find(lp->ll_dict, key, len);
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002751
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002752 /* When assigning to a scope dictionary check that a function and
2753 * variable name is valid (only variable name unless it is l: or
2754 * g: dictionary). Disallow overwriting a builtin function. */
2755 if (rettv != NULL && lp->ll_dict->dv_scope != 0)
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002756 {
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002757 int prevval;
2758 int wrong;
2759
2760 if (len != -1)
2761 {
2762 prevval = key[len];
2763 key[len] = NUL;
2764 }
Bram Moolenaar4380d1e2013-06-09 20:51:00 +02002765 else
2766 prevval = 0; /* avoid compiler warning */
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002767 wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE
2768 && rettv->v_type == VAR_FUNC
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002769 && var_check_func_name(key, lp->ll_di == NULL))
Bram Moolenaarbdb62052012-07-16 17:31:53 +02002770 || !valid_varname(key);
2771 if (len != -1)
2772 key[len] = prevval;
2773 if (wrong)
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002774 return NULL;
2775 }
2776
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002777 if (lp->ll_di == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002778 {
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002779 /* Can't add "v:" variable. */
2780 if (lp->ll_dict == &vimvardict)
2781 {
2782 EMSG2(_(e_illvar), name);
2783 return NULL;
2784 }
2785
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002786 /* Key does not exist in dict: may need to add it. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002787 if (*p == '[' || *p == '.' || unlet)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002788 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002789 if (!quiet)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002790 EMSG2(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002791 if (len == -1)
2792 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002793 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002794 }
2795 if (len == -1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002796 lp->ll_newkey = vim_strsave(key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002797 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002798 lp->ll_newkey = vim_strnsave(key, len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002799 if (len == -1)
2800 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002801 if (lp->ll_newkey == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002802 p = NULL;
2803 break;
2804 }
Bram Moolenaar4228bec2011-03-27 16:03:15 +02002805 /* existing variable, need to check if it can be changed */
2806 else if (var_check_ro(lp->ll_di->di_flags, name))
2807 return NULL;
2808
Bram Moolenaar8c711452005-01-14 21:53:12 +00002809 if (len == -1)
2810 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002811 lp->ll_tv = &lp->ll_di->di_tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002812 }
2813 else
2814 {
2815 /*
2816 * Get the number and item for the only or first index of the List.
2817 */
2818 if (empty1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002819 lp->ll_n1 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002820 else
2821 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002822 lp->ll_n1 = get_tv_number(&var1); /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002823 clear_tv(&var1);
2824 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002825 lp->ll_dict = NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002826 lp->ll_list = lp->ll_tv->vval.v_list;
2827 lp->ll_li = list_find(lp->ll_list, lp->ll_n1);
2828 if (lp->ll_li == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002829 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00002830 if (lp->ll_n1 < 0)
2831 {
2832 lp->ll_n1 = 0;
2833 lp->ll_li = list_find(lp->ll_list, lp->ll_n1);
2834 }
2835 }
2836 if (lp->ll_li == NULL)
2837 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002838 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002839 clear_tv(&var2);
Bram Moolenaare9623882011-04-21 14:27:28 +02002840 if (!quiet)
2841 EMSGN(_(e_listidx), lp->ll_n1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002842 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002843 }
2844
2845 /*
2846 * May need to find the item or absolute index for the second
2847 * index of a range.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002848 * When no index given: "lp->ll_empty2" is TRUE.
2849 * Otherwise "lp->ll_n2" is set to the second index.
Bram Moolenaar8c711452005-01-14 21:53:12 +00002850 */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002851 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002852 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002853 lp->ll_n2 = get_tv_number(&var2); /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002854 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002855 if (lp->ll_n2 < 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002856 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002857 ni = list_find(lp->ll_list, lp->ll_n2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002858 if (ni == NULL)
Bram Moolenaare9623882011-04-21 14:27:28 +02002859 {
2860 if (!quiet)
2861 EMSGN(_(e_listidx), lp->ll_n2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002862 return NULL;
Bram Moolenaare9623882011-04-21 14:27:28 +02002863 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002864 lp->ll_n2 = list_idx_of_item(lp->ll_list, ni);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002865 }
2866
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002867 /* Check that lp->ll_n2 isn't before lp->ll_n1. */
2868 if (lp->ll_n1 < 0)
2869 lp->ll_n1 = list_idx_of_item(lp->ll_list, lp->ll_li);
2870 if (lp->ll_n2 < lp->ll_n1)
Bram Moolenaare9623882011-04-21 14:27:28 +02002871 {
2872 if (!quiet)
2873 EMSGN(_(e_listidx), lp->ll_n2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002874 return NULL;
Bram Moolenaare9623882011-04-21 14:27:28 +02002875 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002876 }
2877
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002878 lp->ll_tv = &lp->ll_li->li_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002879 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002880 }
2881
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002882 return p;
2883}
2884
2885/*
Bram Moolenaar33570922005-01-25 22:26:29 +00002886 * Clear lval "lp" that was filled by get_lval().
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002887 */
2888 static void
2889clear_lval(lp)
Bram Moolenaar33570922005-01-25 22:26:29 +00002890 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002891{
2892 vim_free(lp->ll_exp_name);
2893 vim_free(lp->ll_newkey);
2894}
2895
2896/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002897 * Set a variable that was parsed by get_lval() to "rettv".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002898 * "endp" points to just after the parsed name.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002899 * "op" is NULL, "+" for "+=", "-" for "-=", "." for ".=" or "=" for "=".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002900 */
2901 static void
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002902set_var_lval(lp, endp, rettv, copy, op)
Bram Moolenaar33570922005-01-25 22:26:29 +00002903 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002904 char_u *endp;
Bram Moolenaar33570922005-01-25 22:26:29 +00002905 typval_T *rettv;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002906 int copy;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002907 char_u *op;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002908{
2909 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00002910 listitem_T *ri;
2911 dictitem_T *di;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002912
2913 if (lp->ll_tv == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002914 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002915 if (!check_changedtick(lp->ll_name))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002916 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002917 cc = *endp;
2918 *endp = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002919 if (op != NULL && *op != '=')
2920 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002921 typval_T tv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002922
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002923 /* handle +=, -= and .= */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00002924 if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
Bram Moolenaar6d977d62014-01-14 15:24:39 +01002925 &tv, TRUE, FALSE) == OK)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002926 {
2927 if (tv_op(&tv, rettv, op) == OK)
2928 set_var(lp->ll_name, &tv, FALSE);
2929 clear_tv(&tv);
2930 }
2931 }
2932 else
2933 set_var(lp->ll_name, rettv, copy);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002934 *endp = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002935 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002936 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002937 else if (tv_check_lock(lp->ll_newkey == NULL
2938 ? lp->ll_tv->v_lock
2939 : lp->ll_tv->vval.v_dict->dv_lock, lp->ll_name))
2940 ;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002941 else if (lp->ll_range)
2942 {
2943 /*
2944 * Assign the List values to the list items.
2945 */
2946 for (ri = rettv->vval.v_list->lv_first; ri != NULL; )
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002947 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002948 if (op != NULL && *op != '=')
2949 tv_op(&lp->ll_li->li_tv, &ri->li_tv, op);
2950 else
2951 {
2952 clear_tv(&lp->ll_li->li_tv);
2953 copy_tv(&ri->li_tv, &lp->ll_li->li_tv);
2954 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002955 ri = ri->li_next;
2956 if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == lp->ll_n1))
2957 break;
2958 if (lp->ll_li->li_next == NULL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002959 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002960 /* Need to add an empty item. */
Bram Moolenaar4463f292005-09-25 22:20:24 +00002961 if (list_append_number(lp->ll_list, 0) == FAIL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002962 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002963 ri = NULL;
2964 break;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002965 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002966 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002967 lp->ll_li = lp->ll_li->li_next;
2968 ++lp->ll_n1;
2969 }
2970 if (ri != NULL)
2971 EMSG(_("E710: List value has more items than target"));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002972 else if (lp->ll_empty2
2973 ? (lp->ll_li != NULL && lp->ll_li->li_next != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002974 : lp->ll_n1 != lp->ll_n2)
2975 EMSG(_("E711: List value has not enough items"));
2976 }
2977 else
2978 {
2979 /*
2980 * Assign to a List or Dictionary item.
2981 */
2982 if (lp->ll_newkey != NULL)
2983 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002984 if (op != NULL && *op != '=')
2985 {
2986 EMSG2(_(e_letwrong), op);
2987 return;
2988 }
2989
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002990 /* Need to add an item to the Dictionary. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002991 di = dictitem_alloc(lp->ll_newkey);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002992 if (di == NULL)
2993 return;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002994 if (dict_add(lp->ll_tv->vval.v_dict, di) == FAIL)
2995 {
2996 vim_free(di);
2997 return;
2998 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002999 lp->ll_tv = &di->di_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00003000 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003001 else if (op != NULL && *op != '=')
3002 {
3003 tv_op(lp->ll_tv, rettv, op);
3004 return;
3005 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003006 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003007 clear_tv(lp->ll_tv);
Bram Moolenaar8c711452005-01-14 21:53:12 +00003008
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003009 /*
3010 * Assign the value to the variable or list item.
3011 */
3012 if (copy)
3013 copy_tv(rettv, lp->ll_tv);
3014 else
3015 {
3016 *lp->ll_tv = *rettv;
Bram Moolenaar758711c2005-02-02 23:11:38 +00003017 lp->ll_tv->v_lock = 0;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003018 init_tv(rettv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003019 }
3020 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003021}
3022
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003023/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003024 * Handle "tv1 += tv2", "tv1 -= tv2" and "tv1 .= tv2"
3025 * Returns OK or FAIL.
3026 */
3027 static int
3028tv_op(tv1, tv2, op)
Bram Moolenaar33570922005-01-25 22:26:29 +00003029 typval_T *tv1;
3030 typval_T *tv2;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003031 char_u *op;
3032{
3033 long n;
3034 char_u numbuf[NUMBUFLEN];
3035 char_u *s;
3036
3037 /* Can't do anything with a Funcref or a Dict on the right. */
3038 if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT)
3039 {
3040 switch (tv1->v_type)
3041 {
3042 case VAR_DICT:
3043 case VAR_FUNC:
3044 break;
3045
3046 case VAR_LIST:
3047 if (*op != '+' || tv2->v_type != VAR_LIST)
3048 break;
3049 /* List += List */
3050 if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL)
3051 list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL);
3052 return OK;
3053
3054 case VAR_NUMBER:
3055 case VAR_STRING:
3056 if (tv2->v_type == VAR_LIST)
3057 break;
3058 if (*op == '+' || *op == '-')
3059 {
3060 /* nr += nr or nr -= nr*/
3061 n = get_tv_number(tv1);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003062#ifdef FEAT_FLOAT
3063 if (tv2->v_type == VAR_FLOAT)
3064 {
3065 float_T f = n;
3066
3067 if (*op == '+')
3068 f += tv2->vval.v_float;
3069 else
3070 f -= tv2->vval.v_float;
3071 clear_tv(tv1);
3072 tv1->v_type = VAR_FLOAT;
3073 tv1->vval.v_float = f;
3074 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003075 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003076#endif
3077 {
3078 if (*op == '+')
3079 n += get_tv_number(tv2);
3080 else
3081 n -= get_tv_number(tv2);
3082 clear_tv(tv1);
3083 tv1->v_type = VAR_NUMBER;
3084 tv1->vval.v_number = n;
3085 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003086 }
3087 else
3088 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003089 if (tv2->v_type == VAR_FLOAT)
3090 break;
3091
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003092 /* str .= str */
3093 s = get_tv_string(tv1);
3094 s = concat_str(s, get_tv_string_buf(tv2, numbuf));
3095 clear_tv(tv1);
3096 tv1->v_type = VAR_STRING;
3097 tv1->vval.v_string = s;
3098 }
3099 return OK;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003100
3101#ifdef FEAT_FLOAT
3102 case VAR_FLOAT:
3103 {
3104 float_T f;
3105
3106 if (*op == '.' || (tv2->v_type != VAR_FLOAT
3107 && tv2->v_type != VAR_NUMBER
3108 && tv2->v_type != VAR_STRING))
3109 break;
3110 if (tv2->v_type == VAR_FLOAT)
3111 f = tv2->vval.v_float;
3112 else
3113 f = get_tv_number(tv2);
3114 if (*op == '+')
3115 tv1->vval.v_float += f;
3116 else
3117 tv1->vval.v_float -= f;
3118 }
3119 return OK;
3120#endif
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003121 }
3122 }
3123
3124 EMSG2(_(e_letwrong), op);
3125 return FAIL;
3126}
3127
3128/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003129 * Add a watcher to a list.
3130 */
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003131 void
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003132list_add_watch(l, lw)
Bram Moolenaar33570922005-01-25 22:26:29 +00003133 list_T *l;
3134 listwatch_T *lw;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003135{
3136 lw->lw_next = l->lv_watch;
3137 l->lv_watch = lw;
3138}
3139
3140/*
Bram Moolenaar758711c2005-02-02 23:11:38 +00003141 * Remove a watcher from a list.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003142 * No warning when it isn't found...
3143 */
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003144 void
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003145list_rem_watch(l, lwrem)
Bram Moolenaar33570922005-01-25 22:26:29 +00003146 list_T *l;
3147 listwatch_T *lwrem;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003148{
Bram Moolenaar33570922005-01-25 22:26:29 +00003149 listwatch_T *lw, **lwp;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003150
3151 lwp = &l->lv_watch;
3152 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
3153 {
3154 if (lw == lwrem)
3155 {
3156 *lwp = lw->lw_next;
3157 break;
3158 }
3159 lwp = &lw->lw_next;
3160 }
3161}
3162
3163/*
3164 * Just before removing an item from a list: advance watchers to the next
3165 * item.
3166 */
3167 static void
3168list_fix_watch(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00003169 list_T *l;
3170 listitem_T *item;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003171{
Bram Moolenaar33570922005-01-25 22:26:29 +00003172 listwatch_T *lw;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003173
3174 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
3175 if (lw->lw_item == item)
3176 lw->lw_item = item->li_next;
3177}
3178
3179/*
3180 * Evaluate the expression used in a ":for var in expr" command.
3181 * "arg" points to "var".
3182 * Set "*errp" to TRUE for an error, FALSE otherwise;
3183 * Return a pointer that holds the info. Null when there is an error.
3184 */
3185 void *
3186eval_for_line(arg, errp, nextcmdp, skip)
3187 char_u *arg;
3188 int *errp;
3189 char_u **nextcmdp;
3190 int skip;
3191{
Bram Moolenaar33570922005-01-25 22:26:29 +00003192 forinfo_T *fi;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003193 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +00003194 typval_T tv;
3195 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003196
3197 *errp = TRUE; /* default: there is an error */
3198
Bram Moolenaar33570922005-01-25 22:26:29 +00003199 fi = (forinfo_T *)alloc_clear(sizeof(forinfo_T));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003200 if (fi == NULL)
3201 return NULL;
3202
3203 expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
3204 if (expr == NULL)
3205 return fi;
3206
3207 expr = skipwhite(expr);
3208 if (expr[0] != 'i' || expr[1] != 'n' || !vim_iswhite(expr[2]))
3209 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003210 EMSG(_("E690: Missing \"in\" after :for"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003211 return fi;
3212 }
3213
3214 if (skip)
3215 ++emsg_skip;
3216 if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK)
3217 {
3218 *errp = FALSE;
3219 if (!skip)
3220 {
3221 l = tv.vval.v_list;
3222 if (tv.v_type != VAR_LIST || l == NULL)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00003223 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003224 EMSG(_(e_listreq));
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00003225 clear_tv(&tv);
3226 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003227 else
3228 {
Bram Moolenaar7bb4c6e2005-09-07 21:22:27 +00003229 /* No need to increment the refcount, it's already set for the
3230 * list being used in "tv". */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003231 fi->fi_list = l;
3232 list_add_watch(l, &fi->fi_lw);
3233 fi->fi_lw.lw_item = l->lv_first;
3234 }
3235 }
3236 }
3237 if (skip)
3238 --emsg_skip;
3239
3240 return fi;
3241}
3242
3243/*
3244 * Use the first item in a ":for" list. Advance to the next.
3245 * Assign the values to the variable (list). "arg" points to the first one.
3246 * Return TRUE when a valid item was found, FALSE when at end of list or
3247 * something wrong.
3248 */
3249 int
3250next_for_item(fi_void, arg)
3251 void *fi_void;
3252 char_u *arg;
3253{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003254 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003255 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00003256 listitem_T *item;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003257
3258 item = fi->fi_lw.lw_item;
3259 if (item == NULL)
3260 result = FALSE;
3261 else
3262 {
3263 fi->fi_lw.lw_item = item->li_next;
3264 result = (ex_let_vars(arg, &item->li_tv, TRUE,
3265 fi->fi_semicolon, fi->fi_varcount, NULL) == OK);
3266 }
3267 return result;
3268}
3269
3270/*
3271 * Free the structure used to store info used by ":for".
3272 */
3273 void
3274free_for_info(fi_void)
3275 void *fi_void;
3276{
Bram Moolenaar33570922005-01-25 22:26:29 +00003277 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003278
Bram Moolenaarab7013c2005-01-09 21:23:56 +00003279 if (fi != NULL && fi->fi_list != NULL)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00003280 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003281 list_rem_watch(fi->fi_list, &fi->fi_lw);
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00003282 list_unref(fi->fi_list);
3283 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003284 vim_free(fi);
3285}
3286
Bram Moolenaar071d4272004-06-13 20:20:40 +00003287#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
3288
3289 void
3290set_context_for_expression(xp, arg, cmdidx)
3291 expand_T *xp;
3292 char_u *arg;
3293 cmdidx_T cmdidx;
3294{
3295 int got_eq = FALSE;
3296 int c;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003297 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003298
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003299 if (cmdidx == CMD_let)
3300 {
3301 xp->xp_context = EXPAND_USER_VARS;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00003302 if (vim_strpbrk(arg, (char_u *)"\"'+-*/%.=!?~|&$([<>,#") == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003303 {
3304 /* ":let var1 var2 ...": find last space. */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00003305 for (p = arg + STRLEN(arg); p >= arg; )
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003306 {
3307 xp->xp_pattern = p;
Bram Moolenaar33570922005-01-25 22:26:29 +00003308 mb_ptr_back(arg, p);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003309 if (vim_iswhite(*p))
3310 break;
3311 }
3312 return;
3313 }
3314 }
3315 else
3316 xp->xp_context = cmdidx == CMD_call ? EXPAND_FUNCTIONS
3317 : EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003318 while ((xp->xp_pattern = vim_strpbrk(arg,
3319 (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL)
3320 {
3321 c = *xp->xp_pattern;
3322 if (c == '&')
3323 {
3324 c = xp->xp_pattern[1];
3325 if (c == '&')
3326 {
3327 ++xp->xp_pattern;
3328 xp->xp_context = cmdidx != CMD_let || got_eq
3329 ? EXPAND_EXPRESSION : EXPAND_NOTHING;
3330 }
3331 else if (c != ' ')
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00003332 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00003333 xp->xp_context = EXPAND_SETTINGS;
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00003334 if ((c == 'l' || c == 'g') && xp->xp_pattern[2] == ':')
3335 xp->xp_pattern += 2;
3336
3337 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003338 }
3339 else if (c == '$')
3340 {
3341 /* environment variable */
3342 xp->xp_context = EXPAND_ENV_VARS;
3343 }
3344 else if (c == '=')
3345 {
3346 got_eq = TRUE;
3347 xp->xp_context = EXPAND_EXPRESSION;
3348 }
3349 else if (c == '<'
3350 && xp->xp_context == EXPAND_FUNCTIONS
3351 && vim_strchr(xp->xp_pattern, '(') == NULL)
3352 {
3353 /* Function name can start with "<SNR>" */
3354 break;
3355 }
3356 else if (cmdidx != CMD_let || got_eq)
3357 {
3358 if (c == '"') /* string */
3359 {
3360 while ((c = *++xp->xp_pattern) != NUL && c != '"')
3361 if (c == '\\' && xp->xp_pattern[1] != NUL)
3362 ++xp->xp_pattern;
3363 xp->xp_context = EXPAND_NOTHING;
3364 }
3365 else if (c == '\'') /* literal string */
3366 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00003367 /* Trick: '' is like stopping and starting a literal string. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003368 while ((c = *++xp->xp_pattern) != NUL && c != '\'')
3369 /* skip */ ;
3370 xp->xp_context = EXPAND_NOTHING;
3371 }
3372 else if (c == '|')
3373 {
3374 if (xp->xp_pattern[1] == '|')
3375 {
3376 ++xp->xp_pattern;
3377 xp->xp_context = EXPAND_EXPRESSION;
3378 }
3379 else
3380 xp->xp_context = EXPAND_COMMANDS;
3381 }
3382 else
3383 xp->xp_context = EXPAND_EXPRESSION;
3384 }
3385 else
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003386 /* Doesn't look like something valid, expand as an expression
3387 * anyway. */
3388 xp->xp_context = EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003389 arg = xp->xp_pattern;
3390 if (*arg != NUL)
3391 while ((c = *++arg) != NUL && (c == ' ' || c == '\t'))
3392 /* skip */ ;
3393 }
3394 xp->xp_pattern = arg;
3395}
3396
3397#endif /* FEAT_CMDL_COMPL */
3398
3399/*
3400 * ":1,25call func(arg1, arg2)" function call.
3401 */
3402 void
3403ex_call(eap)
3404 exarg_T *eap;
3405{
3406 char_u *arg = eap->arg;
3407 char_u *startarg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003408 char_u *name;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003409 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003410 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +00003411 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003412 linenr_T lnum;
3413 int doesrange;
3414 int failed = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00003415 funcdict_T fudi;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003416
Bram Moolenaar6d0efda2011-01-04 19:03:27 +01003417 if (eap->skip)
3418 {
3419 /* trans_function_name() doesn't work well when skipping, use eval0()
3420 * instead to skip to any following command, e.g. for:
3421 * :if 0 | call dict.foo().bar() | endif */
Bram Moolenaar25091292011-09-30 18:35:57 +02003422 ++emsg_skip;
3423 if (eval0(eap->arg, &rettv, &eap->nextcmd, FALSE) != FAIL)
3424 clear_tv(&rettv);
3425 --emsg_skip;
Bram Moolenaar6d0efda2011-01-04 19:03:27 +01003426 return;
3427 }
3428
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003429 tofree = trans_function_name(&arg, eap->skip, TFN_INT, &fudi);
Bram Moolenaara2a31752006-10-24 11:49:25 +00003430 if (fudi.fd_newkey != NULL)
3431 {
3432 /* Still need to give an error message for missing key. */
3433 EMSG2(_(e_dictkey), fudi.fd_newkey);
3434 vim_free(fudi.fd_newkey);
3435 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003436 if (tofree == NULL)
3437 return;
3438
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003439 /* Increase refcount on dictionary, it could get deleted when evaluating
3440 * the arguments. */
3441 if (fudi.fd_dict != NULL)
3442 ++fudi.fd_dict->dv_refcount;
3443
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003444 /* If it is the name of a variable of type VAR_FUNC use its contents. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003445 len = (int)STRLEN(tofree);
Bram Moolenaar8822a9c2014-01-14 19:44:34 +01003446 name = deref_func_name(tofree, &len, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003447
Bram Moolenaar532c7802005-01-27 14:44:31 +00003448 /* Skip white space to allow ":call func ()". Not good, but required for
3449 * backward compatibility. */
3450 startarg = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003451 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003452
3453 if (*startarg != '(')
3454 {
Bram Moolenaar8dd9ac52008-11-06 10:05:42 +00003455 EMSG2(_("E107: Missing parentheses: %s"), eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003456 goto end;
3457 }
3458
3459 /*
3460 * When skipping, evaluate the function once, to find the end of the
3461 * arguments.
3462 * When the function takes a range, this is discovered after the first
3463 * call, and the loop is broken.
3464 */
3465 if (eap->skip)
3466 {
3467 ++emsg_skip;
3468 lnum = eap->line2; /* do it once, also with an invalid range */
3469 }
3470 else
3471 lnum = eap->line1;
3472 for ( ; lnum <= eap->line2; ++lnum)
3473 {
3474 if (!eap->skip && eap->addr_count > 0)
3475 {
3476 curwin->w_cursor.lnum = lnum;
3477 curwin->w_cursor.col = 0;
Bram Moolenaar0acc5612011-07-15 21:24:11 +02003478#ifdef FEAT_VIRTUALEDIT
3479 curwin->w_cursor.coladd = 0;
3480#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003481 }
3482 arg = startarg;
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003483 if (get_func_tv(name, (int)STRLEN(name), &rettv, &arg,
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003484 eap->line1, eap->line2, &doesrange,
3485 !eap->skip, fudi.fd_dict) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003486 {
3487 failed = TRUE;
3488 break;
3489 }
Bram Moolenaarf2789872006-11-28 19:54:04 +00003490
3491 /* Handle a function returning a Funcref, Dictionary or List. */
3492 if (handle_subscript(&arg, &rettv, !eap->skip, TRUE) == FAIL)
3493 {
3494 failed = TRUE;
3495 break;
3496 }
3497
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003498 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003499 if (doesrange || eap->skip)
3500 break;
Bram Moolenaarf2789872006-11-28 19:54:04 +00003501
Bram Moolenaar071d4272004-06-13 20:20:40 +00003502 /* Stop when immediately aborting on error, or when an interrupt
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003503 * occurred or an exception was thrown but not caught.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003504 * get_func_tv() returned OK, so that the check for trailing
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003505 * characters below is executed. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003506 if (aborting())
3507 break;
3508 }
3509 if (eap->skip)
3510 --emsg_skip;
3511
3512 if (!failed)
3513 {
3514 /* Check for trailing illegal characters and a following command. */
3515 if (!ends_excmd(*arg))
3516 {
3517 emsg_severe = TRUE;
3518 EMSG(_(e_trailing));
3519 }
3520 else
3521 eap->nextcmd = check_nextcmd(arg);
3522 }
3523
3524end:
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003525 dict_unref(fudi.fd_dict);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003526 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003527}
3528
3529/*
3530 * ":unlet[!] var1 ... " command.
3531 */
3532 void
3533ex_unlet(eap)
3534 exarg_T *eap;
3535{
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003536 ex_unletlock(eap, eap->arg, 0);
3537}
3538
3539/*
3540 * ":lockvar" and ":unlockvar" commands
3541 */
3542 void
3543ex_lockvar(eap)
3544 exarg_T *eap;
3545{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003546 char_u *arg = eap->arg;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003547 int deep = 2;
3548
3549 if (eap->forceit)
3550 deep = -1;
3551 else if (vim_isdigit(*arg))
3552 {
3553 deep = getdigits(&arg);
3554 arg = skipwhite(arg);
3555 }
3556
3557 ex_unletlock(eap, arg, deep);
3558}
3559
3560/*
3561 * ":unlet", ":lockvar" and ":unlockvar" are quite similar.
3562 */
3563 static void
3564ex_unletlock(eap, argstart, deep)
3565 exarg_T *eap;
3566 char_u *argstart;
3567 int deep;
3568{
3569 char_u *arg = argstart;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003570 char_u *name_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003571 int error = FALSE;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003572 lval_T lv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003573
3574 do
3575 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003576 /* Parse the name and find the end. */
Bram Moolenaar6d977d62014-01-14 15:24:39 +01003577 name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error, 0,
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00003578 FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003579 if (lv.ll_name == NULL)
3580 error = TRUE; /* error but continue parsing */
3581 if (name_end == NULL || (!vim_iswhite(*name_end)
3582 && !ends_excmd(*name_end)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003583 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003584 if (name_end != NULL)
3585 {
3586 emsg_severe = TRUE;
3587 EMSG(_(e_trailing));
3588 }
3589 if (!(eap->skip || error))
3590 clear_lval(&lv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003591 break;
3592 }
3593
3594 if (!error && !eap->skip)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003595 {
3596 if (eap->cmdidx == CMD_unlet)
3597 {
3598 if (do_unlet_var(&lv, name_end, eap->forceit) == FAIL)
3599 error = TRUE;
3600 }
3601 else
3602 {
3603 if (do_lock_var(&lv, name_end, deep,
3604 eap->cmdidx == CMD_lockvar) == FAIL)
3605 error = TRUE;
3606 }
3607 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003608
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003609 if (!eap->skip)
3610 clear_lval(&lv);
3611
Bram Moolenaar071d4272004-06-13 20:20:40 +00003612 arg = skipwhite(name_end);
3613 } while (!ends_excmd(*arg));
3614
3615 eap->nextcmd = check_nextcmd(arg);
3616}
3617
Bram Moolenaar8c711452005-01-14 21:53:12 +00003618 static int
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003619do_unlet_var(lp, name_end, forceit)
Bram Moolenaar33570922005-01-25 22:26:29 +00003620 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003621 char_u *name_end;
Bram Moolenaar8c711452005-01-14 21:53:12 +00003622 int forceit;
3623{
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003624 int ret = OK;
3625 int cc;
3626
3627 if (lp->ll_tv == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00003628 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003629 cc = *name_end;
3630 *name_end = NUL;
3631
3632 /* Normal name or expanded name. */
3633 if (check_changedtick(lp->ll_name))
3634 ret = FAIL;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003635 else if (do_unlet(lp->ll_name, forceit) == FAIL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003636 ret = FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003637 *name_end = cc;
Bram Moolenaar8c711452005-01-14 21:53:12 +00003638 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003639 else if (tv_check_lock(lp->ll_tv->v_lock, lp->ll_name))
3640 return FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003641 else if (lp->ll_range)
3642 {
Bram Moolenaar33570922005-01-25 22:26:29 +00003643 listitem_T *li;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003644
3645 /* Delete a range of List items. */
3646 while (lp->ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
3647 {
3648 li = lp->ll_li->li_next;
3649 listitem_remove(lp->ll_list, lp->ll_li);
3650 lp->ll_li = li;
3651 ++lp->ll_n1;
3652 }
3653 }
3654 else
3655 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003656 if (lp->ll_list != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003657 /* unlet a List item. */
3658 listitem_remove(lp->ll_list, lp->ll_li);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003659 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003660 /* unlet a Dictionary item. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003661 dictitem_remove(lp->ll_dict, lp->ll_di);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003662 }
3663
3664 return ret;
Bram Moolenaar8c711452005-01-14 21:53:12 +00003665}
3666
Bram Moolenaar071d4272004-06-13 20:20:40 +00003667/*
3668 * "unlet" a variable. Return OK if it existed, FAIL if not.
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003669 * When "forceit" is TRUE don't complain if the variable doesn't exist.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003670 */
3671 int
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003672do_unlet(name, forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003673 char_u *name;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003674 int forceit;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003675{
Bram Moolenaar33570922005-01-25 22:26:29 +00003676 hashtab_T *ht;
3677 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003678 char_u *varname;
Bram Moolenaarafbdeb82008-01-05 21:16:31 +00003679 dictitem_T *di;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003680
Bram Moolenaar33570922005-01-25 22:26:29 +00003681 ht = find_var_ht(name, &varname);
3682 if (ht != NULL && *varname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003683 {
Bram Moolenaar33570922005-01-25 22:26:29 +00003684 hi = hash_find(ht, varname);
3685 if (!HASHITEM_EMPTY(hi))
Bram Moolenaara7043832005-01-21 11:56:39 +00003686 {
Bram Moolenaarafbdeb82008-01-05 21:16:31 +00003687 di = HI2DI(hi);
3688 if (var_check_fixed(di->di_flags, name)
3689 || var_check_ro(di->di_flags, name))
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003690 return FAIL;
3691 delete_var(ht, hi);
3692 return OK;
Bram Moolenaara7043832005-01-21 11:56:39 +00003693 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003694 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003695 if (forceit)
3696 return OK;
3697 EMSG2(_("E108: No such variable: \"%s\""), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003698 return FAIL;
3699}
3700
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003701/*
3702 * Lock or unlock variable indicated by "lp".
3703 * "deep" is the levels to go (-1 for unlimited);
3704 * "lock" is TRUE for ":lockvar", FALSE for ":unlockvar".
3705 */
3706 static int
3707do_lock_var(lp, name_end, deep, lock)
3708 lval_T *lp;
3709 char_u *name_end;
3710 int deep;
3711 int lock;
3712{
3713 int ret = OK;
3714 int cc;
3715 dictitem_T *di;
3716
3717 if (deep == 0) /* nothing to do */
3718 return OK;
3719
3720 if (lp->ll_tv == NULL)
3721 {
3722 cc = *name_end;
3723 *name_end = NUL;
3724
3725 /* Normal name or expanded name. */
3726 if (check_changedtick(lp->ll_name))
3727 ret = FAIL;
3728 else
3729 {
Bram Moolenaar6d977d62014-01-14 15:24:39 +01003730 di = find_var(lp->ll_name, NULL, TRUE);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003731 if (di == NULL)
3732 ret = FAIL;
3733 else
3734 {
3735 if (lock)
3736 di->di_flags |= DI_FLAGS_LOCK;
3737 else
3738 di->di_flags &= ~DI_FLAGS_LOCK;
3739 item_lock(&di->di_tv, deep, lock);
3740 }
3741 }
3742 *name_end = cc;
3743 }
3744 else if (lp->ll_range)
3745 {
3746 listitem_T *li = lp->ll_li;
3747
3748 /* (un)lock a range of List items. */
3749 while (li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
3750 {
3751 item_lock(&li->li_tv, deep, lock);
3752 li = li->li_next;
3753 ++lp->ll_n1;
3754 }
3755 }
3756 else if (lp->ll_list != NULL)
3757 /* (un)lock a List item. */
3758 item_lock(&lp->ll_li->li_tv, deep, lock);
3759 else
3760 /* un(lock) a Dictionary item. */
3761 item_lock(&lp->ll_di->di_tv, deep, lock);
3762
3763 return ret;
3764}
3765
3766/*
3767 * Lock or unlock an item. "deep" is nr of levels to go.
3768 */
3769 static void
3770item_lock(tv, deep, lock)
3771 typval_T *tv;
3772 int deep;
3773 int lock;
3774{
3775 static int recurse = 0;
3776 list_T *l;
3777 listitem_T *li;
3778 dict_T *d;
3779 hashitem_T *hi;
3780 int todo;
3781
3782 if (recurse >= DICT_MAXNEST)
3783 {
3784 EMSG(_("E743: variable nested too deep for (un)lock"));
3785 return;
3786 }
3787 if (deep == 0)
3788 return;
3789 ++recurse;
3790
3791 /* lock/unlock the item itself */
3792 if (lock)
3793 tv->v_lock |= VAR_LOCKED;
3794 else
3795 tv->v_lock &= ~VAR_LOCKED;
3796
3797 switch (tv->v_type)
3798 {
3799 case VAR_LIST:
3800 if ((l = tv->vval.v_list) != NULL)
3801 {
3802 if (lock)
3803 l->lv_lock |= VAR_LOCKED;
3804 else
3805 l->lv_lock &= ~VAR_LOCKED;
3806 if (deep < 0 || deep > 1)
3807 /* recursive: lock/unlock the items the List contains */
3808 for (li = l->lv_first; li != NULL; li = li->li_next)
3809 item_lock(&li->li_tv, deep - 1, lock);
3810 }
3811 break;
3812 case VAR_DICT:
3813 if ((d = tv->vval.v_dict) != NULL)
3814 {
3815 if (lock)
3816 d->dv_lock |= VAR_LOCKED;
3817 else
3818 d->dv_lock &= ~VAR_LOCKED;
3819 if (deep < 0 || deep > 1)
3820 {
3821 /* recursive: lock/unlock the items the List contains */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003822 todo = (int)d->dv_hashtab.ht_used;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003823 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
3824 {
3825 if (!HASHITEM_EMPTY(hi))
3826 {
3827 --todo;
3828 item_lock(&HI2DI(hi)->di_tv, deep - 1, lock);
3829 }
3830 }
3831 }
3832 }
3833 }
3834 --recurse;
3835}
3836
Bram Moolenaara40058a2005-07-11 22:42:07 +00003837/*
Bram Moolenaar61c4e2c2008-08-25 02:49:18 +00003838 * Return TRUE if typeval "tv" is locked: Either that value is locked itself
3839 * or it refers to a List or Dictionary that is locked.
Bram Moolenaara40058a2005-07-11 22:42:07 +00003840 */
3841 static int
3842tv_islocked(tv)
3843 typval_T *tv;
3844{
3845 return (tv->v_lock & VAR_LOCKED)
3846 || (tv->v_type == VAR_LIST
3847 && tv->vval.v_list != NULL
3848 && (tv->vval.v_list->lv_lock & VAR_LOCKED))
3849 || (tv->v_type == VAR_DICT
3850 && tv->vval.v_dict != NULL
3851 && (tv->vval.v_dict->dv_lock & VAR_LOCKED));
3852}
3853
Bram Moolenaar071d4272004-06-13 20:20:40 +00003854#if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO)
3855/*
3856 * Delete all "menutrans_" variables.
3857 */
3858 void
3859del_menutrans_vars()
3860{
Bram Moolenaar33570922005-01-25 22:26:29 +00003861 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003862 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003863
Bram Moolenaar33570922005-01-25 22:26:29 +00003864 hash_lock(&globvarht);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003865 todo = (int)globvarht.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00003866 for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaara7043832005-01-21 11:56:39 +00003867 {
3868 if (!HASHITEM_EMPTY(hi))
3869 {
3870 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00003871 if (STRNCMP(HI2DI(hi)->di_key, "menutrans_", 10) == 0)
3872 delete_var(&globvarht, hi);
Bram Moolenaara7043832005-01-21 11:56:39 +00003873 }
3874 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003875 hash_unlock(&globvarht);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003876}
3877#endif
3878
3879#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
3880
3881/*
3882 * Local string buffer for the next two functions to store a variable name
3883 * with its prefix. Allocated in cat_prefix_varname(), freed later in
3884 * get_user_var_name().
3885 */
3886
3887static char_u *cat_prefix_varname __ARGS((int prefix, char_u *name));
3888
3889static char_u *varnamebuf = NULL;
3890static int varnamebuflen = 0;
3891
3892/*
3893 * Function to concatenate a prefix and a variable name.
3894 */
3895 static char_u *
3896cat_prefix_varname(prefix, name)
3897 int prefix;
3898 char_u *name;
3899{
3900 int len;
3901
3902 len = (int)STRLEN(name) + 3;
3903 if (len > varnamebuflen)
3904 {
3905 vim_free(varnamebuf);
3906 len += 10; /* some additional space */
3907 varnamebuf = alloc(len);
3908 if (varnamebuf == NULL)
3909 {
3910 varnamebuflen = 0;
3911 return NULL;
3912 }
3913 varnamebuflen = len;
3914 }
3915 *varnamebuf = prefix;
3916 varnamebuf[1] = ':';
3917 STRCPY(varnamebuf + 2, name);
3918 return varnamebuf;
3919}
3920
3921/*
3922 * Function given to ExpandGeneric() to obtain the list of user defined
3923 * (global/buffer/window/built-in) variable names.
3924 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003925 char_u *
3926get_user_var_name(xp, idx)
3927 expand_T *xp;
3928 int idx;
3929{
Bram Moolenaar532c7802005-01-27 14:44:31 +00003930 static long_u gdone;
3931 static long_u bdone;
3932 static long_u wdone;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003933#ifdef FEAT_WINDOWS
3934 static long_u tdone;
3935#endif
Bram Moolenaar532c7802005-01-27 14:44:31 +00003936 static int vidx;
3937 static hashitem_T *hi;
3938 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003939
3940 if (idx == 0)
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003941 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003942 gdone = bdone = wdone = vidx = 0;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003943#ifdef FEAT_WINDOWS
3944 tdone = 0;
3945#endif
3946 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003947
3948 /* Global variables */
3949 if (gdone < globvarht.ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003950 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003951 if (gdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003952 hi = globvarht.ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003953 else
3954 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003955 while (HASHITEM_EMPTY(hi))
3956 ++hi;
3957 if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
3958 return cat_prefix_varname('g', hi->hi_key);
3959 return hi->hi_key;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003960 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003961
3962 /* b: variables */
Bram Moolenaar429fa852013-04-15 12:27:36 +02003963 ht = &curbuf->b_vars->dv_hashtab;
Bram Moolenaar33570922005-01-25 22:26:29 +00003964 if (bdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003965 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003966 if (bdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003967 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003968 else
3969 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003970 while (HASHITEM_EMPTY(hi))
3971 ++hi;
3972 return cat_prefix_varname('b', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003973 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003974 if (bdone == ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003975 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003976 ++bdone;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003977 return (char_u *)"b:changedtick";
3978 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003979
3980 /* w: variables */
Bram Moolenaar429fa852013-04-15 12:27:36 +02003981 ht = &curwin->w_vars->dv_hashtab;
Bram Moolenaar33570922005-01-25 22:26:29 +00003982 if (wdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003983 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00003984 if (wdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003985 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003986 else
3987 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003988 while (HASHITEM_EMPTY(hi))
3989 ++hi;
3990 return cat_prefix_varname('w', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003991 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003992
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003993#ifdef FEAT_WINDOWS
3994 /* t: variables */
Bram Moolenaar429fa852013-04-15 12:27:36 +02003995 ht = &curtab->tp_vars->dv_hashtab;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003996 if (tdone < ht->ht_used)
3997 {
3998 if (tdone++ == 0)
3999 hi = ht->ht_array;
4000 else
4001 ++hi;
4002 while (HASHITEM_EMPTY(hi))
4003 ++hi;
4004 return cat_prefix_varname('t', hi->hi_key);
4005 }
4006#endif
4007
Bram Moolenaar33570922005-01-25 22:26:29 +00004008 /* v: variables */
4009 if (vidx < VV_LEN)
4010 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].vv_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004011
4012 vim_free(varnamebuf);
4013 varnamebuf = NULL;
4014 varnamebuflen = 0;
4015 return NULL;
4016}
4017
4018#endif /* FEAT_CMDL_COMPL */
4019
4020/*
4021 * types for expressions.
4022 */
4023typedef enum
4024{
4025 TYPE_UNKNOWN = 0
4026 , TYPE_EQUAL /* == */
4027 , TYPE_NEQUAL /* != */
4028 , TYPE_GREATER /* > */
4029 , TYPE_GEQUAL /* >= */
4030 , TYPE_SMALLER /* < */
4031 , TYPE_SEQUAL /* <= */
4032 , TYPE_MATCH /* =~ */
4033 , TYPE_NOMATCH /* !~ */
4034} exptype_T;
4035
4036/*
4037 * The "evaluate" argument: When FALSE, the argument is only parsed but not
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004038 * executed. The function may return OK, but the rettv will be of type
Bram Moolenaar071d4272004-06-13 20:20:40 +00004039 * VAR_UNKNOWN. The function still returns FAIL for a syntax error.
4040 */
4041
4042/*
4043 * Handle zero level expression.
4044 * This calls eval1() and handles error message and nextcmd.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004045 * Put the result in "rettv" when returning OK and "evaluate" is TRUE.
Bram Moolenaar4463f292005-09-25 22:20:24 +00004046 * Note: "rettv.v_lock" is not set.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004047 * Return OK or FAIL.
4048 */
4049 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004050eval0(arg, rettv, nextcmd, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004051 char_u *arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004052 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004053 char_u **nextcmd;
4054 int evaluate;
4055{
4056 int ret;
4057 char_u *p;
4058
4059 p = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004060 ret = eval1(&p, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004061 if (ret == FAIL || !ends_excmd(*p))
4062 {
4063 if (ret != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004064 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004065 /*
4066 * Report the invalid expression unless the expression evaluation has
4067 * been cancelled due to an aborting error, an interrupt, or an
4068 * exception.
4069 */
4070 if (!aborting())
4071 EMSG2(_(e_invexpr2), arg);
4072 ret = FAIL;
4073 }
4074 if (nextcmd != NULL)
4075 *nextcmd = check_nextcmd(p);
4076
4077 return ret;
4078}
4079
4080/*
4081 * Handle top level expression:
Bram Moolenaarb67cc162009-02-04 15:27:06 +00004082 * expr2 ? expr1 : expr1
Bram Moolenaar071d4272004-06-13 20:20:40 +00004083 *
4084 * "arg" must point to the first non-white of the expression.
4085 * "arg" is advanced to the next non-white after the recognized expression.
4086 *
Bram Moolenaar4463f292005-09-25 22:20:24 +00004087 * Note: "rettv.v_lock" is not set.
4088 *
Bram Moolenaar071d4272004-06-13 20:20:40 +00004089 * Return OK or FAIL.
4090 */
4091 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004092eval1(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004093 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004094 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004095 int evaluate;
4096{
4097 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00004098 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004099
4100 /*
4101 * Get the first variable.
4102 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004103 if (eval2(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004104 return FAIL;
4105
4106 if ((*arg)[0] == '?')
4107 {
4108 result = FALSE;
4109 if (evaluate)
4110 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004111 int error = FALSE;
4112
4113 if (get_tv_number_chk(rettv, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004114 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004115 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004116 if (error)
4117 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004118 }
4119
4120 /*
4121 * Get the second variable.
4122 */
4123 *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004124 if (eval1(arg, rettv, evaluate && result) == FAIL) /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004125 return FAIL;
4126
4127 /*
4128 * Check for the ":".
4129 */
4130 if ((*arg)[0] != ':')
4131 {
4132 EMSG(_("E109: Missing ':' after '?'"));
4133 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004134 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004135 return FAIL;
4136 }
4137
4138 /*
4139 * Get the third variable.
4140 */
4141 *arg = skipwhite(*arg + 1);
4142 if (eval1(arg, &var2, evaluate && !result) == FAIL) /* recursive! */
4143 {
4144 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004145 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004146 return FAIL;
4147 }
4148 if (evaluate && !result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004149 *rettv = var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004150 }
4151
4152 return OK;
4153}
4154
4155/*
4156 * Handle first level expression:
4157 * expr2 || expr2 || expr2 logical OR
4158 *
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 *
4162 * Return OK or FAIL.
4163 */
4164 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004165eval2(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004166 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004167 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004168 int evaluate;
4169{
Bram Moolenaar33570922005-01-25 22:26:29 +00004170 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004171 long result;
4172 int first;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004173 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004174
4175 /*
4176 * Get the first variable.
4177 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004178 if (eval3(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004179 return FAIL;
4180
4181 /*
4182 * Repeat until there is no following "||".
4183 */
4184 first = TRUE;
4185 result = FALSE;
4186 while ((*arg)[0] == '|' && (*arg)[1] == '|')
4187 {
4188 if (evaluate && first)
4189 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004190 if (get_tv_number_chk(rettv, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004191 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004192 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004193 if (error)
4194 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004195 first = FALSE;
4196 }
4197
4198 /*
4199 * Get the second variable.
4200 */
4201 *arg = skipwhite(*arg + 2);
4202 if (eval3(arg, &var2, evaluate && !result) == FAIL)
4203 return FAIL;
4204
4205 /*
4206 * Compute the result.
4207 */
4208 if (evaluate && !result)
4209 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004210 if (get_tv_number_chk(&var2, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004211 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004212 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004213 if (error)
4214 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004215 }
4216 if (evaluate)
4217 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004218 rettv->v_type = VAR_NUMBER;
4219 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004220 }
4221 }
4222
4223 return OK;
4224}
4225
4226/*
4227 * Handle second level expression:
4228 * expr3 && expr3 && expr3 logical AND
4229 *
4230 * "arg" must point to the first non-white of the expression.
4231 * "arg" is advanced to the next non-white after the recognized expression.
4232 *
4233 * Return OK or FAIL.
4234 */
4235 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004236eval3(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004237 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004238 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004239 int evaluate;
4240{
Bram Moolenaar33570922005-01-25 22:26:29 +00004241 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004242 long result;
4243 int first;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004244 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004245
4246 /*
4247 * Get the first variable.
4248 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004249 if (eval4(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004250 return FAIL;
4251
4252 /*
4253 * Repeat until there is no following "&&".
4254 */
4255 first = TRUE;
4256 result = TRUE;
4257 while ((*arg)[0] == '&' && (*arg)[1] == '&')
4258 {
4259 if (evaluate && first)
4260 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004261 if (get_tv_number_chk(rettv, &error) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004262 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004263 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004264 if (error)
4265 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004266 first = FALSE;
4267 }
4268
4269 /*
4270 * Get the second variable.
4271 */
4272 *arg = skipwhite(*arg + 2);
4273 if (eval4(arg, &var2, evaluate && result) == FAIL)
4274 return FAIL;
4275
4276 /*
4277 * Compute the result.
4278 */
4279 if (evaluate && result)
4280 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004281 if (get_tv_number_chk(&var2, &error) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004282 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004283 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004284 if (error)
4285 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004286 }
4287 if (evaluate)
4288 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004289 rettv->v_type = VAR_NUMBER;
4290 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004291 }
4292 }
4293
4294 return OK;
4295}
4296
4297/*
4298 * Handle third level expression:
4299 * var1 == var2
4300 * var1 =~ var2
4301 * var1 != var2
4302 * var1 !~ var2
4303 * var1 > var2
4304 * var1 >= var2
4305 * var1 < var2
4306 * var1 <= var2
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004307 * var1 is var2
4308 * var1 isnot var2
Bram Moolenaar071d4272004-06-13 20:20:40 +00004309 *
4310 * "arg" must point to the first non-white of the expression.
4311 * "arg" is advanced to the next non-white after the recognized expression.
4312 *
4313 * Return OK or FAIL.
4314 */
4315 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004316eval4(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004317 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004318 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004319 int evaluate;
4320{
Bram Moolenaar33570922005-01-25 22:26:29 +00004321 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004322 char_u *p;
4323 int i;
4324 exptype_T type = TYPE_UNKNOWN;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004325 int type_is = FALSE; /* TRUE for "is" and "isnot" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004326 int len = 2;
4327 long n1, n2;
4328 char_u *s1, *s2;
4329 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4330 regmatch_T regmatch;
4331 int ic;
4332 char_u *save_cpo;
4333
4334 /*
4335 * Get the first variable.
4336 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004337 if (eval5(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004338 return FAIL;
4339
4340 p = *arg;
4341 switch (p[0])
4342 {
4343 case '=': if (p[1] == '=')
4344 type = TYPE_EQUAL;
4345 else if (p[1] == '~')
4346 type = TYPE_MATCH;
4347 break;
4348 case '!': if (p[1] == '=')
4349 type = TYPE_NEQUAL;
4350 else if (p[1] == '~')
4351 type = TYPE_NOMATCH;
4352 break;
4353 case '>': if (p[1] != '=')
4354 {
4355 type = TYPE_GREATER;
4356 len = 1;
4357 }
4358 else
4359 type = TYPE_GEQUAL;
4360 break;
4361 case '<': if (p[1] != '=')
4362 {
4363 type = TYPE_SMALLER;
4364 len = 1;
4365 }
4366 else
4367 type = TYPE_SEQUAL;
4368 break;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004369 case 'i': if (p[1] == 's')
4370 {
4371 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
4372 len = 5;
4373 if (!vim_isIDc(p[len]))
4374 {
4375 type = len == 2 ? TYPE_EQUAL : TYPE_NEQUAL;
4376 type_is = TRUE;
4377 }
4378 }
4379 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004380 }
4381
4382 /*
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004383 * If there is a comparative operator, use it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004384 */
4385 if (type != TYPE_UNKNOWN)
4386 {
4387 /* extra question mark appended: ignore case */
4388 if (p[len] == '?')
4389 {
4390 ic = TRUE;
4391 ++len;
4392 }
4393 /* extra '#' appended: match case */
4394 else if (p[len] == '#')
4395 {
4396 ic = FALSE;
4397 ++len;
4398 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004399 /* nothing appended: use 'ignorecase' */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004400 else
4401 ic = p_ic;
4402
4403 /*
4404 * Get the second variable.
4405 */
4406 *arg = skipwhite(p + len);
4407 if (eval5(arg, &var2, evaluate) == FAIL)
4408 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004409 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004410 return FAIL;
4411 }
4412
4413 if (evaluate)
4414 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004415 if (type_is && rettv->v_type != var2.v_type)
4416 {
4417 /* For "is" a different type always means FALSE, for "notis"
4418 * it means TRUE. */
4419 n1 = (type == TYPE_NEQUAL);
4420 }
4421 else if (rettv->v_type == VAR_LIST || var2.v_type == VAR_LIST)
4422 {
4423 if (type_is)
4424 {
4425 n1 = (rettv->v_type == var2.v_type
4426 && rettv->vval.v_list == var2.vval.v_list);
4427 if (type == TYPE_NEQUAL)
4428 n1 = !n1;
4429 }
4430 else if (rettv->v_type != var2.v_type
4431 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
4432 {
4433 if (rettv->v_type != var2.v_type)
Bram Moolenaare49b69a2005-01-08 16:11:57 +00004434 EMSG(_("E691: Can only compare List with List"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004435 else
Bram Moolenaar59838522014-05-13 13:46:33 +02004436 EMSG(_("E692: Invalid operation for List"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004437 clear_tv(rettv);
4438 clear_tv(&var2);
4439 return FAIL;
4440 }
4441 else
4442 {
4443 /* Compare two Lists for being equal or unequal. */
Bram Moolenaar67b3f992010-11-10 20:41:57 +01004444 n1 = list_equal(rettv->vval.v_list, var2.vval.v_list,
4445 ic, FALSE);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004446 if (type == TYPE_NEQUAL)
4447 n1 = !n1;
4448 }
4449 }
4450
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004451 else if (rettv->v_type == VAR_DICT || var2.v_type == VAR_DICT)
4452 {
4453 if (type_is)
4454 {
4455 n1 = (rettv->v_type == var2.v_type
4456 && rettv->vval.v_dict == var2.vval.v_dict);
4457 if (type == TYPE_NEQUAL)
4458 n1 = !n1;
4459 }
4460 else if (rettv->v_type != var2.v_type
4461 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
4462 {
4463 if (rettv->v_type != var2.v_type)
4464 EMSG(_("E735: Can only compare Dictionary with Dictionary"));
4465 else
4466 EMSG(_("E736: Invalid operation for Dictionary"));
4467 clear_tv(rettv);
4468 clear_tv(&var2);
4469 return FAIL;
4470 }
4471 else
4472 {
4473 /* Compare two Dictionaries for being equal or unequal. */
Bram Moolenaar67b3f992010-11-10 20:41:57 +01004474 n1 = dict_equal(rettv->vval.v_dict, var2.vval.v_dict,
4475 ic, FALSE);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004476 if (type == TYPE_NEQUAL)
4477 n1 = !n1;
4478 }
4479 }
4480
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004481 else if (rettv->v_type == VAR_FUNC || var2.v_type == VAR_FUNC)
4482 {
4483 if (rettv->v_type != var2.v_type
4484 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
4485 {
4486 if (rettv->v_type != var2.v_type)
Bram Moolenaare49b69a2005-01-08 16:11:57 +00004487 EMSG(_("E693: Can only compare Funcref with Funcref"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004488 else
Bram Moolenaare49b69a2005-01-08 16:11:57 +00004489 EMSG(_("E694: Invalid operation for Funcrefs"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004490 clear_tv(rettv);
4491 clear_tv(&var2);
4492 return FAIL;
4493 }
4494 else
4495 {
4496 /* Compare two Funcrefs for being equal or unequal. */
4497 if (rettv->vval.v_string == NULL
4498 || var2.vval.v_string == NULL)
4499 n1 = FALSE;
4500 else
4501 n1 = STRCMP(rettv->vval.v_string,
4502 var2.vval.v_string) == 0;
4503 if (type == TYPE_NEQUAL)
4504 n1 = !n1;
4505 }
4506 }
4507
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004508#ifdef FEAT_FLOAT
4509 /*
4510 * If one of the two variables is a float, compare as a float.
4511 * When using "=~" or "!~", always compare as string.
4512 */
4513 else if ((rettv->v_type == VAR_FLOAT || var2.v_type == VAR_FLOAT)
4514 && type != TYPE_MATCH && type != TYPE_NOMATCH)
4515 {
4516 float_T f1, f2;
4517
4518 if (rettv->v_type == VAR_FLOAT)
4519 f1 = rettv->vval.v_float;
4520 else
4521 f1 = get_tv_number(rettv);
4522 if (var2.v_type == VAR_FLOAT)
4523 f2 = var2.vval.v_float;
4524 else
4525 f2 = get_tv_number(&var2);
4526 n1 = FALSE;
4527 switch (type)
4528 {
4529 case TYPE_EQUAL: n1 = (f1 == f2); break;
4530 case TYPE_NEQUAL: n1 = (f1 != f2); break;
4531 case TYPE_GREATER: n1 = (f1 > f2); break;
4532 case TYPE_GEQUAL: n1 = (f1 >= f2); break;
4533 case TYPE_SMALLER: n1 = (f1 < f2); break;
4534 case TYPE_SEQUAL: n1 = (f1 <= f2); break;
4535 case TYPE_UNKNOWN:
4536 case TYPE_MATCH:
4537 case TYPE_NOMATCH: break; /* avoid gcc warning */
4538 }
4539 }
4540#endif
4541
Bram Moolenaar071d4272004-06-13 20:20:40 +00004542 /*
4543 * If one of the two variables is a number, compare as a number.
4544 * When using "=~" or "!~", always compare as string.
4545 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004546 else if ((rettv->v_type == VAR_NUMBER || var2.v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004547 && type != TYPE_MATCH && type != TYPE_NOMATCH)
4548 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004549 n1 = get_tv_number(rettv);
4550 n2 = get_tv_number(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004551 switch (type)
4552 {
4553 case TYPE_EQUAL: n1 = (n1 == n2); break;
4554 case TYPE_NEQUAL: n1 = (n1 != n2); break;
4555 case TYPE_GREATER: n1 = (n1 > n2); break;
4556 case TYPE_GEQUAL: n1 = (n1 >= n2); break;
4557 case TYPE_SMALLER: n1 = (n1 < n2); break;
4558 case TYPE_SEQUAL: n1 = (n1 <= n2); break;
4559 case TYPE_UNKNOWN:
4560 case TYPE_MATCH:
4561 case TYPE_NOMATCH: break; /* avoid gcc warning */
4562 }
4563 }
4564 else
4565 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004566 s1 = get_tv_string_buf(rettv, buf1);
4567 s2 = get_tv_string_buf(&var2, buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004568 if (type != TYPE_MATCH && type != TYPE_NOMATCH)
4569 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2);
4570 else
4571 i = 0;
4572 n1 = FALSE;
4573 switch (type)
4574 {
4575 case TYPE_EQUAL: n1 = (i == 0); break;
4576 case TYPE_NEQUAL: n1 = (i != 0); break;
4577 case TYPE_GREATER: n1 = (i > 0); break;
4578 case TYPE_GEQUAL: n1 = (i >= 0); break;
4579 case TYPE_SMALLER: n1 = (i < 0); break;
4580 case TYPE_SEQUAL: n1 = (i <= 0); break;
4581
4582 case TYPE_MATCH:
4583 case TYPE_NOMATCH:
4584 /* avoid 'l' flag in 'cpoptions' */
4585 save_cpo = p_cpo;
4586 p_cpo = (char_u *)"";
4587 regmatch.regprog = vim_regcomp(s2,
4588 RE_MAGIC + RE_STRING);
4589 regmatch.rm_ic = ic;
4590 if (regmatch.regprog != NULL)
4591 {
4592 n1 = vim_regexec_nl(&regmatch, s1, (colnr_T)0);
Bram Moolenaar473de612013-06-08 18:19:48 +02004593 vim_regfree(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004594 if (type == TYPE_NOMATCH)
4595 n1 = !n1;
4596 }
4597 p_cpo = save_cpo;
4598 break;
4599
4600 case TYPE_UNKNOWN: break; /* avoid gcc warning */
4601 }
4602 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004603 clear_tv(rettv);
4604 clear_tv(&var2);
4605 rettv->v_type = VAR_NUMBER;
4606 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004607 }
4608 }
4609
4610 return OK;
4611}
4612
4613/*
4614 * Handle fourth level expression:
4615 * + number addition
4616 * - number subtraction
4617 * . string concatenation
4618 *
4619 * "arg" must point to the first non-white of the expression.
4620 * "arg" is advanced to the next non-white after the recognized expression.
4621 *
4622 * Return OK or FAIL.
4623 */
4624 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004625eval5(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004626 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004627 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004628 int evaluate;
4629{
Bram Moolenaar33570922005-01-25 22:26:29 +00004630 typval_T var2;
4631 typval_T var3;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004632 int op;
4633 long n1, n2;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004634#ifdef FEAT_FLOAT
4635 float_T f1 = 0, f2 = 0;
4636#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004637 char_u *s1, *s2;
4638 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4639 char_u *p;
4640
4641 /*
4642 * Get the first variable.
4643 */
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004644 if (eval6(arg, rettv, evaluate, FALSE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004645 return FAIL;
4646
4647 /*
4648 * Repeat computing, until no '+', '-' or '.' is following.
4649 */
4650 for (;;)
4651 {
4652 op = **arg;
4653 if (op != '+' && op != '-' && op != '.')
4654 break;
4655
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004656 if ((op != '+' || rettv->v_type != VAR_LIST)
4657#ifdef FEAT_FLOAT
4658 && (op == '.' || rettv->v_type != VAR_FLOAT)
4659#endif
4660 )
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004661 {
4662 /* For "list + ...", an illegal use of the first operand as
4663 * a number cannot be determined before evaluating the 2nd
4664 * operand: if this is also a list, all is ok.
4665 * For "something . ...", "something - ..." or "non-list + ...",
4666 * we know that the first operand needs to be a string or number
4667 * without evaluating the 2nd operand. So check before to avoid
4668 * side effects after an error. */
4669 if (evaluate && get_tv_string_chk(rettv) == NULL)
4670 {
4671 clear_tv(rettv);
4672 return FAIL;
4673 }
4674 }
4675
Bram Moolenaar071d4272004-06-13 20:20:40 +00004676 /*
4677 * Get the second variable.
4678 */
4679 *arg = skipwhite(*arg + 1);
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004680 if (eval6(arg, &var2, evaluate, op == '.') == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004681 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004682 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004683 return FAIL;
4684 }
4685
4686 if (evaluate)
4687 {
4688 /*
4689 * Compute the result.
4690 */
4691 if (op == '.')
4692 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004693 s1 = get_tv_string_buf(rettv, buf1); /* already checked */
4694 s2 = get_tv_string_buf_chk(&var2, buf2);
4695 if (s2 == NULL) /* type error ? */
4696 {
4697 clear_tv(rettv);
4698 clear_tv(&var2);
4699 return FAIL;
4700 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004701 p = concat_str(s1, s2);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004702 clear_tv(rettv);
4703 rettv->v_type = VAR_STRING;
4704 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004705 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00004706 else if (op == '+' && rettv->v_type == VAR_LIST
4707 && var2.v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004708 {
4709 /* concatenate Lists */
4710 if (list_concat(rettv->vval.v_list, var2.vval.v_list,
4711 &var3) == FAIL)
4712 {
4713 clear_tv(rettv);
4714 clear_tv(&var2);
4715 return FAIL;
4716 }
4717 clear_tv(rettv);
4718 *rettv = var3;
4719 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004720 else
4721 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004722 int error = FALSE;
4723
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004724#ifdef FEAT_FLOAT
4725 if (rettv->v_type == VAR_FLOAT)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004726 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004727 f1 = rettv->vval.v_float;
4728 n1 = 0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004729 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004730 else
4731#endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004732 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004733 n1 = get_tv_number_chk(rettv, &error);
4734 if (error)
4735 {
4736 /* This can only happen for "list + non-list". For
4737 * "non-list + ..." or "something - ...", we returned
4738 * before evaluating the 2nd operand. */
4739 clear_tv(rettv);
4740 return FAIL;
4741 }
4742#ifdef FEAT_FLOAT
4743 if (var2.v_type == VAR_FLOAT)
4744 f1 = n1;
4745#endif
4746 }
4747#ifdef FEAT_FLOAT
4748 if (var2.v_type == VAR_FLOAT)
4749 {
4750 f2 = var2.vval.v_float;
4751 n2 = 0;
4752 }
4753 else
4754#endif
4755 {
4756 n2 = get_tv_number_chk(&var2, &error);
4757 if (error)
4758 {
4759 clear_tv(rettv);
4760 clear_tv(&var2);
4761 return FAIL;
4762 }
4763#ifdef FEAT_FLOAT
4764 if (rettv->v_type == VAR_FLOAT)
4765 f2 = n2;
4766#endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004767 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004768 clear_tv(rettv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004769
4770#ifdef FEAT_FLOAT
4771 /* If there is a float on either side the result is a float. */
4772 if (rettv->v_type == VAR_FLOAT || var2.v_type == VAR_FLOAT)
4773 {
4774 if (op == '+')
4775 f1 = f1 + f2;
4776 else
4777 f1 = f1 - f2;
4778 rettv->v_type = VAR_FLOAT;
4779 rettv->vval.v_float = f1;
4780 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004781 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004782#endif
4783 {
4784 if (op == '+')
4785 n1 = n1 + n2;
4786 else
4787 n1 = n1 - n2;
4788 rettv->v_type = VAR_NUMBER;
4789 rettv->vval.v_number = n1;
4790 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004791 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004792 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004793 }
4794 }
4795 return OK;
4796}
4797
4798/*
4799 * Handle fifth level expression:
4800 * * number multiplication
4801 * / number division
4802 * % number modulo
4803 *
4804 * "arg" must point to the first non-white of the expression.
4805 * "arg" is advanced to the next non-white after the recognized expression.
4806 *
4807 * Return OK or FAIL.
4808 */
4809 static int
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004810eval6(arg, rettv, evaluate, want_string)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004811 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004812 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004813 int evaluate;
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004814 int want_string; /* after "." operator */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004815{
Bram Moolenaar33570922005-01-25 22:26:29 +00004816 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004817 int op;
4818 long n1, n2;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004819#ifdef FEAT_FLOAT
4820 int use_float = FALSE;
4821 float_T f1 = 0, f2;
4822#endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004823 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004824
4825 /*
4826 * Get the first variable.
4827 */
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004828 if (eval7(arg, rettv, evaluate, want_string) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004829 return FAIL;
4830
4831 /*
4832 * Repeat computing, until no '*', '/' or '%' is following.
4833 */
4834 for (;;)
4835 {
4836 op = **arg;
4837 if (op != '*' && op != '/' && op != '%')
4838 break;
4839
4840 if (evaluate)
4841 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004842#ifdef FEAT_FLOAT
4843 if (rettv->v_type == VAR_FLOAT)
4844 {
4845 f1 = rettv->vval.v_float;
4846 use_float = TRUE;
4847 n1 = 0;
4848 }
4849 else
4850#endif
4851 n1 = get_tv_number_chk(rettv, &error);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004852 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004853 if (error)
4854 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004855 }
4856 else
4857 n1 = 0;
4858
4859 /*
4860 * Get the second variable.
4861 */
4862 *arg = skipwhite(*arg + 1);
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004863 if (eval7(arg, &var2, evaluate, FALSE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004864 return FAIL;
4865
4866 if (evaluate)
4867 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004868#ifdef FEAT_FLOAT
4869 if (var2.v_type == VAR_FLOAT)
4870 {
4871 if (!use_float)
4872 {
4873 f1 = n1;
4874 use_float = TRUE;
4875 }
4876 f2 = var2.vval.v_float;
4877 n2 = 0;
4878 }
4879 else
4880#endif
4881 {
4882 n2 = get_tv_number_chk(&var2, &error);
4883 clear_tv(&var2);
4884 if (error)
4885 return FAIL;
4886#ifdef FEAT_FLOAT
4887 if (use_float)
4888 f2 = n2;
4889#endif
4890 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004891
4892 /*
4893 * Compute the result.
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004894 * When either side is a float the result is a float.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004895 */
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004896#ifdef FEAT_FLOAT
4897 if (use_float)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004898 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004899 if (op == '*')
4900 f1 = f1 * f2;
4901 else if (op == '/')
4902 {
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004903# ifdef VMS
4904 /* VMS crashes on divide by zero, work around it */
4905 if (f2 == 0.0)
4906 {
4907 if (f1 == 0)
Bram Moolenaar314f11d2010-08-09 22:07:08 +02004908 f1 = -1 * __F_FLT_MAX - 1L; /* similar to NaN */
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004909 else if (f1 < 0)
Bram Moolenaar314f11d2010-08-09 22:07:08 +02004910 f1 = -1 * __F_FLT_MAX;
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004911 else
Bram Moolenaar314f11d2010-08-09 22:07:08 +02004912 f1 = __F_FLT_MAX;
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004913 }
4914 else
4915 f1 = f1 / f2;
4916# else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004917 /* We rely on the floating point library to handle divide
4918 * by zero to result in "inf" and not a crash. */
4919 f1 = f1 / f2;
Bram Moolenaarf878bcf2010-07-30 22:29:41 +02004920# endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004921 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004922 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004923 {
Bram Moolenaar1378fca2008-07-04 16:51:55 +00004924 EMSG(_("E804: Cannot use '%' with Float"));
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004925 return FAIL;
4926 }
4927 rettv->v_type = VAR_FLOAT;
4928 rettv->vval.v_float = f1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004929 }
4930 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004931#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004932 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004933 if (op == '*')
4934 n1 = n1 * n2;
4935 else if (op == '/')
4936 {
4937 if (n2 == 0) /* give an error message? */
4938 {
4939 if (n1 == 0)
4940 n1 = -0x7fffffffL - 1L; /* similar to NaN */
4941 else if (n1 < 0)
4942 n1 = -0x7fffffffL;
4943 else
4944 n1 = 0x7fffffffL;
4945 }
4946 else
4947 n1 = n1 / n2;
4948 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004949 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004950 {
4951 if (n2 == 0) /* give an error message? */
4952 n1 = 0;
4953 else
4954 n1 = n1 % n2;
4955 }
4956 rettv->v_type = VAR_NUMBER;
4957 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004958 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004959 }
4960 }
4961
4962 return OK;
4963}
4964
4965/*
4966 * Handle sixth level expression:
4967 * number number constant
Bram Moolenaarbae0c162007-05-10 19:30:25 +00004968 * "string" string constant
4969 * 'string' literal string constant
Bram Moolenaar071d4272004-06-13 20:20:40 +00004970 * &option-name option value
4971 * @r register contents
4972 * identifier variable value
4973 * function() function call
4974 * $VAR environment variable
4975 * (expression) nested expression
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00004976 * [expr, expr] List
4977 * {key: val, key: val} Dictionary
Bram Moolenaar071d4272004-06-13 20:20:40 +00004978 *
4979 * Also handle:
4980 * ! in front logical NOT
4981 * - in front unary minus
4982 * + in front unary plus (ignored)
Bram Moolenaar8c711452005-01-14 21:53:12 +00004983 * trailing [] subscript in String or List
4984 * trailing .name entry in Dictionary
Bram Moolenaar071d4272004-06-13 20:20:40 +00004985 *
4986 * "arg" must point to the first non-white of the expression.
4987 * "arg" is advanced to the next non-white after the recognized expression.
4988 *
4989 * Return OK or FAIL.
4990 */
4991 static int
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00004992eval7(arg, rettv, evaluate, want_string)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004993 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004994 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004995 int evaluate;
Bram Moolenaardb7c6862010-05-21 16:33:48 +02004996 int want_string UNUSED; /* after "." operator */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004997{
Bram Moolenaar071d4272004-06-13 20:20:40 +00004998 long n;
4999 int len;
5000 char_u *s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005001 char_u *start_leader, *end_leader;
5002 int ret = OK;
5003 char_u *alias;
5004
5005 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005006 * Initialise variable so that clear_tv() can't mistake this for a
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005007 * string and free a string that isn't there.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005008 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005009 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005010
5011 /*
5012 * Skip '!' and '-' characters. They are handled later.
5013 */
5014 start_leader = *arg;
5015 while (**arg == '!' || **arg == '-' || **arg == '+')
5016 *arg = skipwhite(*arg + 1);
5017 end_leader = *arg;
5018
5019 switch (**arg)
5020 {
5021 /*
5022 * Number constant.
5023 */
5024 case '0':
5025 case '1':
5026 case '2':
5027 case '3':
5028 case '4':
5029 case '5':
5030 case '6':
5031 case '7':
5032 case '8':
5033 case '9':
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005034 {
5035#ifdef FEAT_FLOAT
5036 char_u *p = skipdigits(*arg + 1);
5037 int get_float = FALSE;
5038
5039 /* We accept a float when the format matches
5040 * "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very
Bram Moolenaar8d00f9c2008-06-28 13:09:56 +00005041 * strict to avoid backwards compatibility problems.
5042 * Don't look for a float after the "." operator, so that
5043 * ":let vers = 1.2.3" doesn't fail. */
5044 if (!want_string && p[0] == '.' && vim_isdigit(p[1]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005045 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005046 get_float = TRUE;
5047 p = skipdigits(p + 2);
5048 if (*p == 'e' || *p == 'E')
5049 {
5050 ++p;
5051 if (*p == '-' || *p == '+')
5052 ++p;
5053 if (!vim_isdigit(*p))
5054 get_float = FALSE;
5055 else
5056 p = skipdigits(p + 1);
5057 }
5058 if (ASCII_ISALPHA(*p) || *p == '.')
5059 get_float = FALSE;
5060 }
5061 if (get_float)
5062 {
5063 float_T f;
5064
5065 *arg += string2float(*arg, &f);
5066 if (evaluate)
5067 {
5068 rettv->v_type = VAR_FLOAT;
5069 rettv->vval.v_float = f;
5070 }
5071 }
5072 else
5073#endif
5074 {
5075 vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL);
5076 *arg += len;
5077 if (evaluate)
5078 {
5079 rettv->v_type = VAR_NUMBER;
5080 rettv->vval.v_number = n;
5081 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005082 }
5083 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005084 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005085
5086 /*
5087 * String constant: "string".
5088 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005089 case '"': ret = get_string_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005090 break;
5091
5092 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005093 * Literal string constant: 'str''ing'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005094 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005095 case '\'': ret = get_lit_string_tv(arg, rettv, evaluate);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005096 break;
5097
5098 /*
5099 * List: [expr, expr]
5100 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005101 case '[': ret = get_list_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005102 break;
5103
5104 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005105 * Dictionary: {key: val, key: val}
5106 */
5107 case '{': ret = get_dict_tv(arg, rettv, evaluate);
5108 break;
5109
5110 /*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005111 * Option value: &name
Bram Moolenaar071d4272004-06-13 20:20:40 +00005112 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00005113 case '&': ret = get_option_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005114 break;
5115
5116 /*
5117 * Environment variable: $VAR.
5118 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005119 case '$': ret = get_env_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005120 break;
5121
5122 /*
5123 * Register contents: @r.
5124 */
5125 case '@': ++*arg;
5126 if (evaluate)
5127 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005128 rettv->v_type = VAR_STRING;
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +02005129 rettv->vval.v_string = get_reg_contents(**arg,
5130 GREG_EXPR_SRC);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005131 }
5132 if (**arg != NUL)
5133 ++*arg;
5134 break;
5135
5136 /*
5137 * nested expression: (expression).
5138 */
5139 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005140 ret = eval1(arg, rettv, evaluate); /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005141 if (**arg == ')')
5142 ++*arg;
5143 else if (ret == OK)
5144 {
5145 EMSG(_("E110: Missing ')'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005146 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005147 ret = FAIL;
5148 }
5149 break;
5150
Bram Moolenaar8c711452005-01-14 21:53:12 +00005151 default: ret = NOTDONE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005152 break;
5153 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005154
5155 if (ret == NOTDONE)
5156 {
5157 /*
5158 * Must be a variable or function name.
5159 * Can also be a curly-braces kind of name: {expr}.
5160 */
5161 s = *arg;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005162 len = get_name_len(arg, &alias, evaluate, TRUE);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005163 if (alias != NULL)
5164 s = alias;
5165
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005166 if (len <= 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005167 ret = FAIL;
5168 else
5169 {
5170 if (**arg == '(') /* recursive! */
5171 {
5172 /* If "s" is the name of a variable of type VAR_FUNC
5173 * use its contents. */
Bram Moolenaarf31ecce2014-02-05 22:13:05 +01005174 s = deref_func_name(s, &len, !evaluate);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005175
5176 /* Invoke the function. */
5177 ret = get_func_tv(s, len, rettv, arg,
5178 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
Bram Moolenaare9a41262005-01-15 22:18:47 +00005179 &len, evaluate, NULL);
Bram Moolenaare17c2602013-02-26 19:36:15 +01005180
5181 /* If evaluate is FALSE rettv->v_type was not set in
5182 * get_func_tv, but it's needed in handle_subscript() to parse
5183 * what follows. So set it here. */
5184 if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(')
5185 {
Bram Moolenaar988232f2013-02-26 21:43:32 +01005186 rettv->vval.v_string = vim_strsave((char_u *)"");
Bram Moolenaare17c2602013-02-26 19:36:15 +01005187 rettv->v_type = VAR_FUNC;
5188 }
5189
Bram Moolenaar8c711452005-01-14 21:53:12 +00005190 /* Stop the expression evaluation when immediately
5191 * aborting on error, or when an interrupt occurred or
5192 * an exception was thrown but not caught. */
5193 if (aborting())
5194 {
5195 if (ret == OK)
5196 clear_tv(rettv);
5197 ret = FAIL;
5198 }
5199 }
5200 else if (evaluate)
Bram Moolenaar6d977d62014-01-14 15:24:39 +01005201 ret = get_var_tv(s, len, rettv, TRUE, FALSE);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005202 else
5203 ret = OK;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005204 }
Bram Moolenaar3c2d6532011-02-01 13:48:53 +01005205 vim_free(alias);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005206 }
5207
Bram Moolenaar071d4272004-06-13 20:20:40 +00005208 *arg = skipwhite(*arg);
5209
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005210 /* Handle following '[', '(' and '.' for expr[expr], expr.name,
5211 * expr(expr). */
5212 if (ret == OK)
5213 ret = handle_subscript(arg, rettv, evaluate, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005214
5215 /*
5216 * Apply logical NOT and unary '-', from right to left, ignore '+'.
5217 */
5218 if (ret == OK && evaluate && end_leader > start_leader)
5219 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005220 int error = FALSE;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005221 int val = 0;
5222#ifdef FEAT_FLOAT
5223 float_T f = 0.0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005224
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005225 if (rettv->v_type == VAR_FLOAT)
5226 f = rettv->vval.v_float;
5227 else
5228#endif
5229 val = get_tv_number_chk(rettv, &error);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005230 if (error)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005231 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005232 clear_tv(rettv);
5233 ret = FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005234 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005235 else
5236 {
5237 while (end_leader > start_leader)
5238 {
5239 --end_leader;
5240 if (*end_leader == '!')
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005241 {
5242#ifdef FEAT_FLOAT
5243 if (rettv->v_type == VAR_FLOAT)
5244 f = !f;
5245 else
5246#endif
5247 val = !val;
5248 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005249 else if (*end_leader == '-')
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005250 {
5251#ifdef FEAT_FLOAT
5252 if (rettv->v_type == VAR_FLOAT)
5253 f = -f;
5254 else
5255#endif
5256 val = -val;
5257 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005258 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00005259#ifdef FEAT_FLOAT
5260 if (rettv->v_type == VAR_FLOAT)
5261 {
5262 clear_tv(rettv);
5263 rettv->vval.v_float = f;
5264 }
5265 else
5266#endif
5267 {
5268 clear_tv(rettv);
5269 rettv->v_type = VAR_NUMBER;
5270 rettv->vval.v_number = val;
5271 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005272 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005273 }
5274
5275 return ret;
5276}
5277
5278/*
Bram Moolenaar9e54a0e2006-04-14 20:42:25 +00005279 * Evaluate an "[expr]" or "[expr:expr]" index. Also "dict.key".
5280 * "*arg" points to the '[' or '.'.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005281 * Returns FAIL or OK. "*arg" is advanced to after the ']'.
5282 */
5283 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005284eval_index(arg, rettv, evaluate, verbose)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005285 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00005286 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005287 int evaluate;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005288 int verbose; /* give error messages */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005289{
5290 int empty1 = FALSE, empty2 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00005291 typval_T var1, var2;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005292 long n1, n2 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005293 long len = -1;
5294 int range = FALSE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005295 char_u *s;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005296 char_u *key = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005297
Bram Moolenaar2a876e42013-06-12 22:08:58 +02005298 if (rettv->v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005299 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005300 if (verbose)
5301 EMSG(_("E695: Cannot index a Funcref"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005302 return FAIL;
5303 }
Bram Moolenaar2a876e42013-06-12 22:08:58 +02005304#ifdef FEAT_FLOAT
5305 else if (rettv->v_type == VAR_FLOAT)
5306 {
5307 if (verbose)
5308 EMSG(_(e_float_as_string));
5309 return FAIL;
5310 }
5311#endif
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005312
Bram Moolenaar8c711452005-01-14 21:53:12 +00005313 if (**arg == '.')
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005314 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005315 /*
5316 * dict.name
5317 */
5318 key = *arg + 1;
5319 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
5320 ;
5321 if (len == 0)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005322 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005323 *arg = skipwhite(key + len);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005324 }
5325 else
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005326 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005327 /*
5328 * something[idx]
5329 *
5330 * Get the (first) variable from inside the [].
5331 */
5332 *arg = skipwhite(*arg + 1);
5333 if (**arg == ':')
5334 empty1 = TRUE;
5335 else if (eval1(arg, &var1, evaluate) == FAIL) /* recursive! */
5336 return FAIL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005337 else if (evaluate && get_tv_string_chk(&var1) == NULL)
5338 {
5339 /* not a number or string */
5340 clear_tv(&var1);
5341 return FAIL;
5342 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005343
5344 /*
5345 * Get the second variable from inside the [:].
5346 */
5347 if (**arg == ':')
5348 {
5349 range = TRUE;
5350 *arg = skipwhite(*arg + 1);
5351 if (**arg == ']')
5352 empty2 = TRUE;
5353 else if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */
5354 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005355 if (!empty1)
5356 clear_tv(&var1);
5357 return FAIL;
5358 }
5359 else if (evaluate && get_tv_string_chk(&var2) == NULL)
5360 {
5361 /* not a number or string */
5362 if (!empty1)
5363 clear_tv(&var1);
5364 clear_tv(&var2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005365 return FAIL;
5366 }
5367 }
5368
5369 /* Check for the ']'. */
5370 if (**arg != ']')
5371 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005372 if (verbose)
5373 EMSG(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00005374 clear_tv(&var1);
5375 if (range)
5376 clear_tv(&var2);
5377 return FAIL;
5378 }
5379 *arg = skipwhite(*arg + 1); /* skip the ']' */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005380 }
5381
5382 if (evaluate)
5383 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005384 n1 = 0;
5385 if (!empty1 && rettv->v_type != VAR_DICT)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005386 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005387 n1 = get_tv_number(&var1);
5388 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005389 }
5390 if (range)
5391 {
5392 if (empty2)
5393 n2 = -1;
5394 else
5395 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005396 n2 = get_tv_number(&var2);
5397 clear_tv(&var2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005398 }
5399 }
5400
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005401 switch (rettv->v_type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005402 {
5403 case VAR_NUMBER:
5404 case VAR_STRING:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005405 s = get_tv_string(rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005406 len = (long)STRLEN(s);
5407 if (range)
5408 {
5409 /* The resulting variable is a substring. If the indexes
5410 * are out of range the result is empty. */
5411 if (n1 < 0)
5412 {
5413 n1 = len + n1;
5414 if (n1 < 0)
5415 n1 = 0;
5416 }
5417 if (n2 < 0)
5418 n2 = len + n2;
5419 else if (n2 >= len)
5420 n2 = len;
5421 if (n1 >= len || n2 < 0 || n1 > n2)
5422 s = NULL;
5423 else
5424 s = vim_strnsave(s + n1, (int)(n2 - n1 + 1));
5425 }
5426 else
5427 {
5428 /* The resulting variable is a string of a single
5429 * character. If the index is too big or negative the
5430 * result is empty. */
5431 if (n1 >= len || n1 < 0)
5432 s = NULL;
5433 else
5434 s = vim_strnsave(s + n1, 1);
5435 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005436 clear_tv(rettv);
5437 rettv->v_type = VAR_STRING;
5438 rettv->vval.v_string = s;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005439 break;
5440
5441 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005442 len = list_len(rettv->vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005443 if (n1 < 0)
5444 n1 = len + n1;
5445 if (!empty1 && (n1 < 0 || n1 >= len))
5446 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00005447 /* For a range we allow invalid values and return an empty
5448 * list. A list index out of range is an error. */
5449 if (!range)
5450 {
5451 if (verbose)
5452 EMSGN(_(e_listidx), n1);
5453 return FAIL;
5454 }
5455 n1 = len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005456 }
5457 if (range)
5458 {
Bram Moolenaar33570922005-01-25 22:26:29 +00005459 list_T *l;
5460 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005461
5462 if (n2 < 0)
5463 n2 = len + n2;
Bram Moolenaar9e54a0e2006-04-14 20:42:25 +00005464 else if (n2 >= len)
5465 n2 = len - 1;
5466 if (!empty2 && (n2 < 0 || n2 + 1 < n1))
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00005467 n2 = -1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005468 l = list_alloc();
5469 if (l == NULL)
5470 return FAIL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005471 for (item = list_find(rettv->vval.v_list, n1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005472 n1 <= n2; ++n1)
5473 {
5474 if (list_append_tv(l, &item->li_tv) == FAIL)
5475 {
Bram Moolenaar685295c2006-10-15 20:37:38 +00005476 list_free(l, TRUE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005477 return FAIL;
5478 }
5479 item = item->li_next;
5480 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005481 clear_tv(rettv);
5482 rettv->v_type = VAR_LIST;
5483 rettv->vval.v_list = l;
Bram Moolenaar0d660222005-01-07 21:51:51 +00005484 ++l->lv_refcount;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005485 }
5486 else
5487 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00005488 copy_tv(&list_find(rettv->vval.v_list, n1)->li_tv, &var1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005489 clear_tv(rettv);
5490 *rettv = var1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005491 }
5492 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005493
5494 case VAR_DICT:
5495 if (range)
5496 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005497 if (verbose)
5498 EMSG(_(e_dictrange));
Bram Moolenaar8c711452005-01-14 21:53:12 +00005499 if (len == -1)
5500 clear_tv(&var1);
5501 return FAIL;
5502 }
5503 {
Bram Moolenaar33570922005-01-25 22:26:29 +00005504 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005505
5506 if (len == -1)
5507 {
5508 key = get_tv_string(&var1);
5509 if (*key == NUL)
5510 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005511 if (verbose)
5512 EMSG(_(e_emptykey));
Bram Moolenaar8c711452005-01-14 21:53:12 +00005513 clear_tv(&var1);
5514 return FAIL;
5515 }
5516 }
5517
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005518 item = dict_find(rettv->vval.v_dict, key, (int)len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005519
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005520 if (item == NULL && verbose)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005521 EMSG2(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005522 if (len == -1)
5523 clear_tv(&var1);
5524 if (item == NULL)
5525 return FAIL;
5526
5527 copy_tv(&item->di_tv, &var1);
5528 clear_tv(rettv);
5529 *rettv = var1;
5530 }
5531 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005532 }
5533 }
5534
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005535 return OK;
5536}
5537
5538/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005539 * Get an option value.
5540 * "arg" points to the '&' or '+' before the option name.
5541 * "arg" is advanced to character after the option name.
5542 * Return OK or FAIL.
5543 */
5544 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005545get_option_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005546 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00005547 typval_T *rettv; /* when NULL, only check if option exists */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005548 int evaluate;
5549{
5550 char_u *option_end;
5551 long numval;
5552 char_u *stringval;
5553 int opt_type;
5554 int c;
5555 int working = (**arg == '+'); /* has("+option") */
5556 int ret = OK;
5557 int opt_flags;
5558
5559 /*
5560 * Isolate the option name and find its value.
5561 */
5562 option_end = find_option_end(arg, &opt_flags);
5563 if (option_end == NULL)
5564 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005565 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005566 EMSG2(_("E112: Option name missing: %s"), *arg);
5567 return FAIL;
5568 }
5569
5570 if (!evaluate)
5571 {
5572 *arg = option_end;
5573 return OK;
5574 }
5575
5576 c = *option_end;
5577 *option_end = NUL;
5578 opt_type = get_option_value(*arg, &numval,
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005579 rettv == NULL ? NULL : &stringval, opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005580
5581 if (opt_type == -3) /* invalid name */
5582 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005583 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005584 EMSG2(_("E113: Unknown option: %s"), *arg);
5585 ret = FAIL;
5586 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005587 else if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005588 {
5589 if (opt_type == -2) /* hidden string option */
5590 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005591 rettv->v_type = VAR_STRING;
5592 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005593 }
5594 else if (opt_type == -1) /* hidden number option */
5595 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005596 rettv->v_type = VAR_NUMBER;
5597 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005598 }
5599 else if (opt_type == 1) /* number option */
5600 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005601 rettv->v_type = VAR_NUMBER;
5602 rettv->vval.v_number = numval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005603 }
5604 else /* string option */
5605 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005606 rettv->v_type = VAR_STRING;
5607 rettv->vval.v_string = stringval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005608 }
5609 }
5610 else if (working && (opt_type == -2 || opt_type == -1))
5611 ret = FAIL;
5612
5613 *option_end = c; /* put back for error messages */
5614 *arg = option_end;
5615
5616 return ret;
5617}
5618
5619/*
5620 * Allocate a variable for a string constant.
5621 * Return OK or FAIL.
5622 */
5623 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005624get_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005625 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00005626 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005627 int evaluate;
5628{
5629 char_u *p;
5630 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005631 int extra = 0;
5632
5633 /*
5634 * Find the end of the string, skipping backslashed characters.
5635 */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005636 for (p = *arg + 1; *p != NUL && *p != '"'; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005637 {
5638 if (*p == '\\' && p[1] != NUL)
5639 {
5640 ++p;
5641 /* A "\<x>" form occupies at least 4 characters, and produces up
5642 * to 6 characters: reserve space for 2 extra */
5643 if (*p == '<')
5644 extra += 2;
5645 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005646 }
5647
5648 if (*p != '"')
5649 {
5650 EMSG2(_("E114: Missing quote: %s"), *arg);
5651 return FAIL;
5652 }
5653
5654 /* If only parsing, set *arg and return here */
5655 if (!evaluate)
5656 {
5657 *arg = p + 1;
5658 return OK;
5659 }
5660
5661 /*
5662 * Copy the string into allocated memory, handling backslashed
5663 * characters.
5664 */
5665 name = alloc((unsigned)(p - *arg + extra));
5666 if (name == NULL)
5667 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005668 rettv->v_type = VAR_STRING;
5669 rettv->vval.v_string = name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005670
Bram Moolenaar8c711452005-01-14 21:53:12 +00005671 for (p = *arg + 1; *p != NUL && *p != '"'; )
Bram Moolenaar071d4272004-06-13 20:20:40 +00005672 {
5673 if (*p == '\\')
5674 {
5675 switch (*++p)
5676 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005677 case 'b': *name++ = BS; ++p; break;
5678 case 'e': *name++ = ESC; ++p; break;
5679 case 'f': *name++ = FF; ++p; break;
5680 case 'n': *name++ = NL; ++p; break;
5681 case 'r': *name++ = CAR; ++p; break;
5682 case 't': *name++ = TAB; ++p; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005683
5684 case 'X': /* hex: "\x1", "\x12" */
5685 case 'x':
5686 case 'u': /* Unicode: "\u0023" */
5687 case 'U':
5688 if (vim_isxdigit(p[1]))
5689 {
5690 int n, nr;
5691 int c = toupper(*p);
5692
5693 if (c == 'X')
5694 n = 2;
5695 else
5696 n = 4;
5697 nr = 0;
5698 while (--n >= 0 && vim_isxdigit(p[1]))
5699 {
5700 ++p;
5701 nr = (nr << 4) + hex2nr(*p);
5702 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005703 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005704#ifdef FEAT_MBYTE
5705 /* For "\u" store the number according to
5706 * 'encoding'. */
5707 if (c != 'X')
Bram Moolenaar8c711452005-01-14 21:53:12 +00005708 name += (*mb_char2bytes)(nr, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005709 else
5710#endif
Bram Moolenaar8c711452005-01-14 21:53:12 +00005711 *name++ = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005712 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005713 break;
5714
5715 /* octal: "\1", "\12", "\123" */
5716 case '0':
5717 case '1':
5718 case '2':
5719 case '3':
5720 case '4':
5721 case '5':
5722 case '6':
Bram Moolenaar8c711452005-01-14 21:53:12 +00005723 case '7': *name = *p++ - '0';
5724 if (*p >= '0' && *p <= '7')
Bram Moolenaar071d4272004-06-13 20:20:40 +00005725 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005726 *name = (*name << 3) + *p++ - '0';
5727 if (*p >= '0' && *p <= '7')
5728 *name = (*name << 3) + *p++ - '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +00005729 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005730 ++name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005731 break;
5732
5733 /* Special key, e.g.: "\<C-W>" */
Bram Moolenaar8c711452005-01-14 21:53:12 +00005734 case '<': extra = trans_special(&p, name, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005735 if (extra != 0)
5736 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005737 name += extra;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005738 break;
5739 }
5740 /* FALLTHROUGH */
5741
Bram Moolenaar8c711452005-01-14 21:53:12 +00005742 default: MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005743 break;
5744 }
5745 }
5746 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00005747 MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005748
Bram Moolenaar071d4272004-06-13 20:20:40 +00005749 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005750 *name = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005751 *arg = p + 1;
5752
Bram Moolenaar071d4272004-06-13 20:20:40 +00005753 return OK;
5754}
5755
5756/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005757 * Allocate a variable for a 'str''ing' constant.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005758 * Return OK or FAIL.
5759 */
5760 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005761get_lit_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005762 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00005763 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005764 int evaluate;
5765{
5766 char_u *p;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005767 char_u *str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005768 int reduce = 0;
5769
5770 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005771 * Find the end of the string, skipping ''.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005772 */
5773 for (p = *arg + 1; *p != NUL; mb_ptr_adv(p))
5774 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005775 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005776 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005777 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005778 break;
5779 ++reduce;
5780 ++p;
5781 }
5782 }
5783
Bram Moolenaar8c711452005-01-14 21:53:12 +00005784 if (*p != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005785 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005786 EMSG2(_("E115: Missing quote: %s"), *arg);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005787 return FAIL;
5788 }
5789
Bram Moolenaar8c711452005-01-14 21:53:12 +00005790 /* If only parsing return after setting "*arg" */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005791 if (!evaluate)
5792 {
5793 *arg = p + 1;
5794 return OK;
5795 }
5796
5797 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005798 * Copy the string into allocated memory, handling '' to ' reduction.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005799 */
5800 str = alloc((unsigned)((p - *arg) - reduce));
5801 if (str == NULL)
5802 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005803 rettv->v_type = VAR_STRING;
5804 rettv->vval.v_string = str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005805
Bram Moolenaar8c711452005-01-14 21:53:12 +00005806 for (p = *arg + 1; *p != NUL; )
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005807 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005808 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005809 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005810 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005811 break;
5812 ++p;
5813 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005814 MB_COPY_CHAR(p, str);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005815 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005816 *str = NUL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005817 *arg = p + 1;
5818
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005819 return OK;
5820}
5821
5822/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005823 * Allocate a variable for a List and fill it from "*arg".
5824 * Return OK or FAIL.
5825 */
5826 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005827get_list_tv(arg, rettv, evaluate)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005828 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00005829 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005830 int evaluate;
5831{
Bram Moolenaar33570922005-01-25 22:26:29 +00005832 list_T *l = NULL;
5833 typval_T tv;
5834 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005835
5836 if (evaluate)
5837 {
5838 l = list_alloc();
5839 if (l == NULL)
5840 return FAIL;
5841 }
5842
5843 *arg = skipwhite(*arg + 1);
5844 while (**arg != ']' && **arg != NUL)
5845 {
5846 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
5847 goto failret;
5848 if (evaluate)
5849 {
5850 item = listitem_alloc();
5851 if (item != NULL)
5852 {
5853 item->li_tv = tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005854 item->li_tv.v_lock = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005855 list_append(l, item);
5856 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005857 else
5858 clear_tv(&tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005859 }
5860
5861 if (**arg == ']')
5862 break;
5863 if (**arg != ',')
5864 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005865 EMSG2(_("E696: Missing comma in List: %s"), *arg);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005866 goto failret;
5867 }
5868 *arg = skipwhite(*arg + 1);
5869 }
5870
5871 if (**arg != ']')
5872 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005873 EMSG2(_("E697: Missing end of List ']': %s"), *arg);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005874failret:
5875 if (evaluate)
Bram Moolenaar685295c2006-10-15 20:37:38 +00005876 list_free(l, TRUE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005877 return FAIL;
5878 }
5879
5880 *arg = skipwhite(*arg + 1);
5881 if (evaluate)
5882 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005883 rettv->v_type = VAR_LIST;
5884 rettv->vval.v_list = l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005885 ++l->lv_refcount;
5886 }
5887
5888 return OK;
5889}
5890
5891/*
5892 * Allocate an empty header for a list.
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00005893 * Caller should take care of the reference count.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005894 */
Bram Moolenaar1ef15e32006-02-01 21:56:25 +00005895 list_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005896list_alloc()
5897{
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005898 list_T *l;
5899
5900 l = (list_T *)alloc_clear(sizeof(list_T));
5901 if (l != NULL)
5902 {
5903 /* Prepend the list to the list of lists for garbage collection. */
5904 if (first_list != NULL)
5905 first_list->lv_used_prev = l;
5906 l->lv_used_prev = NULL;
5907 l->lv_used_next = first_list;
5908 first_list = l;
5909 }
5910 return l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005911}
5912
5913/*
Bram Moolenaareddf53b2006-02-27 00:11:10 +00005914 * Allocate an empty list for a return value.
5915 * Returns OK or FAIL.
5916 */
5917 static int
5918rettv_list_alloc(rettv)
5919 typval_T *rettv;
5920{
5921 list_T *l = list_alloc();
5922
5923 if (l == NULL)
5924 return FAIL;
5925
5926 rettv->vval.v_list = l;
5927 rettv->v_type = VAR_LIST;
5928 ++l->lv_refcount;
5929 return OK;
5930}
5931
5932/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005933 * Unreference a list: decrement the reference count and free it when it
5934 * becomes zero.
5935 */
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00005936 void
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005937list_unref(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00005938 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005939{
Bram Moolenaar685295c2006-10-15 20:37:38 +00005940 if (l != NULL && --l->lv_refcount <= 0)
5941 list_free(l, TRUE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005942}
5943
5944/*
5945 * Free a list, including all items it points to.
5946 * Ignores the reference count.
5947 */
Bram Moolenaar1ef15e32006-02-01 21:56:25 +00005948 void
Bram Moolenaar685295c2006-10-15 20:37:38 +00005949list_free(l, recurse)
5950 list_T *l;
5951 int recurse; /* Free Lists and Dictionaries recursively. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005952{
Bram Moolenaar33570922005-01-25 22:26:29 +00005953 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005954
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005955 /* Remove the list from the list of lists for garbage collection. */
5956 if (l->lv_used_prev == NULL)
5957 first_list = l->lv_used_next;
5958 else
5959 l->lv_used_prev->lv_used_next = l->lv_used_next;
5960 if (l->lv_used_next != NULL)
5961 l->lv_used_next->lv_used_prev = l->lv_used_prev;
5962
Bram Moolenaard9fba312005-06-26 22:34:35 +00005963 for (item = l->lv_first; item != NULL; item = l->lv_first)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005964 {
Bram Moolenaard9fba312005-06-26 22:34:35 +00005965 /* Remove the item before deleting it. */
5966 l->lv_first = item->li_next;
Bram Moolenaar685295c2006-10-15 20:37:38 +00005967 if (recurse || (item->li_tv.v_type != VAR_LIST
5968 && item->li_tv.v_type != VAR_DICT))
5969 clear_tv(&item->li_tv);
5970 vim_free(item);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005971 }
5972 vim_free(l);
5973}
5974
5975/*
5976 * Allocate a list item.
5977 */
Bram Moolenaardb913952012-06-29 12:54:53 +02005978 listitem_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005979listitem_alloc()
5980{
Bram Moolenaar33570922005-01-25 22:26:29 +00005981 return (listitem_T *)alloc(sizeof(listitem_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005982}
5983
5984/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00005985 * Free a list item. Also clears the value. Does not notify watchers.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005986 */
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005987 void
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005988listitem_free(item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005989 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005990{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005991 clear_tv(&item->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005992 vim_free(item);
5993}
5994
5995/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005996 * Remove a list item from a List and free it. Also clears the value.
5997 */
Bram Moolenaardb913952012-06-29 12:54:53 +02005998 void
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005999listitem_remove(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00006000 list_T *l;
6001 listitem_T *item;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00006002{
Bram Moolenaar3ec7f4e2014-05-07 17:31:37 +02006003 vimlist_remove(l, item, item);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00006004 listitem_free(item);
6005}
6006
6007/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006008 * Get the number of items in a list.
6009 */
6010 static long
6011list_len(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00006012 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006013{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006014 if (l == NULL)
6015 return 0L;
Bram Moolenaar758711c2005-02-02 23:11:38 +00006016 return l->lv_len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006017}
6018
6019/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006020 * Return TRUE when two lists have exactly the same values.
6021 */
6022 static int
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006023list_equal(l1, l2, ic, recursive)
Bram Moolenaar33570922005-01-25 22:26:29 +00006024 list_T *l1;
6025 list_T *l2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006026 int ic; /* ignore case for strings */
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006027 int recursive; /* TRUE when used recursively */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006028{
Bram Moolenaar33570922005-01-25 22:26:29 +00006029 listitem_T *item1, *item2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006030
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00006031 if (l1 == NULL || l2 == NULL)
6032 return FALSE;
Bram Moolenaar8b402a02006-10-17 13:16:39 +00006033 if (l1 == l2)
6034 return TRUE;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006035 if (list_len(l1) != list_len(l2))
6036 return FALSE;
6037
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006038 for (item1 = l1->lv_first, item2 = l2->lv_first;
6039 item1 != NULL && item2 != NULL;
6040 item1 = item1->li_next, item2 = item2->li_next)
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006041 if (!tv_equal(&item1->li_tv, &item2->li_tv, ic, recursive))
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006042 return FALSE;
6043 return item1 == NULL && item2 == NULL;
6044}
6045
Bram Moolenaarbd5e15f2010-07-17 21:19:38 +02006046#if defined(FEAT_RUBY) || defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) \
6047 || defined(FEAT_MZSCHEME) || defined(FEAT_LUA) || defined(PROTO)
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006048/*
6049 * Return the dictitem that an entry in a hashtable points to.
6050 */
6051 dictitem_T *
6052dict_lookup(hi)
6053 hashitem_T *hi;
6054{
6055 return HI2DI(hi);
6056}
6057#endif
6058
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006059/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006060 * Return TRUE when two dictionaries have exactly the same key/values.
6061 */
6062 static int
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006063dict_equal(d1, d2, ic, recursive)
Bram Moolenaar33570922005-01-25 22:26:29 +00006064 dict_T *d1;
6065 dict_T *d2;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006066 int ic; /* ignore case for strings */
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006067 int recursive; /* TRUE when used recursively */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006068{
Bram Moolenaar33570922005-01-25 22:26:29 +00006069 hashitem_T *hi;
6070 dictitem_T *item2;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006071 int todo;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006072
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00006073 if (d1 == NULL || d2 == NULL)
6074 return FALSE;
Bram Moolenaar8b402a02006-10-17 13:16:39 +00006075 if (d1 == d2)
6076 return TRUE;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006077 if (dict_len(d1) != dict_len(d2))
6078 return FALSE;
6079
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00006080 todo = (int)d1->dv_hashtab.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00006081 for (hi = d1->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006082 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006083 if (!HASHITEM_EMPTY(hi))
6084 {
6085 item2 = dict_find(d2, hi->hi_key, -1);
6086 if (item2 == NULL)
6087 return FALSE;
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006088 if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic, recursive))
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006089 return FALSE;
6090 --todo;
6091 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006092 }
6093 return TRUE;
6094}
6095
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006096static int tv_equal_recurse_limit;
6097
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006098/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006099 * Return TRUE if "tv1" and "tv2" have the same value.
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00006100 * Compares the items just like "==" would compare them, but strings and
Bram Moolenaar8c8de832008-06-24 22:58:06 +00006101 * numbers are different. Floats and numbers are also different.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006102 */
6103 static int
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006104tv_equal(tv1, tv2, ic, recursive)
Bram Moolenaar33570922005-01-25 22:26:29 +00006105 typval_T *tv1;
6106 typval_T *tv2;
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006107 int ic; /* ignore case */
6108 int recursive; /* TRUE when used recursively */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006109{
6110 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006111 char_u *s1, *s2;
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006112 static int recursive_cnt = 0; /* catch recursive loops */
Bram Moolenaarb47a2402006-10-15 13:09:12 +00006113 int r;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006114
Bram Moolenaar8b402a02006-10-17 13:16:39 +00006115 if (tv1->v_type != tv2->v_type)
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00006116 return FALSE;
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006117
Bram Moolenaar8b402a02006-10-17 13:16:39 +00006118 /* Catch lists and dicts that have an endless loop by limiting
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006119 * recursiveness to a limit. We guess they are equal then.
6120 * A fixed limit has the problem of still taking an awful long time.
6121 * Reduce the limit every time running into it. That should work fine for
6122 * deeply linked structures that are not recursively linked and catch
6123 * recursiveness quickly. */
6124 if (!recursive)
6125 tv_equal_recurse_limit = 1000;
6126 if (recursive_cnt >= tv_equal_recurse_limit)
6127 {
6128 --tv_equal_recurse_limit;
Bram Moolenaar8b402a02006-10-17 13:16:39 +00006129 return TRUE;
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006130 }
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00006131
6132 switch (tv1->v_type)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006133 {
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00006134 case VAR_LIST:
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006135 ++recursive_cnt;
6136 r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic, TRUE);
6137 --recursive_cnt;
Bram Moolenaarb47a2402006-10-15 13:09:12 +00006138 return r;
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00006139
6140 case VAR_DICT:
Bram Moolenaar67b3f992010-11-10 20:41:57 +01006141 ++recursive_cnt;
6142 r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, TRUE);
6143 --recursive_cnt;
Bram Moolenaarb47a2402006-10-15 13:09:12 +00006144 return r;
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00006145
6146 case VAR_FUNC:
6147 return (tv1->vval.v_string != NULL
6148 && tv2->vval.v_string != NULL
6149 && STRCMP(tv1->vval.v_string, tv2->vval.v_string) == 0);
6150
6151 case VAR_NUMBER:
6152 return tv1->vval.v_number == tv2->vval.v_number;
6153
Bram Moolenaar8c8de832008-06-24 22:58:06 +00006154#ifdef FEAT_FLOAT
6155 case VAR_FLOAT:
6156 return tv1->vval.v_float == tv2->vval.v_float;
6157#endif
6158
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00006159 case VAR_STRING:
6160 s1 = get_tv_string_buf(tv1, buf1);
6161 s2 = get_tv_string_buf(tv2, buf2);
6162 return ((ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2)) == 0);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006163 }
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00006164
6165 EMSG2(_(e_intern2), "tv_equal()");
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006166 return TRUE;
6167}
6168
6169/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006170 * Locate item with index "n" in list "l" and return it.
6171 * A negative index is counted from the end; -1 is the last item.
6172 * Returns NULL when "n" is out of range.
6173 */
Bram Moolenaardb913952012-06-29 12:54:53 +02006174 listitem_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006175list_find(l, n)
Bram Moolenaar33570922005-01-25 22:26:29 +00006176 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006177 long n;
6178{
Bram Moolenaar33570922005-01-25 22:26:29 +00006179 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006180 long idx;
6181
6182 if (l == NULL)
6183 return NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +00006184
6185 /* Negative index is relative to the end. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006186 if (n < 0)
Bram Moolenaar758711c2005-02-02 23:11:38 +00006187 n = l->lv_len + n;
6188
6189 /* Check for index out of range. */
6190 if (n < 0 || n >= l->lv_len)
6191 return NULL;
6192
6193 /* When there is a cached index may start search from there. */
6194 if (l->lv_idx_item != NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006195 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00006196 if (n < l->lv_idx / 2)
6197 {
6198 /* closest to the start of the list */
6199 item = l->lv_first;
6200 idx = 0;
6201 }
6202 else if (n > (l->lv_idx + l->lv_len) / 2)
6203 {
6204 /* closest to the end of the list */
6205 item = l->lv_last;
6206 idx = l->lv_len - 1;
6207 }
6208 else
6209 {
6210 /* closest to the cached index */
6211 item = l->lv_idx_item;
6212 idx = l->lv_idx;
6213 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006214 }
6215 else
6216 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00006217 if (n < l->lv_len / 2)
6218 {
6219 /* closest to the start of the list */
6220 item = l->lv_first;
6221 idx = 0;
6222 }
6223 else
6224 {
6225 /* closest to the end of the list */
6226 item = l->lv_last;
6227 idx = l->lv_len - 1;
6228 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006229 }
Bram Moolenaar758711c2005-02-02 23:11:38 +00006230
6231 while (n > idx)
6232 {
6233 /* search forward */
6234 item = item->li_next;
6235 ++idx;
6236 }
6237 while (n < idx)
6238 {
6239 /* search backward */
6240 item = item->li_prev;
6241 --idx;
6242 }
6243
6244 /* cache the used index */
6245 l->lv_idx = idx;
6246 l->lv_idx_item = item;
6247
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006248 return item;
6249}
6250
6251/*
Bram Moolenaara5525202006-03-02 22:52:09 +00006252 * Get list item "l[idx]" as a number.
6253 */
6254 static long
6255list_find_nr(l, idx, errorp)
6256 list_T *l;
6257 long idx;
6258 int *errorp; /* set to TRUE when something wrong */
6259{
6260 listitem_T *li;
6261
6262 li = list_find(l, idx);
6263 if (li == NULL)
6264 {
6265 if (errorp != NULL)
6266 *errorp = TRUE;
6267 return -1L;
6268 }
6269 return get_tv_number_chk(&li->li_tv, errorp);
6270}
6271
6272/*
Bram Moolenaard812df62008-11-09 12:46:09 +00006273 * Get list item "l[idx - 1]" as a string. Returns NULL for failure.
6274 */
6275 char_u *
6276list_find_str(l, idx)
6277 list_T *l;
6278 long idx;
6279{
6280 listitem_T *li;
6281
6282 li = list_find(l, idx - 1);
6283 if (li == NULL)
6284 {
6285 EMSGN(_(e_listidx), idx);
6286 return NULL;
6287 }
6288 return get_tv_string(&li->li_tv);
6289}
6290
6291/*
Bram Moolenaar6cc16192005-01-08 21:49:45 +00006292 * Locate "item" list "l" and return its index.
6293 * Returns -1 when "item" is not in the list.
6294 */
6295 static long
6296list_idx_of_item(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00006297 list_T *l;
6298 listitem_T *item;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00006299{
6300 long idx = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00006301 listitem_T *li;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00006302
6303 if (l == NULL)
6304 return -1;
6305 idx = 0;
6306 for (li = l->lv_first; li != NULL && li != item; li = li->li_next)
6307 ++idx;
6308 if (li == NULL)
6309 return -1;
Bram Moolenaar75c50c42005-06-04 22:06:24 +00006310 return idx;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00006311}
6312
6313/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006314 * Append item "item" to the end of list "l".
6315 */
Bram Moolenaardb913952012-06-29 12:54:53 +02006316 void
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006317list_append(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00006318 list_T *l;
6319 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006320{
6321 if (l->lv_last == NULL)
6322 {
6323 /* empty list */
6324 l->lv_first = item;
6325 l->lv_last = item;
6326 item->li_prev = NULL;
6327 }
6328 else
6329 {
6330 l->lv_last->li_next = item;
6331 item->li_prev = l->lv_last;
6332 l->lv_last = item;
6333 }
Bram Moolenaar758711c2005-02-02 23:11:38 +00006334 ++l->lv_len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006335 item->li_next = NULL;
6336}
6337
6338/*
Bram Moolenaar33570922005-01-25 22:26:29 +00006339 * Append typval_T "tv" to the end of list "l".
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006340 * Return FAIL when out of memory.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006341 */
Bram Moolenaar7e506b62010-01-19 15:55:06 +01006342 int
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006343list_append_tv(l, tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006344 list_T *l;
6345 typval_T *tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006346{
Bram Moolenaar05159a02005-02-26 23:04:13 +00006347 listitem_T *li = listitem_alloc();
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006348
Bram Moolenaar05159a02005-02-26 23:04:13 +00006349 if (li == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006350 return FAIL;
Bram Moolenaar05159a02005-02-26 23:04:13 +00006351 copy_tv(tv, &li->li_tv);
6352 list_append(l, li);
6353 return OK;
6354}
6355
6356/*
Bram Moolenaar2641f772005-03-25 21:58:17 +00006357 * Add a dictionary to a list. Used by getqflist().
Bram Moolenaar05159a02005-02-26 23:04:13 +00006358 * Return FAIL when out of memory.
6359 */
6360 int
6361list_append_dict(list, dict)
6362 list_T *list;
6363 dict_T *dict;
6364{
6365 listitem_T *li = listitem_alloc();
6366
6367 if (li == NULL)
6368 return FAIL;
6369 li->li_tv.v_type = VAR_DICT;
6370 li->li_tv.v_lock = 0;
6371 li->li_tv.vval.v_dict = dict;
6372 list_append(list, li);
6373 ++dict->dv_refcount;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006374 return OK;
6375}
6376
6377/*
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00006378 * Make a copy of "str" and append it as an item to list "l".
Bram Moolenaar4463f292005-09-25 22:20:24 +00006379 * When "len" >= 0 use "str[len]".
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00006380 * Returns FAIL when out of memory.
6381 */
Bram Moolenaard812df62008-11-09 12:46:09 +00006382 int
Bram Moolenaar4463f292005-09-25 22:20:24 +00006383list_append_string(l, str, len)
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00006384 list_T *l;
6385 char_u *str;
Bram Moolenaar4463f292005-09-25 22:20:24 +00006386 int len;
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00006387{
6388 listitem_T *li = listitem_alloc();
6389
6390 if (li == NULL)
6391 return FAIL;
6392 list_append(l, li);
6393 li->li_tv.v_type = VAR_STRING;
6394 li->li_tv.v_lock = 0;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00006395 if (str == NULL)
6396 li->li_tv.vval.v_string = NULL;
6397 else if ((li->li_tv.vval.v_string = (len >= 0 ? vim_strnsave(str, len)
Bram Moolenaar482aaeb2005-09-29 18:26:07 +00006398 : vim_strsave(str))) == NULL)
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00006399 return FAIL;
6400 return OK;
6401}
6402
6403/*
Bram Moolenaar4463f292005-09-25 22:20:24 +00006404 * Append "n" to list "l".
6405 * Returns FAIL when out of memory.
6406 */
6407 static int
6408list_append_number(l, n)
6409 list_T *l;
6410 varnumber_T n;
6411{
6412 listitem_T *li;
6413
6414 li = listitem_alloc();
6415 if (li == NULL)
6416 return FAIL;
6417 li->li_tv.v_type = VAR_NUMBER;
6418 li->li_tv.v_lock = 0;
6419 li->li_tv.vval.v_number = n;
6420 list_append(l, li);
6421 return OK;
6422}
6423
6424/*
Bram Moolenaar33570922005-01-25 22:26:29 +00006425 * Insert typval_T "tv" in list "l" before "item".
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006426 * If "item" is NULL append at the end.
6427 * Return FAIL when out of memory.
6428 */
Bram Moolenaardb913952012-06-29 12:54:53 +02006429 int
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006430list_insert_tv(l, tv, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00006431 list_T *l;
6432 typval_T *tv;
6433 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006434{
Bram Moolenaar33570922005-01-25 22:26:29 +00006435 listitem_T *ni = listitem_alloc();
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006436
6437 if (ni == NULL)
6438 return FAIL;
6439 copy_tv(tv, &ni->li_tv);
Bram Moolenaar063a46b2014-01-14 16:36:51 +01006440 list_insert(l, ni, item);
6441 return OK;
6442}
6443
6444 void
6445list_insert(l, ni, item)
6446 list_T *l;
6447 listitem_T *ni;
6448 listitem_T *item;
6449{
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006450 if (item == NULL)
6451 /* Append new item at end of list. */
6452 list_append(l, ni);
6453 else
6454 {
6455 /* Insert new item before existing item. */
6456 ni->li_prev = item->li_prev;
6457 ni->li_next = item;
6458 if (item->li_prev == NULL)
Bram Moolenaar758711c2005-02-02 23:11:38 +00006459 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006460 l->lv_first = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00006461 ++l->lv_idx;
6462 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006463 else
Bram Moolenaar758711c2005-02-02 23:11:38 +00006464 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006465 item->li_prev->li_next = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00006466 l->lv_idx_item = NULL;
6467 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006468 item->li_prev = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00006469 ++l->lv_len;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006470 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006471}
6472
6473/*
6474 * Extend "l1" with "l2".
6475 * If "bef" is NULL append at the end, otherwise insert before this item.
6476 * Returns FAIL when out of memory.
6477 */
6478 static int
6479list_extend(l1, l2, bef)
Bram Moolenaar33570922005-01-25 22:26:29 +00006480 list_T *l1;
6481 list_T *l2;
6482 listitem_T *bef;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006483{
Bram Moolenaar33570922005-01-25 22:26:29 +00006484 listitem_T *item;
Bram Moolenaardc9cf9c2008-08-08 10:36:31 +00006485 int todo = l2->lv_len;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006486
Bram Moolenaardc9cf9c2008-08-08 10:36:31 +00006487 /* We also quit the loop when we have inserted the original item count of
6488 * the list, avoid a hang when we extend a list with itself. */
6489 for (item = l2->lv_first; item != NULL && --todo >= 0; item = item->li_next)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006490 if (list_insert_tv(l1, &item->li_tv, bef) == FAIL)
6491 return FAIL;
6492 return OK;
6493}
6494
6495/*
6496 * Concatenate lists "l1" and "l2" into a new list, stored in "tv".
6497 * Return FAIL when out of memory.
6498 */
6499 static int
6500list_concat(l1, l2, tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006501 list_T *l1;
6502 list_T *l2;
6503 typval_T *tv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006504{
Bram Moolenaar33570922005-01-25 22:26:29 +00006505 list_T *l;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006506
Bram Moolenaar9bf749b2008-07-27 13:57:29 +00006507 if (l1 == NULL || l2 == NULL)
6508 return FAIL;
6509
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006510 /* make a copy of the first list. */
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006511 l = list_copy(l1, FALSE, 0);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006512 if (l == NULL)
6513 return FAIL;
6514 tv->v_type = VAR_LIST;
6515 tv->vval.v_list = l;
6516
6517 /* append all items from the second list */
6518 return list_extend(l, l2, NULL);
6519}
6520
6521/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00006522 * Make a copy of list "orig". Shallow if "deep" is FALSE.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006523 * The refcount of the new list is set to 1.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006524 * See item_copy() for "copyID".
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006525 * Returns NULL when out of memory.
6526 */
Bram Moolenaar33570922005-01-25 22:26:29 +00006527 static list_T *
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006528list_copy(orig, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00006529 list_T *orig;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006530 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006531 int copyID;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006532{
Bram Moolenaar33570922005-01-25 22:26:29 +00006533 list_T *copy;
6534 listitem_T *item;
6535 listitem_T *ni;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006536
6537 if (orig == NULL)
6538 return NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006539
6540 copy = list_alloc();
6541 if (copy != NULL)
6542 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006543 if (copyID != 0)
6544 {
6545 /* Do this before adding the items, because one of the items may
6546 * refer back to this list. */
6547 orig->lv_copyID = copyID;
6548 orig->lv_copylist = copy;
6549 }
6550 for (item = orig->lv_first; item != NULL && !got_int;
6551 item = item->li_next)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006552 {
6553 ni = listitem_alloc();
6554 if (ni == NULL)
6555 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006556 if (deep)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006557 {
6558 if (item_copy(&item->li_tv, &ni->li_tv, deep, copyID) == FAIL)
6559 {
6560 vim_free(ni);
6561 break;
6562 }
6563 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006564 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006565 copy_tv(&item->li_tv, &ni->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006566 list_append(copy, ni);
6567 }
6568 ++copy->lv_refcount;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006569 if (item != NULL)
6570 {
6571 list_unref(copy);
6572 copy = NULL;
6573 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006574 }
6575
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006576 return copy;
6577}
6578
6579/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006580 * Remove items "item" to "item2" from list "l".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00006581 * Does not free the listitem or the value!
Bram Moolenaar3ec7f4e2014-05-07 17:31:37 +02006582 * This used to be called list_remove, but that conflicts with a Sun header
6583 * file.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006584 */
Bram Moolenaardb913952012-06-29 12:54:53 +02006585 void
Bram Moolenaar3ec7f4e2014-05-07 17:31:37 +02006586vimlist_remove(l, item, item2)
Bram Moolenaar33570922005-01-25 22:26:29 +00006587 list_T *l;
6588 listitem_T *item;
6589 listitem_T *item2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006590{
Bram Moolenaar33570922005-01-25 22:26:29 +00006591 listitem_T *ip;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006592
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006593 /* notify watchers */
6594 for (ip = item; ip != NULL; ip = ip->li_next)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006595 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00006596 --l->lv_len;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006597 list_fix_watch(l, ip);
6598 if (ip == item2)
6599 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006600 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006601
6602 if (item2->li_next == NULL)
6603 l->lv_last = item->li_prev;
6604 else
6605 item2->li_next->li_prev = item->li_prev;
6606 if (item->li_prev == NULL)
6607 l->lv_first = item2->li_next;
6608 else
6609 item->li_prev->li_next = item2->li_next;
Bram Moolenaar758711c2005-02-02 23:11:38 +00006610 l->lv_idx_item = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006611}
6612
6613/*
6614 * Return an allocated string with the string representation of a list.
6615 * May return NULL.
6616 */
6617 static char_u *
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006618list2string(tv, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00006619 typval_T *tv;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006620 int copyID;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006621{
6622 garray_T ga;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006623
6624 if (tv->vval.v_list == NULL)
6625 return NULL;
6626 ga_init2(&ga, (int)sizeof(char), 80);
6627 ga_append(&ga, '[');
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006628 if (list_join(&ga, tv->vval.v_list, (char_u *)", ", FALSE, copyID) == FAIL)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006629 {
6630 vim_free(ga.ga_data);
6631 return NULL;
6632 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006633 ga_append(&ga, ']');
6634 ga_append(&ga, NUL);
6635 return (char_u *)ga.ga_data;
6636}
6637
Bram Moolenaar3fe37d62012-02-06 00:13:22 +01006638typedef struct join_S {
6639 char_u *s;
6640 char_u *tofree;
6641} join_T;
6642
6643 static int
6644list_join_inner(gap, l, sep, echo_style, copyID, join_gap)
6645 garray_T *gap; /* to store the result in */
6646 list_T *l;
6647 char_u *sep;
6648 int echo_style;
6649 int copyID;
6650 garray_T *join_gap; /* to keep each list item string */
6651{
6652 int i;
6653 join_T *p;
6654 int len;
6655 int sumlen = 0;
6656 int first = TRUE;
6657 char_u *tofree;
6658 char_u numbuf[NUMBUFLEN];
6659 listitem_T *item;
6660 char_u *s;
6661
6662 /* Stringify each item in the list. */
6663 for (item = l->lv_first; item != NULL && !got_int; item = item->li_next)
6664 {
6665 if (echo_style)
6666 s = echo_string(&item->li_tv, &tofree, numbuf, copyID);
6667 else
6668 s = tv2string(&item->li_tv, &tofree, numbuf, copyID);
6669 if (s == NULL)
6670 return FAIL;
6671
6672 len = (int)STRLEN(s);
6673 sumlen += len;
6674
6675 ga_grow(join_gap, 1);
6676 p = ((join_T *)join_gap->ga_data) + (join_gap->ga_len++);
6677 if (tofree != NULL || s != numbuf)
6678 {
6679 p->s = s;
6680 p->tofree = tofree;
6681 }
6682 else
6683 {
6684 p->s = vim_strnsave(s, len);
6685 p->tofree = p->s;
6686 }
6687
6688 line_breakcheck();
6689 }
6690
6691 /* Allocate result buffer with its total size, avoid re-allocation and
6692 * multiple copy operations. Add 2 for a tailing ']' and NUL. */
6693 if (join_gap->ga_len >= 2)
6694 sumlen += (int)STRLEN(sep) * (join_gap->ga_len - 1);
6695 if (ga_grow(gap, sumlen + 2) == FAIL)
6696 return FAIL;
6697
6698 for (i = 0; i < join_gap->ga_len && !got_int; ++i)
6699 {
6700 if (first)
6701 first = FALSE;
6702 else
6703 ga_concat(gap, sep);
6704 p = ((join_T *)join_gap->ga_data) + i;
6705
6706 if (p->s != NULL)
6707 ga_concat(gap, p->s);
6708 line_breakcheck();
6709 }
6710
6711 return OK;
6712}
6713
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006714/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006715 * Join list "l" into a string in "*gap", using separator "sep".
Bram Moolenaar70b2a562012-01-10 22:26:17 +01006716 * When "echo_style" is TRUE use String as echoed, otherwise as inside a List.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006717 * Return FAIL or OK.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006718 */
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006719 static int
Bram Moolenaar70b2a562012-01-10 22:26:17 +01006720list_join(gap, l, sep, echo_style, copyID)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006721 garray_T *gap;
Bram Moolenaar33570922005-01-25 22:26:29 +00006722 list_T *l;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006723 char_u *sep;
Bram Moolenaar70b2a562012-01-10 22:26:17 +01006724 int echo_style;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006725 int copyID;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006726{
Bram Moolenaar3fe37d62012-02-06 00:13:22 +01006727 garray_T join_ga;
6728 int retval;
6729 join_T *p;
6730 int i;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006731
Bram Moolenaar3fe37d62012-02-06 00:13:22 +01006732 ga_init2(&join_ga, (int)sizeof(join_T), l->lv_len);
6733 retval = list_join_inner(gap, l, sep, echo_style, copyID, &join_ga);
6734
6735 /* Dispose each item in join_ga. */
6736 if (join_ga.ga_data != NULL)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006737 {
Bram Moolenaar3fe37d62012-02-06 00:13:22 +01006738 p = (join_T *)join_ga.ga_data;
6739 for (i = 0; i < join_ga.ga_len; ++i)
6740 {
6741 vim_free(p->tofree);
6742 ++p;
6743 }
6744 ga_clear(&join_ga);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006745 }
Bram Moolenaar3fe37d62012-02-06 00:13:22 +01006746
6747 return retval;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006748}
6749
6750/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006751 * Garbage collection for lists and dictionaries.
6752 *
6753 * We use reference counts to be able to free most items right away when they
6754 * are no longer used. But for composite items it's possible that it becomes
6755 * unused while the reference count is > 0: When there is a recursive
6756 * reference. Example:
6757 * :let l = [1, 2, 3]
6758 * :let d = {9: l}
6759 * :let l[1] = d
6760 *
6761 * Since this is quite unusual we handle this with garbage collection: every
6762 * once in a while find out which lists and dicts are not referenced from any
6763 * variable.
6764 *
6765 * Here is a good reference text about garbage collection (refers to Python
6766 * but it applies to all reference-counting mechanisms):
6767 * http://python.ca/nas/python/gc/
Bram Moolenaard9fba312005-06-26 22:34:35 +00006768 */
Bram Moolenaard9fba312005-06-26 22:34:35 +00006769
6770/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006771 * Do garbage collection for lists and dicts.
6772 * Return TRUE if some memory was freed.
Bram Moolenaard9fba312005-06-26 22:34:35 +00006773 */
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006774 int
6775garbage_collect()
Bram Moolenaard9fba312005-06-26 22:34:35 +00006776{
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006777 int copyID;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006778 buf_T *buf;
6779 win_T *wp;
6780 int i;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +00006781 funccall_T *fc, **pfc;
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006782 int did_free;
6783 int did_free_funccal = FALSE;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00006784#ifdef FEAT_WINDOWS
6785 tabpage_T *tp;
6786#endif
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006787
Bram Moolenaar9fecb462006-09-05 10:59:47 +00006788 /* Only do this once. */
6789 want_garbage_collect = FALSE;
6790 may_garbage_collect = FALSE;
Bram Moolenaar9d2c8c12007-09-25 16:00:00 +00006791 garbage_collect_at_exit = FALSE;
Bram Moolenaar9fecb462006-09-05 10:59:47 +00006792
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006793 /* We advance by two because we add one for items referenced through
6794 * previous_funccal. */
6795 current_copyID += COPYID_INC;
6796 copyID = current_copyID;
6797
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006798 /*
6799 * 1. Go through all accessible variables and mark all lists and dicts
6800 * with copyID.
6801 */
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006802
6803 /* Don't free variables in the previous_funccal list unless they are only
6804 * referenced through previous_funccal. This must be first, because if
Bram Moolenaar2c2398c2009-06-03 11:22:45 +00006805 * the item is referenced elsewhere the funccal must not be freed. */
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006806 for (fc = previous_funccal; fc != NULL; fc = fc->caller)
6807 {
6808 set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1);
6809 set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1);
6810 }
6811
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006812 /* script-local variables */
6813 for (i = 1; i <= ga_scripts.ga_len; ++i)
6814 set_ref_in_ht(&SCRIPT_VARS(i), copyID);
6815
6816 /* buffer-local variables */
6817 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
Bram Moolenaar429fa852013-04-15 12:27:36 +02006818 set_ref_in_item(&buf->b_bufvar.di_tv, copyID);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006819
6820 /* window-local variables */
Bram Moolenaar910f66f2006-04-05 20:41:53 +00006821 FOR_ALL_TAB_WINDOWS(tp, wp)
Bram Moolenaar429fa852013-04-15 12:27:36 +02006822 set_ref_in_item(&wp->w_winvar.di_tv, copyID);
Bram Moolenaar3bb28552013-04-15 18:25:59 +02006823#ifdef FEAT_AUTOCMD
6824 if (aucmd_win != NULL)
6825 set_ref_in_item(&aucmd_win->w_winvar.di_tv, copyID);
6826#endif
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006827
Bram Moolenaar910f66f2006-04-05 20:41:53 +00006828#ifdef FEAT_WINDOWS
6829 /* tabpage-local variables */
6830 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
Bram Moolenaar429fa852013-04-15 12:27:36 +02006831 set_ref_in_item(&tp->tp_winvar.di_tv, copyID);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00006832#endif
6833
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006834 /* global variables */
6835 set_ref_in_ht(&globvarht, copyID);
6836
6837 /* function-local variables */
6838 for (fc = current_funccal; fc != NULL; fc = fc->caller)
6839 {
6840 set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID);
6841 set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID);
6842 }
6843
Bram Moolenaard812df62008-11-09 12:46:09 +00006844 /* v: vars */
6845 set_ref_in_ht(&vimvarht, copyID);
6846
Bram Moolenaar1dced572012-04-05 16:54:08 +02006847#ifdef FEAT_LUA
6848 set_ref_in_lua(copyID);
6849#endif
6850
Bram Moolenaardb913952012-06-29 12:54:53 +02006851#ifdef FEAT_PYTHON
6852 set_ref_in_python(copyID);
6853#endif
6854
6855#ifdef FEAT_PYTHON3
6856 set_ref_in_python3(copyID);
6857#endif
6858
Bram Moolenaar2c2398c2009-06-03 11:22:45 +00006859 /*
6860 * 2. Free lists and dictionaries that are not referenced.
6861 */
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006862 did_free = free_unref_items(copyID);
6863
Bram Moolenaar2c2398c2009-06-03 11:22:45 +00006864 /*
6865 * 3. Check if any funccal can be freed now.
6866 */
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006867 for (pfc = &previous_funccal; *pfc != NULL; )
6868 {
6869 if (can_free_funccal(*pfc, copyID))
6870 {
6871 fc = *pfc;
6872 *pfc = fc->caller;
6873 free_funccal(fc, TRUE);
6874 did_free = TRUE;
6875 did_free_funccal = TRUE;
6876 }
6877 else
6878 pfc = &(*pfc)->caller;
6879 }
6880 if (did_free_funccal)
6881 /* When a funccal was freed some more items might be garbage
6882 * collected, so run again. */
6883 (void)garbage_collect();
6884
6885 return did_free;
6886}
6887
6888/*
6889 * Free lists and dictionaries that are no longer referenced.
6890 */
6891 static int
6892free_unref_items(copyID)
6893 int copyID;
6894{
6895 dict_T *dd;
6896 list_T *ll;
6897 int did_free = FALSE;
6898
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006899 /*
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006900 * Go through the list of dicts and free items without the copyID.
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006901 */
6902 for (dd = first_dict; dd != NULL; )
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006903 if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK))
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006904 {
Bram Moolenaar685295c2006-10-15 20:37:38 +00006905 /* Free the Dictionary and ordinary items it contains, but don't
6906 * recurse into Lists and Dictionaries, they will be in the list
6907 * of dicts or list of lists. */
6908 dict_free(dd, FALSE);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006909 did_free = TRUE;
6910
6911 /* restart, next dict may also have been freed */
6912 dd = first_dict;
6913 }
6914 else
6915 dd = dd->dv_used_next;
6916
6917 /*
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006918 * Go through the list of lists and free items without the copyID.
6919 * But don't free a list that has a watcher (used in a for loop), these
6920 * are not referenced anywhere.
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006921 */
6922 for (ll = first_list; ll != NULL; )
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +00006923 if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)
6924 && ll->lv_watch == NULL)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006925 {
Bram Moolenaar685295c2006-10-15 20:37:38 +00006926 /* Free the List and ordinary items it contains, but don't recurse
6927 * into Lists and Dictionaries, they will be in the list of dicts
6928 * or list of lists. */
6929 list_free(ll, FALSE);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006930 did_free = TRUE;
6931
Bram Moolenaar7bb4c6e2005-09-07 21:22:27 +00006932 /* restart, next list may also have been freed */
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006933 ll = first_list;
6934 }
6935 else
6936 ll = ll->lv_used_next;
6937
6938 return did_free;
6939}
6940
6941/*
6942 * Mark all lists and dicts referenced through hashtab "ht" with "copyID".
6943 */
Bram Moolenaardb913952012-06-29 12:54:53 +02006944 void
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006945set_ref_in_ht(ht, copyID)
6946 hashtab_T *ht;
6947 int copyID;
6948{
6949 int todo;
6950 hashitem_T *hi;
6951
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00006952 todo = (int)ht->ht_used;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006953 for (hi = ht->ht_array; todo > 0; ++hi)
6954 if (!HASHITEM_EMPTY(hi))
6955 {
6956 --todo;
6957 set_ref_in_item(&HI2DI(hi)->di_tv, copyID);
6958 }
6959}
6960
6961/*
6962 * Mark all lists and dicts referenced through list "l" with "copyID".
6963 */
Bram Moolenaardb913952012-06-29 12:54:53 +02006964 void
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006965set_ref_in_list(l, copyID)
6966 list_T *l;
6967 int copyID;
6968{
6969 listitem_T *li;
6970
6971 for (li = l->lv_first; li != NULL; li = li->li_next)
6972 set_ref_in_item(&li->li_tv, copyID);
6973}
6974
6975/*
6976 * Mark all lists and dicts referenced through typval "tv" with "copyID".
6977 */
Bram Moolenaardb913952012-06-29 12:54:53 +02006978 void
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006979set_ref_in_item(tv, copyID)
6980 typval_T *tv;
6981 int copyID;
6982{
6983 dict_T *dd;
6984 list_T *ll;
Bram Moolenaard9fba312005-06-26 22:34:35 +00006985
6986 switch (tv->v_type)
6987 {
6988 case VAR_DICT:
6989 dd = tv->vval.v_dict;
Bram Moolenaard812df62008-11-09 12:46:09 +00006990 if (dd != NULL && dd->dv_copyID != copyID)
Bram Moolenaard9fba312005-06-26 22:34:35 +00006991 {
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006992 /* Didn't see this dict yet. */
6993 dd->dv_copyID = copyID;
6994 set_ref_in_ht(&dd->dv_hashtab, copyID);
Bram Moolenaard9fba312005-06-26 22:34:35 +00006995 }
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006996 break;
Bram Moolenaard9fba312005-06-26 22:34:35 +00006997
6998 case VAR_LIST:
6999 ll = tv->vval.v_list;
Bram Moolenaard812df62008-11-09 12:46:09 +00007000 if (ll != NULL && ll->lv_copyID != copyID)
Bram Moolenaard9fba312005-06-26 22:34:35 +00007001 {
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007002 /* Didn't see this list yet. */
7003 ll->lv_copyID = copyID;
7004 set_ref_in_list(ll, copyID);
Bram Moolenaard9fba312005-06-26 22:34:35 +00007005 }
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007006 break;
Bram Moolenaard9fba312005-06-26 22:34:35 +00007007 }
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007008 return;
Bram Moolenaard9fba312005-06-26 22:34:35 +00007009}
7010
7011/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00007012 * Allocate an empty header for a dictionary.
7013 */
Bram Moolenaar05159a02005-02-26 23:04:13 +00007014 dict_T *
Bram Moolenaar8c711452005-01-14 21:53:12 +00007015dict_alloc()
7016{
Bram Moolenaar33570922005-01-25 22:26:29 +00007017 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007018
Bram Moolenaar33570922005-01-25 22:26:29 +00007019 d = (dict_T *)alloc(sizeof(dict_T));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007020 if (d != NULL)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007021 {
Bram Moolenaarbdb62052012-07-16 17:31:53 +02007022 /* Add the dict to the list of dicts for garbage collection. */
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007023 if (first_dict != NULL)
7024 first_dict->dv_used_prev = d;
7025 d->dv_used_next = first_dict;
7026 d->dv_used_prev = NULL;
Bram Moolenaar685295c2006-10-15 20:37:38 +00007027 first_dict = d;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007028
Bram Moolenaar33570922005-01-25 22:26:29 +00007029 hash_init(&d->dv_hashtab);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007030 d->dv_lock = 0;
Bram Moolenaarbdb62052012-07-16 17:31:53 +02007031 d->dv_scope = 0;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007032 d->dv_refcount = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007033 d->dv_copyID = 0;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007034 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007035 return d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007036}
7037
7038/*
Bram Moolenaara800b422010-06-27 01:15:55 +02007039 * Allocate an empty dict for a return value.
7040 * Returns OK or FAIL.
7041 */
7042 static int
7043rettv_dict_alloc(rettv)
7044 typval_T *rettv;
7045{
7046 dict_T *d = dict_alloc();
7047
7048 if (d == NULL)
7049 return FAIL;
7050
7051 rettv->vval.v_dict = d;
7052 rettv->v_type = VAR_DICT;
7053 ++d->dv_refcount;
7054 return OK;
7055}
7056
7057
7058/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00007059 * Unreference a Dictionary: decrement the reference count and free it when it
7060 * becomes zero.
7061 */
Bram Moolenaar82139082011-09-14 16:52:09 +02007062 void
Bram Moolenaar8c711452005-01-14 21:53:12 +00007063dict_unref(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00007064 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007065{
Bram Moolenaar685295c2006-10-15 20:37:38 +00007066 if (d != NULL && --d->dv_refcount <= 0)
7067 dict_free(d, TRUE);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007068}
7069
7070/*
7071 * Free a Dictionary, including all items it contains.
7072 * Ignores the reference count.
7073 */
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02007074 void
Bram Moolenaar685295c2006-10-15 20:37:38 +00007075dict_free(d, recurse)
7076 dict_T *d;
7077 int recurse; /* Free Lists and Dictionaries recursively. */
Bram Moolenaar8c711452005-01-14 21:53:12 +00007078{
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007079 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00007080 hashitem_T *hi;
Bram Moolenaard9fba312005-06-26 22:34:35 +00007081 dictitem_T *di;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007082
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007083 /* Remove the dict from the list of dicts for garbage collection. */
7084 if (d->dv_used_prev == NULL)
7085 first_dict = d->dv_used_next;
7086 else
7087 d->dv_used_prev->dv_used_next = d->dv_used_next;
7088 if (d->dv_used_next != NULL)
7089 d->dv_used_next->dv_used_prev = d->dv_used_prev;
7090
7091 /* Lock the hashtab, we don't want it to resize while freeing items. */
Bram Moolenaard9fba312005-06-26 22:34:35 +00007092 hash_lock(&d->dv_hashtab);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007093 todo = (int)d->dv_hashtab.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00007094 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +00007095 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007096 if (!HASHITEM_EMPTY(hi))
7097 {
Bram Moolenaard9fba312005-06-26 22:34:35 +00007098 /* Remove the item before deleting it, just in case there is
7099 * something recursive causing trouble. */
7100 di = HI2DI(hi);
7101 hash_remove(&d->dv_hashtab, hi);
Bram Moolenaar685295c2006-10-15 20:37:38 +00007102 if (recurse || (di->di_tv.v_type != VAR_LIST
7103 && di->di_tv.v_type != VAR_DICT))
7104 clear_tv(&di->di_tv);
7105 vim_free(di);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007106 --todo;
7107 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00007108 }
Bram Moolenaar33570922005-01-25 22:26:29 +00007109 hash_clear(&d->dv_hashtab);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007110 vim_free(d);
7111}
7112
7113/*
7114 * Allocate a Dictionary item.
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007115 * The "key" is copied to the new item.
7116 * Note that the value of the item "di_tv" still needs to be initialized!
7117 * Returns NULL when out of memory.
Bram Moolenaar8c711452005-01-14 21:53:12 +00007118 */
Bram Moolenaar7e506b62010-01-19 15:55:06 +01007119 dictitem_T *
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007120dictitem_alloc(key)
7121 char_u *key;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007122{
Bram Moolenaar33570922005-01-25 22:26:29 +00007123 dictitem_T *di;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007124
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007125 di = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T) + STRLEN(key)));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007126 if (di != NULL)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007127 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007128 STRCPY(di->di_key, key);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007129 di->di_flags = 0;
7130 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007131 return di;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007132}
7133
7134/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00007135 * Make a copy of a Dictionary item.
7136 */
Bram Moolenaar33570922005-01-25 22:26:29 +00007137 static dictitem_T *
Bram Moolenaare9a41262005-01-15 22:18:47 +00007138dictitem_copy(org)
Bram Moolenaar33570922005-01-25 22:26:29 +00007139 dictitem_T *org;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007140{
Bram Moolenaar33570922005-01-25 22:26:29 +00007141 dictitem_T *di;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007142
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007143 di = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
7144 + STRLEN(org->di_key)));
Bram Moolenaare9a41262005-01-15 22:18:47 +00007145 if (di != NULL)
7146 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007147 STRCPY(di->di_key, org->di_key);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007148 di->di_flags = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007149 copy_tv(&org->di_tv, &di->di_tv);
7150 }
7151 return di;
7152}
7153
7154/*
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007155 * Remove item "item" from Dictionary "dict" and free it.
7156 */
7157 static void
7158dictitem_remove(dict, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00007159 dict_T *dict;
7160 dictitem_T *item;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007161{
Bram Moolenaar33570922005-01-25 22:26:29 +00007162 hashitem_T *hi;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007163
Bram Moolenaar33570922005-01-25 22:26:29 +00007164 hi = hash_find(&dict->dv_hashtab, item->di_key);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007165 if (HASHITEM_EMPTY(hi))
7166 EMSG2(_(e_intern2), "dictitem_remove()");
7167 else
Bram Moolenaar33570922005-01-25 22:26:29 +00007168 hash_remove(&dict->dv_hashtab, hi);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007169 dictitem_free(item);
7170}
7171
7172/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00007173 * Free a dict item. Also clears the value.
7174 */
Bram Moolenaar7e506b62010-01-19 15:55:06 +01007175 void
Bram Moolenaar8c711452005-01-14 21:53:12 +00007176dictitem_free(item)
Bram Moolenaar33570922005-01-25 22:26:29 +00007177 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007178{
Bram Moolenaar8c711452005-01-14 21:53:12 +00007179 clear_tv(&item->di_tv);
7180 vim_free(item);
7181}
7182
7183/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00007184 * Make a copy of dict "d". Shallow if "deep" is FALSE.
7185 * The refcount of the new dict is set to 1.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007186 * See item_copy() for "copyID".
Bram Moolenaare9a41262005-01-15 22:18:47 +00007187 * Returns NULL when out of memory.
7188 */
Bram Moolenaar33570922005-01-25 22:26:29 +00007189 static dict_T *
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007190dict_copy(orig, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00007191 dict_T *orig;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007192 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007193 int copyID;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007194{
Bram Moolenaar33570922005-01-25 22:26:29 +00007195 dict_T *copy;
7196 dictitem_T *di;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007197 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00007198 hashitem_T *hi;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007199
7200 if (orig == NULL)
7201 return NULL;
7202
7203 copy = dict_alloc();
7204 if (copy != NULL)
7205 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007206 if (copyID != 0)
7207 {
7208 orig->dv_copyID = copyID;
7209 orig->dv_copydict = copy;
7210 }
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007211 todo = (int)orig->dv_hashtab.ht_used;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007212 for (hi = orig->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007213 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007214 if (!HASHITEM_EMPTY(hi))
Bram Moolenaare9a41262005-01-15 22:18:47 +00007215 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007216 --todo;
7217
7218 di = dictitem_alloc(hi->hi_key);
7219 if (di == NULL)
7220 break;
7221 if (deep)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007222 {
7223 if (item_copy(&HI2DI(hi)->di_tv, &di->di_tv, deep,
7224 copyID) == FAIL)
7225 {
7226 vim_free(di);
7227 break;
7228 }
7229 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007230 else
7231 copy_tv(&HI2DI(hi)->di_tv, &di->di_tv);
7232 if (dict_add(copy, di) == FAIL)
7233 {
7234 dictitem_free(di);
7235 break;
7236 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007237 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007238 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007239
Bram Moolenaare9a41262005-01-15 22:18:47 +00007240 ++copy->dv_refcount;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007241 if (todo > 0)
7242 {
7243 dict_unref(copy);
7244 copy = NULL;
7245 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007246 }
7247
7248 return copy;
7249}
7250
7251/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00007252 * Add item "item" to Dictionary "d".
Bram Moolenaara800b422010-06-27 01:15:55 +02007253 * Returns FAIL when out of memory and when key already exists.
Bram Moolenaar8c711452005-01-14 21:53:12 +00007254 */
Bram Moolenaar7e506b62010-01-19 15:55:06 +01007255 int
Bram Moolenaar8c711452005-01-14 21:53:12 +00007256dict_add(d, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00007257 dict_T *d;
7258 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007259{
Bram Moolenaar33570922005-01-25 22:26:29 +00007260 return hash_add(&d->dv_hashtab, item->di_key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007261}
7262
Bram Moolenaar8c711452005-01-14 21:53:12 +00007263/*
Bram Moolenaar05159a02005-02-26 23:04:13 +00007264 * Add a number or string entry to dictionary "d".
7265 * When "str" is NULL use number "nr", otherwise use "str".
7266 * Returns FAIL when out of memory and when key already exists.
7267 */
7268 int
7269dict_add_nr_str(d, key, nr, str)
7270 dict_T *d;
7271 char *key;
7272 long nr;
7273 char_u *str;
7274{
7275 dictitem_T *item;
7276
7277 item = dictitem_alloc((char_u *)key);
7278 if (item == NULL)
7279 return FAIL;
7280 item->di_tv.v_lock = 0;
7281 if (str == NULL)
7282 {
7283 item->di_tv.v_type = VAR_NUMBER;
7284 item->di_tv.vval.v_number = nr;
7285 }
7286 else
7287 {
7288 item->di_tv.v_type = VAR_STRING;
7289 item->di_tv.vval.v_string = vim_strsave(str);
7290 }
7291 if (dict_add(d, item) == FAIL)
7292 {
7293 dictitem_free(item);
7294 return FAIL;
7295 }
7296 return OK;
7297}
7298
7299/*
Bram Moolenaar217d2852010-09-14 12:47:37 +02007300 * Add a list entry to dictionary "d".
Bram Moolenaara800b422010-06-27 01:15:55 +02007301 * Returns FAIL when out of memory and when key already exists.
7302 */
7303 int
7304dict_add_list(d, key, list)
7305 dict_T *d;
7306 char *key;
7307 list_T *list;
7308{
7309 dictitem_T *item;
7310
7311 item = dictitem_alloc((char_u *)key);
7312 if (item == NULL)
7313 return FAIL;
7314 item->di_tv.v_lock = 0;
7315 item->di_tv.v_type = VAR_LIST;
7316 item->di_tv.vval.v_list = list;
7317 if (dict_add(d, item) == FAIL)
7318 {
7319 dictitem_free(item);
7320 return FAIL;
7321 }
Bram Moolenaar217d2852010-09-14 12:47:37 +02007322 ++list->lv_refcount;
Bram Moolenaara800b422010-06-27 01:15:55 +02007323 return OK;
7324}
7325
7326/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00007327 * Get the number of items in a Dictionary.
7328 */
7329 static long
7330dict_len(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00007331 dict_T *d;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007332{
Bram Moolenaare9a41262005-01-15 22:18:47 +00007333 if (d == NULL)
7334 return 0L;
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007335 return (long)d->dv_hashtab.ht_used;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007336}
7337
7338/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00007339 * Find item "key[len]" in Dictionary "d".
7340 * If "len" is negative use strlen(key).
7341 * Returns NULL when not found.
7342 */
Bram Moolenaar8bcf9652010-06-12 20:12:02 +02007343 dictitem_T *
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007344dict_find(d, key, len)
Bram Moolenaar33570922005-01-25 22:26:29 +00007345 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007346 char_u *key;
7347 int len;
7348{
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007349#define AKEYLEN 200
7350 char_u buf[AKEYLEN];
7351 char_u *akey;
7352 char_u *tofree = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00007353 hashitem_T *hi;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007354
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007355 if (len < 0)
7356 akey = key;
7357 else if (len >= AKEYLEN)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00007358 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007359 tofree = akey = vim_strnsave(key, len);
7360 if (akey == NULL)
7361 return NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00007362 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007363 else
7364 {
7365 /* Avoid a malloc/free by using buf[]. */
Bram Moolenaarce0842a2005-07-18 21:58:11 +00007366 vim_strncpy(buf, key, len);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007367 akey = buf;
7368 }
7369
Bram Moolenaar33570922005-01-25 22:26:29 +00007370 hi = hash_find(&d->dv_hashtab, akey);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007371 vim_free(tofree);
7372 if (HASHITEM_EMPTY(hi))
7373 return NULL;
7374 return HI2DI(hi);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007375}
7376
7377/*
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00007378 * Get a string item from a dictionary.
7379 * When "save" is TRUE allocate memory for it.
Bram Moolenaar2641f772005-03-25 21:58:17 +00007380 * Returns NULL if the entry doesn't exist or out of memory.
7381 */
7382 char_u *
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00007383get_dict_string(d, key, save)
Bram Moolenaar2641f772005-03-25 21:58:17 +00007384 dict_T *d;
7385 char_u *key;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00007386 int save;
Bram Moolenaar2641f772005-03-25 21:58:17 +00007387{
7388 dictitem_T *di;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00007389 char_u *s;
Bram Moolenaar2641f772005-03-25 21:58:17 +00007390
7391 di = dict_find(d, key, -1);
7392 if (di == NULL)
7393 return NULL;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00007394 s = get_tv_string(&di->di_tv);
7395 if (save && s != NULL)
7396 s = vim_strsave(s);
7397 return s;
Bram Moolenaar2641f772005-03-25 21:58:17 +00007398}
7399
7400/*
7401 * Get a number item from a dictionary.
7402 * Returns 0 if the entry doesn't exist or out of memory.
7403 */
7404 long
7405get_dict_number(d, key)
7406 dict_T *d;
7407 char_u *key;
7408{
7409 dictitem_T *di;
7410
7411 di = dict_find(d, key, -1);
7412 if (di == NULL)
7413 return 0;
7414 return get_tv_number(&di->di_tv);
7415}
7416
7417/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00007418 * Return an allocated string with the string representation of a Dictionary.
7419 * May return NULL.
7420 */
7421 static char_u *
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007422dict2string(tv, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00007423 typval_T *tv;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007424 int copyID;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007425{
7426 garray_T ga;
7427 int first = TRUE;
7428 char_u *tofree;
7429 char_u numbuf[NUMBUFLEN];
Bram Moolenaar33570922005-01-25 22:26:29 +00007430 hashitem_T *hi;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007431 char_u *s;
Bram Moolenaar33570922005-01-25 22:26:29 +00007432 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007433 int todo;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007434
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007435 if ((d = tv->vval.v_dict) == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00007436 return NULL;
7437 ga_init2(&ga, (int)sizeof(char), 80);
7438 ga_append(&ga, '{');
7439
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007440 todo = (int)d->dv_hashtab.ht_used;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007441 for (hi = d->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +00007442 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007443 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar8c711452005-01-14 21:53:12 +00007444 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007445 --todo;
7446
7447 if (first)
7448 first = FALSE;
7449 else
7450 ga_concat(&ga, (char_u *)", ");
7451
7452 tofree = string_quote(hi->hi_key, FALSE);
7453 if (tofree != NULL)
7454 {
7455 ga_concat(&ga, tofree);
7456 vim_free(tofree);
7457 }
7458 ga_concat(&ga, (char_u *)": ");
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007459 s = tv2string(&HI2DI(hi)->di_tv, &tofree, numbuf, copyID);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007460 if (s != NULL)
7461 ga_concat(&ga, s);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007462 vim_free(tofree);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007463 if (s == NULL)
7464 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007465 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00007466 }
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007467 if (todo > 0)
7468 {
7469 vim_free(ga.ga_data);
7470 return NULL;
7471 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00007472
7473 ga_append(&ga, '}');
7474 ga_append(&ga, NUL);
7475 return (char_u *)ga.ga_data;
7476}
7477
7478/*
7479 * Allocate a variable for a Dictionary and fill it from "*arg".
7480 * Return OK or FAIL. Returns NOTDONE for {expr}.
7481 */
7482 static int
7483get_dict_tv(arg, rettv, evaluate)
7484 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00007485 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007486 int evaluate;
7487{
Bram Moolenaar33570922005-01-25 22:26:29 +00007488 dict_T *d = NULL;
7489 typval_T tvkey;
7490 typval_T tv;
Bram Moolenaarad6c2272007-09-17 20:21:33 +00007491 char_u *key = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00007492 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007493 char_u *start = skipwhite(*arg + 1);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007494 char_u buf[NUMBUFLEN];
Bram Moolenaar8c711452005-01-14 21:53:12 +00007495
7496 /*
7497 * First check if it's not a curly-braces thing: {expr}.
7498 * Must do this without evaluating, otherwise a function may be called
7499 * twice. Unfortunately this means we need to call eval1() twice for the
7500 * first item.
Bram Moolenaare9a41262005-01-15 22:18:47 +00007501 * But {} is an empty Dictionary.
Bram Moolenaar8c711452005-01-14 21:53:12 +00007502 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00007503 if (*start != '}')
7504 {
7505 if (eval1(&start, &tv, FALSE) == FAIL) /* recursive! */
7506 return FAIL;
7507 if (*start == '}')
7508 return NOTDONE;
7509 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00007510
7511 if (evaluate)
7512 {
7513 d = dict_alloc();
7514 if (d == NULL)
7515 return FAIL;
7516 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007517 tvkey.v_type = VAR_UNKNOWN;
7518 tv.v_type = VAR_UNKNOWN;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007519
7520 *arg = skipwhite(*arg + 1);
7521 while (**arg != '}' && **arg != NUL)
7522 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007523 if (eval1(arg, &tvkey, evaluate) == FAIL) /* recursive! */
Bram Moolenaar8c711452005-01-14 21:53:12 +00007524 goto failret;
7525 if (**arg != ':')
7526 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007527 EMSG2(_("E720: Missing colon in Dictionary: %s"), *arg);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007528 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007529 goto failret;
7530 }
Bram Moolenaar037cc642007-09-13 18:40:54 +00007531 if (evaluate)
Bram Moolenaar8c711452005-01-14 21:53:12 +00007532 {
Bram Moolenaar037cc642007-09-13 18:40:54 +00007533 key = get_tv_string_buf_chk(&tvkey, buf);
7534 if (key == NULL || *key == NUL)
7535 {
7536 /* "key" is NULL when get_tv_string_buf_chk() gave an errmsg */
7537 if (key != NULL)
7538 EMSG(_(e_emptykey));
7539 clear_tv(&tvkey);
7540 goto failret;
7541 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00007542 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00007543
7544 *arg = skipwhite(*arg + 1);
7545 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
7546 {
Bram Moolenaar037cc642007-09-13 18:40:54 +00007547 if (evaluate)
7548 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007549 goto failret;
7550 }
7551 if (evaluate)
7552 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007553 item = dict_find(d, key, -1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007554 if (item != NULL)
7555 {
Bram Moolenaarb982ca52005-03-28 21:02:15 +00007556 EMSG2(_("E721: Duplicate key in Dictionary: \"%s\""), key);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007557 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007558 clear_tv(&tv);
7559 goto failret;
7560 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007561 item = dictitem_alloc(key);
7562 clear_tv(&tvkey);
7563 if (item != NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00007564 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00007565 item->di_tv = tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007566 item->di_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007567 if (dict_add(d, item) == FAIL)
7568 dictitem_free(item);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007569 }
7570 }
7571
7572 if (**arg == '}')
7573 break;
7574 if (**arg != ',')
7575 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007576 EMSG2(_("E722: Missing comma in Dictionary: %s"), *arg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007577 goto failret;
7578 }
7579 *arg = skipwhite(*arg + 1);
7580 }
7581
7582 if (**arg != '}')
7583 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007584 EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007585failret:
7586 if (evaluate)
Bram Moolenaar685295c2006-10-15 20:37:38 +00007587 dict_free(d, TRUE);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007588 return FAIL;
7589 }
7590
7591 *arg = skipwhite(*arg + 1);
7592 if (evaluate)
7593 {
7594 rettv->v_type = VAR_DICT;
7595 rettv->vval.v_dict = d;
7596 ++d->dv_refcount;
7597 }
7598
7599 return OK;
7600}
7601
Bram Moolenaar8c711452005-01-14 21:53:12 +00007602/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007603 * Return a string with the string representation of a variable.
7604 * If the memory is allocated "tofree" is set to it, otherwise NULL.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007605 * "numbuf" is used for a number.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007606 * Does not put quotes around strings, as ":echo" displays values.
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007607 * When "copyID" is not NULL replace recursive lists and dicts with "...".
Bram Moolenaar92c5aba2007-08-14 20:29:31 +00007608 * May return NULL.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007609 */
7610 static char_u *
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007611echo_string(tv, tofree, numbuf, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00007612 typval_T *tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007613 char_u **tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007614 char_u *numbuf;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007615 int copyID;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007616{
Bram Moolenaare9a41262005-01-15 22:18:47 +00007617 static int recurse = 0;
7618 char_u *r = NULL;
7619
Bram Moolenaar33570922005-01-25 22:26:29 +00007620 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007621 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007622 EMSG(_("E724: variable nested too deep for displaying"));
Bram Moolenaare9a41262005-01-15 22:18:47 +00007623 *tofree = NULL;
7624 return NULL;
7625 }
7626 ++recurse;
7627
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007628 switch (tv->v_type)
7629 {
7630 case VAR_FUNC:
7631 *tofree = NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007632 r = tv->vval.v_string;
7633 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007634
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007635 case VAR_LIST:
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007636 if (tv->vval.v_list == NULL)
7637 {
7638 *tofree = NULL;
7639 r = NULL;
7640 }
7641 else if (copyID != 0 && tv->vval.v_list->lv_copyID == copyID)
7642 {
7643 *tofree = NULL;
7644 r = (char_u *)"[...]";
7645 }
7646 else
7647 {
7648 tv->vval.v_list->lv_copyID = copyID;
7649 *tofree = list2string(tv, copyID);
7650 r = *tofree;
7651 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007652 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007653
Bram Moolenaar8c711452005-01-14 21:53:12 +00007654 case VAR_DICT:
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007655 if (tv->vval.v_dict == NULL)
7656 {
7657 *tofree = NULL;
7658 r = NULL;
7659 }
7660 else if (copyID != 0 && tv->vval.v_dict->dv_copyID == copyID)
7661 {
7662 *tofree = NULL;
7663 r = (char_u *)"{...}";
7664 }
7665 else
7666 {
7667 tv->vval.v_dict->dv_copyID = copyID;
7668 *tofree = dict2string(tv, copyID);
7669 r = *tofree;
7670 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007671 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007672
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007673 case VAR_STRING:
7674 case VAR_NUMBER:
Bram Moolenaare9a41262005-01-15 22:18:47 +00007675 *tofree = NULL;
7676 r = get_tv_string_buf(tv, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007677 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007678
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007679#ifdef FEAT_FLOAT
7680 case VAR_FLOAT:
7681 *tofree = NULL;
7682 vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv->vval.v_float);
7683 r = numbuf;
7684 break;
7685#endif
7686
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007687 default:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007688 EMSG2(_(e_intern2), "echo_string()");
Bram Moolenaare9a41262005-01-15 22:18:47 +00007689 *tofree = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007690 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007691
7692 --recurse;
7693 return r;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007694}
7695
7696/*
7697 * Return a string with the string representation of a variable.
7698 * If the memory is allocated "tofree" is set to it, otherwise NULL.
7699 * "numbuf" is used for a number.
7700 * Puts quotes around strings, so that they can be parsed back by eval().
Bram Moolenaar92c5aba2007-08-14 20:29:31 +00007701 * May return NULL.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007702 */
7703 static char_u *
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007704tv2string(tv, tofree, numbuf, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00007705 typval_T *tv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007706 char_u **tofree;
7707 char_u *numbuf;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007708 int copyID;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007709{
7710 switch (tv->v_type)
7711 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007712 case VAR_FUNC:
7713 *tofree = string_quote(tv->vval.v_string, TRUE);
7714 return *tofree;
7715 case VAR_STRING:
7716 *tofree = string_quote(tv->vval.v_string, FALSE);
7717 return *tofree;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007718#ifdef FEAT_FLOAT
7719 case VAR_FLOAT:
7720 *tofree = NULL;
7721 vim_snprintf((char *)numbuf, NUMBUFLEN - 1, "%g", tv->vval.v_float);
7722 return numbuf;
7723#endif
Bram Moolenaare9a41262005-01-15 22:18:47 +00007724 case VAR_NUMBER:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007725 case VAR_LIST:
Bram Moolenaar8c711452005-01-14 21:53:12 +00007726 case VAR_DICT:
Bram Moolenaare9a41262005-01-15 22:18:47 +00007727 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007728 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007729 EMSG2(_(e_intern2), "tv2string()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007730 }
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00007731 return echo_string(tv, tofree, numbuf, copyID);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007732}
7733
7734/*
Bram Moolenaar33570922005-01-25 22:26:29 +00007735 * Return string "str" in ' quotes, doubling ' characters.
7736 * If "str" is NULL an empty string is assumed.
Bram Moolenaar8c711452005-01-14 21:53:12 +00007737 * If "function" is TRUE make it function('string').
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007738 */
7739 static char_u *
7740string_quote(str, function)
7741 char_u *str;
7742 int function;
7743{
Bram Moolenaar33570922005-01-25 22:26:29 +00007744 unsigned len;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007745 char_u *p, *r, *s;
7746
Bram Moolenaar33570922005-01-25 22:26:29 +00007747 len = (function ? 13 : 3);
7748 if (str != NULL)
7749 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007750 len += (unsigned)STRLEN(str);
Bram Moolenaar33570922005-01-25 22:26:29 +00007751 for (p = str; *p != NUL; mb_ptr_adv(p))
7752 if (*p == '\'')
7753 ++len;
7754 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007755 s = r = alloc(len);
7756 if (r != NULL)
7757 {
7758 if (function)
7759 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00007760 STRCPY(r, "function('");
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007761 r += 10;
7762 }
7763 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00007764 *r++ = '\'';
Bram Moolenaar33570922005-01-25 22:26:29 +00007765 if (str != NULL)
7766 for (p = str; *p != NUL; )
7767 {
7768 if (*p == '\'')
7769 *r++ = '\'';
7770 MB_COPY_CHAR(p, r);
7771 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00007772 *r++ = '\'';
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007773 if (function)
7774 *r++ = ')';
7775 *r++ = NUL;
7776 }
7777 return s;
7778}
7779
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007780#ifdef FEAT_FLOAT
7781/*
7782 * Convert the string "text" to a floating point number.
7783 * This uses strtod(). setlocale(LC_NUMERIC, "C") has been used to make sure
7784 * this always uses a decimal point.
7785 * Returns the length of the text that was consumed.
7786 */
7787 static int
7788string2float(text, value)
7789 char_u *text;
7790 float_T *value; /* result stored here */
7791{
7792 char *s = (char *)text;
7793 float_T f;
7794
7795 f = strtod(s, &s);
7796 *value = f;
7797 return (int)((char_u *)s - text);
7798}
7799#endif
7800
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007801/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007802 * Get the value of an environment variable.
7803 * "arg" is pointing to the '$'. It is advanced to after the name.
7804 * If the environment variable was not set, silently assume it is empty.
Bram Moolenaare512c8c2014-04-29 17:41:22 +02007805 * Return FAIL if the name is invalid.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007806 */
7807 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007808get_env_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007809 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00007810 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007811 int evaluate;
7812{
7813 char_u *string = NULL;
7814 int len;
7815 int cc;
7816 char_u *name;
Bram Moolenaar05159a02005-02-26 23:04:13 +00007817 int mustfree = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007818
7819 ++*arg;
7820 name = *arg;
7821 len = get_env_len(arg);
7822 if (evaluate)
7823 {
Bram Moolenaare512c8c2014-04-29 17:41:22 +02007824 if (len == 0)
7825 return FAIL; /* can't be an environment variable */
Bram Moolenaar05159a02005-02-26 23:04:13 +00007826
Bram Moolenaare512c8c2014-04-29 17:41:22 +02007827 cc = name[len];
7828 name[len] = NUL;
7829 /* first try vim_getenv(), fast for normal environment vars */
7830 string = vim_getenv(name, &mustfree);
7831 if (string != NULL && *string != NUL)
7832 {
7833 if (!mustfree)
7834 string = vim_strsave(string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007835 }
Bram Moolenaare512c8c2014-04-29 17:41:22 +02007836 else
7837 {
7838 if (mustfree)
7839 vim_free(string);
7840
7841 /* next try expanding things like $VIM and ${HOME} */
7842 string = expand_env_save(name - 1);
7843 if (string != NULL && *string == '$')
7844 {
7845 vim_free(string);
7846 string = NULL;
7847 }
7848 }
7849 name[len] = cc;
7850
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007851 rettv->v_type = VAR_STRING;
7852 rettv->vval.v_string = string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007853 }
7854
7855 return OK;
7856}
7857
7858/*
7859 * Array with names and number of arguments of all internal functions
7860 * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH!
7861 */
7862static struct fst
7863{
7864 char *f_name; /* function name */
7865 char f_min_argc; /* minimal number of arguments */
7866 char f_max_argc; /* maximal number of arguments */
Bram Moolenaar33570922005-01-25 22:26:29 +00007867 void (*f_func) __ARGS((typval_T *args, typval_T *rvar));
Bram Moolenaarbae0c162007-05-10 19:30:25 +00007868 /* implementation of function */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007869} functions[] =
7870{
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007871#ifdef FEAT_FLOAT
7872 {"abs", 1, 1, f_abs},
Bram Moolenaardb7c6862010-05-21 16:33:48 +02007873 {"acos", 1, 1, f_acos}, /* WJMc */
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007874#endif
Bram Moolenaar0d660222005-01-07 21:51:51 +00007875 {"add", 2, 2, f_add},
Bram Moolenaard6e256c2011-12-14 15:32:50 +01007876 {"and", 2, 2, f_and},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007877 {"append", 2, 2, f_append},
7878 {"argc", 0, 0, f_argc},
7879 {"argidx", 0, 0, f_argidx},
Bram Moolenaar2d1fe052014-05-28 18:22:57 +02007880 {"arglistid", 0, 2, f_arglistid},
Bram Moolenaare2f98b92006-03-29 21:18:24 +00007881 {"argv", 0, 1, f_argv},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007882#ifdef FEAT_FLOAT
Bram Moolenaardb7c6862010-05-21 16:33:48 +02007883 {"asin", 1, 1, f_asin}, /* WJMc */
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007884 {"atan", 1, 1, f_atan},
Bram Moolenaardb7c6862010-05-21 16:33:48 +02007885 {"atan2", 2, 2, f_atan2},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007886#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007887 {"browse", 4, 4, f_browse},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007888 {"browsedir", 2, 2, f_browsedir},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007889 {"bufexists", 1, 1, f_bufexists},
7890 {"buffer_exists", 1, 1, f_bufexists}, /* obsolete */
7891 {"buffer_name", 1, 1, f_bufname}, /* obsolete */
7892 {"buffer_number", 1, 1, f_bufnr}, /* obsolete */
7893 {"buflisted", 1, 1, f_buflisted},
7894 {"bufloaded", 1, 1, f_bufloaded},
7895 {"bufname", 1, 1, f_bufname},
Bram Moolenaar0e34f622006-03-03 23:00:03 +00007896 {"bufnr", 1, 2, f_bufnr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007897 {"bufwinnr", 1, 1, f_bufwinnr},
7898 {"byte2line", 1, 1, f_byte2line},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007899 {"byteidx", 2, 2, f_byteidx},
Bram Moolenaar0ffbbf92013-11-02 23:29:26 +01007900 {"byteidxcomp", 2, 2, f_byteidxcomp},
Bram Moolenaare9a41262005-01-15 22:18:47 +00007901 {"call", 2, 3, f_call},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007902#ifdef FEAT_FLOAT
7903 {"ceil", 1, 1, f_ceil},
7904#endif
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00007905 {"changenr", 0, 0, f_changenr},
Bram Moolenaard35d7842013-01-23 17:17:10 +01007906 {"char2nr", 1, 2, f_char2nr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007907 {"cindent", 1, 1, f_cindent},
Bram Moolenaar6ee10162007-07-26 20:58:42 +00007908 {"clearmatches", 0, 0, f_clearmatches},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007909 {"col", 1, 1, f_col},
Bram Moolenaar572cb562005-08-05 21:35:02 +00007910#if defined(FEAT_INS_EXPAND)
Bram Moolenaarade00832006-03-10 21:46:58 +00007911 {"complete", 2, 2, f_complete},
Bram Moolenaar572cb562005-08-05 21:35:02 +00007912 {"complete_add", 1, 1, f_complete_add},
7913 {"complete_check", 0, 0, f_complete_check},
7914#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007915 {"confirm", 1, 4, f_confirm},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007916 {"copy", 1, 1, f_copy},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007917#ifdef FEAT_FLOAT
7918 {"cos", 1, 1, f_cos},
Bram Moolenaardb7c6862010-05-21 16:33:48 +02007919 {"cosh", 1, 1, f_cosh},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007920#endif
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007921 {"count", 2, 4, f_count},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007922 {"cscope_connection",0,3, f_cscope_connection},
Bram Moolenaara5525202006-03-02 22:52:09 +00007923 {"cursor", 1, 3, f_cursor},
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007924 {"deepcopy", 1, 2, f_deepcopy},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007925 {"delete", 1, 1, f_delete},
7926 {"did_filetype", 0, 0, f_did_filetype},
Bram Moolenaar47136d72004-10-12 20:02:24 +00007927 {"diff_filler", 1, 1, f_diff_filler},
7928 {"diff_hlID", 2, 2, f_diff_hlID},
Bram Moolenaare49b69a2005-01-08 16:11:57 +00007929 {"empty", 1, 1, f_empty},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007930 {"escape", 2, 2, f_escape},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007931 {"eval", 1, 1, f_eval},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007932 {"eventhandler", 0, 0, f_eventhandler},
7933 {"executable", 1, 1, f_executable},
Bram Moolenaarc7f02552014-04-01 21:00:59 +02007934 {"exepath", 1, 1, f_exepath},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007935 {"exists", 1, 1, f_exists},
Bram Moolenaardb7c6862010-05-21 16:33:48 +02007936#ifdef FEAT_FLOAT
7937 {"exp", 1, 1, f_exp},
7938#endif
Bram Moolenaar146e9c32012-03-07 19:18:23 +01007939 {"expand", 1, 3, f_expand},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007940 {"extend", 2, 3, f_extend},
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00007941 {"feedkeys", 1, 2, f_feedkeys},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007942 {"file_readable", 1, 1, f_filereadable}, /* obsolete */
7943 {"filereadable", 1, 1, f_filereadable},
7944 {"filewritable", 1, 1, f_filewritable},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007945 {"filter", 2, 2, f_filter},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007946 {"finddir", 1, 3, f_finddir},
7947 {"findfile", 1, 3, f_findfile},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007948#ifdef FEAT_FLOAT
7949 {"float2nr", 1, 1, f_float2nr},
7950 {"floor", 1, 1, f_floor},
Bram Moolenaardb7c6862010-05-21 16:33:48 +02007951 {"fmod", 2, 2, f_fmod},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007952#endif
Bram Moolenaaraebaf892008-05-28 14:49:58 +00007953 {"fnameescape", 1, 1, f_fnameescape},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007954 {"fnamemodify", 2, 2, f_fnamemodify},
7955 {"foldclosed", 1, 1, f_foldclosed},
7956 {"foldclosedend", 1, 1, f_foldclosedend},
7957 {"foldlevel", 1, 1, f_foldlevel},
7958 {"foldtext", 0, 0, f_foldtext},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007959 {"foldtextresult", 1, 1, f_foldtextresult},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007960 {"foreground", 0, 0, f_foreground},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007961 {"function", 1, 1, f_function},
Bram Moolenaar9d2c8c12007-09-25 16:00:00 +00007962 {"garbagecollect", 0, 1, f_garbagecollect},
Bram Moolenaar0d660222005-01-07 21:51:51 +00007963 {"get", 2, 3, f_get},
Bram Moolenaar80fc0432005-07-20 22:06:07 +00007964 {"getbufline", 2, 3, f_getbufline},
Bram Moolenaar63dbda12013-02-20 21:12:10 +01007965 {"getbufvar", 2, 3, f_getbufvar},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007966 {"getchar", 0, 1, f_getchar},
7967 {"getcharmod", 0, 0, f_getcharmod},
7968 {"getcmdline", 0, 0, f_getcmdline},
7969 {"getcmdpos", 0, 0, f_getcmdpos},
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +00007970 {"getcmdtype", 0, 0, f_getcmdtype},
Bram Moolenaar6f6c0f82014-05-28 20:31:42 +02007971 {"getcurpos", 0, 0, f_getcurpos},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007972 {"getcwd", 0, 0, f_getcwd},
Bram Moolenaar46c9c732004-12-12 11:37:09 +00007973 {"getfontname", 0, 1, f_getfontname},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007974 {"getfperm", 1, 1, f_getfperm},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007975 {"getfsize", 1, 1, f_getfsize},
7976 {"getftime", 1, 1, f_getftime},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007977 {"getftype", 1, 1, f_getftype},
Bram Moolenaar0d660222005-01-07 21:51:51 +00007978 {"getline", 1, 2, f_getline},
Bram Moolenaar280f1262006-01-30 00:14:18 +00007979 {"getloclist", 1, 1, f_getqflist},
Bram Moolenaar2240aeb2007-07-27 19:33:14 +00007980 {"getmatches", 0, 0, f_getmatches},
Bram Moolenaar18081e32008-02-20 19:11:07 +00007981 {"getpid", 0, 0, f_getpid},
Bram Moolenaara5525202006-03-02 22:52:09 +00007982 {"getpos", 1, 1, f_getpos},
Bram Moolenaar2641f772005-03-25 21:58:17 +00007983 {"getqflist", 0, 0, f_getqflist},
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +02007984 {"getreg", 0, 3, f_getreg},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007985 {"getregtype", 0, 1, f_getregtype},
Bram Moolenaar63dbda12013-02-20 21:12:10 +01007986 {"gettabvar", 2, 3, f_gettabvar},
7987 {"gettabwinvar", 3, 4, f_gettabwinvar},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007988 {"getwinposx", 0, 0, f_getwinposx},
7989 {"getwinposy", 0, 0, f_getwinposy},
Bram Moolenaar63dbda12013-02-20 21:12:10 +01007990 {"getwinvar", 2, 3, f_getwinvar},
Bram Moolenaar146e9c32012-03-07 19:18:23 +01007991 {"glob", 1, 3, f_glob},
Bram Moolenaar1b1063a2014-05-07 18:35:30 +02007992 {"globpath", 2, 4, f_globpath},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007993 {"has", 1, 1, f_has},
Bram Moolenaare9a41262005-01-15 22:18:47 +00007994 {"has_key", 2, 2, f_has_key},
Bram Moolenaard267b9c2007-04-26 15:06:45 +00007995 {"haslocaldir", 0, 0, f_haslocaldir},
Bram Moolenaar2c932302006-03-18 21:42:09 +00007996 {"hasmapto", 1, 3, f_hasmapto},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007997 {"highlightID", 1, 1, f_hlID}, /* obsolete */
7998 {"highlight_exists",1, 1, f_hlexists}, /* obsolete */
7999 {"histadd", 2, 2, f_histadd},
8000 {"histdel", 1, 2, f_histdel},
8001 {"histget", 1, 2, f_histget},
8002 {"histnr", 1, 1, f_histnr},
8003 {"hlID", 1, 1, f_hlID},
8004 {"hlexists", 1, 1, f_hlexists},
8005 {"hostname", 0, 0, f_hostname},
8006 {"iconv", 3, 3, f_iconv},
8007 {"indent", 1, 1, f_indent},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008008 {"index", 2, 4, f_index},
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +00008009 {"input", 1, 3, f_input},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008010 {"inputdialog", 1, 3, f_inputdialog},
Bram Moolenaar6efa2b32005-09-10 19:26:26 +00008011 {"inputlist", 1, 1, f_inputlist},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008012 {"inputrestore", 0, 0, f_inputrestore},
8013 {"inputsave", 0, 0, f_inputsave},
8014 {"inputsecret", 1, 2, f_inputsecret},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008015 {"insert", 2, 3, f_insert},
Bram Moolenaard6e256c2011-12-14 15:32:50 +01008016 {"invert", 1, 1, f_invert},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008017 {"isdirectory", 1, 1, f_isdirectory},
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008018 {"islocked", 1, 1, f_islocked},
Bram Moolenaar8c711452005-01-14 21:53:12 +00008019 {"items", 1, 1, f_items},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008020 {"join", 1, 2, f_join},
Bram Moolenaar8c711452005-01-14 21:53:12 +00008021 {"keys", 1, 1, f_keys},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008022 {"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008023 {"len", 1, 1, f_len},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008024 {"libcall", 3, 3, f_libcall},
8025 {"libcallnr", 3, 3, f_libcallnr},
8026 {"line", 1, 1, f_line},
8027 {"line2byte", 1, 1, f_line2byte},
8028 {"lispindent", 1, 1, f_lispindent},
8029 {"localtime", 0, 0, f_localtime},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008030#ifdef FEAT_FLOAT
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008031 {"log", 1, 1, f_log},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008032 {"log10", 1, 1, f_log10},
8033#endif
Bram Moolenaar1dced572012-04-05 16:54:08 +02008034#ifdef FEAT_LUA
Bram Moolenaar9feaf622014-02-22 22:18:47 +01008035 {"luaeval", 1, 2, f_luaeval},
Bram Moolenaar1dced572012-04-05 16:54:08 +02008036#endif
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008037 {"map", 2, 2, f_map},
Bram Moolenaarbd743252010-10-20 21:23:33 +02008038 {"maparg", 1, 4, f_maparg},
Bram Moolenaar2c932302006-03-18 21:42:09 +00008039 {"mapcheck", 1, 3, f_mapcheck},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008040 {"match", 2, 4, f_match},
Bram Moolenaar6ee10162007-07-26 20:58:42 +00008041 {"matchadd", 2, 4, f_matchadd},
Bram Moolenaar910f66f2006-04-05 20:41:53 +00008042 {"matcharg", 1, 1, f_matcharg},
Bram Moolenaar6ee10162007-07-26 20:58:42 +00008043 {"matchdelete", 1, 1, f_matchdelete},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008044 {"matchend", 2, 4, f_matchend},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008045 {"matchlist", 2, 4, f_matchlist},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008046 {"matchstr", 2, 4, f_matchstr},
Bram Moolenaar6cc16192005-01-08 21:49:45 +00008047 {"max", 1, 1, f_max},
8048 {"min", 1, 1, f_min},
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008049#ifdef vim_mkdir
8050 {"mkdir", 1, 3, f_mkdir},
8051#endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008052 {"mode", 0, 1, f_mode},
Bram Moolenaar7e506b62010-01-19 15:55:06 +01008053#ifdef FEAT_MZSCHEME
8054 {"mzeval", 1, 1, f_mzeval},
8055#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008056 {"nextnonblank", 1, 1, f_nextnonblank},
Bram Moolenaard35d7842013-01-23 17:17:10 +01008057 {"nr2char", 1, 2, f_nr2char},
Bram Moolenaard6e256c2011-12-14 15:32:50 +01008058 {"or", 2, 2, f_or},
Bram Moolenaar910f66f2006-04-05 20:41:53 +00008059 {"pathshorten", 1, 1, f_pathshorten},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008060#ifdef FEAT_FLOAT
8061 {"pow", 2, 2, f_pow},
8062#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008063 {"prevnonblank", 1, 1, f_prevnonblank},
Bram Moolenaar4be06f92005-07-29 22:36:03 +00008064 {"printf", 2, 19, f_printf},
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00008065 {"pumvisible", 0, 0, f_pumvisible},
Bram Moolenaardb913952012-06-29 12:54:53 +02008066#ifdef FEAT_PYTHON3
8067 {"py3eval", 1, 1, f_py3eval},
8068#endif
8069#ifdef FEAT_PYTHON
8070 {"pyeval", 1, 1, f_pyeval},
8071#endif
Bram Moolenaar8c711452005-01-14 21:53:12 +00008072 {"range", 1, 3, f_range},
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008073 {"readfile", 1, 3, f_readfile},
Bram Moolenaare580b0c2006-03-21 21:33:03 +00008074 {"reltime", 0, 2, f_reltime},
8075 {"reltimestr", 1, 1, f_reltimestr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008076 {"remote_expr", 2, 3, f_remote_expr},
8077 {"remote_foreground", 1, 1, f_remote_foreground},
8078 {"remote_peek", 1, 2, f_remote_peek},
8079 {"remote_read", 1, 1, f_remote_read},
8080 {"remote_send", 2, 3, f_remote_send},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008081 {"remove", 2, 3, f_remove},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008082 {"rename", 2, 2, f_rename},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00008083 {"repeat", 2, 2, f_repeat},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008084 {"resolve", 1, 1, f_resolve},
Bram Moolenaar0d660222005-01-07 21:51:51 +00008085 {"reverse", 1, 1, f_reverse},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008086#ifdef FEAT_FLOAT
8087 {"round", 1, 1, f_round},
8088#endif
Bram Moolenaar9a773482013-06-11 18:40:13 +02008089 {"screenattr", 2, 2, f_screenattr},
8090 {"screenchar", 2, 2, f_screenchar},
Bram Moolenaar9750bb12012-12-05 16:10:42 +01008091 {"screencol", 0, 0, f_screencol},
8092 {"screenrow", 0, 0, f_screenrow},
Bram Moolenaar76929292008-01-06 19:07:36 +00008093 {"search", 1, 4, f_search},
Bram Moolenaare6facf92005-09-13 21:22:27 +00008094 {"searchdecl", 1, 3, f_searchdecl},
Bram Moolenaar76929292008-01-06 19:07:36 +00008095 {"searchpair", 3, 7, f_searchpair},
8096 {"searchpairpos", 3, 7, f_searchpairpos},
8097 {"searchpos", 1, 4, f_searchpos},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008098 {"server2client", 2, 2, f_server2client},
8099 {"serverlist", 0, 0, f_serverlist},
8100 {"setbufvar", 3, 3, f_setbufvar},
8101 {"setcmdpos", 1, 1, f_setcmdpos},
8102 {"setline", 2, 2, f_setline},
Bram Moolenaar17c7c012006-01-26 22:25:15 +00008103 {"setloclist", 2, 3, f_setloclist},
Bram Moolenaar6ee10162007-07-26 20:58:42 +00008104 {"setmatches", 1, 1, f_setmatches},
Bram Moolenaar0e34f622006-03-03 23:00:03 +00008105 {"setpos", 2, 2, f_setpos},
Bram Moolenaarf4630b62005-05-20 21:31:17 +00008106 {"setqflist", 1, 2, f_setqflist},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008107 {"setreg", 2, 3, f_setreg},
Bram Moolenaar06b5d512010-05-22 15:37:44 +02008108 {"settabvar", 3, 3, f_settabvar},
Bram Moolenaar99ebf042006-04-15 20:28:54 +00008109 {"settabwinvar", 4, 4, f_settabwinvar},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008110 {"setwinvar", 3, 3, f_setwinvar},
Bram Moolenaaraf9aeb92013-02-13 17:35:04 +01008111#ifdef FEAT_CRYPT
8112 {"sha256", 1, 1, f_sha256},
8113#endif
Bram Moolenaar05bb9532008-07-04 09:44:11 +00008114 {"shellescape", 1, 2, f_shellescape},
Bram Moolenaar2d17fa32012-10-21 00:45:18 +02008115 {"shiftwidth", 0, 0, f_shiftwidth},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008116 {"simplify", 1, 1, f_simplify},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008117#ifdef FEAT_FLOAT
8118 {"sin", 1, 1, f_sin},
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008119 {"sinh", 1, 1, f_sinh},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008120#endif
Bram Moolenaar5f894962011-06-19 02:55:37 +02008121 {"sort", 1, 3, f_sort},
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00008122 {"soundfold", 1, 1, f_soundfold},
Bram Moolenaar4463f292005-09-25 22:20:24 +00008123 {"spellbadword", 0, 1, f_spellbadword},
Bram Moolenaar69e0ff92005-09-30 21:23:56 +00008124 {"spellsuggest", 1, 3, f_spellsuggest},
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00008125 {"split", 1, 3, f_split},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008126#ifdef FEAT_FLOAT
8127 {"sqrt", 1, 1, f_sqrt},
8128 {"str2float", 1, 1, f_str2float},
8129#endif
Bram Moolenaar2c932302006-03-18 21:42:09 +00008130 {"str2nr", 1, 2, f_str2nr},
Bram Moolenaar72597a52010-07-18 15:31:08 +02008131 {"strchars", 1, 1, f_strchars},
Bram Moolenaardc536092010-07-18 15:45:49 +02008132 {"strdisplaywidth", 1, 2, f_strdisplaywidth},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008133#ifdef HAVE_STRFTIME
8134 {"strftime", 1, 2, f_strftime},
8135#endif
Bram Moolenaar33570922005-01-25 22:26:29 +00008136 {"stridx", 2, 3, f_stridx},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008137 {"string", 1, 1, f_string},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008138 {"strlen", 1, 1, f_strlen},
8139 {"strpart", 2, 3, f_strpart},
Bram Moolenaar532c7802005-01-27 14:44:31 +00008140 {"strridx", 2, 3, f_strridx},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008141 {"strtrans", 1, 1, f_strtrans},
Bram Moolenaar72597a52010-07-18 15:31:08 +02008142 {"strwidth", 1, 1, f_strwidth},
Bram Moolenaar41571762014-04-02 19:00:58 +02008143 {"submatch", 1, 2, f_submatch},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008144 {"substitute", 4, 4, f_substitute},
8145 {"synID", 3, 3, f_synID},
8146 {"synIDattr", 2, 3, f_synIDattr},
8147 {"synIDtrans", 1, 1, f_synIDtrans},
Bram Moolenaar7510fe72010-07-25 12:46:44 +02008148 {"synconcealed", 2, 2, f_synconcealed},
Bram Moolenaar9d188ab2008-01-10 21:24:39 +00008149 {"synstack", 2, 2, f_synstack},
Bram Moolenaarc0197e22004-09-13 20:26:32 +00008150 {"system", 1, 2, f_system},
Bram Moolenaar39c29ed2014-04-05 19:44:40 +02008151 {"systemlist", 1, 2, f_systemlist},
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00008152 {"tabpagebuflist", 0, 1, f_tabpagebuflist},
Bram Moolenaar7e8fd632006-02-18 22:14:51 +00008153 {"tabpagenr", 0, 1, f_tabpagenr},
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00008154 {"tabpagewinnr", 1, 2, f_tabpagewinnr},
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00008155 {"tagfiles", 0, 0, f_tagfiles},
Bram Moolenaar19a09a12005-03-04 23:39:37 +00008156 {"taglist", 1, 1, f_taglist},
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008157#ifdef FEAT_FLOAT
8158 {"tan", 1, 1, f_tan},
8159 {"tanh", 1, 1, f_tanh},
8160#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008161 {"tempname", 0, 0, f_tempname},
Bram Moolenaard52d9742005-08-21 22:20:28 +00008162 {"test", 1, 1, f_test},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008163 {"tolower", 1, 1, f_tolower},
8164 {"toupper", 1, 1, f_toupper},
Bram Moolenaar8299df92004-07-10 09:47:34 +00008165 {"tr", 3, 3, f_tr},
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008166#ifdef FEAT_FLOAT
8167 {"trunc", 1, 1, f_trunc},
8168#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008169 {"type", 1, 1, f_type},
Bram Moolenaara17d4c12010-05-30 18:30:36 +02008170 {"undofile", 1, 1, f_undofile},
Bram Moolenaara800b422010-06-27 01:15:55 +02008171 {"undotree", 0, 0, f_undotree},
Bram Moolenaar327aa022014-03-25 18:24:23 +01008172 {"uniq", 1, 3, f_uniq},
Bram Moolenaar8c711452005-01-14 21:53:12 +00008173 {"values", 1, 1, f_values},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008174 {"virtcol", 1, 1, f_virtcol},
8175 {"visualmode", 0, 1, f_visualmode},
Bram Moolenaar8738fc12013-02-20 17:59:11 +01008176 {"wildmenumode", 0, 0, f_wildmenumode},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008177 {"winbufnr", 1, 1, f_winbufnr},
8178 {"wincol", 0, 0, f_wincol},
8179 {"winheight", 1, 1, f_winheight},
8180 {"winline", 0, 0, f_winline},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008181 {"winnr", 0, 1, f_winnr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008182 {"winrestcmd", 0, 0, f_winrestcmd},
Bram Moolenaar768b8c42006-03-04 21:58:33 +00008183 {"winrestview", 1, 1, f_winrestview},
8184 {"winsaveview", 0, 0, f_winsaveview},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008185 {"winwidth", 1, 1, f_winwidth},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008186 {"writefile", 2, 3, f_writefile},
Bram Moolenaard6e256c2011-12-14 15:32:50 +01008187 {"xor", 2, 2, f_xor},
Bram Moolenaar071d4272004-06-13 20:20:40 +00008188};
8189
8190#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
8191
8192/*
8193 * Function given to ExpandGeneric() to obtain the list of internal
8194 * or user defined function names.
8195 */
8196 char_u *
8197get_function_name(xp, idx)
8198 expand_T *xp;
8199 int idx;
8200{
8201 static int intidx = -1;
8202 char_u *name;
8203
8204 if (idx == 0)
8205 intidx = -1;
8206 if (intidx < 0)
8207 {
8208 name = get_user_func_name(xp, idx);
8209 if (name != NULL)
8210 return name;
8211 }
8212 if (++intidx < (int)(sizeof(functions) / sizeof(struct fst)))
8213 {
8214 STRCPY(IObuff, functions[intidx].f_name);
8215 STRCAT(IObuff, "(");
8216 if (functions[intidx].f_max_argc == 0)
8217 STRCAT(IObuff, ")");
8218 return IObuff;
8219 }
8220
8221 return NULL;
8222}
8223
8224/*
8225 * Function given to ExpandGeneric() to obtain the list of internal or
8226 * user defined variable or function names.
8227 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008228 char_u *
8229get_expr_name(xp, idx)
8230 expand_T *xp;
8231 int idx;
8232{
8233 static int intidx = -1;
8234 char_u *name;
8235
8236 if (idx == 0)
8237 intidx = -1;
8238 if (intidx < 0)
8239 {
8240 name = get_function_name(xp, idx);
8241 if (name != NULL)
8242 return name;
8243 }
8244 return get_user_var_name(xp, ++intidx);
8245}
8246
8247#endif /* FEAT_CMDL_COMPL */
8248
Bram Moolenaar2c704a72010-06-03 21:17:25 +02008249#if defined(EBCDIC) || defined(PROTO)
8250/*
8251 * Compare struct fst by function name.
8252 */
8253 static int
8254compare_func_name(s1, s2)
8255 const void *s1;
8256 const void *s2;
8257{
8258 struct fst *p1 = (struct fst *)s1;
8259 struct fst *p2 = (struct fst *)s2;
8260
8261 return STRCMP(p1->f_name, p2->f_name);
8262}
8263
8264/*
8265 * Sort the function table by function name.
8266 * The sorting of the table above is ASCII dependant.
8267 * On machines using EBCDIC we have to sort it.
8268 */
8269 static void
8270sortFunctions()
8271{
8272 int funcCnt = (int)(sizeof(functions) / sizeof(struct fst)) - 1;
8273
8274 qsort(functions, (size_t)funcCnt, sizeof(struct fst), compare_func_name);
8275}
8276#endif
8277
8278
Bram Moolenaar071d4272004-06-13 20:20:40 +00008279/*
8280 * Find internal function in table above.
8281 * Return index, or -1 if not found
8282 */
8283 static int
8284find_internal_func(name)
8285 char_u *name; /* name of the function */
8286{
8287 int first = 0;
8288 int last = (int)(sizeof(functions) / sizeof(struct fst)) - 1;
8289 int cmp;
8290 int x;
8291
8292 /*
8293 * Find the function name in the table. Binary search.
8294 */
8295 while (first <= last)
8296 {
8297 x = first + ((unsigned)(last - first) >> 1);
8298 cmp = STRCMP(name, functions[x].f_name);
8299 if (cmp < 0)
8300 last = x - 1;
8301 else if (cmp > 0)
8302 first = x + 1;
8303 else
8304 return x;
8305 }
8306 return -1;
8307}
8308
8309/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008310 * Check if "name" is a variable of type VAR_FUNC. If so, return the function
8311 * name it contains, otherwise return "name".
8312 */
8313 static char_u *
Bram Moolenaar8822a9c2014-01-14 19:44:34 +01008314deref_func_name(name, lenp, no_autoload)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008315 char_u *name;
8316 int *lenp;
Bram Moolenaar8822a9c2014-01-14 19:44:34 +01008317 int no_autoload;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008318{
Bram Moolenaar33570922005-01-25 22:26:29 +00008319 dictitem_T *v;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008320 int cc;
8321
8322 cc = name[*lenp];
8323 name[*lenp] = NUL;
Bram Moolenaar8822a9c2014-01-14 19:44:34 +01008324 v = find_var(name, NULL, no_autoload);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008325 name[*lenp] = cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00008326 if (v != NULL && v->di_tv.v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008327 {
Bram Moolenaar33570922005-01-25 22:26:29 +00008328 if (v->di_tv.vval.v_string == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008329 {
8330 *lenp = 0;
8331 return (char_u *)""; /* just in case */
8332 }
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008333 *lenp = (int)STRLEN(v->di_tv.vval.v_string);
Bram Moolenaar33570922005-01-25 22:26:29 +00008334 return v->di_tv.vval.v_string;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008335 }
8336
8337 return name;
8338}
8339
8340/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008341 * Allocate a variable for the result of a function.
8342 * Return OK or FAIL.
8343 */
8344 static int
Bram Moolenaare9a41262005-01-15 22:18:47 +00008345get_func_tv(name, len, rettv, arg, firstline, lastline, doesrange,
8346 evaluate, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008347 char_u *name; /* name of the function */
8348 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +00008349 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008350 char_u **arg; /* argument, pointing to the '(' */
8351 linenr_T firstline; /* first line of range */
8352 linenr_T lastline; /* last line of range */
8353 int *doesrange; /* return: function handled range */
8354 int evaluate;
Bram Moolenaar33570922005-01-25 22:26:29 +00008355 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008356{
8357 char_u *argp;
8358 int ret = OK;
Bram Moolenaareb3593b2006-04-22 22:33:57 +00008359 typval_T argvars[MAX_FUNC_ARGS + 1]; /* vars for arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008360 int argcount = 0; /* number of arguments found */
8361
8362 /*
8363 * Get the arguments.
8364 */
8365 argp = *arg;
8366 while (argcount < MAX_FUNC_ARGS)
8367 {
8368 argp = skipwhite(argp + 1); /* skip the '(' or ',' */
8369 if (*argp == ')' || *argp == ',' || *argp == NUL)
8370 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008371 if (eval1(&argp, &argvars[argcount], evaluate) == FAIL)
8372 {
8373 ret = FAIL;
8374 break;
8375 }
8376 ++argcount;
8377 if (*argp != ',')
8378 break;
8379 }
8380 if (*argp == ')')
8381 ++argp;
8382 else
8383 ret = FAIL;
8384
8385 if (ret == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008386 ret = call_func(name, len, rettv, argcount, argvars,
Bram Moolenaare9a41262005-01-15 22:18:47 +00008387 firstline, lastline, doesrange, evaluate, selfdict);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008388 else if (!aborting())
Bram Moolenaar33570922005-01-25 22:26:29 +00008389 {
8390 if (argcount == MAX_FUNC_ARGS)
Bram Moolenaar7b76b0a2009-01-28 18:09:38 +00008391 emsg_funcname(N_("E740: Too many arguments for function %s"), name);
Bram Moolenaar33570922005-01-25 22:26:29 +00008392 else
Bram Moolenaar7b76b0a2009-01-28 18:09:38 +00008393 emsg_funcname(N_("E116: Invalid arguments for function %s"), name);
Bram Moolenaar33570922005-01-25 22:26:29 +00008394 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008395
8396 while (--argcount >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008397 clear_tv(&argvars[argcount]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008398
8399 *arg = skipwhite(argp);
8400 return ret;
8401}
8402
8403
8404/*
8405 * Call a function with its resolved parameters
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02008406 * Return FAIL when the function can't be called, OK otherwise.
Bram Moolenaar280f1262006-01-30 00:14:18 +00008407 * Also returns OK when an error was encountered while executing the function.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008408 */
8409 static int
Bram Moolenaarf506c5b2010-06-22 06:28:58 +02008410call_func(funcname, len, rettv, argcount, argvars, firstline, lastline,
Bram Moolenaare9a41262005-01-15 22:18:47 +00008411 doesrange, evaluate, selfdict)
Bram Moolenaarf506c5b2010-06-22 06:28:58 +02008412 char_u *funcname; /* name of the function */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008413 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +00008414 typval_T *rettv; /* return value goes here */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008415 int argcount; /* number of "argvars" */
Bram Moolenaareb3593b2006-04-22 22:33:57 +00008416 typval_T *argvars; /* vars for arguments, must have "argcount"
8417 PLUS ONE elements! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008418 linenr_T firstline; /* first line of range */
8419 linenr_T lastline; /* last line of range */
8420 int *doesrange; /* return: function handled range */
8421 int evaluate;
Bram Moolenaar33570922005-01-25 22:26:29 +00008422 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008423{
8424 int ret = FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008425#define ERROR_UNKNOWN 0
8426#define ERROR_TOOMANY 1
8427#define ERROR_TOOFEW 2
8428#define ERROR_SCRIPT 3
Bram Moolenaare9a41262005-01-15 22:18:47 +00008429#define ERROR_DICT 4
8430#define ERROR_NONE 5
8431#define ERROR_OTHER 6
Bram Moolenaar071d4272004-06-13 20:20:40 +00008432 int error = ERROR_NONE;
8433 int i;
8434 int llen;
8435 ufunc_T *fp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008436#define FLEN_FIXED 40
8437 char_u fname_buf[FLEN_FIXED + 1];
8438 char_u *fname;
Bram Moolenaarbc42c1e2010-05-28 22:06:46 +02008439 char_u *name;
8440
8441 /* Make a copy of the name, if it comes from a funcref variable it could
8442 * be changed or deleted in the called function. */
Bram Moolenaarf506c5b2010-06-22 06:28:58 +02008443 name = vim_strnsave(funcname, len);
Bram Moolenaarbc42c1e2010-05-28 22:06:46 +02008444 if (name == NULL)
8445 return ret;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008446
8447 /*
8448 * In a script change <SID>name() and s:name() to K_SNR 123_name().
8449 * Change <SNR>123_name() to K_SNR 123_name().
8450 * Use fname_buf[] when it fits, otherwise allocate memory (slow).
8451 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008452 llen = eval_fname_script(name);
8453 if (llen > 0)
8454 {
8455 fname_buf[0] = K_SPECIAL;
8456 fname_buf[1] = KS_EXTRA;
8457 fname_buf[2] = (int)KE_SNR;
8458 i = 3;
8459 if (eval_fname_sid(name)) /* "<SID>" or "s:" */
8460 {
8461 if (current_SID <= 0)
8462 error = ERROR_SCRIPT;
8463 else
8464 {
8465 sprintf((char *)fname_buf + 3, "%ld_", (long)current_SID);
8466 i = (int)STRLEN(fname_buf);
8467 }
8468 }
8469 if (i + STRLEN(name + llen) < FLEN_FIXED)
8470 {
8471 STRCPY(fname_buf + i, name + llen);
8472 fname = fname_buf;
8473 }
8474 else
8475 {
8476 fname = alloc((unsigned)(i + STRLEN(name + llen) + 1));
8477 if (fname == NULL)
8478 error = ERROR_OTHER;
8479 else
8480 {
8481 mch_memmove(fname, fname_buf, (size_t)i);
8482 STRCPY(fname + i, name + llen);
8483 }
8484 }
8485 }
8486 else
8487 fname = name;
8488
8489 *doesrange = FALSE;
8490
8491
8492 /* execute the function if no errors detected and executing */
8493 if (evaluate && error == ERROR_NONE)
8494 {
Bram Moolenaara4f317d2014-04-24 17:12:33 +02008495 char_u *rfname = fname;
8496
8497 /* Ignore "g:" before a function name. */
8498 if (fname[0] == 'g' && fname[1] == ':')
8499 rfname = fname + 2;
8500
Bram Moolenaar798b30b2009-04-22 10:56:16 +00008501 rettv->v_type = VAR_NUMBER; /* default rettv is number zero */
8502 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008503 error = ERROR_UNKNOWN;
8504
Bram Moolenaara4f317d2014-04-24 17:12:33 +02008505 if (!builtin_function(rfname, -1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008506 {
8507 /*
8508 * User defined function.
8509 */
Bram Moolenaara4f317d2014-04-24 17:12:33 +02008510 fp = find_func(rfname);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008511
Bram Moolenaar071d4272004-06-13 20:20:40 +00008512#ifdef FEAT_AUTOCMD
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008513 /* Trigger FuncUndefined event, may load the function. */
8514 if (fp == NULL
8515 && apply_autocmds(EVENT_FUNCUNDEFINED,
Bram Moolenaara4f317d2014-04-24 17:12:33 +02008516 rfname, rfname, TRUE, NULL)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008517 && !aborting())
Bram Moolenaar071d4272004-06-13 20:20:40 +00008518 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008519 /* executed an autocommand, search for the function again */
Bram Moolenaara4f317d2014-04-24 17:12:33 +02008520 fp = find_func(rfname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008521 }
8522#endif
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008523 /* Try loading a package. */
Bram Moolenaara4f317d2014-04-24 17:12:33 +02008524 if (fp == NULL && script_autoload(rfname, TRUE) && !aborting())
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008525 {
8526 /* loaded a package, search for the function again */
Bram Moolenaara4f317d2014-04-24 17:12:33 +02008527 fp = find_func(rfname);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00008528 }
8529
Bram Moolenaar071d4272004-06-13 20:20:40 +00008530 if (fp != NULL)
8531 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008532 if (fp->uf_flags & FC_RANGE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008533 *doesrange = TRUE;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008534 if (argcount < fp->uf_args.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008535 error = ERROR_TOOFEW;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008536 else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008537 error = ERROR_TOOMANY;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008538 else if ((fp->uf_flags & FC_DICT) && selfdict == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008539 error = ERROR_DICT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008540 else
8541 {
8542 /*
8543 * Call the user function.
8544 * Save and restore search patterns, script variables and
8545 * redo buffer.
8546 */
8547 save_search_patterns();
8548 saveRedobuff();
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008549 ++fp->uf_calls;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008550 call_user_func(fp, argcount, argvars, rettv,
Bram Moolenaare9a41262005-01-15 22:18:47 +00008551 firstline, lastline,
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008552 (fp->uf_flags & FC_DICT) ? selfdict : NULL);
8553 if (--fp->uf_calls <= 0 && isdigit(*fp->uf_name)
8554 && fp->uf_refcount <= 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00008555 /* Function was unreferenced while being used, free it
8556 * now. */
8557 func_free(fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008558 restoreRedobuff();
8559 restore_search_patterns();
8560 error = ERROR_NONE;
8561 }
8562 }
8563 }
8564 else
8565 {
8566 /*
8567 * Find the function name in the table, call its implementation.
8568 */
8569 i = find_internal_func(fname);
8570 if (i >= 0)
8571 {
8572 if (argcount < functions[i].f_min_argc)
8573 error = ERROR_TOOFEW;
8574 else if (argcount > functions[i].f_max_argc)
8575 error = ERROR_TOOMANY;
8576 else
8577 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008578 argvars[argcount].v_type = VAR_UNKNOWN;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008579 functions[i].f_func(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008580 error = ERROR_NONE;
8581 }
8582 }
8583 }
8584 /*
8585 * The function call (or "FuncUndefined" autocommand sequence) might
8586 * have been aborted by an error, an interrupt, or an explicitly thrown
8587 * exception that has not been caught so far. This situation can be
8588 * tested for by calling aborting(). For an error in an internal
8589 * function or for the "E132" error in call_user_func(), however, the
8590 * throw point at which the "force_abort" flag (temporarily reset by
8591 * emsg()) is normally updated has not been reached yet. We need to
8592 * update that flag first to make aborting() reliable.
8593 */
8594 update_force_abort();
8595 }
8596 if (error == ERROR_NONE)
8597 ret = OK;
8598
8599 /*
8600 * Report an error unless the argument evaluation or function call has been
8601 * cancelled due to an aborting error, an interrupt, or an exception.
8602 */
Bram Moolenaar8c711452005-01-14 21:53:12 +00008603 if (!aborting())
8604 {
8605 switch (error)
8606 {
8607 case ERROR_UNKNOWN:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008608 emsg_funcname(N_("E117: Unknown function: %s"), name);
Bram Moolenaar8c711452005-01-14 21:53:12 +00008609 break;
8610 case ERROR_TOOMANY:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008611 emsg_funcname(e_toomanyarg, name);
Bram Moolenaar8c711452005-01-14 21:53:12 +00008612 break;
8613 case ERROR_TOOFEW:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008614 emsg_funcname(N_("E119: Not enough arguments for function: %s"),
Bram Moolenaar8c711452005-01-14 21:53:12 +00008615 name);
8616 break;
8617 case ERROR_SCRIPT:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008618 emsg_funcname(N_("E120: Using <SID> not in a script context: %s"),
Bram Moolenaar8c711452005-01-14 21:53:12 +00008619 name);
8620 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008621 case ERROR_DICT:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008622 emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"),
Bram Moolenaare9a41262005-01-15 22:18:47 +00008623 name);
8624 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00008625 }
8626 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008627
Bram Moolenaar071d4272004-06-13 20:20:40 +00008628 if (fname != name && fname != fname_buf)
8629 vim_free(fname);
Bram Moolenaarbc42c1e2010-05-28 22:06:46 +02008630 vim_free(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008631
8632 return ret;
8633}
8634
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008635/*
8636 * Give an error message with a function name. Handle <SNR> things.
Bram Moolenaar7b76b0a2009-01-28 18:09:38 +00008637 * "ermsg" is to be passed without translation, use N_() instead of _().
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008638 */
8639 static void
Bram Moolenaar89d40322006-08-29 15:30:07 +00008640emsg_funcname(ermsg, name)
8641 char *ermsg;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008642 char_u *name;
8643{
8644 char_u *p;
8645
8646 if (*name == K_SPECIAL)
8647 p = concat_str((char_u *)"<SNR>", name + 3);
8648 else
8649 p = name;
Bram Moolenaar89d40322006-08-29 15:30:07 +00008650 EMSG2(_(ermsg), p);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008651 if (p != name)
8652 vim_free(p);
8653}
8654
Bram Moolenaar05bb9532008-07-04 09:44:11 +00008655/*
8656 * Return TRUE for a non-zero Number and a non-empty String.
8657 */
8658 static int
8659non_zero_arg(argvars)
8660 typval_T *argvars;
8661{
8662 return ((argvars[0].v_type == VAR_NUMBER
8663 && argvars[0].vval.v_number != 0)
8664 || (argvars[0].v_type == VAR_STRING
8665 && argvars[0].vval.v_string != NULL
8666 && *argvars[0].vval.v_string != NUL));
8667}
8668
Bram Moolenaar071d4272004-06-13 20:20:40 +00008669/*********************************************
8670 * Implementation of the built-in functions
8671 */
8672
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008673#ifdef FEAT_FLOAT
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008674static int get_float_arg __ARGS((typval_T *argvars, float_T *f));
8675
8676/*
8677 * Get the float value of "argvars[0]" into "f".
8678 * Returns FAIL when the argument is not a Number or Float.
8679 */
8680 static int
8681get_float_arg(argvars, f)
8682 typval_T *argvars;
8683 float_T *f;
8684{
8685 if (argvars[0].v_type == VAR_FLOAT)
8686 {
8687 *f = argvars[0].vval.v_float;
8688 return OK;
8689 }
8690 if (argvars[0].v_type == VAR_NUMBER)
8691 {
8692 *f = (float_T)argvars[0].vval.v_number;
8693 return OK;
8694 }
8695 EMSG(_("E808: Number or Float required"));
8696 return FAIL;
8697}
8698
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008699/*
8700 * "abs(expr)" function
8701 */
8702 static void
8703f_abs(argvars, rettv)
8704 typval_T *argvars;
8705 typval_T *rettv;
8706{
8707 if (argvars[0].v_type == VAR_FLOAT)
8708 {
8709 rettv->v_type = VAR_FLOAT;
8710 rettv->vval.v_float = fabs(argvars[0].vval.v_float);
8711 }
8712 else
8713 {
8714 varnumber_T n;
8715 int error = FALSE;
8716
8717 n = get_tv_number_chk(&argvars[0], &error);
8718 if (error)
8719 rettv->vval.v_number = -1;
8720 else if (n > 0)
8721 rettv->vval.v_number = n;
8722 else
8723 rettv->vval.v_number = -n;
8724 }
8725}
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008726
8727/*
8728 * "acos()" function
8729 */
8730 static void
8731f_acos(argvars, rettv)
8732 typval_T *argvars;
8733 typval_T *rettv;
8734{
8735 float_T f;
8736
8737 rettv->v_type = VAR_FLOAT;
8738 if (get_float_arg(argvars, &f) == OK)
8739 rettv->vval.v_float = acos(f);
8740 else
8741 rettv->vval.v_float = 0.0;
8742}
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008743#endif
8744
Bram Moolenaar071d4272004-06-13 20:20:40 +00008745/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00008746 * "add(list, item)" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00008747 */
8748 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +00008749f_add(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008750 typval_T *argvars;
8751 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008752{
Bram Moolenaar33570922005-01-25 22:26:29 +00008753 list_T *l;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008754
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008755 rettv->vval.v_number = 1; /* Default: Failed */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008756 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008757 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008758 if ((l = argvars[0].vval.v_list) != NULL
Bram Moolenaar32f649e2011-04-11 13:46:13 +02008759 && !tv_check_lock(l->lv_lock, (char_u *)_("add() argument"))
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008760 && list_append_tv(l, &argvars[1]) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008761 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008762 }
8763 else
Bram Moolenaar0d660222005-01-07 21:51:51 +00008764 EMSG(_(e_listreq));
8765}
8766
8767/*
Bram Moolenaard6e256c2011-12-14 15:32:50 +01008768 * "and(expr, expr)" function
8769 */
8770 static void
8771f_and(argvars, rettv)
8772 typval_T *argvars;
8773 typval_T *rettv;
8774{
8775 rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL)
8776 & get_tv_number_chk(&argvars[1], NULL);
8777}
8778
8779/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00008780 * "append(lnum, string/list)" function
8781 */
8782 static void
8783f_append(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008784 typval_T *argvars;
8785 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008786{
8787 long lnum;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008788 char_u *line;
Bram Moolenaar33570922005-01-25 22:26:29 +00008789 list_T *l = NULL;
8790 listitem_T *li = NULL;
8791 typval_T *tv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008792 long added = 0;
8793
Bram Moolenaar3c1e9c22013-07-04 20:25:41 +02008794 /* When coming here from Insert mode, sync undo, so that this can be
8795 * undone separately from what was previously inserted. */
8796 if (u_sync_once == 2)
8797 {
8798 u_sync_once = 1; /* notify that u_sync() was called */
8799 u_sync(TRUE);
8800 }
8801
Bram Moolenaar0d660222005-01-07 21:51:51 +00008802 lnum = get_tv_lnum(argvars);
8803 if (lnum >= 0
8804 && lnum <= curbuf->b_ml.ml_line_count
8805 && u_save(lnum, lnum + 1) == OK)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008806 {
Bram Moolenaar0d660222005-01-07 21:51:51 +00008807 if (argvars[1].v_type == VAR_LIST)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008808 {
Bram Moolenaar0d660222005-01-07 21:51:51 +00008809 l = argvars[1].vval.v_list;
8810 if (l == NULL)
8811 return;
8812 li = l->lv_first;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008813 }
Bram Moolenaar0d660222005-01-07 21:51:51 +00008814 for (;;)
8815 {
8816 if (l == NULL)
8817 tv = &argvars[1]; /* append a string */
8818 else if (li == NULL)
8819 break; /* end of list */
8820 else
8821 tv = &li->li_tv; /* append item from list */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008822 line = get_tv_string_chk(tv);
8823 if (line == NULL) /* type error */
8824 {
8825 rettv->vval.v_number = 1; /* Failed */
8826 break;
8827 }
8828 ml_append(lnum + added, line, (colnr_T)0, FALSE);
Bram Moolenaar0d660222005-01-07 21:51:51 +00008829 ++added;
8830 if (l == NULL)
8831 break;
8832 li = li->li_next;
8833 }
8834
8835 appended_lines_mark(lnum, added);
8836 if (curwin->w_cursor.lnum > lnum)
8837 curwin->w_cursor.lnum += added;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008838 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008839 else
8840 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008841}
8842
8843/*
8844 * "argc()" function
8845 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008846 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008847f_argc(argvars, rettv)
Bram Moolenaar78a15312009-05-15 19:33:18 +00008848 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +00008849 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008850{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008851 rettv->vval.v_number = ARGCOUNT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008852}
8853
8854/*
8855 * "argidx()" function
8856 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008857 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008858f_argidx(argvars, rettv)
Bram Moolenaar78a15312009-05-15 19:33:18 +00008859 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +00008860 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008861{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008862 rettv->vval.v_number = curwin->w_arg_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008863}
8864
8865/*
Bram Moolenaar2d1fe052014-05-28 18:22:57 +02008866 * "arglistid()" function
8867 */
8868 static void
8869f_arglistid(argvars, rettv)
8870 typval_T *argvars UNUSED;
8871 typval_T *rettv;
8872{
8873 win_T *wp;
8874 tabpage_T *tp = NULL;
8875 long n;
8876
8877 rettv->vval.v_number = -1;
8878 if (argvars[0].v_type != VAR_UNKNOWN)
8879 {
8880 if (argvars[1].v_type != VAR_UNKNOWN)
8881 {
8882 n = get_tv_number(&argvars[1]);
8883 if (n >= 0)
8884 tp = find_tabpage(n);
8885 }
8886 else
8887 tp = curtab;
8888
8889 if (tp != NULL)
8890 {
8891 wp = find_win_by_nr(&argvars[0], tp);
8892 if (wp != NULL)
8893 rettv->vval.v_number = wp->w_alist->id;
8894 }
8895 }
8896 else
8897 rettv->vval.v_number = curwin->w_alist->id;
8898}
8899
8900/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008901 * "argv(nr)" function
8902 */
8903 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008904f_argv(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008905 typval_T *argvars;
8906 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008907{
8908 int idx;
8909
Bram Moolenaare2f98b92006-03-29 21:18:24 +00008910 if (argvars[0].v_type != VAR_UNKNOWN)
8911 {
8912 idx = get_tv_number_chk(&argvars[0], NULL);
8913 if (idx >= 0 && idx < ARGCOUNT)
8914 rettv->vval.v_string = vim_strsave(alist_name(&ARGLIST[idx]));
8915 else
8916 rettv->vval.v_string = NULL;
8917 rettv->v_type = VAR_STRING;
8918 }
8919 else if (rettv_list_alloc(rettv) == OK)
8920 for (idx = 0; idx < ARGCOUNT; ++idx)
8921 list_append_string(rettv->vval.v_list,
8922 alist_name(&ARGLIST[idx]), -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008923}
8924
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008925#ifdef FEAT_FLOAT
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008926/*
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008927 * "asin()" function
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008928 */
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008929 static void
8930f_asin(argvars, rettv)
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008931 typval_T *argvars;
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008932 typval_T *rettv;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008933{
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008934 float_T f;
8935
8936 rettv->v_type = VAR_FLOAT;
8937 if (get_float_arg(argvars, &f) == OK)
8938 rettv->vval.v_float = asin(f);
8939 else
8940 rettv->vval.v_float = 0.0;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008941}
8942
8943/*
8944 * "atan()" function
8945 */
8946 static void
8947f_atan(argvars, rettv)
8948 typval_T *argvars;
8949 typval_T *rettv;
8950{
8951 float_T f;
8952
8953 rettv->v_type = VAR_FLOAT;
8954 if (get_float_arg(argvars, &f) == OK)
8955 rettv->vval.v_float = atan(f);
8956 else
8957 rettv->vval.v_float = 0.0;
8958}
Bram Moolenaardb7c6862010-05-21 16:33:48 +02008959
8960/*
8961 * "atan2()" function
8962 */
8963 static void
8964f_atan2(argvars, rettv)
8965 typval_T *argvars;
8966 typval_T *rettv;
8967{
8968 float_T fx, fy;
8969
8970 rettv->v_type = VAR_FLOAT;
8971 if (get_float_arg(argvars, &fx) == OK
8972 && get_float_arg(&argvars[1], &fy) == OK)
8973 rettv->vval.v_float = atan2(fx, fy);
8974 else
8975 rettv->vval.v_float = 0.0;
8976}
Bram Moolenaar8c8de832008-06-24 22:58:06 +00008977#endif
8978
Bram Moolenaar071d4272004-06-13 20:20:40 +00008979/*
8980 * "browse(save, title, initdir, default)" function
8981 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008982 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008983f_browse(argvars, rettv)
Bram Moolenaar78a15312009-05-15 19:33:18 +00008984 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +00008985 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008986{
8987#ifdef FEAT_BROWSE
8988 int save;
8989 char_u *title;
8990 char_u *initdir;
8991 char_u *defname;
8992 char_u buf[NUMBUFLEN];
8993 char_u buf2[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008994 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008995
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008996 save = get_tv_number_chk(&argvars[0], &error);
8997 title = get_tv_string_chk(&argvars[1]);
8998 initdir = get_tv_string_buf_chk(&argvars[2], buf);
8999 defname = get_tv_string_buf_chk(&argvars[3], buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009000
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009001 if (error || title == NULL || initdir == NULL || defname == NULL)
9002 rettv->vval.v_string = NULL;
9003 else
9004 rettv->vval.v_string =
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009005 do_browse(save ? BROWSE_SAVE : 0,
9006 title, defname, NULL, initdir, NULL, curbuf);
9007#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009008 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009009#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009010 rettv->v_type = VAR_STRING;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009011}
9012
9013/*
9014 * "browsedir(title, initdir)" function
9015 */
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009016 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009017f_browsedir(argvars, rettv)
Bram Moolenaar78a15312009-05-15 19:33:18 +00009018 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +00009019 typval_T *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009020{
9021#ifdef FEAT_BROWSE
9022 char_u *title;
9023 char_u *initdir;
9024 char_u buf[NUMBUFLEN];
9025
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009026 title = get_tv_string_chk(&argvars[0]);
9027 initdir = get_tv_string_buf_chk(&argvars[1], buf);
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009028
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009029 if (title == NULL || initdir == NULL)
9030 rettv->vval.v_string = NULL;
9031 else
9032 rettv->vval.v_string = do_browse(BROWSE_DIR,
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009033 title, NULL, NULL, initdir, NULL, curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009034#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009035 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009036#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009037 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009038}
9039
Bram Moolenaar33570922005-01-25 22:26:29 +00009040static buf_T *find_buffer __ARGS((typval_T *avar));
Bram Moolenaar0d660222005-01-07 21:51:51 +00009041
Bram Moolenaar071d4272004-06-13 20:20:40 +00009042/*
9043 * Find a buffer by number or exact name.
9044 */
9045 static buf_T *
9046find_buffer(avar)
Bram Moolenaar33570922005-01-25 22:26:29 +00009047 typval_T *avar;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009048{
9049 buf_T *buf = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009050
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009051 if (avar->v_type == VAR_NUMBER)
9052 buf = buflist_findnr((int)avar->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +00009053 else if (avar->v_type == VAR_STRING && avar->vval.v_string != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009054 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009055 buf = buflist_findname_exp(avar->vval.v_string);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00009056 if (buf == NULL)
9057 {
9058 /* No full path name match, try a match with a URL or a "nofile"
9059 * buffer, these don't use the full path. */
9060 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
9061 if (buf->b_fname != NULL
9062 && (path_with_url(buf->b_fname)
9063#ifdef FEAT_QUICKFIX
9064 || bt_nofile(buf)
9065#endif
9066 )
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009067 && STRCMP(buf->b_fname, avar->vval.v_string) == 0)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00009068 break;
9069 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009070 }
9071 return buf;
9072}
9073
9074/*
9075 * "bufexists(expr)" function
9076 */
9077 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009078f_bufexists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009079 typval_T *argvars;
9080 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009081{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009082 rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009083}
9084
9085/*
9086 * "buflisted(expr)" function
9087 */
9088 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009089f_buflisted(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009090 typval_T *argvars;
9091 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009092{
9093 buf_T *buf;
9094
9095 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009096 rettv->vval.v_number = (buf != NULL && buf->b_p_bl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009097}
9098
9099/*
9100 * "bufloaded(expr)" function
9101 */
9102 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009103f_bufloaded(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009104 typval_T *argvars;
9105 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009106{
9107 buf_T *buf;
9108
9109 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009110 rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009111}
9112
Bram Moolenaar0c279bb2013-03-19 14:25:54 +01009113static buf_T *get_buf_tv __ARGS((typval_T *tv, int curtab_only));
Bram Moolenaar0d660222005-01-07 21:51:51 +00009114
Bram Moolenaar071d4272004-06-13 20:20:40 +00009115/*
9116 * Get buffer by number or pattern.
9117 */
9118 static buf_T *
Bram Moolenaar0c279bb2013-03-19 14:25:54 +01009119get_buf_tv(tv, curtab_only)
Bram Moolenaar33570922005-01-25 22:26:29 +00009120 typval_T *tv;
Bram Moolenaar0c279bb2013-03-19 14:25:54 +01009121 int curtab_only;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009122{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009123 char_u *name = tv->vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009124 int save_magic;
9125 char_u *save_cpo;
9126 buf_T *buf;
9127
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009128 if (tv->v_type == VAR_NUMBER)
9129 return buflist_findnr((int)tv->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +00009130 if (tv->v_type != VAR_STRING)
9131 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009132 if (name == NULL || *name == NUL)
9133 return curbuf;
9134 if (name[0] == '$' && name[1] == NUL)
9135 return lastbuf;
9136
9137 /* Ignore 'magic' and 'cpoptions' here to make scripts portable */
9138 save_magic = p_magic;
9139 p_magic = TRUE;
9140 save_cpo = p_cpo;
9141 p_cpo = (char_u *)"";
9142
9143 buf = buflist_findnr(buflist_findpat(name, name + STRLEN(name),
Bram Moolenaar0c279bb2013-03-19 14:25:54 +01009144 TRUE, FALSE, curtab_only));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009145
9146 p_magic = save_magic;
9147 p_cpo = save_cpo;
9148
9149 /* If not found, try expanding the name, like done for bufexists(). */
9150 if (buf == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009151 buf = find_buffer(tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009152
9153 return buf;
9154}
9155
9156/*
9157 * "bufname(expr)" function
9158 */
9159 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009160f_bufname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009161 typval_T *argvars;
9162 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009163{
9164 buf_T *buf;
9165
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009166 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009167 ++emsg_off;
Bram Moolenaar0c279bb2013-03-19 14:25:54 +01009168 buf = get_buf_tv(&argvars[0], FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009169 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009170 if (buf != NULL && buf->b_fname != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009171 rettv->vval.v_string = vim_strsave(buf->b_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009172 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009173 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009174 --emsg_off;
9175}
9176
9177/*
9178 * "bufnr(expr)" function
9179 */
9180 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009181f_bufnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009182 typval_T *argvars;
9183 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009184{
9185 buf_T *buf;
Bram Moolenaar0e34f622006-03-03 23:00:03 +00009186 int error = FALSE;
9187 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009188
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009189 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009190 ++emsg_off;
Bram Moolenaar0c279bb2013-03-19 14:25:54 +01009191 buf = get_buf_tv(&argvars[0], FALSE);
Bram Moolenaar0e34f622006-03-03 23:00:03 +00009192 --emsg_off;
9193
9194 /* If the buffer isn't found and the second argument is not zero create a
9195 * new buffer. */
9196 if (buf == NULL
9197 && argvars[1].v_type != VAR_UNKNOWN
9198 && get_tv_number_chk(&argvars[1], &error) != 0
9199 && !error
9200 && (name = get_tv_string_chk(&argvars[0])) != NULL
9201 && !error)
9202 buf = buflist_new(name, NULL, (linenr_T)1, 0);
9203
Bram Moolenaar071d4272004-06-13 20:20:40 +00009204 if (buf != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009205 rettv->vval.v_number = buf->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009206 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009207 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009208}
9209
9210/*
9211 * "bufwinnr(nr)" function
9212 */
9213 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009214f_bufwinnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009215 typval_T *argvars;
9216 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009217{
9218#ifdef FEAT_WINDOWS
9219 win_T *wp;
9220 int winnr = 0;
9221#endif
9222 buf_T *buf;
9223
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009224 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009225 ++emsg_off;
Bram Moolenaar0c279bb2013-03-19 14:25:54 +01009226 buf = get_buf_tv(&argvars[0], TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009227#ifdef FEAT_WINDOWS
9228 for (wp = firstwin; wp; wp = wp->w_next)
9229 {
9230 ++winnr;
9231 if (wp->w_buffer == buf)
9232 break;
9233 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009234 rettv->vval.v_number = (wp != NULL ? winnr : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009235#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009236 rettv->vval.v_number = (curwin->w_buffer == buf ? 1 : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009237#endif
9238 --emsg_off;
9239}
9240
9241/*
9242 * "byte2line(byte)" function
9243 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009244 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009245f_byte2line(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009246 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +00009247 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009248{
9249#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009250 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009251#else
9252 long boff = 0;
9253
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009254 boff = get_tv_number(&argvars[0]) - 1; /* boff gets -1 on type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009255 if (boff < 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009256 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009257 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009258 rettv->vval.v_number = ml_find_line_or_offset(curbuf,
Bram Moolenaar071d4272004-06-13 20:20:40 +00009259 (linenr_T)0, &boff);
9260#endif
9261}
9262
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00009263 static void
Bram Moolenaar0ffbbf92013-11-02 23:29:26 +01009264byteidx(argvars, rettv, comp)
Bram Moolenaar33570922005-01-25 22:26:29 +00009265 typval_T *argvars;
9266 typval_T *rettv;
Bram Moolenaarf30caaf2014-02-23 22:54:58 +01009267 int comp UNUSED;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00009268{
9269#ifdef FEAT_MBYTE
9270 char_u *t;
9271#endif
9272 char_u *str;
9273 long idx;
9274
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009275 str = get_tv_string_chk(&argvars[0]);
9276 idx = get_tv_number_chk(&argvars[1], NULL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009277 rettv->vval.v_number = -1;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009278 if (str == NULL || idx < 0)
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00009279 return;
9280
9281#ifdef FEAT_MBYTE
9282 t = str;
9283 for ( ; idx > 0; idx--)
9284 {
9285 if (*t == NUL) /* EOL reached */
9286 return;
Bram Moolenaar0ffbbf92013-11-02 23:29:26 +01009287 if (enc_utf8 && comp)
9288 t += utf_ptr2len(t);
9289 else
9290 t += (*mb_ptr2len)(t);
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00009291 }
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00009292 rettv->vval.v_number = (varnumber_T)(t - str);
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00009293#else
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009294 if ((size_t)idx <= STRLEN(str))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009295 rettv->vval.v_number = idx;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00009296#endif
9297}
9298
Bram Moolenaar0ffbbf92013-11-02 23:29:26 +01009299/*
9300 * "byteidx()" function
9301 */
9302 static void
9303f_byteidx(argvars, rettv)
9304 typval_T *argvars;
9305 typval_T *rettv;
9306{
9307 byteidx(argvars, rettv, FALSE);
9308}
9309
9310/*
9311 * "byteidxcomp()" function
9312 */
9313 static void
9314f_byteidxcomp(argvars, rettv)
9315 typval_T *argvars;
9316 typval_T *rettv;
9317{
9318 byteidx(argvars, rettv, TRUE);
9319}
9320
Bram Moolenaardb913952012-06-29 12:54:53 +02009321 int
9322func_call(name, args, selfdict, rettv)
9323 char_u *name;
9324 typval_T *args;
9325 dict_T *selfdict;
9326 typval_T *rettv;
9327{
9328 listitem_T *item;
9329 typval_T argv[MAX_FUNC_ARGS + 1];
9330 int argc = 0;
9331 int dummy;
9332 int r = 0;
9333
9334 for (item = args->vval.v_list->lv_first; item != NULL;
9335 item = item->li_next)
9336 {
9337 if (argc == MAX_FUNC_ARGS)
9338 {
9339 EMSG(_("E699: Too many arguments"));
9340 break;
9341 }
9342 /* Make a copy of each argument. This is needed to be able to set
9343 * v_lock to VAR_FIXED in the copy without changing the original list.
9344 */
9345 copy_tv(&item->li_tv, &argv[argc++]);
9346 }
9347
9348 if (item == NULL)
9349 r = call_func(name, (int)STRLEN(name), rettv, argc, argv,
9350 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
9351 &dummy, TRUE, selfdict);
9352
9353 /* Free the arguments. */
9354 while (argc > 0)
9355 clear_tv(&argv[--argc]);
9356
9357 return r;
9358}
9359
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00009360/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009361 * "call(func, arglist)" function
9362 */
9363 static void
9364f_call(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009365 typval_T *argvars;
9366 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009367{
9368 char_u *func;
Bram Moolenaar33570922005-01-25 22:26:29 +00009369 dict_T *selfdict = NULL;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009370
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009371 if (argvars[1].v_type != VAR_LIST)
9372 {
9373 EMSG(_(e_listreq));
9374 return;
9375 }
9376 if (argvars[1].vval.v_list == NULL)
9377 return;
9378
9379 if (argvars[0].v_type == VAR_FUNC)
9380 func = argvars[0].vval.v_string;
9381 else
9382 func = get_tv_string(&argvars[0]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009383 if (*func == NUL)
9384 return; /* type error or empty name */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009385
Bram Moolenaare9a41262005-01-15 22:18:47 +00009386 if (argvars[2].v_type != VAR_UNKNOWN)
9387 {
9388 if (argvars[2].v_type != VAR_DICT)
9389 {
9390 EMSG(_(e_dictreq));
9391 return;
9392 }
9393 selfdict = argvars[2].vval.v_dict;
9394 }
9395
Bram Moolenaardb913952012-06-29 12:54:53 +02009396 (void)func_call(func, &argvars[1], selfdict, rettv);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009397}
9398
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009399#ifdef FEAT_FLOAT
9400/*
9401 * "ceil({float})" function
9402 */
9403 static void
9404f_ceil(argvars, rettv)
9405 typval_T *argvars;
9406 typval_T *rettv;
9407{
9408 float_T f;
9409
9410 rettv->v_type = VAR_FLOAT;
9411 if (get_float_arg(argvars, &f) == OK)
9412 rettv->vval.v_float = ceil(f);
9413 else
9414 rettv->vval.v_float = 0.0;
9415}
9416#endif
9417
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009418/*
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00009419 * "changenr()" function
9420 */
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00009421 static void
9422f_changenr(argvars, rettv)
Bram Moolenaar78a15312009-05-15 19:33:18 +00009423 typval_T *argvars UNUSED;
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00009424 typval_T *rettv;
9425{
9426 rettv->vval.v_number = curbuf->b_u_seq_cur;
9427}
9428
9429/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009430 * "char2nr(string)" function
9431 */
9432 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009433f_char2nr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009434 typval_T *argvars;
9435 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009436{
9437#ifdef FEAT_MBYTE
9438 if (has_mbyte)
Bram Moolenaard35d7842013-01-23 17:17:10 +01009439 {
9440 int utf8 = 0;
9441
9442 if (argvars[1].v_type != VAR_UNKNOWN)
9443 utf8 = get_tv_number_chk(&argvars[1], NULL);
9444
9445 if (utf8)
9446 rettv->vval.v_number = (*utf_ptr2char)(get_tv_string(&argvars[0]));
9447 else
9448 rettv->vval.v_number = (*mb_ptr2char)(get_tv_string(&argvars[0]));
9449 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009450 else
9451#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009452 rettv->vval.v_number = get_tv_string(&argvars[0])[0];
Bram Moolenaar071d4272004-06-13 20:20:40 +00009453}
9454
9455/*
9456 * "cindent(lnum)" function
9457 */
9458 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009459f_cindent(argvars, rettv)
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +01009460 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +00009461 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009462{
9463#ifdef FEAT_CINDENT
9464 pos_T pos;
9465 linenr_T lnum;
9466
9467 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009468 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009469 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
9470 {
9471 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009472 rettv->vval.v_number = get_c_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +00009473 curwin->w_cursor = pos;
9474 }
9475 else
9476#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009477 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009478}
9479
9480/*
Bram Moolenaar6ee10162007-07-26 20:58:42 +00009481 * "clearmatches()" function
9482 */
Bram Moolenaar6ee10162007-07-26 20:58:42 +00009483 static void
9484f_clearmatches(argvars, rettv)
Bram Moolenaar78a15312009-05-15 19:33:18 +00009485 typval_T *argvars UNUSED;
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009486 typval_T *rettv UNUSED;
Bram Moolenaar6ee10162007-07-26 20:58:42 +00009487{
9488#ifdef FEAT_SEARCH_EXTRA
9489 clear_matches(curwin);
9490#endif
9491}
9492
9493/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009494 * "col(string)" function
9495 */
9496 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009497f_col(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009498 typval_T *argvars;
9499 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009500{
9501 colnr_T col = 0;
9502 pos_T *fp;
Bram Moolenaar0e34f622006-03-03 23:00:03 +00009503 int fnum = curbuf->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009504
Bram Moolenaar0e34f622006-03-03 23:00:03 +00009505 fp = var2fpos(&argvars[0], FALSE, &fnum);
9506 if (fp != NULL && fnum == curbuf->b_fnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009507 {
9508 if (fp->col == MAXCOL)
9509 {
9510 /* '> can be MAXCOL, get the length of the line then */
9511 if (fp->lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00009512 col = (colnr_T)STRLEN(ml_get(fp->lnum)) + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009513 else
9514 col = MAXCOL;
9515 }
9516 else
9517 {
9518 col = fp->col + 1;
9519#ifdef FEAT_VIRTUALEDIT
9520 /* col(".") when the cursor is on the NUL at the end of the line
9521 * because of "coladd" can be seen as an extra column. */
9522 if (virtual_active() && fp == &curwin->w_cursor)
9523 {
9524 char_u *p = ml_get_cursor();
9525
9526 if (curwin->w_cursor.coladd >= (colnr_T)chartabsize(p,
9527 curwin->w_virtcol - curwin->w_cursor.coladd))
9528 {
9529# ifdef FEAT_MBYTE
9530 int l;
9531
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00009532 if (*p != NUL && p[(l = (*mb_ptr2len)(p))] == NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009533 col += l;
9534# else
9535 if (*p != NUL && p[1] == NUL)
9536 ++col;
9537# endif
9538 }
9539 }
9540#endif
9541 }
9542 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009543 rettv->vval.v_number = col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009544}
9545
Bram Moolenaar572cb562005-08-05 21:35:02 +00009546#if defined(FEAT_INS_EXPAND)
9547/*
Bram Moolenaarade00832006-03-10 21:46:58 +00009548 * "complete()" function
9549 */
Bram Moolenaarade00832006-03-10 21:46:58 +00009550 static void
9551f_complete(argvars, rettv)
9552 typval_T *argvars;
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009553 typval_T *rettv UNUSED;
Bram Moolenaarade00832006-03-10 21:46:58 +00009554{
9555 int startcol;
9556
9557 if ((State & INSERT) == 0)
9558 {
9559 EMSG(_("E785: complete() can only be used in Insert mode"));
9560 return;
9561 }
Bram Moolenaarce6ef252006-07-12 19:49:41 +00009562
9563 /* Check for undo allowed here, because if something was already inserted
9564 * the line was already saved for undo and this check isn't done. */
9565 if (!undo_allowed())
9566 return;
9567
Bram Moolenaarade00832006-03-10 21:46:58 +00009568 if (argvars[1].v_type != VAR_LIST || argvars[1].vval.v_list == NULL)
9569 {
9570 EMSG(_(e_invarg));
9571 return;
9572 }
9573
9574 startcol = get_tv_number_chk(&argvars[0], NULL);
9575 if (startcol <= 0)
9576 return;
9577
9578 set_completion(startcol - 1, argvars[1].vval.v_list);
9579}
9580
9581/*
Bram Moolenaar572cb562005-08-05 21:35:02 +00009582 * "complete_add()" function
9583 */
Bram Moolenaar572cb562005-08-05 21:35:02 +00009584 static void
9585f_complete_add(argvars, rettv)
9586 typval_T *argvars;
9587 typval_T *rettv;
9588{
Bram Moolenaarceaf7b82006-03-19 22:18:55 +00009589 rettv->vval.v_number = ins_compl_add_tv(&argvars[0], 0);
Bram Moolenaar572cb562005-08-05 21:35:02 +00009590}
9591
9592/*
9593 * "complete_check()" function
9594 */
Bram Moolenaar572cb562005-08-05 21:35:02 +00009595 static void
9596f_complete_check(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009597 typval_T *argvars UNUSED;
Bram Moolenaar572cb562005-08-05 21:35:02 +00009598 typval_T *rettv;
9599{
9600 int saved = RedrawingDisabled;
9601
9602 RedrawingDisabled = 0;
9603 ins_compl_check_keys(0);
9604 rettv->vval.v_number = compl_interrupted;
9605 RedrawingDisabled = saved;
9606}
9607#endif
9608
Bram Moolenaar071d4272004-06-13 20:20:40 +00009609/*
9610 * "confirm(message, buttons[, default [, type]])" function
9611 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009612 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009613f_confirm(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009614 typval_T *argvars UNUSED;
9615 typval_T *rettv UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009616{
9617#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
9618 char_u *message;
9619 char_u *buttons = NULL;
9620 char_u buf[NUMBUFLEN];
9621 char_u buf2[NUMBUFLEN];
9622 int def = 1;
9623 int type = VIM_GENERIC;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009624 char_u *typestr;
9625 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009626
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009627 message = get_tv_string_chk(&argvars[0]);
9628 if (message == NULL)
9629 error = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009630 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009631 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009632 buttons = get_tv_string_buf_chk(&argvars[1], buf);
9633 if (buttons == NULL)
9634 error = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009635 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009636 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009637 def = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009638 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009639 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009640 typestr = get_tv_string_buf_chk(&argvars[3], buf2);
9641 if (typestr == NULL)
9642 error = TRUE;
9643 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00009644 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009645 switch (TOUPPER_ASC(*typestr))
9646 {
9647 case 'E': type = VIM_ERROR; break;
9648 case 'Q': type = VIM_QUESTION; break;
9649 case 'I': type = VIM_INFO; break;
9650 case 'W': type = VIM_WARNING; break;
9651 case 'G': type = VIM_GENERIC; break;
9652 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009653 }
9654 }
9655 }
9656 }
9657
9658 if (buttons == NULL || *buttons == NUL)
9659 buttons = (char_u *)_("&Ok");
9660
Bram Moolenaar798b30b2009-04-22 10:56:16 +00009661 if (!error)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009662 rettv->vval.v_number = do_dialog(type, NULL, message, buttons,
Bram Moolenaard2c340a2011-01-17 20:08:11 +01009663 def, NULL, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009664#endif
9665}
9666
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009667/*
9668 * "copy()" function
9669 */
9670 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009671f_copy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009672 typval_T *argvars;
9673 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009674{
Bram Moolenaar81bf7082005-02-12 14:31:42 +00009675 item_copy(&argvars[0], rettv, FALSE, 0);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009676}
Bram Moolenaar071d4272004-06-13 20:20:40 +00009677
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009678#ifdef FEAT_FLOAT
9679/*
9680 * "cos()" function
9681 */
9682 static void
9683f_cos(argvars, rettv)
9684 typval_T *argvars;
9685 typval_T *rettv;
9686{
9687 float_T f;
9688
9689 rettv->v_type = VAR_FLOAT;
9690 if (get_float_arg(argvars, &f) == OK)
9691 rettv->vval.v_float = cos(f);
9692 else
9693 rettv->vval.v_float = 0.0;
9694}
Bram Moolenaardb7c6862010-05-21 16:33:48 +02009695
9696/*
9697 * "cosh()" function
9698 */
9699 static void
9700f_cosh(argvars, rettv)
9701 typval_T *argvars;
9702 typval_T *rettv;
9703{
9704 float_T f;
9705
9706 rettv->v_type = VAR_FLOAT;
9707 if (get_float_arg(argvars, &f) == OK)
9708 rettv->vval.v_float = cosh(f);
9709 else
9710 rettv->vval.v_float = 0.0;
9711}
Bram Moolenaar8c8de832008-06-24 22:58:06 +00009712#endif
9713
Bram Moolenaar071d4272004-06-13 20:20:40 +00009714/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009715 * "count()" function
9716 */
9717 static void
9718f_count(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009719 typval_T *argvars;
9720 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009721{
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009722 long n = 0;
9723 int ic = FALSE;
9724
Bram Moolenaare9a41262005-01-15 22:18:47 +00009725 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009726 {
Bram Moolenaar33570922005-01-25 22:26:29 +00009727 listitem_T *li;
9728 list_T *l;
Bram Moolenaare9a41262005-01-15 22:18:47 +00009729 long idx;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00009730
Bram Moolenaare9a41262005-01-15 22:18:47 +00009731 if ((l = argvars[0].vval.v_list) != NULL)
9732 {
9733 li = l->lv_first;
9734 if (argvars[2].v_type != VAR_UNKNOWN)
9735 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009736 int error = FALSE;
9737
9738 ic = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaare9a41262005-01-15 22:18:47 +00009739 if (argvars[3].v_type != VAR_UNKNOWN)
9740 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009741 idx = get_tv_number_chk(&argvars[3], &error);
9742 if (!error)
9743 {
9744 li = list_find(l, idx);
9745 if (li == NULL)
9746 EMSGN(_(e_listidx), idx);
9747 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00009748 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009749 if (error)
9750 li = NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00009751 }
9752
9753 for ( ; li != NULL; li = li->li_next)
Bram Moolenaar67b3f992010-11-10 20:41:57 +01009754 if (tv_equal(&li->li_tv, &argvars[1], ic, FALSE))
Bram Moolenaare9a41262005-01-15 22:18:47 +00009755 ++n;
9756 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009757 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00009758 else if (argvars[0].v_type == VAR_DICT)
9759 {
Bram Moolenaar33570922005-01-25 22:26:29 +00009760 int todo;
9761 dict_T *d;
9762 hashitem_T *hi;
Bram Moolenaare9a41262005-01-15 22:18:47 +00009763
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00009764 if ((d = argvars[0].vval.v_dict) != NULL)
9765 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009766 int error = FALSE;
9767
Bram Moolenaare9a41262005-01-15 22:18:47 +00009768 if (argvars[2].v_type != VAR_UNKNOWN)
9769 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009770 ic = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaare9a41262005-01-15 22:18:47 +00009771 if (argvars[3].v_type != VAR_UNKNOWN)
9772 EMSG(_(e_invarg));
9773 }
9774
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00009775 todo = error ? 0 : (int)d->dv_hashtab.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00009776 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00009777 {
9778 if (!HASHITEM_EMPTY(hi))
9779 {
9780 --todo;
Bram Moolenaar67b3f992010-11-10 20:41:57 +01009781 if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic, FALSE))
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00009782 ++n;
9783 }
9784 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00009785 }
9786 }
9787 else
9788 EMSG2(_(e_listdictarg), "count()");
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009789 rettv->vval.v_number = n;
9790}
9791
9792/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009793 * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
9794 *
9795 * Checks the existence of a cscope connection.
9796 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009797 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009798f_cscope_connection(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009799 typval_T *argvars UNUSED;
9800 typval_T *rettv UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009801{
9802#ifdef FEAT_CSCOPE
9803 int num = 0;
9804 char_u *dbpath = NULL;
9805 char_u *prepend = NULL;
9806 char_u buf[NUMBUFLEN];
9807
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009808 if (argvars[0].v_type != VAR_UNKNOWN
9809 && argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009810 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009811 num = (int)get_tv_number(&argvars[0]);
9812 dbpath = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009813 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009814 prepend = get_tv_string_buf(&argvars[2], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009815 }
9816
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009817 rettv->vval.v_number = cs_connection(num, dbpath, prepend);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009818#endif
9819}
9820
9821/*
9822 * "cursor(lnum, col)" function
9823 *
Bram Moolenaar798b30b2009-04-22 10:56:16 +00009824 * Moves the cursor to the specified line and column.
9825 * Returns 0 when the position could be set, -1 otherwise.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009826 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009827 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009828f_cursor(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009829 typval_T *argvars;
9830 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009831{
9832 long line, col;
Bram Moolenaara5525202006-03-02 22:52:09 +00009833#ifdef FEAT_VIRTUALEDIT
9834 long coladd = 0;
9835#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009836
Bram Moolenaar798b30b2009-04-22 10:56:16 +00009837 rettv->vval.v_number = -1;
Bram Moolenaara5525202006-03-02 22:52:09 +00009838 if (argvars[1].v_type == VAR_UNKNOWN)
9839 {
Bram Moolenaar0e34f622006-03-03 23:00:03 +00009840 pos_T pos;
Bram Moolenaar493c1782014-05-28 14:34:46 +02009841 colnr_T curswant = -1;
Bram Moolenaara5525202006-03-02 22:52:09 +00009842
Bram Moolenaar493c1782014-05-28 14:34:46 +02009843 if (list2fpos(argvars, &pos, NULL, &curswant) == FAIL)
Bram Moolenaara5525202006-03-02 22:52:09 +00009844 return;
Bram Moolenaar0e34f622006-03-03 23:00:03 +00009845 line = pos.lnum;
9846 col = pos.col;
Bram Moolenaara5525202006-03-02 22:52:09 +00009847#ifdef FEAT_VIRTUALEDIT
Bram Moolenaar0e34f622006-03-03 23:00:03 +00009848 coladd = pos.coladd;
Bram Moolenaara5525202006-03-02 22:52:09 +00009849#endif
Bram Moolenaar493c1782014-05-28 14:34:46 +02009850 if (curswant >= 0)
9851 curwin->w_curswant = curswant - 1;
Bram Moolenaara5525202006-03-02 22:52:09 +00009852 }
9853 else
9854 {
9855 line = get_tv_lnum(argvars);
9856 col = get_tv_number_chk(&argvars[1], NULL);
9857#ifdef FEAT_VIRTUALEDIT
9858 if (argvars[2].v_type != VAR_UNKNOWN)
9859 coladd = get_tv_number_chk(&argvars[2], NULL);
9860#endif
9861 }
9862 if (line < 0 || col < 0
9863#ifdef FEAT_VIRTUALEDIT
9864 || coladd < 0
9865#endif
9866 )
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009867 return; /* type error; errmsg already given */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009868 if (line > 0)
9869 curwin->w_cursor.lnum = line;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009870 if (col > 0)
9871 curwin->w_cursor.col = col - 1;
9872#ifdef FEAT_VIRTUALEDIT
Bram Moolenaara5525202006-03-02 22:52:09 +00009873 curwin->w_cursor.coladd = coladd;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009874#endif
9875
9876 /* Make sure the cursor is in a valid position. */
9877 check_cursor();
9878#ifdef FEAT_MBYTE
9879 /* Correct cursor for multi-byte character. */
9880 if (has_mbyte)
9881 mb_adjust_cursor();
9882#endif
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00009883
9884 curwin->w_set_curswant = TRUE;
Bram Moolenaar798b30b2009-04-22 10:56:16 +00009885 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009886}
9887
9888/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009889 * "deepcopy()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00009890 */
9891 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009892f_deepcopy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009893 typval_T *argvars;
9894 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009895{
Bram Moolenaar81bf7082005-02-12 14:31:42 +00009896 int noref = 0;
9897
9898 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009899 noref = get_tv_number_chk(&argvars[1], NULL);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00009900 if (noref < 0 || noref > 1)
9901 EMSG(_(e_invarg));
9902 else
Bram Moolenaar2c2398c2009-06-03 11:22:45 +00009903 {
9904 current_copyID += COPYID_INC;
9905 item_copy(&argvars[0], rettv, TRUE, noref == 0 ? current_copyID : 0);
9906 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009907}
9908
9909/*
9910 * "delete()" function
9911 */
9912 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009913f_delete(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009914 typval_T *argvars;
9915 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009916{
9917 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009918 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009919 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009920 rettv->vval.v_number = mch_remove(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009921}
9922
9923/*
9924 * "did_filetype()" function
9925 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009926 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009927f_did_filetype(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009928 typval_T *argvars UNUSED;
9929 typval_T *rettv UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009930{
9931#ifdef FEAT_AUTOCMD
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009932 rettv->vval.v_number = did_filetype;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009933#endif
9934}
9935
9936/*
Bram Moolenaar47136d72004-10-12 20:02:24 +00009937 * "diff_filler()" function
9938 */
Bram Moolenaar47136d72004-10-12 20:02:24 +00009939 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009940f_diff_filler(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009941 typval_T *argvars UNUSED;
9942 typval_T *rettv UNUSED;
Bram Moolenaar47136d72004-10-12 20:02:24 +00009943{
9944#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009945 rettv->vval.v_number = diff_check_fill(curwin, get_tv_lnum(argvars));
Bram Moolenaar47136d72004-10-12 20:02:24 +00009946#endif
9947}
9948
9949/*
9950 * "diff_hlID()" function
9951 */
Bram Moolenaar47136d72004-10-12 20:02:24 +00009952 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009953f_diff_hlID(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +00009954 typval_T *argvars UNUSED;
9955 typval_T *rettv UNUSED;
Bram Moolenaar47136d72004-10-12 20:02:24 +00009956{
9957#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009958 linenr_T lnum = get_tv_lnum(argvars);
Bram Moolenaar47136d72004-10-12 20:02:24 +00009959 static linenr_T prev_lnum = 0;
9960 static int changedtick = 0;
9961 static int fnum = 0;
9962 static int change_start = 0;
9963 static int change_end = 0;
Bram Moolenaar6f192452007-11-08 19:49:02 +00009964 static hlf_T hlID = (hlf_T)0;
Bram Moolenaar47136d72004-10-12 20:02:24 +00009965 int filler_lines;
9966 int col;
9967
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009968 if (lnum < 0) /* ignore type error in {lnum} arg */
9969 lnum = 0;
Bram Moolenaar47136d72004-10-12 20:02:24 +00009970 if (lnum != prev_lnum
9971 || changedtick != curbuf->b_changedtick
9972 || fnum != curbuf->b_fnum)
9973 {
9974 /* New line, buffer, change: need to get the values. */
9975 filler_lines = diff_check(curwin, lnum);
9976 if (filler_lines < 0)
9977 {
9978 if (filler_lines == -1)
9979 {
9980 change_start = MAXCOL;
9981 change_end = -1;
9982 if (diff_find_change(curwin, lnum, &change_start, &change_end))
9983 hlID = HLF_ADD; /* added line */
9984 else
9985 hlID = HLF_CHD; /* changed line */
9986 }
9987 else
9988 hlID = HLF_ADD; /* added line */
9989 }
9990 else
Bram Moolenaar482aaeb2005-09-29 18:26:07 +00009991 hlID = (hlf_T)0;
Bram Moolenaar47136d72004-10-12 20:02:24 +00009992 prev_lnum = lnum;
9993 changedtick = curbuf->b_changedtick;
9994 fnum = curbuf->b_fnum;
9995 }
9996
9997 if (hlID == HLF_CHD || hlID == HLF_TXD)
9998 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009999 col = get_tv_number(&argvars[1]) - 1; /* ignore type error in {col} */
Bram Moolenaar47136d72004-10-12 20:02:24 +000010000 if (col >= change_start && col <= change_end)
10001 hlID = HLF_TXD; /* changed text */
10002 else
10003 hlID = HLF_CHD; /* changed line */
10004 }
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000010005 rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (int)hlID;
Bram Moolenaar47136d72004-10-12 20:02:24 +000010006#endif
10007}
10008
10009/*
Bram Moolenaare49b69a2005-01-08 16:11:57 +000010010 * "empty({expr})" function
10011 */
10012 static void
10013f_empty(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010014 typval_T *argvars;
10015 typval_T *rettv;
Bram Moolenaare49b69a2005-01-08 16:11:57 +000010016{
10017 int n;
10018
10019 switch (argvars[0].v_type)
10020 {
10021 case VAR_STRING:
10022 case VAR_FUNC:
10023 n = argvars[0].vval.v_string == NULL
10024 || *argvars[0].vval.v_string == NUL;
10025 break;
10026 case VAR_NUMBER:
10027 n = argvars[0].vval.v_number == 0;
10028 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000010029#ifdef FEAT_FLOAT
10030 case VAR_FLOAT:
10031 n = argvars[0].vval.v_float == 0.0;
10032 break;
10033#endif
Bram Moolenaare49b69a2005-01-08 16:11:57 +000010034 case VAR_LIST:
10035 n = argvars[0].vval.v_list == NULL
10036 || argvars[0].vval.v_list->lv_first == NULL;
10037 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010038 case VAR_DICT:
10039 n = argvars[0].vval.v_dict == NULL
Bram Moolenaar33570922005-01-25 22:26:29 +000010040 || argvars[0].vval.v_dict->dv_hashtab.ht_used == 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010041 break;
Bram Moolenaare49b69a2005-01-08 16:11:57 +000010042 default:
10043 EMSG2(_(e_intern2), "f_empty()");
10044 n = 0;
10045 }
10046
10047 rettv->vval.v_number = n;
10048}
10049
10050/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010051 * "escape({string}, {chars})" function
10052 */
10053 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010054f_escape(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010055 typval_T *argvars;
10056 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010057{
10058 char_u buf[NUMBUFLEN];
10059
Bram Moolenaar758711c2005-02-02 23:11:38 +000010060 rettv->vval.v_string = vim_strsave_escaped(get_tv_string(&argvars[0]),
10061 get_tv_string_buf(&argvars[1], buf));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010062 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010063}
10064
10065/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010066 * "eval()" function
10067 */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010068 static void
10069f_eval(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010070 typval_T *argvars;
10071 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010072{
10073 char_u *s;
10074
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010075 s = get_tv_string_chk(&argvars[0]);
10076 if (s != NULL)
10077 s = skipwhite(s);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010078
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010079 if (s == NULL || eval1(&s, rettv, TRUE) == FAIL)
10080 {
10081 rettv->v_type = VAR_NUMBER;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010082 rettv->vval.v_number = 0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010083 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010084 else if (*s != NUL)
10085 EMSG(_(e_trailing));
10086}
10087
10088/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010089 * "eventhandler()" function
10090 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010091 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010092f_eventhandler(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000010093 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000010094 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010095{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010096 rettv->vval.v_number = vgetc_busy;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010097}
10098
10099/*
10100 * "executable()" function
10101 */
10102 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010103f_executable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010104 typval_T *argvars;
10105 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010106{
Bram Moolenaarc7f02552014-04-01 21:00:59 +020010107 rettv->vval.v_number = mch_can_exe(get_tv_string(&argvars[0]), NULL);
10108}
10109
10110/*
10111 * "exepath()" function
10112 */
10113 static void
10114f_exepath(argvars, rettv)
10115 typval_T *argvars;
10116 typval_T *rettv;
10117{
10118 char_u *p = NULL;
10119
10120 (void)mch_can_exe(get_tv_string(&argvars[0]), &p);
10121 rettv->v_type = VAR_STRING;
10122 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010123}
10124
10125/*
10126 * "exists()" function
10127 */
10128 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010129f_exists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010130 typval_T *argvars;
10131 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010132{
10133 char_u *p;
10134 char_u *name;
10135 int n = FALSE;
10136 int len = 0;
10137
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010138 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010139 if (*p == '$') /* environment variable */
10140 {
10141 /* first try "normal" environment variables (fast) */
10142 if (mch_getenv(p + 1) != NULL)
10143 n = TRUE;
10144 else
10145 {
10146 /* try expanding things like $VIM and ${HOME} */
10147 p = expand_env_save(p);
10148 if (p != NULL && *p != '$')
10149 n = TRUE;
10150 vim_free(p);
10151 }
10152 }
10153 else if (*p == '&' || *p == '+') /* option */
Bram Moolenaar79783442006-05-05 21:18:03 +000010154 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010155 n = (get_option_tv(&p, NULL, TRUE) == OK);
Bram Moolenaar79783442006-05-05 21:18:03 +000010156 if (*skipwhite(p) != NUL)
10157 n = FALSE; /* trailing garbage */
10158 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010159 else if (*p == '*') /* internal or user defined function */
10160 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010161 n = function_exists(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010162 }
10163 else if (*p == ':')
10164 {
10165 n = cmd_exists(p + 1);
10166 }
10167 else if (*p == '#')
10168 {
10169#ifdef FEAT_AUTOCMD
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +000010170 if (p[1] == '#')
10171 n = autocmd_supported(p + 2);
10172 else
10173 n = au_exists(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010174#endif
10175 }
10176 else /* internal variable */
10177 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010178 char_u *tofree;
10179 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010180
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010181 /* get_name_len() takes care of expanding curly braces */
10182 name = p;
10183 len = get_name_len(&p, &tofree, TRUE, FALSE);
10184 if (len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010185 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010186 if (tofree != NULL)
10187 name = tofree;
Bram Moolenaar6d977d62014-01-14 15:24:39 +010010188 n = (get_var_tv(name, len, &tv, FALSE, TRUE) == OK);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010189 if (n)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010190 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010191 /* handle d.key, l[idx], f(expr) */
10192 n = (handle_subscript(&p, &tv, TRUE, FALSE) == OK);
10193 if (n)
10194 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010195 }
10196 }
Bram Moolenaar79783442006-05-05 21:18:03 +000010197 if (*p != NUL)
10198 n = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010199
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010200 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010201 }
10202
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010203 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010204}
10205
Bram Moolenaardb7c6862010-05-21 16:33:48 +020010206#ifdef FEAT_FLOAT
10207/*
10208 * "exp()" function
10209 */
10210 static void
10211f_exp(argvars, rettv)
10212 typval_T *argvars;
10213 typval_T *rettv;
10214{
10215 float_T f;
10216
10217 rettv->v_type = VAR_FLOAT;
10218 if (get_float_arg(argvars, &f) == OK)
10219 rettv->vval.v_float = exp(f);
10220 else
10221 rettv->vval.v_float = 0.0;
10222}
10223#endif
10224
Bram Moolenaar071d4272004-06-13 20:20:40 +000010225/*
10226 * "expand()" function
10227 */
10228 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010229f_expand(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010230 typval_T *argvars;
10231 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010232{
10233 char_u *s;
10234 int len;
10235 char_u *errormsg;
Bram Moolenaar005c3c22010-12-02 21:44:40 +010010236 int options = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010237 expand_T xpc;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010238 int error = FALSE;
Bram Moolenaar146e9c32012-03-07 19:18:23 +010010239 char_u *result;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010240
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010241 rettv->v_type = VAR_STRING;
Bram Moolenaar146e9c32012-03-07 19:18:23 +010010242 if (argvars[1].v_type != VAR_UNKNOWN
10243 && argvars[2].v_type != VAR_UNKNOWN
10244 && get_tv_number_chk(&argvars[2], &error)
10245 && !error)
10246 {
10247 rettv->v_type = VAR_LIST;
10248 rettv->vval.v_list = NULL;
10249 }
10250
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010251 s = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010252 if (*s == '%' || *s == '#' || *s == '<')
10253 {
10254 ++emsg_off;
Bram Moolenaar146e9c32012-03-07 19:18:23 +010010255 result = eval_vars(s, s, &len, NULL, &errormsg, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010256 --emsg_off;
Bram Moolenaar146e9c32012-03-07 19:18:23 +010010257 if (rettv->v_type == VAR_LIST)
10258 {
10259 if (rettv_list_alloc(rettv) != FAIL && result != NULL)
10260 list_append_string(rettv->vval.v_list, result, -1);
10261 else
10262 vim_free(result);
10263 }
10264 else
10265 rettv->vval.v_string = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010266 }
10267 else
10268 {
10269 /* When the optional second argument is non-zero, don't remove matches
Bram Moolenaarbb5ddda2008-11-28 10:01:10 +000010270 * for 'wildignore' and don't put matches for 'suffixes' at the end. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010271 if (argvars[1].v_type != VAR_UNKNOWN
10272 && get_tv_number_chk(&argvars[1], &error))
Bram Moolenaar005c3c22010-12-02 21:44:40 +010010273 options |= WILD_KEEP_ALL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010274 if (!error)
10275 {
10276 ExpandInit(&xpc);
10277 xpc.xp_context = EXPAND_FILES;
Bram Moolenaar005c3c22010-12-02 21:44:40 +010010278 if (p_wic)
10279 options += WILD_ICASE;
Bram Moolenaar146e9c32012-03-07 19:18:23 +010010280 if (rettv->v_type == VAR_STRING)
10281 rettv->vval.v_string = ExpandOne(&xpc, s, NULL,
10282 options, WILD_ALL);
10283 else if (rettv_list_alloc(rettv) != FAIL)
10284 {
10285 int i;
10286
10287 ExpandOne(&xpc, s, NULL, options, WILD_ALL_KEEP);
10288 for (i = 0; i < xpc.xp_numfiles; i++)
10289 list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1);
10290 ExpandCleanup(&xpc);
10291 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010292 }
10293 else
10294 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010295 }
10296}
10297
10298/*
Bram Moolenaara9922d62013-05-30 13:01:18 +020010299 * Go over all entries in "d2" and add them to "d1".
10300 * When "action" is "error" then a duplicate key is an error.
10301 * When "action" is "force" then a duplicate key is overwritten.
10302 * Otherwise duplicate keys are ignored ("action" is "keep").
10303 */
10304 void
10305dict_extend(d1, d2, action)
10306 dict_T *d1;
10307 dict_T *d2;
10308 char_u *action;
10309{
10310 dictitem_T *di1;
10311 hashitem_T *hi2;
10312 int todo;
10313
10314 todo = (int)d2->dv_hashtab.ht_used;
10315 for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2)
10316 {
10317 if (!HASHITEM_EMPTY(hi2))
10318 {
10319 --todo;
10320 di1 = dict_find(d1, hi2->hi_key, -1);
10321 if (d1->dv_scope != 0)
10322 {
10323 /* Disallow replacing a builtin function in l: and g:.
10324 * Check the key to be valid when adding to any
10325 * scope. */
10326 if (d1->dv_scope == VAR_DEF_SCOPE
10327 && HI2DI(hi2)->di_tv.v_type == VAR_FUNC
10328 && var_check_func_name(hi2->hi_key,
10329 di1 == NULL))
10330 break;
10331 if (!valid_varname(hi2->hi_key))
10332 break;
10333 }
10334 if (di1 == NULL)
10335 {
10336 di1 = dictitem_copy(HI2DI(hi2));
10337 if (di1 != NULL && dict_add(d1, di1) == FAIL)
10338 dictitem_free(di1);
10339 }
10340 else if (*action == 'e')
10341 {
10342 EMSG2(_("E737: Key already exists: %s"), hi2->hi_key);
10343 break;
10344 }
10345 else if (*action == 'f' && HI2DI(hi2) != di1)
10346 {
10347 clear_tv(&di1->di_tv);
10348 copy_tv(&HI2DI(hi2)->di_tv, &di1->di_tv);
10349 }
10350 }
10351 }
10352}
10353
10354/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010355 * "extend(list, list [, idx])" function
Bram Moolenaare9a41262005-01-15 22:18:47 +000010356 * "extend(dict, dict [, action])" function
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010357 */
10358 static void
10359f_extend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010360 typval_T *argvars;
10361 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010362{
Bram Moolenaar32f649e2011-04-11 13:46:13 +020010363 char *arg_errmsg = N_("extend() argument");
10364
Bram Moolenaare9a41262005-01-15 22:18:47 +000010365 if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010366 {
Bram Moolenaar33570922005-01-25 22:26:29 +000010367 list_T *l1, *l2;
10368 listitem_T *item;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010369 long before;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010370 int error = FALSE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010371
Bram Moolenaare9a41262005-01-15 22:18:47 +000010372 l1 = argvars[0].vval.v_list;
10373 l2 = argvars[1].vval.v_list;
Bram Moolenaar32f649e2011-04-11 13:46:13 +020010374 if (l1 != NULL && !tv_check_lock(l1->lv_lock, (char_u *)_(arg_errmsg))
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010375 && l2 != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000010376 {
10377 if (argvars[2].v_type != VAR_UNKNOWN)
10378 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010379 before = get_tv_number_chk(&argvars[2], &error);
10380 if (error)
10381 return; /* type error; errmsg already given */
10382
Bram Moolenaar758711c2005-02-02 23:11:38 +000010383 if (before == l1->lv_len)
10384 item = NULL;
10385 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000010386 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000010387 item = list_find(l1, before);
10388 if (item == NULL)
10389 {
10390 EMSGN(_(e_listidx), before);
10391 return;
10392 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000010393 }
10394 }
10395 else
10396 item = NULL;
10397 list_extend(l1, l2, item);
10398
Bram Moolenaare9a41262005-01-15 22:18:47 +000010399 copy_tv(&argvars[0], rettv);
10400 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010401 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000010402 else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT)
10403 {
Bram Moolenaara9922d62013-05-30 13:01:18 +020010404 dict_T *d1, *d2;
10405 char_u *action;
10406 int i;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010407
10408 d1 = argvars[0].vval.v_dict;
10409 d2 = argvars[1].vval.v_dict;
Bram Moolenaar32f649e2011-04-11 13:46:13 +020010410 if (d1 != NULL && !tv_check_lock(d1->dv_lock, (char_u *)_(arg_errmsg))
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010411 && d2 != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000010412 {
10413 /* Check the third argument. */
10414 if (argvars[2].v_type != VAR_UNKNOWN)
10415 {
10416 static char *(av[]) = {"keep", "force", "error"};
10417
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010418 action = get_tv_string_chk(&argvars[2]);
10419 if (action == NULL)
10420 return; /* type error; errmsg already given */
Bram Moolenaare9a41262005-01-15 22:18:47 +000010421 for (i = 0; i < 3; ++i)
10422 if (STRCMP(action, av[i]) == 0)
10423 break;
10424 if (i == 3)
10425 {
Bram Moolenaareb3593b2006-04-22 22:33:57 +000010426 EMSG2(_(e_invarg2), action);
Bram Moolenaare9a41262005-01-15 22:18:47 +000010427 return;
10428 }
10429 }
10430 else
10431 action = (char_u *)"force";
10432
Bram Moolenaara9922d62013-05-30 13:01:18 +020010433 dict_extend(d1, d2, action);
Bram Moolenaare9a41262005-01-15 22:18:47 +000010434
Bram Moolenaare9a41262005-01-15 22:18:47 +000010435 copy_tv(&argvars[0], rettv);
10436 }
10437 }
10438 else
10439 EMSG2(_(e_listdictarg), "extend()");
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010440}
10441
10442/*
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000010443 * "feedkeys()" function
10444 */
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000010445 static void
10446f_feedkeys(argvars, rettv)
10447 typval_T *argvars;
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000010448 typval_T *rettv UNUSED;
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000010449{
10450 int remap = TRUE;
10451 char_u *keys, *flags;
10452 char_u nbuf[NUMBUFLEN];
10453 int typed = FALSE;
Bram Moolenaarf193fff2006-04-27 00:02:13 +000010454 char_u *keys_esc;
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000010455
Bram Moolenaar3d43a662007-04-27 20:15:55 +000010456 /* This is not allowed in the sandbox. If the commands would still be
10457 * executed in the sandbox it would be OK, but it probably happens later,
10458 * when "sandbox" is no longer set. */
10459 if (check_secure())
10460 return;
10461
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000010462 keys = get_tv_string(&argvars[0]);
10463 if (*keys != NUL)
10464 {
10465 if (argvars[1].v_type != VAR_UNKNOWN)
10466 {
10467 flags = get_tv_string_buf(&argvars[1], nbuf);
10468 for ( ; *flags != NUL; ++flags)
10469 {
10470 switch (*flags)
10471 {
10472 case 'n': remap = FALSE; break;
10473 case 'm': remap = TRUE; break;
10474 case 't': typed = TRUE; break;
10475 }
10476 }
10477 }
10478
Bram Moolenaarf193fff2006-04-27 00:02:13 +000010479 /* Need to escape K_SPECIAL and CSI before putting the string in the
10480 * typeahead buffer. */
10481 keys_esc = vim_strsave_escape_csi(keys);
10482 if (keys_esc != NULL)
10483 {
10484 ins_typebuf(keys_esc, (remap ? REMAP_YES : REMAP_NONE),
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000010485 typebuf.tb_len, !typed, FALSE);
Bram Moolenaarf193fff2006-04-27 00:02:13 +000010486 vim_free(keys_esc);
Bram Moolenaar437df8f2006-04-27 21:47:44 +000010487 if (vgetc_busy)
10488 typebuf_was_filled = TRUE;
Bram Moolenaarf193fff2006-04-27 00:02:13 +000010489 }
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000010490 }
10491}
10492
10493/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010494 * "filereadable()" function
10495 */
10496 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010497f_filereadable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010498 typval_T *argvars;
10499 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010500{
Bram Moolenaarc236c162008-07-13 17:41:49 +000010501 int fd;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010502 char_u *p;
10503 int n;
10504
Bram Moolenaarc236c162008-07-13 17:41:49 +000010505#ifndef O_NONBLOCK
10506# define O_NONBLOCK 0
10507#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010508 p = get_tv_string(&argvars[0]);
Bram Moolenaarc236c162008-07-13 17:41:49 +000010509 if (*p && !mch_isdir(p) && (fd = mch_open((char *)p,
10510 O_RDONLY | O_NONBLOCK, 0)) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010511 {
10512 n = TRUE;
Bram Moolenaarc236c162008-07-13 17:41:49 +000010513 close(fd);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010514 }
10515 else
10516 n = FALSE;
10517
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010518 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010519}
10520
10521/*
Bram Moolenaar0e4d8772005-06-07 21:12:49 +000010522 * Return 0 for not writable, 1 for writable file, 2 for a dir which we have
Bram Moolenaar071d4272004-06-13 20:20:40 +000010523 * rights to write into.
10524 */
10525 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010526f_filewritable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010527 typval_T *argvars;
10528 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010529{
Bram Moolenaar0e4d8772005-06-07 21:12:49 +000010530 rettv->vval.v_number = filewritable(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010531}
10532
Bram Moolenaar4d0ec162008-02-20 11:24:52 +000010533static void findfilendir __ARGS((typval_T *argvars, typval_T *rettv, int find_what));
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010534
10535 static void
Bram Moolenaar4d0ec162008-02-20 11:24:52 +000010536findfilendir(argvars, rettv, find_what)
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +010010537 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000010538 typval_T *rettv;
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +010010539 int find_what UNUSED;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010540{
10541#ifdef FEAT_SEARCHPATH
10542 char_u *fname;
10543 char_u *fresult = NULL;
10544 char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
10545 char_u *p;
10546 char_u pathbuf[NUMBUFLEN];
10547 int count = 1;
10548 int first = TRUE;
Bram Moolenaar899dddf2006-03-26 21:06:50 +000010549 int error = FALSE;
10550#endif
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010551
Bram Moolenaar899dddf2006-03-26 21:06:50 +000010552 rettv->vval.v_string = NULL;
10553 rettv->v_type = VAR_STRING;
10554
10555#ifdef FEAT_SEARCHPATH
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010556 fname = get_tv_string(&argvars[0]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010557
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010558 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010559 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010560 p = get_tv_string_buf_chk(&argvars[1], pathbuf);
10561 if (p == NULL)
Bram Moolenaar899dddf2006-03-26 21:06:50 +000010562 error = TRUE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010563 else
10564 {
10565 if (*p != NUL)
10566 path = p;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010567
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010568 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar899dddf2006-03-26 21:06:50 +000010569 count = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010570 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010571 }
10572
Bram Moolenaar899dddf2006-03-26 21:06:50 +000010573 if (count < 0 && rettv_list_alloc(rettv) == FAIL)
10574 error = TRUE;
10575
10576 if (*fname != NUL && !error)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010577 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010578 do
10579 {
Bram Moolenaardf2bc272013-06-24 22:17:32 +020010580 if (rettv->v_type == VAR_STRING || rettv->v_type == VAR_LIST)
Bram Moolenaar899dddf2006-03-26 21:06:50 +000010581 vim_free(fresult);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010582 fresult = find_file_in_path_option(first ? fname : NULL,
10583 first ? (int)STRLEN(fname) : 0,
Bram Moolenaar4d0ec162008-02-20 11:24:52 +000010584 0, first, path,
10585 find_what,
10586 curbuf->b_ffname,
10587 find_what == FINDFILE_DIR
10588 ? (char_u *)"" : curbuf->b_p_sua);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010589 first = FALSE;
Bram Moolenaar899dddf2006-03-26 21:06:50 +000010590
10591 if (fresult != NULL && rettv->v_type == VAR_LIST)
10592 list_append_string(rettv->vval.v_list, fresult, -1);
10593
10594 } while ((rettv->v_type == VAR_LIST || --count > 0) && fresult != NULL);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010595 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010596
Bram Moolenaar899dddf2006-03-26 21:06:50 +000010597 if (rettv->v_type == VAR_STRING)
10598 rettv->vval.v_string = fresult;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010599#endif
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010600}
10601
Bram Moolenaar33570922005-01-25 22:26:29 +000010602static void filter_map __ARGS((typval_T *argvars, typval_T *rettv, int map));
10603static int filter_map_one __ARGS((typval_T *tv, char_u *expr, int map, int *remp));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010604
10605/*
10606 * Implementation of map() and filter().
10607 */
10608 static void
10609filter_map(argvars, rettv, map)
Bram Moolenaar33570922005-01-25 22:26:29 +000010610 typval_T *argvars;
10611 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010612 int map;
10613{
10614 char_u buf[NUMBUFLEN];
Bram Moolenaare9a41262005-01-15 22:18:47 +000010615 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +000010616 listitem_T *li, *nli;
10617 list_T *l = NULL;
10618 dictitem_T *di;
10619 hashtab_T *ht;
10620 hashitem_T *hi;
10621 dict_T *d = NULL;
10622 typval_T save_val;
10623 typval_T save_key;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010624 int rem;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010625 int todo;
Bram Moolenaar32f649e2011-04-11 13:46:13 +020010626 char_u *ermsg = (char_u *)(map ? "map()" : "filter()");
10627 char *arg_errmsg = (map ? N_("map() argument")
10628 : N_("filter() argument"));
Bram Moolenaar1f35bf92006-03-07 22:38:47 +000010629 int save_did_emsg;
Bram Moolenaarf506c5b2010-06-22 06:28:58 +020010630 int idx = 0;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010631
Bram Moolenaare9a41262005-01-15 22:18:47 +000010632 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010633 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010634 if ((l = argvars[0].vval.v_list) == NULL
Bram Moolenaar32f649e2011-04-11 13:46:13 +020010635 || tv_check_lock(l->lv_lock, (char_u *)_(arg_errmsg)))
Bram Moolenaare9a41262005-01-15 22:18:47 +000010636 return;
10637 }
10638 else if (argvars[0].v_type == VAR_DICT)
10639 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010640 if ((d = argvars[0].vval.v_dict) == NULL
Bram Moolenaar32f649e2011-04-11 13:46:13 +020010641 || tv_check_lock(d->dv_lock, (char_u *)_(arg_errmsg)))
Bram Moolenaare9a41262005-01-15 22:18:47 +000010642 return;
10643 }
10644 else
10645 {
Bram Moolenaar89d40322006-08-29 15:30:07 +000010646 EMSG2(_(e_listdictarg), ermsg);
Bram Moolenaare9a41262005-01-15 22:18:47 +000010647 return;
10648 }
10649
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010650 expr = get_tv_string_buf_chk(&argvars[1], buf);
10651 /* On type errors, the preceding call has already displayed an error
10652 * message. Avoid a misleading error message for an empty string that
10653 * was not passed as argument. */
10654 if (expr != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000010655 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010656 prepare_vimvar(VV_VAL, &save_val);
10657 expr = skipwhite(expr);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010658
Bram Moolenaar1f35bf92006-03-07 22:38:47 +000010659 /* We reset "did_emsg" to be able to detect whether an error
10660 * occurred during evaluation of the expression. */
10661 save_did_emsg = did_emsg;
10662 did_emsg = FALSE;
Bram Moolenaar280f1262006-01-30 00:14:18 +000010663
Bram Moolenaar627b1d32009-11-17 11:20:35 +000010664 prepare_vimvar(VV_KEY, &save_key);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010665 if (argvars[0].v_type == VAR_DICT)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010666 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010667 vimvars[VV_KEY].vv_type = VAR_STRING;
10668
10669 ht = &d->dv_hashtab;
10670 hash_lock(ht);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000010671 todo = (int)ht->ht_used;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010672 for (hi = ht->ht_array; todo > 0; ++hi)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010673 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010674 if (!HASHITEM_EMPTY(hi))
10675 {
10676 --todo;
10677 di = HI2DI(hi);
Bram Moolenaar32f649e2011-04-11 13:46:13 +020010678 if (tv_check_lock(di->di_tv.v_lock,
10679 (char_u *)_(arg_errmsg)))
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010680 break;
10681 vimvars[VV_KEY].vv_str = vim_strsave(di->di_key);
Bram Moolenaar280f1262006-01-30 00:14:18 +000010682 if (filter_map_one(&di->di_tv, expr, map, &rem) == FAIL
Bram Moolenaar1f35bf92006-03-07 22:38:47 +000010683 || did_emsg)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010684 break;
10685 if (!map && rem)
10686 dictitem_remove(d, di);
10687 clear_tv(&vimvars[VV_KEY].vv_tv);
10688 }
10689 }
10690 hash_unlock(ht);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010691 }
10692 else
10693 {
Bram Moolenaar627b1d32009-11-17 11:20:35 +000010694 vimvars[VV_KEY].vv_type = VAR_NUMBER;
10695
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010696 for (li = l->lv_first; li != NULL; li = nli)
10697 {
Bram Moolenaar32f649e2011-04-11 13:46:13 +020010698 if (tv_check_lock(li->li_tv.v_lock, (char_u *)_(arg_errmsg)))
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010699 break;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010700 nli = li->li_next;
Bram Moolenaarf506c5b2010-06-22 06:28:58 +020010701 vimvars[VV_KEY].vv_nr = idx;
Bram Moolenaar280f1262006-01-30 00:14:18 +000010702 if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL
Bram Moolenaar1f35bf92006-03-07 22:38:47 +000010703 || did_emsg)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010704 break;
10705 if (!map && rem)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010706 listitem_remove(l, li);
Bram Moolenaarf506c5b2010-06-22 06:28:58 +020010707 ++idx;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010708 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010709 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010710
Bram Moolenaar627b1d32009-11-17 11:20:35 +000010711 restore_vimvar(VV_KEY, &save_key);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010712 restore_vimvar(VV_VAL, &save_val);
Bram Moolenaar280f1262006-01-30 00:14:18 +000010713
Bram Moolenaar1f35bf92006-03-07 22:38:47 +000010714 did_emsg |= save_did_emsg;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010715 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000010716
10717 copy_tv(&argvars[0], rettv);
10718}
10719
10720 static int
10721filter_map_one(tv, expr, map, remp)
Bram Moolenaar33570922005-01-25 22:26:29 +000010722 typval_T *tv;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010723 char_u *expr;
10724 int map;
10725 int *remp;
10726{
Bram Moolenaar33570922005-01-25 22:26:29 +000010727 typval_T rettv;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010728 char_u *s;
Bram Moolenaarb4066a12007-09-17 19:38:08 +000010729 int retval = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010730
Bram Moolenaar33570922005-01-25 22:26:29 +000010731 copy_tv(tv, &vimvars[VV_VAL].vv_tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +000010732 s = expr;
10733 if (eval1(&s, &rettv, TRUE) == FAIL)
Bram Moolenaarb4066a12007-09-17 19:38:08 +000010734 goto theend;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010735 if (*s != NUL) /* check for trailing chars after expr */
10736 {
10737 EMSG2(_(e_invexpr2), s);
Bram Moolenaarb4066a12007-09-17 19:38:08 +000010738 goto theend;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010739 }
10740 if (map)
10741 {
10742 /* map(): replace the list item value */
10743 clear_tv(tv);
Bram Moolenaar4463f292005-09-25 22:20:24 +000010744 rettv.v_lock = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010745 *tv = rettv;
10746 }
10747 else
10748 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010749 int error = FALSE;
10750
Bram Moolenaare9a41262005-01-15 22:18:47 +000010751 /* filter(): when expr is zero remove the item */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010752 *remp = (get_tv_number_chk(&rettv, &error) == 0);
Bram Moolenaare9a41262005-01-15 22:18:47 +000010753 clear_tv(&rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010754 /* On type error, nothing has been removed; return FAIL to stop the
10755 * loop. The error message was given by get_tv_number_chk(). */
10756 if (error)
Bram Moolenaarb4066a12007-09-17 19:38:08 +000010757 goto theend;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010758 }
Bram Moolenaarb4066a12007-09-17 19:38:08 +000010759 retval = OK;
10760theend:
Bram Moolenaar33570922005-01-25 22:26:29 +000010761 clear_tv(&vimvars[VV_VAL].vv_tv);
Bram Moolenaarb4066a12007-09-17 19:38:08 +000010762 return retval;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010763}
10764
10765/*
10766 * "filter()" function
10767 */
10768 static void
10769f_filter(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010770 typval_T *argvars;
10771 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010772{
10773 filter_map(argvars, rettv, FALSE);
10774}
10775
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010776/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010777 * "finddir({fname}[, {path}[, {count}]])" function
10778 */
10779 static void
10780f_finddir(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010781 typval_T *argvars;
10782 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010783{
Bram Moolenaar4d0ec162008-02-20 11:24:52 +000010784 findfilendir(argvars, rettv, FINDFILE_DIR);
Bram Moolenaar0d660222005-01-07 21:51:51 +000010785}
10786
10787/*
10788 * "findfile({fname}[, {path}[, {count}]])" function
10789 */
10790 static void
10791f_findfile(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010792 typval_T *argvars;
10793 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010794{
Bram Moolenaar4d0ec162008-02-20 11:24:52 +000010795 findfilendir(argvars, rettv, FINDFILE_FILE);
Bram Moolenaar0d660222005-01-07 21:51:51 +000010796}
10797
Bram Moolenaar8c8de832008-06-24 22:58:06 +000010798#ifdef FEAT_FLOAT
10799/*
10800 * "float2nr({float})" function
10801 */
10802 static void
10803f_float2nr(argvars, rettv)
10804 typval_T *argvars;
10805 typval_T *rettv;
10806{
10807 float_T f;
10808
10809 if (get_float_arg(argvars, &f) == OK)
10810 {
10811 if (f < -0x7fffffff)
10812 rettv->vval.v_number = -0x7fffffff;
10813 else if (f > 0x7fffffff)
10814 rettv->vval.v_number = 0x7fffffff;
10815 else
10816 rettv->vval.v_number = (varnumber_T)f;
10817 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +000010818}
10819
10820/*
10821 * "floor({float})" function
10822 */
10823 static void
10824f_floor(argvars, rettv)
10825 typval_T *argvars;
10826 typval_T *rettv;
10827{
10828 float_T f;
10829
10830 rettv->v_type = VAR_FLOAT;
10831 if (get_float_arg(argvars, &f) == OK)
10832 rettv->vval.v_float = floor(f);
10833 else
10834 rettv->vval.v_float = 0.0;
10835}
Bram Moolenaardb7c6862010-05-21 16:33:48 +020010836
10837/*
10838 * "fmod()" function
10839 */
10840 static void
10841f_fmod(argvars, rettv)
10842 typval_T *argvars;
10843 typval_T *rettv;
10844{
10845 float_T fx, fy;
10846
10847 rettv->v_type = VAR_FLOAT;
10848 if (get_float_arg(argvars, &fx) == OK
10849 && get_float_arg(&argvars[1], &fy) == OK)
10850 rettv->vval.v_float = fmod(fx, fy);
10851 else
10852 rettv->vval.v_float = 0.0;
10853}
Bram Moolenaar8c8de832008-06-24 22:58:06 +000010854#endif
10855
Bram Moolenaar0d660222005-01-07 21:51:51 +000010856/*
Bram Moolenaaraebaf892008-05-28 14:49:58 +000010857 * "fnameescape({string})" function
10858 */
10859 static void
10860f_fnameescape(argvars, rettv)
10861 typval_T *argvars;
10862 typval_T *rettv;
10863{
10864 rettv->vval.v_string = vim_strsave_fnameescape(
10865 get_tv_string(&argvars[0]), FALSE);
10866 rettv->v_type = VAR_STRING;
10867}
10868
10869/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010870 * "fnamemodify({fname}, {mods})" function
10871 */
10872 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010873f_fnamemodify(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010874 typval_T *argvars;
10875 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010876{
10877 char_u *fname;
10878 char_u *mods;
10879 int usedlen = 0;
10880 int len;
10881 char_u *fbuf = NULL;
10882 char_u buf[NUMBUFLEN];
10883
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010884 fname = get_tv_string_chk(&argvars[0]);
10885 mods = get_tv_string_buf_chk(&argvars[1], buf);
10886 if (fname == NULL || mods == NULL)
10887 fname = NULL;
10888 else
10889 {
10890 len = (int)STRLEN(fname);
10891 (void)modify_fname(mods, &usedlen, &fname, &fbuf, &len);
10892 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010893
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010894 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010895 if (fname == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010896 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010897 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010898 rettv->vval.v_string = vim_strnsave(fname, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010899 vim_free(fbuf);
10900}
10901
Bram Moolenaar33570922005-01-25 22:26:29 +000010902static void foldclosed_both __ARGS((typval_T *argvars, typval_T *rettv, int end));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010903
10904/*
10905 * "foldclosed()" function
10906 */
10907 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010908foldclosed_both(argvars, rettv, end)
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +010010909 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000010910 typval_T *rettv;
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +010010911 int end UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010912{
10913#ifdef FEAT_FOLDING
10914 linenr_T lnum;
10915 linenr_T first, last;
10916
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010917 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010918 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
10919 {
10920 if (hasFoldingWin(curwin, lnum, &first, &last, FALSE, NULL))
10921 {
10922 if (end)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010923 rettv->vval.v_number = (varnumber_T)last;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010924 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010925 rettv->vval.v_number = (varnumber_T)first;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010926 return;
10927 }
10928 }
10929#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010930 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010931}
10932
10933/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010934 * "foldclosed()" function
10935 */
10936 static void
10937f_foldclosed(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010938 typval_T *argvars;
10939 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010940{
10941 foldclosed_both(argvars, rettv, FALSE);
10942}
10943
10944/*
10945 * "foldclosedend()" function
10946 */
10947 static void
10948f_foldclosedend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010949 typval_T *argvars;
10950 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010951{
10952 foldclosed_both(argvars, rettv, TRUE);
10953}
10954
10955/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010956 * "foldlevel()" function
10957 */
10958 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010959f_foldlevel(argvars, rettv)
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +010010960 typval_T *argvars UNUSED;
10961 typval_T *rettv UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010962{
10963#ifdef FEAT_FOLDING
10964 linenr_T lnum;
10965
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010966 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010967 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010968 rettv->vval.v_number = foldLevel(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010969#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010970}
10971
10972/*
10973 * "foldtext()" function
10974 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010975 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010976f_foldtext(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000010977 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000010978 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010979{
10980#ifdef FEAT_FOLDING
10981 linenr_T lnum;
10982 char_u *s;
10983 char_u *r;
10984 int len;
10985 char *txt;
10986#endif
10987
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010988 rettv->v_type = VAR_STRING;
10989 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010990#ifdef FEAT_FOLDING
Bram Moolenaare9a41262005-01-15 22:18:47 +000010991 if ((linenr_T)vimvars[VV_FOLDSTART].vv_nr > 0
10992 && (linenr_T)vimvars[VV_FOLDEND].vv_nr
10993 <= curbuf->b_ml.ml_line_count
10994 && vimvars[VV_FOLDDASHES].vv_str != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010995 {
10996 /* Find first non-empty line in the fold. */
Bram Moolenaare9a41262005-01-15 22:18:47 +000010997 lnum = (linenr_T)vimvars[VV_FOLDSTART].vv_nr;
10998 while (lnum < (linenr_T)vimvars[VV_FOLDEND].vv_nr)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010999 {
11000 if (!linewhite(lnum))
11001 break;
11002 ++lnum;
11003 }
11004
11005 /* Find interesting text in this line. */
11006 s = skipwhite(ml_get(lnum));
11007 /* skip C comment-start */
11008 if (s[0] == '/' && (s[1] == '*' || s[1] == '/'))
Bram Moolenaar293ee4d2004-12-09 21:34:53 +000011009 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000011010 s = skipwhite(s + 2);
Bram Moolenaar293ee4d2004-12-09 21:34:53 +000011011 if (*skipwhite(s) == NUL
Bram Moolenaare9a41262005-01-15 22:18:47 +000011012 && lnum + 1 < (linenr_T)vimvars[VV_FOLDEND].vv_nr)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +000011013 {
11014 s = skipwhite(ml_get(lnum + 1));
11015 if (*s == '*')
11016 s = skipwhite(s + 1);
11017 }
11018 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011019 txt = _("+-%s%3ld lines: ");
11020 r = alloc((unsigned)(STRLEN(txt)
Bram Moolenaare9a41262005-01-15 22:18:47 +000011021 + STRLEN(vimvars[VV_FOLDDASHES].vv_str) /* for %s */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011022 + 20 /* for %3ld */
11023 + STRLEN(s))); /* concatenated */
11024 if (r != NULL)
11025 {
Bram Moolenaare9a41262005-01-15 22:18:47 +000011026 sprintf((char *)r, txt, vimvars[VV_FOLDDASHES].vv_str,
11027 (long)((linenr_T)vimvars[VV_FOLDEND].vv_nr
11028 - (linenr_T)vimvars[VV_FOLDSTART].vv_nr + 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +000011029 len = (int)STRLEN(r);
11030 STRCAT(r, s);
11031 /* remove 'foldmarker' and 'commentstring' */
11032 foldtext_cleanup(r + len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011033 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011034 }
11035 }
11036#endif
11037}
11038
11039/*
Bram Moolenaar7b0294c2004-10-11 10:16:09 +000011040 * "foldtextresult(lnum)" function
11041 */
Bram Moolenaar7b0294c2004-10-11 10:16:09 +000011042 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011043f_foldtextresult(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000011044 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000011045 typval_T *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +000011046{
11047#ifdef FEAT_FOLDING
11048 linenr_T lnum;
11049 char_u *text;
11050 char_u buf[51];
11051 foldinfo_T foldinfo;
11052 int fold_count;
11053#endif
11054
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011055 rettv->v_type = VAR_STRING;
11056 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +000011057#ifdef FEAT_FOLDING
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011058 lnum = get_tv_lnum(argvars);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011059 /* treat illegal types and illegal string values for {lnum} the same */
11060 if (lnum < 0)
11061 lnum = 0;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +000011062 fold_count = foldedCount(curwin, lnum, &foldinfo);
11063 if (fold_count > 0)
11064 {
11065 text = get_foldtext(curwin, lnum, lnum + fold_count - 1,
11066 &foldinfo, buf);
11067 if (text == buf)
11068 text = vim_strsave(text);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011069 rettv->vval.v_string = text;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +000011070 }
11071#endif
11072}
11073
11074/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011075 * "foreground()" function
11076 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011077 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011078f_foreground(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000011079 typval_T *argvars UNUSED;
11080 typval_T *rettv UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011081{
Bram Moolenaar071d4272004-06-13 20:20:40 +000011082#ifdef FEAT_GUI
11083 if (gui.in_use)
11084 gui_mch_set_foreground();
11085#else
11086# ifdef WIN32
11087 win32_set_foreground();
11088# endif
11089#endif
11090}
11091
11092/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011093 * "function()" function
11094 */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011095 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011096f_function(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011097 typval_T *argvars;
11098 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011099{
11100 char_u *s;
11101
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011102 s = get_tv_string(&argvars[0]);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011103 if (s == NULL || *s == NUL || VIM_ISDIGIT(*s))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011104 EMSG2(_(e_invarg2), s);
Bram Moolenaar60bf1f52013-06-12 13:37:43 +020011105 /* Don't check an autoload name for existence here. */
11106 else if (vim_strchr(s, AUTOLOAD_CHAR) == NULL && !function_exists(s))
Bram Moolenaare49b69a2005-01-08 16:11:57 +000011107 EMSG2(_("E700: Unknown function: %s"), s);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011108 else
11109 {
Bram Moolenaar0c6633a2013-06-13 21:24:06 +020011110 if (STRNCMP(s, "s:", 2) == 0 || STRNCMP(s, "<SID>", 5) == 0)
Bram Moolenaar60bf1f52013-06-12 13:37:43 +020011111 {
11112 char sid_buf[25];
Bram Moolenaar0c6633a2013-06-13 21:24:06 +020011113 int off = *s == 's' ? 2 : 5;
Bram Moolenaar60bf1f52013-06-12 13:37:43 +020011114
Bram Moolenaar0c6633a2013-06-13 21:24:06 +020011115 /* Expand s: and <SID> into <SNR>nr_, so that the function can
11116 * also be called from another script. Using trans_function_name()
11117 * would also work, but some plugins depend on the name being
11118 * printable text. */
Bram Moolenaar60bf1f52013-06-12 13:37:43 +020011119 sprintf(sid_buf, "<SNR>%ld_", (long)current_SID);
Bram Moolenaaredb07a22013-06-12 18:13:38 +020011120 rettv->vval.v_string =
Bram Moolenaar0c6633a2013-06-13 21:24:06 +020011121 alloc((int)(STRLEN(sid_buf) + STRLEN(s + off) + 1));
Bram Moolenaar60bf1f52013-06-12 13:37:43 +020011122 if (rettv->vval.v_string != NULL)
11123 {
11124 STRCPY(rettv->vval.v_string, sid_buf);
Bram Moolenaar0c6633a2013-06-13 21:24:06 +020011125 STRCAT(rettv->vval.v_string, s + off);
Bram Moolenaar60bf1f52013-06-12 13:37:43 +020011126 }
11127 }
Bram Moolenaara1544c02013-05-30 12:35:52 +020011128 else
Bram Moolenaar60bf1f52013-06-12 13:37:43 +020011129 rettv->vval.v_string = vim_strsave(s);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011130 rettv->v_type = VAR_FUNC;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011131 }
11132}
11133
11134/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000011135 * "garbagecollect()" function
11136 */
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000011137 static void
11138f_garbagecollect(argvars, rettv)
11139 typval_T *argvars;
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000011140 typval_T *rettv UNUSED;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000011141{
Bram Moolenaar9fecb462006-09-05 10:59:47 +000011142 /* This is postponed until we are back at the toplevel, because we may be
11143 * using Lists and Dicts internally. E.g.: ":echo [garbagecollect()]". */
11144 want_garbage_collect = TRUE;
Bram Moolenaar9d2c8c12007-09-25 16:00:00 +000011145
11146 if (argvars[0].v_type != VAR_UNKNOWN && get_tv_number(&argvars[0]) == 1)
11147 garbage_collect_at_exit = TRUE;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000011148}
11149
11150/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011151 * "get()" function
11152 */
11153 static void
11154f_get(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011155 typval_T *argvars;
11156 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011157{
Bram Moolenaar33570922005-01-25 22:26:29 +000011158 listitem_T *li;
11159 list_T *l;
11160 dictitem_T *di;
11161 dict_T *d;
11162 typval_T *tv = NULL;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011163
Bram Moolenaare9a41262005-01-15 22:18:47 +000011164 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar0d660222005-01-07 21:51:51 +000011165 {
Bram Moolenaare9a41262005-01-15 22:18:47 +000011166 if ((l = argvars[0].vval.v_list) != NULL)
Bram Moolenaar0d660222005-01-07 21:51:51 +000011167 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011168 int error = FALSE;
11169
11170 li = list_find(l, get_tv_number_chk(&argvars[1], &error));
11171 if (!error && li != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000011172 tv = &li->li_tv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011173 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000011174 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000011175 else if (argvars[0].v_type == VAR_DICT)
11176 {
11177 if ((d = argvars[0].vval.v_dict) != NULL)
11178 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011179 di = dict_find(d, get_tv_string(&argvars[1]), -1);
Bram Moolenaare9a41262005-01-15 22:18:47 +000011180 if (di != NULL)
11181 tv = &di->di_tv;
11182 }
11183 }
11184 else
11185 EMSG2(_(e_listdictarg), "get()");
11186
11187 if (tv == NULL)
11188 {
Bram Moolenaar798b30b2009-04-22 10:56:16 +000011189 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaare9a41262005-01-15 22:18:47 +000011190 copy_tv(&argvars[2], rettv);
11191 }
11192 else
11193 copy_tv(tv, rettv);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011194}
11195
Bram Moolenaar342337a2005-07-21 21:11:17 +000011196static void get_buffer_lines __ARGS((buf_T *buf, linenr_T start, linenr_T end, int retlist, typval_T *rettv));
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011197
11198/*
11199 * Get line or list of lines from buffer "buf" into "rettv".
Bram Moolenaar342337a2005-07-21 21:11:17 +000011200 * Return a range (from start to end) of lines in rettv from the specified
11201 * buffer.
11202 * If 'retlist' is TRUE, then the lines are returned as a Vim List.
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011203 */
11204 static void
Bram Moolenaar342337a2005-07-21 21:11:17 +000011205get_buffer_lines(buf, start, end, retlist, rettv)
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011206 buf_T *buf;
11207 linenr_T start;
11208 linenr_T end;
Bram Moolenaar342337a2005-07-21 21:11:17 +000011209 int retlist;
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011210 typval_T *rettv;
11211{
11212 char_u *p;
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011213
Bram Moolenaar959a1432013-12-14 12:17:38 +010011214 rettv->v_type = VAR_STRING;
11215 rettv->vval.v_string = NULL;
Bram Moolenaar798b30b2009-04-22 10:56:16 +000011216 if (retlist && rettv_list_alloc(rettv) == FAIL)
11217 return;
Bram Moolenaar342337a2005-07-21 21:11:17 +000011218
11219 if (buf == NULL || buf->b_ml.ml_mfp == NULL || start < 0)
11220 return;
11221
11222 if (!retlist)
11223 {
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011224 if (start >= 1 && start <= buf->b_ml.ml_line_count)
11225 p = ml_get_buf(buf, start, FALSE);
11226 else
11227 p = (char_u *)"";
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011228 rettv->vval.v_string = vim_strsave(p);
11229 }
11230 else
11231 {
11232 if (end < start)
Bram Moolenaar342337a2005-07-21 21:11:17 +000011233 return;
11234
11235 if (start < 1)
11236 start = 1;
11237 if (end > buf->b_ml.ml_line_count)
11238 end = buf->b_ml.ml_line_count;
11239 while (start <= end)
Bram Moolenaareddf53b2006-02-27 00:11:10 +000011240 if (list_append_string(rettv->vval.v_list,
11241 ml_get_buf(buf, start++, FALSE), -1) == FAIL)
Bram Moolenaar342337a2005-07-21 21:11:17 +000011242 break;
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011243 }
11244}
11245
11246/*
11247 * "getbufline()" function
11248 */
11249 static void
11250f_getbufline(argvars, rettv)
11251 typval_T *argvars;
11252 typval_T *rettv;
11253{
11254 linenr_T lnum;
11255 linenr_T end;
11256 buf_T *buf;
11257
11258 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
11259 ++emsg_off;
Bram Moolenaar0c279bb2013-03-19 14:25:54 +010011260 buf = get_buf_tv(&argvars[0], FALSE);
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011261 --emsg_off;
11262
Bram Moolenaar661b1822005-07-28 22:36:45 +000011263 lnum = get_tv_lnum_buf(&argvars[1], buf);
Bram Moolenaar342337a2005-07-21 21:11:17 +000011264 if (argvars[2].v_type == VAR_UNKNOWN)
11265 end = lnum;
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011266 else
Bram Moolenaar661b1822005-07-28 22:36:45 +000011267 end = get_tv_lnum_buf(&argvars[2], buf);
11268
Bram Moolenaar342337a2005-07-21 21:11:17 +000011269 get_buffer_lines(buf, lnum, end, TRUE, rettv);
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011270}
11271
Bram Moolenaar0d660222005-01-07 21:51:51 +000011272/*
11273 * "getbufvar()" function
11274 */
11275 static void
11276f_getbufvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011277 typval_T *argvars;
11278 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011279{
11280 buf_T *buf;
11281 buf_T *save_curbuf;
11282 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000011283 dictitem_T *v;
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020011284 int done = FALSE;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011285
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011286 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
11287 varname = get_tv_string_chk(&argvars[1]);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011288 ++emsg_off;
Bram Moolenaar0c279bb2013-03-19 14:25:54 +010011289 buf = get_buf_tv(&argvars[0], FALSE);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011290
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020011291 rettv->v_type = VAR_STRING;
11292 rettv->vval.v_string = NULL;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011293
11294 if (buf != NULL && varname != NULL)
11295 {
Bram Moolenaar632deed2008-06-27 18:26:11 +000011296 /* set curbuf to be our buf, temporarily */
11297 save_curbuf = curbuf;
11298 curbuf = buf;
11299
Bram Moolenaar0d660222005-01-07 21:51:51 +000011300 if (*varname == '&') /* buffer-local-option */
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020011301 {
11302 if (get_option_tv(&varname, rettv, TRUE) == OK)
11303 done = TRUE;
11304 }
Bram Moolenaar445edda2011-01-22 01:13:39 +010011305 else if (STRCMP(varname, "changedtick") == 0)
11306 {
11307 rettv->v_type = VAR_NUMBER;
11308 rettv->vval.v_number = curbuf->b_changedtick;
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020011309 done = TRUE;
Bram Moolenaar445edda2011-01-22 01:13:39 +010011310 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000011311 else
11312 {
Bram Moolenaar332ac062013-04-15 13:06:21 +020011313 /* Look up the variable. */
11314 /* Let getbufvar({nr}, "") return the "b:" dictionary. */
11315 v = find_var_in_ht(&curbuf->b_vars->dv_hashtab,
11316 'b', varname, FALSE);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011317 if (v != NULL)
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020011318 {
Bram Moolenaar33570922005-01-25 22:26:29 +000011319 copy_tv(&v->di_tv, rettv);
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020011320 done = TRUE;
11321 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000011322 }
Bram Moolenaar632deed2008-06-27 18:26:11 +000011323
11324 /* restore previous notion of curbuf */
11325 curbuf = save_curbuf;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011326 }
11327
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020011328 if (!done && argvars[2].v_type != VAR_UNKNOWN)
11329 /* use the default value */
11330 copy_tv(&argvars[2], rettv);
11331
Bram Moolenaar0d660222005-01-07 21:51:51 +000011332 --emsg_off;
11333}
11334
11335/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011336 * "getchar()" function
11337 */
11338 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011339f_getchar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011340 typval_T *argvars;
11341 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011342{
11343 varnumber_T n;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011344 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011345
Bram Moolenaar4015b2c2006-06-22 19:01:34 +000011346 /* Position the cursor. Needed after a message that ends in a space. */
11347 windgoto(msg_row, msg_col);
11348
Bram Moolenaar071d4272004-06-13 20:20:40 +000011349 ++no_mapping;
11350 ++allow_keys;
Bram Moolenaar9c8791f2007-09-05 19:47:23 +000011351 for (;;)
11352 {
11353 if (argvars[0].v_type == VAR_UNKNOWN)
11354 /* getchar(): blocking wait. */
11355 n = safe_vgetc();
11356 else if (get_tv_number_chk(&argvars[0], &error) == 1)
11357 /* getchar(1): only check if char avail */
Bram Moolenaar9a665ba2014-05-22 18:59:58 +020011358 n = vpeekc_any();
11359 else if (error || vpeekc_any() == NUL)
Bram Moolenaar9c8791f2007-09-05 19:47:23 +000011360 /* illegal argument or getchar(0) and no char avail: return zero */
11361 n = 0;
11362 else
11363 /* getchar(0) and char avail: return char */
11364 n = safe_vgetc();
Bram Moolenaar9a665ba2014-05-22 18:59:58 +020011365
Bram Moolenaar9c8791f2007-09-05 19:47:23 +000011366 if (n == K_IGNORE)
11367 continue;
11368 break;
11369 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011370 --no_mapping;
11371 --allow_keys;
11372
Bram Moolenaar219b8702006-11-01 14:32:36 +000011373 vimvars[VV_MOUSE_WIN].vv_nr = 0;
11374 vimvars[VV_MOUSE_LNUM].vv_nr = 0;
11375 vimvars[VV_MOUSE_COL].vv_nr = 0;
11376
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011377 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011378 if (IS_SPECIAL(n) || mod_mask != 0)
11379 {
11380 char_u temp[10]; /* modifier: 3, mbyte-char: 6, NUL: 1 */
11381 int i = 0;
11382
11383 /* Turn a special key into three bytes, plus modifier. */
11384 if (mod_mask != 0)
11385 {
11386 temp[i++] = K_SPECIAL;
11387 temp[i++] = KS_MODIFIER;
11388 temp[i++] = mod_mask;
11389 }
11390 if (IS_SPECIAL(n))
11391 {
11392 temp[i++] = K_SPECIAL;
11393 temp[i++] = K_SECOND(n);
11394 temp[i++] = K_THIRD(n);
11395 }
11396#ifdef FEAT_MBYTE
11397 else if (has_mbyte)
11398 i += (*mb_char2bytes)(n, temp + i);
11399#endif
11400 else
11401 temp[i++] = n;
11402 temp[i++] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011403 rettv->v_type = VAR_STRING;
11404 rettv->vval.v_string = vim_strsave(temp);
Bram Moolenaar219b8702006-11-01 14:32:36 +000011405
11406#ifdef FEAT_MOUSE
Bram Moolenaar2526ef22013-03-16 14:20:51 +010011407 if (is_mouse_key(n))
Bram Moolenaar219b8702006-11-01 14:32:36 +000011408 {
11409 int row = mouse_row;
11410 int col = mouse_col;
11411 win_T *win;
11412 linenr_T lnum;
11413# ifdef FEAT_WINDOWS
11414 win_T *wp;
11415# endif
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +000011416 int winnr = 1;
Bram Moolenaar219b8702006-11-01 14:32:36 +000011417
11418 if (row >= 0 && col >= 0)
11419 {
11420 /* Find the window at the mouse coordinates and compute the
11421 * text position. */
11422 win = mouse_find_win(&row, &col);
11423 (void)mouse_comp_pos(win, &row, &col, &lnum);
11424# ifdef FEAT_WINDOWS
11425 for (wp = firstwin; wp != win; wp = wp->w_next)
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +000011426 ++winnr;
Bram Moolenaar219b8702006-11-01 14:32:36 +000011427# endif
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +000011428 vimvars[VV_MOUSE_WIN].vv_nr = winnr;
Bram Moolenaar219b8702006-11-01 14:32:36 +000011429 vimvars[VV_MOUSE_LNUM].vv_nr = lnum;
11430 vimvars[VV_MOUSE_COL].vv_nr = col + 1;
11431 }
11432 }
11433#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000011434 }
11435}
11436
11437/*
11438 * "getcharmod()" function
11439 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011440 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011441f_getcharmod(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000011442 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000011443 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011444{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011445 rettv->vval.v_number = mod_mask;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011446}
11447
11448/*
11449 * "getcmdline()" function
11450 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011451 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011452f_getcmdline(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000011453 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000011454 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011455{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011456 rettv->v_type = VAR_STRING;
11457 rettv->vval.v_string = get_cmdline_str();
Bram Moolenaar071d4272004-06-13 20:20:40 +000011458}
11459
11460/*
11461 * "getcmdpos()" function
11462 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011463 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011464f_getcmdpos(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000011465 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000011466 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011467{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011468 rettv->vval.v_number = get_cmdline_pos() + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011469}
11470
11471/*
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000011472 * "getcmdtype()" function
11473 */
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000011474 static void
11475f_getcmdtype(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000011476 typval_T *argvars UNUSED;
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000011477 typval_T *rettv;
11478{
11479 rettv->v_type = VAR_STRING;
11480 rettv->vval.v_string = alloc(2);
11481 if (rettv->vval.v_string != NULL)
11482 {
11483 rettv->vval.v_string[0] = get_cmdline_type();
11484 rettv->vval.v_string[1] = NUL;
11485 }
11486}
11487
11488/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011489 * "getcwd()" function
11490 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011491 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011492f_getcwd(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000011493 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000011494 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011495{
Bram Moolenaard9462e32011-04-11 21:35:11 +020011496 char_u *cwd;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011497
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011498 rettv->v_type = VAR_STRING;
Bram Moolenaard9462e32011-04-11 21:35:11 +020011499 rettv->vval.v_string = NULL;
11500 cwd = alloc(MAXPATHL);
11501 if (cwd != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011502 {
Bram Moolenaard9462e32011-04-11 21:35:11 +020011503 if (mch_dirname(cwd, MAXPATHL) != FAIL)
11504 {
11505 rettv->vval.v_string = vim_strsave(cwd);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011506#ifdef BACKSLASH_IN_FILENAME
Bram Moolenaard9462e32011-04-11 21:35:11 +020011507 if (rettv->vval.v_string != NULL)
11508 slash_adjust(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011509#endif
Bram Moolenaard9462e32011-04-11 21:35:11 +020011510 }
11511 vim_free(cwd);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011512 }
11513}
11514
11515/*
Bram Moolenaar46c9c732004-12-12 11:37:09 +000011516 * "getfontname()" function
11517 */
11518 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011519f_getfontname(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000011520 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000011521 typval_T *rettv;
Bram Moolenaar46c9c732004-12-12 11:37:09 +000011522{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011523 rettv->v_type = VAR_STRING;
11524 rettv->vval.v_string = NULL;
Bram Moolenaar46c9c732004-12-12 11:37:09 +000011525#ifdef FEAT_GUI
11526 if (gui.in_use)
11527 {
11528 GuiFont font;
11529 char_u *name = NULL;
11530
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011531 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +000011532 {
11533 /* Get the "Normal" font. Either the name saved by
11534 * hl_set_font_name() or from the font ID. */
11535 font = gui.norm_font;
11536 name = hl_get_font_name();
11537 }
11538 else
11539 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011540 name = get_tv_string(&argvars[0]);
Bram Moolenaar46c9c732004-12-12 11:37:09 +000011541 if (STRCMP(name, "*") == 0) /* don't use font dialog */
11542 return;
11543 font = gui_mch_get_font(name, FALSE);
11544 if (font == NOFONT)
11545 return; /* Invalid font name, return empty string. */
11546 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011547 rettv->vval.v_string = gui_mch_get_fontname(font, name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011548 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +000011549 gui_mch_free_font(font);
11550 }
11551#endif
11552}
11553
11554/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011555 * "getfperm({fname})" function
11556 */
11557 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011558f_getfperm(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011559 typval_T *argvars;
11560 typval_T *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011561{
11562 char_u *fname;
11563 struct stat st;
11564 char_u *perm = NULL;
11565 char_u flags[] = "rwx";
11566 int i;
11567
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011568 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011569
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011570 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011571 if (mch_stat((char *)fname, &st) >= 0)
11572 {
11573 perm = vim_strsave((char_u *)"---------");
11574 if (perm != NULL)
11575 {
11576 for (i = 0; i < 9; i++)
11577 {
11578 if (st.st_mode & (1 << (8 - i)))
11579 perm[i] = flags[i % 3];
11580 }
11581 }
11582 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011583 rettv->vval.v_string = perm;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011584}
11585
11586/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011587 * "getfsize({fname})" function
11588 */
11589 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011590f_getfsize(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011591 typval_T *argvars;
11592 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011593{
11594 char_u *fname;
11595 struct stat st;
11596
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011597 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011598
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011599 rettv->v_type = VAR_NUMBER;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011600
11601 if (mch_stat((char *)fname, &st) >= 0)
11602 {
11603 if (mch_isdir(fname))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011604 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011605 else
Bram Moolenaard827ada2007-06-19 15:19:55 +000011606 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011607 rettv->vval.v_number = (varnumber_T)st.st_size;
Bram Moolenaard827ada2007-06-19 15:19:55 +000011608
11609 /* non-perfect check for overflow */
11610 if ((off_t)rettv->vval.v_number != (off_t)st.st_size)
11611 rettv->vval.v_number = -2;
11612 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011613 }
11614 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011615 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011616}
11617
11618/*
11619 * "getftime({fname})" function
11620 */
11621 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011622f_getftime(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011623 typval_T *argvars;
11624 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011625{
11626 char_u *fname;
11627 struct stat st;
11628
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011629 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011630
11631 if (mch_stat((char *)fname, &st) >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011632 rettv->vval.v_number = (varnumber_T)st.st_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011633 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011634 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011635}
11636
11637/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011638 * "getftype({fname})" function
11639 */
11640 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011641f_getftype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011642 typval_T *argvars;
11643 typval_T *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011644{
11645 char_u *fname;
11646 struct stat st;
11647 char_u *type = NULL;
11648 char *t;
11649
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011650 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011651
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011652 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011653 if (mch_lstat((char *)fname, &st) >= 0)
11654 {
11655#ifdef S_ISREG
11656 if (S_ISREG(st.st_mode))
11657 t = "file";
11658 else if (S_ISDIR(st.st_mode))
11659 t = "dir";
11660# ifdef S_ISLNK
11661 else if (S_ISLNK(st.st_mode))
11662 t = "link";
11663# endif
11664# ifdef S_ISBLK
11665 else if (S_ISBLK(st.st_mode))
11666 t = "bdev";
11667# endif
11668# ifdef S_ISCHR
11669 else if (S_ISCHR(st.st_mode))
11670 t = "cdev";
11671# endif
11672# ifdef S_ISFIFO
11673 else if (S_ISFIFO(st.st_mode))
11674 t = "fifo";
11675# endif
11676# ifdef S_ISSOCK
11677 else if (S_ISSOCK(st.st_mode))
11678 t = "fifo";
11679# endif
11680 else
11681 t = "other";
11682#else
11683# ifdef S_IFMT
11684 switch (st.st_mode & S_IFMT)
11685 {
11686 case S_IFREG: t = "file"; break;
11687 case S_IFDIR: t = "dir"; break;
11688# ifdef S_IFLNK
11689 case S_IFLNK: t = "link"; break;
11690# endif
11691# ifdef S_IFBLK
11692 case S_IFBLK: t = "bdev"; break;
11693# endif
11694# ifdef S_IFCHR
11695 case S_IFCHR: t = "cdev"; break;
11696# endif
11697# ifdef S_IFIFO
11698 case S_IFIFO: t = "fifo"; break;
11699# endif
11700# ifdef S_IFSOCK
11701 case S_IFSOCK: t = "socket"; break;
11702# endif
11703 default: t = "other";
11704 }
11705# else
11706 if (mch_isdir(fname))
11707 t = "dir";
11708 else
11709 t = "file";
11710# endif
11711#endif
11712 type = vim_strsave((char_u *)t);
11713 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011714 rettv->vval.v_string = type;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011715}
11716
11717/*
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011718 * "getline(lnum, [end])" function
Bram Moolenaar0d660222005-01-07 21:51:51 +000011719 */
11720 static void
11721f_getline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011722 typval_T *argvars;
11723 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011724{
11725 linenr_T lnum;
11726 linenr_T end;
Bram Moolenaar342337a2005-07-21 21:11:17 +000011727 int retlist;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011728
11729 lnum = get_tv_lnum(argvars);
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011730 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar342337a2005-07-21 21:11:17 +000011731 {
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011732 end = 0;
Bram Moolenaar342337a2005-07-21 21:11:17 +000011733 retlist = FALSE;
11734 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000011735 else
Bram Moolenaar342337a2005-07-21 21:11:17 +000011736 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000011737 end = get_tv_lnum(&argvars[1]);
Bram Moolenaar342337a2005-07-21 21:11:17 +000011738 retlist = TRUE;
11739 }
Bram Moolenaar80fc0432005-07-20 22:06:07 +000011740
Bram Moolenaar342337a2005-07-21 21:11:17 +000011741 get_buffer_lines(curbuf, lnum, end, retlist, rettv);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011742}
11743
11744/*
Bram Moolenaar6ee10162007-07-26 20:58:42 +000011745 * "getmatches()" function
11746 */
Bram Moolenaar6ee10162007-07-26 20:58:42 +000011747 static void
11748f_getmatches(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000011749 typval_T *argvars UNUSED;
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +010011750 typval_T *rettv UNUSED;
Bram Moolenaar6ee10162007-07-26 20:58:42 +000011751{
11752#ifdef FEAT_SEARCH_EXTRA
11753 dict_T *dict;
11754 matchitem_T *cur = curwin->w_match_head;
11755
Bram Moolenaar6ee10162007-07-26 20:58:42 +000011756 if (rettv_list_alloc(rettv) == OK)
11757 {
11758 while (cur != NULL)
11759 {
11760 dict = dict_alloc();
11761 if (dict == NULL)
11762 return;
Bram Moolenaar6ee10162007-07-26 20:58:42 +000011763 dict_add_nr_str(dict, "group", 0L, syn_id2name(cur->hlg_id));
11764 dict_add_nr_str(dict, "pattern", 0L, cur->pattern);
11765 dict_add_nr_str(dict, "priority", (long)cur->priority, NULL);
11766 dict_add_nr_str(dict, "id", (long)cur->id, NULL);
11767 list_append_dict(rettv->vval.v_list, dict);
11768 cur = cur->next;
11769 }
11770 }
11771#endif
11772}
11773
11774/*
Bram Moolenaar18081e32008-02-20 19:11:07 +000011775 * "getpid()" function
11776 */
Bram Moolenaar18081e32008-02-20 19:11:07 +000011777 static void
11778f_getpid(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000011779 typval_T *argvars UNUSED;
Bram Moolenaar18081e32008-02-20 19:11:07 +000011780 typval_T *rettv;
11781{
11782 rettv->vval.v_number = mch_get_pid();
11783}
11784
Bram Moolenaar6f6c0f82014-05-28 20:31:42 +020011785static void getpos_both __ARGS((typval_T *argvars, typval_T *rettv, int getcurpos));
11786
11787/*
11788 * "getcurpos()" function
11789 */
11790 static void
11791f_getcurpos(argvars, rettv)
11792 typval_T *argvars;
11793 typval_T *rettv;
11794{
11795 getpos_both(argvars, rettv, TRUE);
11796}
11797
Bram Moolenaar18081e32008-02-20 19:11:07 +000011798/*
Bram Moolenaara5525202006-03-02 22:52:09 +000011799 * "getpos(string)" function
11800 */
11801 static void
11802f_getpos(argvars, rettv)
11803 typval_T *argvars;
11804 typval_T *rettv;
11805{
Bram Moolenaar6f6c0f82014-05-28 20:31:42 +020011806 getpos_both(argvars, rettv, FALSE);
11807}
11808
11809 static void
11810getpos_both(argvars, rettv, getcurpos)
11811 typval_T *argvars;
11812 typval_T *rettv;
11813 int getcurpos;
11814{
Bram Moolenaara5525202006-03-02 22:52:09 +000011815 pos_T *fp;
11816 list_T *l;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000011817 int fnum = -1;
Bram Moolenaara5525202006-03-02 22:52:09 +000011818
11819 if (rettv_list_alloc(rettv) == OK)
11820 {
11821 l = rettv->vval.v_list;
Bram Moolenaar6f6c0f82014-05-28 20:31:42 +020011822 if (getcurpos)
11823 fp = &curwin->w_cursor;
11824 else
11825 fp = var2fpos(&argvars[0], TRUE, &fnum);
Bram Moolenaar0e34f622006-03-03 23:00:03 +000011826 if (fnum != -1)
11827 list_append_number(l, (varnumber_T)fnum);
11828 else
11829 list_append_number(l, (varnumber_T)0);
Bram Moolenaara5525202006-03-02 22:52:09 +000011830 list_append_number(l, (fp != NULL) ? (varnumber_T)fp->lnum
11831 : (varnumber_T)0);
Bram Moolenaare65f7322007-10-02 20:08:54 +000011832 list_append_number(l, (fp != NULL)
11833 ? (varnumber_T)(fp->col == MAXCOL ? MAXCOL : fp->col + 1)
Bram Moolenaara5525202006-03-02 22:52:09 +000011834 : (varnumber_T)0);
11835 list_append_number(l,
11836#ifdef FEAT_VIRTUALEDIT
11837 (fp != NULL) ? (varnumber_T)fp->coladd :
11838#endif
11839 (varnumber_T)0);
Bram Moolenaar6f6c0f82014-05-28 20:31:42 +020011840 if (getcurpos)
Bram Moolenaar493c1782014-05-28 14:34:46 +020011841 list_append_number(l, (varnumber_T)curwin->w_curswant + 1);
Bram Moolenaara5525202006-03-02 22:52:09 +000011842 }
11843 else
11844 rettv->vval.v_number = FALSE;
11845}
11846
11847/*
Bram Moolenaar280f1262006-01-30 00:14:18 +000011848 * "getqflist()" and "getloclist()" functions
Bram Moolenaar2641f772005-03-25 21:58:17 +000011849 */
Bram Moolenaar2641f772005-03-25 21:58:17 +000011850 static void
Bram Moolenaar280f1262006-01-30 00:14:18 +000011851f_getqflist(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000011852 typval_T *argvars UNUSED;
11853 typval_T *rettv UNUSED;
Bram Moolenaar2641f772005-03-25 21:58:17 +000011854{
11855#ifdef FEAT_QUICKFIX
Bram Moolenaar280f1262006-01-30 00:14:18 +000011856 win_T *wp;
Bram Moolenaar2641f772005-03-25 21:58:17 +000011857#endif
11858
Bram Moolenaar2641f772005-03-25 21:58:17 +000011859#ifdef FEAT_QUICKFIX
Bram Moolenaareddf53b2006-02-27 00:11:10 +000011860 if (rettv_list_alloc(rettv) == OK)
Bram Moolenaar2641f772005-03-25 21:58:17 +000011861 {
Bram Moolenaar280f1262006-01-30 00:14:18 +000011862 wp = NULL;
11863 if (argvars[0].v_type != VAR_UNKNOWN) /* getloclist() */
11864 {
Bram Moolenaar99ebf042006-04-15 20:28:54 +000011865 wp = find_win_by_nr(&argvars[0], NULL);
Bram Moolenaar280f1262006-01-30 00:14:18 +000011866 if (wp == NULL)
11867 return;
11868 }
11869
Bram Moolenaareddf53b2006-02-27 00:11:10 +000011870 (void)get_errorlist(wp, rettv->vval.v_list);
Bram Moolenaar2641f772005-03-25 21:58:17 +000011871 }
11872#endif
11873}
11874
11875/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011876 * "getreg()" function
11877 */
11878 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011879f_getreg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011880 typval_T *argvars;
11881 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011882{
11883 char_u *strregname;
11884 int regname;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000011885 int arg2 = FALSE;
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +020011886 int return_list = FALSE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011887 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011888
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011889 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000011890 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011891 strregname = get_tv_string_chk(&argvars[0]);
11892 error = strregname == NULL;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000011893 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +020011894 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011895 arg2 = get_tv_number_chk(&argvars[1], &error);
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +020011896 if (!error && argvars[2].v_type != VAR_UNKNOWN)
11897 return_list = get_tv_number_chk(&argvars[2], &error);
11898 }
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000011899 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011900 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000011901 strregname = vimvars[VV_REG].vv_str;
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +020011902
11903 if (error)
11904 return;
11905
Bram Moolenaar071d4272004-06-13 20:20:40 +000011906 regname = (strregname == NULL ? '"' : *strregname);
11907 if (regname == 0)
11908 regname = '"';
11909
Bram Moolenaarb7cb42b2014-04-02 19:55:10 +020011910 if (return_list)
11911 {
11912 rettv->v_type = VAR_LIST;
11913 rettv->vval.v_list = (list_T *)get_reg_contents(regname,
11914 (arg2 ? GREG_EXPR_SRC : 0) | GREG_LIST);
11915 }
11916 else
11917 {
11918 rettv->v_type = VAR_STRING;
11919 rettv->vval.v_string = get_reg_contents(regname,
11920 arg2 ? GREG_EXPR_SRC : 0);
11921 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011922}
11923
11924/*
11925 * "getregtype()" function
11926 */
11927 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011928f_getregtype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011929 typval_T *argvars;
11930 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011931{
11932 char_u *strregname;
11933 int regname;
11934 char_u buf[NUMBUFLEN + 2];
11935 long reglen = 0;
11936
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011937 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011938 {
11939 strregname = get_tv_string_chk(&argvars[0]);
11940 if (strregname == NULL) /* type error; errmsg already given */
11941 {
11942 rettv->v_type = VAR_STRING;
11943 rettv->vval.v_string = NULL;
11944 return;
11945 }
11946 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011947 else
11948 /* Default to v:register */
Bram Moolenaare9a41262005-01-15 22:18:47 +000011949 strregname = vimvars[VV_REG].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011950
11951 regname = (strregname == NULL ? '"' : *strregname);
11952 if (regname == 0)
11953 regname = '"';
11954
11955 buf[0] = NUL;
11956 buf[1] = NUL;
11957 switch (get_reg_type(regname, &reglen))
11958 {
11959 case MLINE: buf[0] = 'V'; break;
11960 case MCHAR: buf[0] = 'v'; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011961 case MBLOCK:
11962 buf[0] = Ctrl_V;
11963 sprintf((char *)buf + 1, "%ld", reglen + 1);
11964 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011965 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011966 rettv->v_type = VAR_STRING;
11967 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011968}
11969
11970/*
Bram Moolenaar06b5d512010-05-22 15:37:44 +020011971 * "gettabvar()" function
11972 */
11973 static void
11974f_gettabvar(argvars, rettv)
11975 typval_T *argvars;
11976 typval_T *rettv;
11977{
11978 tabpage_T *tp;
11979 dictitem_T *v;
11980 char_u *varname;
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020011981 int done = FALSE;
Bram Moolenaar06b5d512010-05-22 15:37:44 +020011982
11983 rettv->v_type = VAR_STRING;
11984 rettv->vval.v_string = NULL;
11985
11986 varname = get_tv_string_chk(&argvars[1]);
11987 tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL));
11988 if (tp != NULL && varname != NULL)
11989 {
11990 /* look up the variable */
Bram Moolenaar332ac062013-04-15 13:06:21 +020011991 v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 0, varname, FALSE);
Bram Moolenaar06b5d512010-05-22 15:37:44 +020011992 if (v != NULL)
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020011993 {
Bram Moolenaar06b5d512010-05-22 15:37:44 +020011994 copy_tv(&v->di_tv, rettv);
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020011995 done = TRUE;
11996 }
Bram Moolenaar06b5d512010-05-22 15:37:44 +020011997 }
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020011998
11999 if (!done && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar63dbda12013-02-20 21:12:10 +010012000 copy_tv(&argvars[2], rettv);
Bram Moolenaar06b5d512010-05-22 15:37:44 +020012001}
12002
12003/*
Bram Moolenaar99ebf042006-04-15 20:28:54 +000012004 * "gettabwinvar()" function
12005 */
12006 static void
12007f_gettabwinvar(argvars, rettv)
12008 typval_T *argvars;
12009 typval_T *rettv;
12010{
12011 getwinvar(argvars, rettv, 1);
12012}
12013
12014/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012015 * "getwinposx()" function
12016 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012017 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012018f_getwinposx(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000012019 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000012020 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012021{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012022 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012023#ifdef FEAT_GUI
12024 if (gui.in_use)
12025 {
12026 int x, y;
12027
12028 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012029 rettv->vval.v_number = x;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012030 }
12031#endif
12032}
12033
12034/*
12035 * "getwinposy()" function
12036 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012037 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012038f_getwinposy(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000012039 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000012040 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012041{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012042 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012043#ifdef FEAT_GUI
12044 if (gui.in_use)
12045 {
12046 int x, y;
12047
12048 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012049 rettv->vval.v_number = y;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012050 }
12051#endif
12052}
12053
Bram Moolenaar99ebf042006-04-15 20:28:54 +000012054/*
Bram Moolenaar8c8de832008-06-24 22:58:06 +000012055 * Find window specified by "vp" in tabpage "tp".
Bram Moolenaar99ebf042006-04-15 20:28:54 +000012056 */
Bram Moolenaara40058a2005-07-11 22:42:07 +000012057 static win_T *
Bram Moolenaar99ebf042006-04-15 20:28:54 +000012058find_win_by_nr(vp, tp)
Bram Moolenaara40058a2005-07-11 22:42:07 +000012059 typval_T *vp;
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020012060 tabpage_T *tp UNUSED; /* NULL for current tab page */
Bram Moolenaara40058a2005-07-11 22:42:07 +000012061{
12062#ifdef FEAT_WINDOWS
12063 win_T *wp;
12064#endif
12065 int nr;
12066
12067 nr = get_tv_number_chk(vp, NULL);
12068
12069#ifdef FEAT_WINDOWS
12070 if (nr < 0)
12071 return NULL;
12072 if (nr == 0)
12073 return curwin;
12074
Bram Moolenaar99ebf042006-04-15 20:28:54 +000012075 for (wp = (tp == NULL || tp == curtab) ? firstwin : tp->tp_firstwin;
12076 wp != NULL; wp = wp->w_next)
Bram Moolenaara40058a2005-07-11 22:42:07 +000012077 if (--nr <= 0)
12078 break;
12079 return wp;
12080#else
12081 if (nr == 0 || nr == 1)
12082 return curwin;
12083 return NULL;
12084#endif
12085}
12086
Bram Moolenaar071d4272004-06-13 20:20:40 +000012087/*
12088 * "getwinvar()" function
12089 */
12090 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012091f_getwinvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012092 typval_T *argvars;
12093 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012094{
Bram Moolenaar99ebf042006-04-15 20:28:54 +000012095 getwinvar(argvars, rettv, 0);
12096}
12097
12098/*
12099 * getwinvar() and gettabwinvar()
12100 */
12101 static void
12102getwinvar(argvars, rettv, off)
12103 typval_T *argvars;
12104 typval_T *rettv;
12105 int off; /* 1 for gettabwinvar() */
12106{
Bram Moolenaar071d4272004-06-13 20:20:40 +000012107 win_T *win, *oldcurwin;
12108 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000012109 dictitem_T *v;
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020012110 tabpage_T *tp = NULL;
12111 tabpage_T *oldtabpage;
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020012112 int done = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012113
Bram Moolenaar99ebf042006-04-15 20:28:54 +000012114#ifdef FEAT_WINDOWS
12115 if (off == 1)
12116 tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL));
12117 else
12118 tp = curtab;
12119#endif
12120 win = find_win_by_nr(&argvars[off], tp);
12121 varname = get_tv_string_chk(&argvars[off + 1]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012122 ++emsg_off;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012123
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020012124 rettv->v_type = VAR_STRING;
12125 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012126
12127 if (win != NULL && varname != NULL)
12128 {
Bram Moolenaar105bc352013-05-17 16:03:57 +020012129 /* Set curwin to be our win, temporarily. Also set the tabpage,
12130 * otherwise the window is not valid. */
Bram Moolenaard6949742013-06-16 14:18:28 +020012131 switch_win(&oldcurwin, &oldtabpage, win, tp, TRUE);
Bram Moolenaar69a7e432006-10-10 10:55:47 +000012132
Bram Moolenaar071d4272004-06-13 20:20:40 +000012133 if (*varname == '&') /* window-local-option */
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020012134 {
12135 if (get_option_tv(&varname, rettv, 1) == OK)
12136 done = TRUE;
12137 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012138 else
12139 {
Bram Moolenaar332ac062013-04-15 13:06:21 +020012140 /* Look up the variable. */
12141 /* Let getwinvar({nr}, "") return the "w:" dictionary. */
12142 v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w', varname, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012143 if (v != NULL)
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020012144 {
Bram Moolenaar33570922005-01-25 22:26:29 +000012145 copy_tv(&v->di_tv, rettv);
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020012146 done = TRUE;
12147 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012148 }
Bram Moolenaar69a7e432006-10-10 10:55:47 +000012149
12150 /* restore previous notion of curwin */
Bram Moolenaard6949742013-06-16 14:18:28 +020012151 restore_win(oldcurwin, oldtabpage, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012152 }
12153
Bram Moolenaar54c34fa2013-04-15 15:15:35 +020012154 if (!done && argvars[off + 2].v_type != VAR_UNKNOWN)
12155 /* use the default return value */
12156 copy_tv(&argvars[off + 2], rettv);
12157
Bram Moolenaar071d4272004-06-13 20:20:40 +000012158 --emsg_off;
12159}
12160
12161/*
12162 * "glob()" function
12163 */
12164 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012165f_glob(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012166 typval_T *argvars;
12167 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012168{
Bram Moolenaar005c3c22010-12-02 21:44:40 +010012169 int options = WILD_SILENT|WILD_USE_NL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012170 expand_T xpc;
Bram Moolenaarbb5ddda2008-11-28 10:01:10 +000012171 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012172
Bram Moolenaarbb5ddda2008-11-28 10:01:10 +000012173 /* When the optional second argument is non-zero, don't remove matches
Bram Moolenaar146e9c32012-03-07 19:18:23 +010012174 * for 'wildignore' and don't put matches for 'suffixes' at the end. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012175 rettv->v_type = VAR_STRING;
Bram Moolenaar146e9c32012-03-07 19:18:23 +010012176 if (argvars[1].v_type != VAR_UNKNOWN)
12177 {
12178 if (get_tv_number_chk(&argvars[1], &error))
12179 options |= WILD_KEEP_ALL;
12180 if (argvars[2].v_type != VAR_UNKNOWN
12181 && get_tv_number_chk(&argvars[2], &error))
12182 {
12183 rettv->v_type = VAR_LIST;
12184 rettv->vval.v_list = NULL;
12185 }
12186 }
Bram Moolenaarbb5ddda2008-11-28 10:01:10 +000012187 if (!error)
12188 {
12189 ExpandInit(&xpc);
12190 xpc.xp_context = EXPAND_FILES;
Bram Moolenaar005c3c22010-12-02 21:44:40 +010012191 if (p_wic)
12192 options += WILD_ICASE;
Bram Moolenaar146e9c32012-03-07 19:18:23 +010012193 if (rettv->v_type == VAR_STRING)
12194 rettv->vval.v_string = ExpandOne(&xpc, get_tv_string(&argvars[0]),
Bram Moolenaar005c3c22010-12-02 21:44:40 +010012195 NULL, options, WILD_ALL);
Bram Moolenaar146e9c32012-03-07 19:18:23 +010012196 else if (rettv_list_alloc(rettv) != FAIL)
12197 {
12198 int i;
12199
12200 ExpandOne(&xpc, get_tv_string(&argvars[0]),
12201 NULL, options, WILD_ALL_KEEP);
12202 for (i = 0; i < xpc.xp_numfiles; i++)
12203 list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1);
12204
12205 ExpandCleanup(&xpc);
12206 }
Bram Moolenaarbb5ddda2008-11-28 10:01:10 +000012207 }
12208 else
12209 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012210}
12211
12212/*
12213 * "globpath()" function
12214 */
12215 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012216f_globpath(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012217 typval_T *argvars;
12218 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012219{
Bram Moolenaarbb5ddda2008-11-28 10:01:10 +000012220 int flags = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012221 char_u buf1[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012222 char_u *file = get_tv_string_buf_chk(&argvars[1], buf1);
Bram Moolenaarbb5ddda2008-11-28 10:01:10 +000012223 int error = FALSE;
Bram Moolenaar1b1063a2014-05-07 18:35:30 +020012224 garray_T ga;
12225 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012226
Bram Moolenaarbb5ddda2008-11-28 10:01:10 +000012227 /* When the optional second argument is non-zero, don't remove matches
12228 * for 'wildignore' and don't put matches for 'suffixes' at the end. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012229 rettv->v_type = VAR_STRING;
Bram Moolenaar1b1063a2014-05-07 18:35:30 +020012230 if (argvars[2].v_type != VAR_UNKNOWN)
12231 {
12232 if (get_tv_number_chk(&argvars[2], &error))
12233 flags |= WILD_KEEP_ALL;
12234 if (argvars[3].v_type != VAR_UNKNOWN
12235 && get_tv_number_chk(&argvars[3], &error))
12236 {
12237 rettv->v_type = VAR_LIST;
12238 rettv->vval.v_list = NULL;
12239 }
12240 }
12241 if (file != NULL && !error)
12242 {
12243 ga_init2(&ga, (int)sizeof(char_u *), 10);
12244 globpath(get_tv_string(&argvars[0]), file, &ga, flags);
12245 if (rettv->v_type == VAR_STRING)
12246 rettv->vval.v_string = ga_concat_strings(&ga, "\n");
12247 else if (rettv_list_alloc(rettv) != FAIL)
12248 for (i = 0; i < ga.ga_len; ++i)
12249 list_append_string(rettv->vval.v_list,
12250 ((char_u **)(ga.ga_data))[i], -1);
12251 ga_clear_strings(&ga);
12252 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012253 else
Bram Moolenaar1b1063a2014-05-07 18:35:30 +020012254 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012255}
12256
12257/*
12258 * "has()" function
12259 */
12260 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012261f_has(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012262 typval_T *argvars;
12263 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012264{
12265 int i;
12266 char_u *name;
12267 int n = FALSE;
12268 static char *(has_list[]) =
12269 {
12270#ifdef AMIGA
12271 "amiga",
12272# ifdef FEAT_ARP
12273 "arp",
12274# endif
12275#endif
12276#ifdef __BEOS__
12277 "beos",
12278#endif
12279#ifdef MSDOS
12280# ifdef DJGPP
12281 "dos32",
12282# else
12283 "dos16",
12284# endif
12285#endif
Bram Moolenaar241a8aa2005-12-06 20:04:44 +000012286#ifdef MACOS
Bram Moolenaar071d4272004-06-13 20:20:40 +000012287 "mac",
12288#endif
12289#if defined(MACOS_X_UNIX)
12290 "macunix",
12291#endif
12292#ifdef OS2
12293 "os2",
12294#endif
12295#ifdef __QNX__
12296 "qnx",
12297#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012298#ifdef UNIX
12299 "unix",
12300#endif
12301#ifdef VMS
12302 "vms",
12303#endif
12304#ifdef WIN16
12305 "win16",
12306#endif
12307#ifdef WIN32
12308 "win32",
12309#endif
12310#if defined(UNIX) && (defined(__CYGWIN32__) || defined(__CYGWIN__))
12311 "win32unix",
12312#endif
Bram Moolenaare37d7992010-01-12 13:18:33 +010012313#if defined(WIN64) || defined(_WIN64)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012314 "win64",
12315#endif
12316#ifdef EBCDIC
12317 "ebcdic",
12318#endif
12319#ifndef CASE_INSENSITIVE_FILENAME
12320 "fname_case",
12321#endif
Bram Moolenaarb5ef5e12013-08-30 16:35:44 +020012322#ifdef HAVE_ACL
12323 "acl",
12324#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012325#ifdef FEAT_ARABIC
12326 "arabic",
12327#endif
12328#ifdef FEAT_AUTOCMD
12329 "autocmd",
12330#endif
12331#ifdef FEAT_BEVAL
12332 "balloon_eval",
Bram Moolenaar342337a2005-07-21 21:11:17 +000012333# ifndef FEAT_GUI_W32 /* other GUIs always have multiline balloons */
12334 "balloon_multiline",
12335# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012336#endif
12337#if defined(SOME_BUILTIN_TCAPS) || defined(ALL_BUILTIN_TCAPS)
12338 "builtin_terms",
12339# ifdef ALL_BUILTIN_TCAPS
12340 "all_builtin_terms",
12341# endif
12342#endif
Bram Moolenaar77c604d2012-07-10 13:41:14 +020012343#if defined(FEAT_BROWSE) && (defined(USE_FILE_CHOOSER) \
12344 || defined(FEAT_GUI_W32) \
12345 || defined(FEAT_GUI_MOTIF))
12346 "browsefilter",
12347#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012348#ifdef FEAT_BYTEOFF
12349 "byte_offset",
12350#endif
12351#ifdef FEAT_CINDENT
12352 "cindent",
12353#endif
12354#ifdef FEAT_CLIENTSERVER
12355 "clientserver",
12356#endif
12357#ifdef FEAT_CLIPBOARD
12358 "clipboard",
12359#endif
12360#ifdef FEAT_CMDL_COMPL
12361 "cmdline_compl",
12362#endif
12363#ifdef FEAT_CMDHIST
12364 "cmdline_hist",
12365#endif
12366#ifdef FEAT_COMMENTS
12367 "comments",
12368#endif
Bram Moolenaar860cae12010-06-05 23:22:07 +020012369#ifdef FEAT_CONCEAL
12370 "conceal",
12371#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012372#ifdef FEAT_CRYPT
12373 "cryptv",
12374#endif
12375#ifdef FEAT_CSCOPE
12376 "cscope",
12377#endif
Bram Moolenaar860cae12010-06-05 23:22:07 +020012378#ifdef FEAT_CURSORBIND
12379 "cursorbind",
12380#endif
Bram Moolenaarac6e65f2005-08-29 22:25:38 +000012381#ifdef CURSOR_SHAPE
12382 "cursorshape",
12383#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012384#ifdef DEBUG
12385 "debug",
12386#endif
12387#ifdef FEAT_CON_DIALOG
12388 "dialog_con",
12389#endif
12390#ifdef FEAT_GUI_DIALOG
12391 "dialog_gui",
12392#endif
12393#ifdef FEAT_DIFF
12394 "diff",
12395#endif
12396#ifdef FEAT_DIGRAPHS
12397 "digraphs",
12398#endif
12399#ifdef FEAT_DND
12400 "dnd",
12401#endif
12402#ifdef FEAT_EMACS_TAGS
12403 "emacs_tags",
12404#endif
12405 "eval", /* always present, of course! */
12406#ifdef FEAT_EX_EXTRA
12407 "ex_extra",
12408#endif
12409#ifdef FEAT_SEARCH_EXTRA
12410 "extra_search",
12411#endif
12412#ifdef FEAT_FKMAP
12413 "farsi",
12414#endif
12415#ifdef FEAT_SEARCHPATH
12416 "file_in_path",
12417#endif
Bram Moolenaar68a33fc2012-04-25 16:50:48 +020012418#ifdef FEAT_FILTERPIPE
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000012419 "filterpipe",
12420#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012421#ifdef FEAT_FIND_ID
12422 "find_in_path",
12423#endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +000012424#ifdef FEAT_FLOAT
12425 "float",
12426#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012427#ifdef FEAT_FOLDING
12428 "folding",
12429#endif
12430#ifdef FEAT_FOOTER
12431 "footer",
12432#endif
12433#if !defined(USE_SYSTEM) && defined(UNIX)
12434 "fork",
12435#endif
12436#ifdef FEAT_GETTEXT
12437 "gettext",
12438#endif
12439#ifdef FEAT_GUI
12440 "gui",
12441#endif
12442#ifdef FEAT_GUI_ATHENA
12443# ifdef FEAT_GUI_NEXTAW
12444 "gui_neXtaw",
12445# else
12446 "gui_athena",
12447# endif
12448#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012449#ifdef FEAT_GUI_GTK
12450 "gui_gtk",
Bram Moolenaar071d4272004-06-13 20:20:40 +000012451 "gui_gtk2",
Bram Moolenaar071d4272004-06-13 20:20:40 +000012452#endif
Bram Moolenaar7b188622007-09-25 10:51:12 +000012453#ifdef FEAT_GUI_GNOME
12454 "gui_gnome",
12455#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012456#ifdef FEAT_GUI_MAC
12457 "gui_mac",
12458#endif
12459#ifdef FEAT_GUI_MOTIF
12460 "gui_motif",
12461#endif
12462#ifdef FEAT_GUI_PHOTON
12463 "gui_photon",
12464#endif
12465#ifdef FEAT_GUI_W16
12466 "gui_win16",
12467#endif
12468#ifdef FEAT_GUI_W32
12469 "gui_win32",
12470#endif
12471#ifdef FEAT_HANGULIN
12472 "hangul_input",
12473#endif
12474#if defined(HAVE_ICONV_H) && defined(USE_ICONV)
12475 "iconv",
12476#endif
12477#ifdef FEAT_INS_EXPAND
12478 "insert_expand",
12479#endif
12480#ifdef FEAT_JUMPLIST
12481 "jumplist",
12482#endif
12483#ifdef FEAT_KEYMAP
12484 "keymap",
12485#endif
12486#ifdef FEAT_LANGMAP
12487 "langmap",
12488#endif
12489#ifdef FEAT_LIBCALL
12490 "libcall",
12491#endif
12492#ifdef FEAT_LINEBREAK
12493 "linebreak",
12494#endif
12495#ifdef FEAT_LISP
12496 "lispindent",
12497#endif
12498#ifdef FEAT_LISTCMDS
12499 "listcmds",
12500#endif
12501#ifdef FEAT_LOCALMAP
12502 "localmap",
12503#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +020012504#ifdef FEAT_LUA
12505# ifndef DYNAMIC_LUA
12506 "lua",
12507# endif
12508#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012509#ifdef FEAT_MENU
12510 "menu",
12511#endif
12512#ifdef FEAT_SESSION
12513 "mksession",
12514#endif
12515#ifdef FEAT_MODIFY_FNAME
12516 "modify_fname",
12517#endif
12518#ifdef FEAT_MOUSE
12519 "mouse",
12520#endif
12521#ifdef FEAT_MOUSESHAPE
12522 "mouseshape",
12523#endif
12524#if defined(UNIX) || defined(VMS)
12525# ifdef FEAT_MOUSE_DEC
12526 "mouse_dec",
12527# endif
12528# ifdef FEAT_MOUSE_GPM
12529 "mouse_gpm",
12530# endif
12531# ifdef FEAT_MOUSE_JSB
12532 "mouse_jsbterm",
12533# endif
12534# ifdef FEAT_MOUSE_NET
12535 "mouse_netterm",
12536# endif
12537# ifdef FEAT_MOUSE_PTERM
12538 "mouse_pterm",
12539# endif
Bram Moolenaarcfb80702012-10-21 02:17:45 +020012540# ifdef FEAT_MOUSE_SGR
12541 "mouse_sgr",
12542# endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +000012543# ifdef FEAT_SYSMOUSE
12544 "mouse_sysmouse",
12545# endif
Bram Moolenaarcfb80702012-10-21 02:17:45 +020012546# ifdef FEAT_MOUSE_URXVT
12547 "mouse_urxvt",
12548# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012549# ifdef FEAT_MOUSE_XTERM
12550 "mouse_xterm",
12551# endif
12552#endif
12553#ifdef FEAT_MBYTE
12554 "multi_byte",
12555#endif
12556#ifdef FEAT_MBYTE_IME
12557 "multi_byte_ime",
12558#endif
12559#ifdef FEAT_MULTI_LANG
12560 "multi_lang",
12561#endif
Bram Moolenaar325b7a22004-07-05 15:58:32 +000012562#ifdef FEAT_MZSCHEME
Bram Moolenaar33570922005-01-25 22:26:29 +000012563#ifndef DYNAMIC_MZSCHEME
Bram Moolenaar325b7a22004-07-05 15:58:32 +000012564 "mzscheme",
12565#endif
Bram Moolenaar33570922005-01-25 22:26:29 +000012566#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012567#ifdef FEAT_OLE
12568 "ole",
12569#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012570#ifdef FEAT_PATH_EXTRA
12571 "path_extra",
12572#endif
12573#ifdef FEAT_PERL
12574#ifndef DYNAMIC_PERL
12575 "perl",
12576#endif
12577#endif
Bram Moolenaar55debbe2010-05-23 23:34:36 +020012578#ifdef FEAT_PERSISTENT_UNDO
12579 "persistent_undo",
12580#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012581#ifdef FEAT_PYTHON
12582#ifndef DYNAMIC_PYTHON
12583 "python",
12584#endif
12585#endif
Bram Moolenaarbd5e15f2010-07-17 21:19:38 +020012586#ifdef FEAT_PYTHON3
12587#ifndef DYNAMIC_PYTHON3
12588 "python3",
12589#endif
12590#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012591#ifdef FEAT_POSTSCRIPT
12592 "postscript",
12593#endif
12594#ifdef FEAT_PRINTER
12595 "printer",
12596#endif
Bram Moolenaar05159a02005-02-26 23:04:13 +000012597#ifdef FEAT_PROFILE
12598 "profile",
12599#endif
Bram Moolenaare580b0c2006-03-21 21:33:03 +000012600#ifdef FEAT_RELTIME
12601 "reltime",
12602#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012603#ifdef FEAT_QUICKFIX
12604 "quickfix",
12605#endif
12606#ifdef FEAT_RIGHTLEFT
12607 "rightleft",
12608#endif
12609#if defined(FEAT_RUBY) && !defined(DYNAMIC_RUBY)
12610 "ruby",
12611#endif
12612#ifdef FEAT_SCROLLBIND
12613 "scrollbind",
12614#endif
12615#ifdef FEAT_CMDL_INFO
12616 "showcmd",
12617 "cmdline_info",
12618#endif
12619#ifdef FEAT_SIGNS
12620 "signs",
12621#endif
12622#ifdef FEAT_SMARTINDENT
12623 "smartindent",
12624#endif
12625#ifdef FEAT_SNIFF
12626 "sniff",
12627#endif
Bram Moolenaaref94eec2009-11-11 13:22:11 +000012628#ifdef STARTUPTIME
12629 "startuptime",
12630#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012631#ifdef FEAT_STL_OPT
12632 "statusline",
12633#endif
12634#ifdef FEAT_SUN_WORKSHOP
12635 "sun_workshop",
12636#endif
12637#ifdef FEAT_NETBEANS_INTG
12638 "netbeans_intg",
12639#endif
Bram Moolenaar3c56a962006-03-12 22:19:04 +000012640#ifdef FEAT_SPELL
Bram Moolenaar0e4d8772005-06-07 21:12:49 +000012641 "spell",
12642#endif
12643#ifdef FEAT_SYN_HL
Bram Moolenaar071d4272004-06-13 20:20:40 +000012644 "syntax",
12645#endif
12646#if defined(USE_SYSTEM) || !defined(UNIX)
12647 "system",
12648#endif
12649#ifdef FEAT_TAG_BINS
12650 "tag_binary",
12651#endif
12652#ifdef FEAT_TAG_OLDSTATIC
12653 "tag_old_static",
12654#endif
12655#ifdef FEAT_TAG_ANYWHITE
12656 "tag_any_white",
12657#endif
12658#ifdef FEAT_TCL
12659# ifndef DYNAMIC_TCL
12660 "tcl",
12661# endif
12662#endif
12663#ifdef TERMINFO
12664 "terminfo",
12665#endif
12666#ifdef FEAT_TERMRESPONSE
12667 "termresponse",
12668#endif
12669#ifdef FEAT_TEXTOBJ
12670 "textobjects",
12671#endif
12672#ifdef HAVE_TGETENT
12673 "tgetent",
12674#endif
12675#ifdef FEAT_TITLE
12676 "title",
12677#endif
12678#ifdef FEAT_TOOLBAR
12679 "toolbar",
12680#endif
Bram Moolenaarbf9680e2010-12-02 21:43:16 +010012681#if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
12682 "unnamedplus",
12683#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012684#ifdef FEAT_USR_CMDS
12685 "user-commands", /* was accidentally included in 5.4 */
12686 "user_commands",
12687#endif
12688#ifdef FEAT_VIMINFO
12689 "viminfo",
12690#endif
12691#ifdef FEAT_VERTSPLIT
12692 "vertsplit",
12693#endif
12694#ifdef FEAT_VIRTUALEDIT
12695 "virtualedit",
12696#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012697 "visual",
Bram Moolenaar071d4272004-06-13 20:20:40 +000012698#ifdef FEAT_VISUALEXTRA
12699 "visualextra",
12700#endif
12701#ifdef FEAT_VREPLACE
12702 "vreplace",
12703#endif
12704#ifdef FEAT_WILDIGN
12705 "wildignore",
12706#endif
12707#ifdef FEAT_WILDMENU
12708 "wildmenu",
12709#endif
12710#ifdef FEAT_WINDOWS
12711 "windows",
12712#endif
12713#ifdef FEAT_WAK
12714 "winaltkeys",
12715#endif
12716#ifdef FEAT_WRITEBACKUP
12717 "writebackup",
12718#endif
12719#ifdef FEAT_XIM
12720 "xim",
12721#endif
12722#ifdef FEAT_XFONTSET
12723 "xfontset",
12724#endif
Bram Moolenaar79a2a492012-01-04 14:35:37 +010012725#ifdef FEAT_XPM_W32
Bram Moolenaarb5ef5e12013-08-30 16:35:44 +020012726 "xpm",
12727 "xpm_w32", /* for backward compatibility */
12728#else
12729# if defined(HAVE_XPM)
12730 "xpm",
12731# endif
Bram Moolenaar79a2a492012-01-04 14:35:37 +010012732#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012733#ifdef USE_XSMP
12734 "xsmp",
12735#endif
12736#ifdef USE_XSMP_INTERACT
12737 "xsmp_interact",
12738#endif
12739#ifdef FEAT_XCLIPBOARD
12740 "xterm_clipboard",
12741#endif
12742#ifdef FEAT_XTERM_SAVE
12743 "xterm_save",
12744#endif
12745#if defined(UNIX) && defined(FEAT_X11)
12746 "X11",
12747#endif
12748 NULL
12749 };
12750
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012751 name = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012752 for (i = 0; has_list[i] != NULL; ++i)
12753 if (STRICMP(name, has_list[i]) == 0)
12754 {
12755 n = TRUE;
12756 break;
12757 }
12758
12759 if (n == FALSE)
12760 {
12761 if (STRNICMP(name, "patch", 5) == 0)
Bram Moolenaar7f3be402014-04-01 22:08:54 +020012762 {
12763 if (name[5] == '-'
12764 && STRLEN(name) > 11
12765 && vim_isdigit(name[6])
12766 && vim_isdigit(name[8])
12767 && vim_isdigit(name[10]))
12768 {
12769 int major = atoi((char *)name + 6);
12770 int minor = atoi((char *)name + 8);
Bram Moolenaar7f3be402014-04-01 22:08:54 +020012771
12772 /* Expect "patch-9.9.01234". */
12773 n = (major < VIM_VERSION_MAJOR
12774 || (major == VIM_VERSION_MAJOR
12775 && (minor < VIM_VERSION_MINOR
12776 || (minor == VIM_VERSION_MINOR
Bram Moolenaar6716d9a2014-04-02 12:12:08 +020012777 && has_patch(atoi((char *)name + 10))))));
Bram Moolenaar7f3be402014-04-01 22:08:54 +020012778 }
12779 else
12780 n = has_patch(atoi((char *)name + 5));
12781 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012782 else if (STRICMP(name, "vim_starting") == 0)
12783 n = (starting != 0);
Bram Moolenaar42022d52008-12-09 09:57:49 +000012784#ifdef FEAT_MBYTE
12785 else if (STRICMP(name, "multi_byte_encoding") == 0)
12786 n = has_mbyte;
12787#endif
Bram Moolenaar342337a2005-07-21 21:11:17 +000012788#if defined(FEAT_BEVAL) && defined(FEAT_GUI_W32)
12789 else if (STRICMP(name, "balloon_multiline") == 0)
12790 n = multiline_balloon_available();
12791#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012792#ifdef DYNAMIC_TCL
12793 else if (STRICMP(name, "tcl") == 0)
12794 n = tcl_enabled(FALSE);
12795#endif
12796#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
12797 else if (STRICMP(name, "iconv") == 0)
12798 n = iconv_enabled(FALSE);
12799#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +020012800#ifdef DYNAMIC_LUA
12801 else if (STRICMP(name, "lua") == 0)
12802 n = lua_enabled(FALSE);
12803#endif
Bram Moolenaar33570922005-01-25 22:26:29 +000012804#ifdef DYNAMIC_MZSCHEME
12805 else if (STRICMP(name, "mzscheme") == 0)
12806 n = mzscheme_enabled(FALSE);
12807#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012808#ifdef DYNAMIC_RUBY
12809 else if (STRICMP(name, "ruby") == 0)
12810 n = ruby_enabled(FALSE);
12811#endif
Bram Moolenaarbd5e15f2010-07-17 21:19:38 +020012812#ifdef FEAT_PYTHON
Bram Moolenaar071d4272004-06-13 20:20:40 +000012813#ifdef DYNAMIC_PYTHON
12814 else if (STRICMP(name, "python") == 0)
12815 n = python_enabled(FALSE);
12816#endif
Bram Moolenaarbd5e15f2010-07-17 21:19:38 +020012817#endif
12818#ifdef FEAT_PYTHON3
12819#ifdef DYNAMIC_PYTHON3
12820 else if (STRICMP(name, "python3") == 0)
12821 n = python3_enabled(FALSE);
12822#endif
12823#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012824#ifdef DYNAMIC_PERL
12825 else if (STRICMP(name, "perl") == 0)
12826 n = perl_enabled(FALSE);
12827#endif
12828#ifdef FEAT_GUI
12829 else if (STRICMP(name, "gui_running") == 0)
12830 n = (gui.in_use || gui.starting);
12831# ifdef FEAT_GUI_W32
12832 else if (STRICMP(name, "gui_win32s") == 0)
12833 n = gui_is_win32s();
12834# endif
12835# ifdef FEAT_BROWSE
12836 else if (STRICMP(name, "browse") == 0)
12837 n = gui.in_use; /* gui_mch_browse() works when GUI is running */
12838# endif
12839#endif
12840#ifdef FEAT_SYN_HL
12841 else if (STRICMP(name, "syntax_items") == 0)
Bram Moolenaar860cae12010-06-05 23:22:07 +020012842 n = syntax_present(curwin);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012843#endif
12844#if defined(WIN3264)
12845 else if (STRICMP(name, "win95") == 0)
12846 n = mch_windows95();
12847#endif
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +000012848#ifdef FEAT_NETBEANS_INTG
12849 else if (STRICMP(name, "netbeans_enabled") == 0)
Bram Moolenaarb26e6322010-05-22 21:34:09 +020012850 n = netbeans_active();
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +000012851#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012852 }
12853
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012854 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012855}
12856
12857/*
Bram Moolenaare9a41262005-01-15 22:18:47 +000012858 * "has_key()" function
12859 */
12860 static void
12861f_has_key(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012862 typval_T *argvars;
12863 typval_T *rettv;
Bram Moolenaare9a41262005-01-15 22:18:47 +000012864{
Bram Moolenaare9a41262005-01-15 22:18:47 +000012865 if (argvars[0].v_type != VAR_DICT)
12866 {
12867 EMSG(_(e_dictreq));
12868 return;
12869 }
12870 if (argvars[0].vval.v_dict == NULL)
12871 return;
12872
12873 rettv->vval.v_number = dict_find(argvars[0].vval.v_dict,
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000012874 get_tv_string(&argvars[1]), -1) != NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000012875}
12876
12877/*
Bram Moolenaard267b9c2007-04-26 15:06:45 +000012878 * "haslocaldir()" function
12879 */
Bram Moolenaard267b9c2007-04-26 15:06:45 +000012880 static void
12881f_haslocaldir(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000012882 typval_T *argvars UNUSED;
Bram Moolenaard267b9c2007-04-26 15:06:45 +000012883 typval_T *rettv;
12884{
12885 rettv->vval.v_number = (curwin->w_localdir != NULL);
12886}
12887
12888/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012889 * "hasmapto()" function
12890 */
12891 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012892f_hasmapto(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012893 typval_T *argvars;
12894 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012895{
12896 char_u *name;
12897 char_u *mode;
12898 char_u buf[NUMBUFLEN];
Bram Moolenaar2c932302006-03-18 21:42:09 +000012899 int abbr = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012900
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012901 name = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012902 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012903 mode = (char_u *)"nvo";
12904 else
Bram Moolenaar2c932302006-03-18 21:42:09 +000012905 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012906 mode = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar2c932302006-03-18 21:42:09 +000012907 if (argvars[2].v_type != VAR_UNKNOWN)
12908 abbr = get_tv_number(&argvars[2]);
12909 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012910
Bram Moolenaar2c932302006-03-18 21:42:09 +000012911 if (map_to_exists(name, mode, abbr))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012912 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012913 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012914 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012915}
12916
12917/*
12918 * "histadd()" function
12919 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012920 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012921f_histadd(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000012922 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000012923 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012924{
12925#ifdef FEAT_CMDHIST
12926 int histype;
12927 char_u *str;
12928 char_u buf[NUMBUFLEN];
12929#endif
12930
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012931 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012932 if (check_restricted() || check_secure())
12933 return;
12934#ifdef FEAT_CMDHIST
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012935 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
12936 histype = str != NULL ? get_histtype(str) : -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012937 if (histype >= 0)
12938 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012939 str = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012940 if (*str != NUL)
12941 {
Bram Moolenaarc7be3f32009-12-24 14:01:12 +000012942 init_history();
Bram Moolenaar071d4272004-06-13 20:20:40 +000012943 add_to_history(histype, str, FALSE, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012944 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012945 return;
12946 }
12947 }
12948#endif
12949}
12950
12951/*
12952 * "histdel()" function
12953 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012954 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012955f_histdel(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000012956 typval_T *argvars UNUSED;
12957 typval_T *rettv UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012958{
12959#ifdef FEAT_CMDHIST
12960 int n;
12961 char_u buf[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012962 char_u *str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012963
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012964 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
12965 if (str == NULL)
12966 n = 0;
12967 else if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012968 /* only one argument: clear entire history */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012969 n = clr_history(get_histtype(str));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012970 else if (argvars[1].v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012971 /* index given: remove that entry */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012972 n = del_history_idx(get_histtype(str),
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012973 (int)get_tv_number(&argvars[1]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000012974 else
12975 /* string given: remove all matching entries */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012976 n = del_history_entry(get_histtype(str),
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012977 get_tv_string_buf(&argvars[1], buf));
12978 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012979#endif
12980}
12981
12982/*
12983 * "histget()" function
12984 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012985 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012986f_histget(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000012987 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000012988 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012989{
12990#ifdef FEAT_CMDHIST
12991 int type;
12992 int idx;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012993 char_u *str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012994
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012995 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
12996 if (str == NULL)
12997 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012998 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012999 {
13000 type = get_histtype(str);
13001 if (argvars[1].v_type == VAR_UNKNOWN)
13002 idx = get_history_idx(type);
13003 else
13004 idx = (int)get_tv_number_chk(&argvars[1], NULL);
13005 /* -1 on type error */
13006 rettv->vval.v_string = vim_strsave(get_history_entry(type, idx));
13007 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013008#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013009 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013010#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013011 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013012}
13013
13014/*
13015 * "histnr()" function
13016 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013017 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013018f_histnr(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000013019 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000013020 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013021{
13022 int i;
13023
13024#ifdef FEAT_CMDHIST
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013025 char_u *history = get_tv_string_chk(&argvars[0]);
13026
13027 i = history == NULL ? HIST_CMD - 1 : get_histtype(history);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013028 if (i >= HIST_CMD && i < HIST_COUNT)
13029 i = get_history_idx(i);
13030 else
13031#endif
13032 i = -1;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013033 rettv->vval.v_number = i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013034}
13035
13036/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013037 * "highlightID(name)" function
13038 */
13039 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013040f_hlID(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013041 typval_T *argvars;
13042 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013043{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013044 rettv->vval.v_number = syn_name2id(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000013045}
13046
13047/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000013048 * "highlight_exists()" function
13049 */
13050 static void
13051f_hlexists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013052 typval_T *argvars;
13053 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013054{
13055 rettv->vval.v_number = highlight_exists(get_tv_string(&argvars[0]));
13056}
13057
13058/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013059 * "hostname()" function
13060 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013061 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013062f_hostname(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000013063 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000013064 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013065{
13066 char_u hostname[256];
13067
13068 mch_get_host_name(hostname, 256);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013069 rettv->v_type = VAR_STRING;
13070 rettv->vval.v_string = vim_strsave(hostname);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013071}
13072
13073/*
13074 * iconv() function
13075 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013076 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013077f_iconv(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000013078 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000013079 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013080{
13081#ifdef FEAT_MBYTE
13082 char_u buf1[NUMBUFLEN];
13083 char_u buf2[NUMBUFLEN];
13084 char_u *from, *to, *str;
13085 vimconv_T vimconv;
13086#endif
13087
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013088 rettv->v_type = VAR_STRING;
13089 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013090
13091#ifdef FEAT_MBYTE
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013092 str = get_tv_string(&argvars[0]);
13093 from = enc_canonize(enc_skip(get_tv_string_buf(&argvars[1], buf1)));
13094 to = enc_canonize(enc_skip(get_tv_string_buf(&argvars[2], buf2)));
Bram Moolenaar071d4272004-06-13 20:20:40 +000013095 vimconv.vc_type = CONV_NONE;
13096 convert_setup(&vimconv, from, to);
13097
13098 /* If the encodings are equal, no conversion needed. */
13099 if (vimconv.vc_type == CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013100 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013101 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013102 rettv->vval.v_string = string_convert(&vimconv, str, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013103
13104 convert_setup(&vimconv, NULL, NULL);
13105 vim_free(from);
13106 vim_free(to);
13107#endif
13108}
13109
13110/*
13111 * "indent()" function
13112 */
13113 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013114f_indent(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013115 typval_T *argvars;
13116 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013117{
13118 linenr_T lnum;
13119
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013120 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013121 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013122 rettv->vval.v_number = get_indent_lnum(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013123 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013124 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013125}
13126
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013127/*
13128 * "index()" function
13129 */
13130 static void
13131f_index(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013132 typval_T *argvars;
13133 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013134{
Bram Moolenaar33570922005-01-25 22:26:29 +000013135 list_T *l;
13136 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013137 long idx = 0;
13138 int ic = FALSE;
13139
13140 rettv->vval.v_number = -1;
13141 if (argvars[0].v_type != VAR_LIST)
13142 {
13143 EMSG(_(e_listreq));
13144 return;
13145 }
13146 l = argvars[0].vval.v_list;
13147 if (l != NULL)
13148 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000013149 item = l->lv_first;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013150 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000013151 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013152 int error = FALSE;
13153
Bram Moolenaar758711c2005-02-02 23:11:38 +000013154 /* Start at specified item. Use the cached index that list_find()
13155 * sets, so that a negative number also works. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013156 item = list_find(l, get_tv_number_chk(&argvars[2], &error));
Bram Moolenaar758711c2005-02-02 23:11:38 +000013157 idx = l->lv_idx;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000013158 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013159 ic = get_tv_number_chk(&argvars[3], &error);
13160 if (error)
13161 item = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000013162 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013163
Bram Moolenaar758711c2005-02-02 23:11:38 +000013164 for ( ; item != NULL; item = item->li_next, ++idx)
Bram Moolenaar67b3f992010-11-10 20:41:57 +010013165 if (tv_equal(&item->li_tv, &argvars[1], ic, FALSE))
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013166 {
13167 rettv->vval.v_number = idx;
13168 break;
13169 }
13170 }
13171}
13172
Bram Moolenaar071d4272004-06-13 20:20:40 +000013173static int inputsecret_flag = 0;
13174
Bram Moolenaarecbaf552006-07-13 06:31:00 +000013175static void get_user_input __ARGS((typval_T *argvars, typval_T *rettv, int inputdialog));
13176
Bram Moolenaar071d4272004-06-13 20:20:40 +000013177/*
Bram Moolenaarecbaf552006-07-13 06:31:00 +000013178 * This function is used by f_input() and f_inputdialog() functions. The third
13179 * argument to f_input() specifies the type of completion to use at the
13180 * prompt. The third argument to f_inputdialog() specifies the value to return
13181 * when the user cancels the prompt.
Bram Moolenaar071d4272004-06-13 20:20:40 +000013182 */
13183 static void
Bram Moolenaarecbaf552006-07-13 06:31:00 +000013184get_user_input(argvars, rettv, inputdialog)
Bram Moolenaar33570922005-01-25 22:26:29 +000013185 typval_T *argvars;
13186 typval_T *rettv;
Bram Moolenaarecbaf552006-07-13 06:31:00 +000013187 int inputdialog;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013188{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013189 char_u *prompt = get_tv_string_chk(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013190 char_u *p = NULL;
13191 int c;
13192 char_u buf[NUMBUFLEN];
13193 int cmd_silent_save = cmd_silent;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013194 char_u *defstr = (char_u *)"";
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000013195 int xp_type = EXPAND_NOTHING;
13196 char_u *xp_arg = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013197
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013198 rettv->v_type = VAR_STRING;
Bram Moolenaarce85c562007-09-16 12:21:16 +000013199 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013200
13201#ifdef NO_CONSOLE_INPUT
13202 /* While starting up, there is no place to enter text. */
13203 if (no_console_input())
Bram Moolenaar071d4272004-06-13 20:20:40 +000013204 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013205#endif
13206
13207 cmd_silent = FALSE; /* Want to see the prompt. */
13208 if (prompt != NULL)
13209 {
13210 /* Only the part of the message after the last NL is considered as
13211 * prompt for the command line */
13212 p = vim_strrchr(prompt, '\n');
13213 if (p == NULL)
13214 p = prompt;
13215 else
13216 {
13217 ++p;
13218 c = *p;
13219 *p = NUL;
13220 msg_start();
13221 msg_clr_eos();
13222 msg_puts_attr(prompt, echo_attr);
13223 msg_didout = FALSE;
13224 msg_starthere();
13225 *p = c;
13226 }
13227 cmdline_row = msg_row;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013228
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013229 if (argvars[1].v_type != VAR_UNKNOWN)
13230 {
13231 defstr = get_tv_string_buf_chk(&argvars[1], buf);
13232 if (defstr != NULL)
13233 stuffReadbuffSpec(defstr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013234
Bram Moolenaarecbaf552006-07-13 06:31:00 +000013235 if (!inputdialog && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar4463f292005-09-25 22:20:24 +000013236 {
13237 char_u *xp_name;
Bram Moolenaar86c9ee22006-05-13 11:33:27 +000013238 int xp_namelen;
Bram Moolenaar4463f292005-09-25 22:20:24 +000013239 long argt;
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000013240
Bram Moolenaarb5c9cb52012-07-16 19:27:29 +020013241 /* input() with a third argument: completion */
Bram Moolenaar4463f292005-09-25 22:20:24 +000013242 rettv->vval.v_string = NULL;
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000013243
Bram Moolenaar4463f292005-09-25 22:20:24 +000013244 xp_name = get_tv_string_buf_chk(&argvars[2], buf);
13245 if (xp_name == NULL)
13246 return;
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000013247
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000013248 xp_namelen = (int)STRLEN(xp_name);
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000013249
Bram Moolenaar4463f292005-09-25 22:20:24 +000013250 if (parse_compl_arg(xp_name, xp_namelen, &xp_type, &argt,
13251 &xp_arg) == FAIL)
13252 return;
13253 }
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000013254 }
13255
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013256 if (defstr != NULL)
Bram Moolenaar35a7c682013-10-02 16:46:28 +020013257 {
13258# ifdef FEAT_EX_EXTRA
13259 int save_ex_normal_busy = ex_normal_busy;
13260 ex_normal_busy = 0;
13261# endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013262 rettv->vval.v_string =
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000013263 getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr,
13264 xp_type, xp_arg);
Bram Moolenaar35a7c682013-10-02 16:46:28 +020013265# ifdef FEAT_EX_EXTRA
13266 ex_normal_busy = save_ex_normal_busy;
13267# endif
13268 }
Bram Moolenaar04b27512012-08-08 14:33:21 +020013269 if (inputdialog && rettv->vval.v_string == NULL
Bram Moolenaarb5c9cb52012-07-16 19:27:29 +020013270 && argvars[1].v_type != VAR_UNKNOWN
13271 && argvars[2].v_type != VAR_UNKNOWN)
13272 rettv->vval.v_string = vim_strsave(get_tv_string_buf(
13273 &argvars[2], buf));
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000013274
13275 vim_free(xp_arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013276
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013277 /* since the user typed this, no need to wait for return */
13278 need_wait_return = FALSE;
13279 msg_didout = FALSE;
13280 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013281 cmd_silent = cmd_silent_save;
13282}
13283
13284/*
Bram Moolenaarecbaf552006-07-13 06:31:00 +000013285 * "input()" function
13286 * Also handles inputsecret() when inputsecret is set.
13287 */
13288 static void
13289f_input(argvars, rettv)
13290 typval_T *argvars;
13291 typval_T *rettv;
13292{
13293 get_user_input(argvars, rettv, FALSE);
13294}
13295
13296/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013297 * "inputdialog()" function
13298 */
13299 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013300f_inputdialog(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013301 typval_T *argvars;
13302 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013303{
13304#if defined(FEAT_GUI_TEXTDIALOG)
13305 /* Use a GUI dialog if the GUI is running and 'c' is not in 'guioptions' */
13306 if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
13307 {
13308 char_u *message;
13309 char_u buf[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013310 char_u *defstr = (char_u *)"";
Bram Moolenaar071d4272004-06-13 20:20:40 +000013311
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013312 message = get_tv_string_chk(&argvars[0]);
13313 if (argvars[1].v_type != VAR_UNKNOWN
Bram Moolenaarc05f93f2006-05-02 22:09:31 +000013314 && (defstr = get_tv_string_buf_chk(&argvars[1], buf)) != NULL)
Bram Moolenaarce0842a2005-07-18 21:58:11 +000013315 vim_strncpy(IObuff, defstr, IOSIZE - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013316 else
13317 IObuff[0] = NUL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013318 if (message != NULL && defstr != NULL
13319 && do_dialog(VIM_QUESTION, NULL, message,
Bram Moolenaard2c340a2011-01-17 20:08:11 +010013320 (char_u *)_("&OK\n&Cancel"), 1, IObuff, FALSE) == 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013321 rettv->vval.v_string = vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013322 else
13323 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013324 if (message != NULL && defstr != NULL
13325 && argvars[1].v_type != VAR_UNKNOWN
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013326 && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013327 rettv->vval.v_string = vim_strsave(
13328 get_tv_string_buf(&argvars[2], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +000013329 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013330 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013331 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013332 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013333 }
13334 else
13335#endif
Bram Moolenaarecbaf552006-07-13 06:31:00 +000013336 get_user_input(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013337}
13338
Bram Moolenaar6efa2b32005-09-10 19:26:26 +000013339/*
13340 * "inputlist()" function
13341 */
13342 static void
13343f_inputlist(argvars, rettv)
13344 typval_T *argvars;
13345 typval_T *rettv;
13346{
13347 listitem_T *li;
13348 int selected;
13349 int mouse_used;
13350
Bram Moolenaar6efa2b32005-09-10 19:26:26 +000013351#ifdef NO_CONSOLE_INPUT
13352 /* While starting up, there is no place to enter text. */
13353 if (no_console_input())
13354 return;
13355#endif
13356 if (argvars[0].v_type != VAR_LIST || argvars[0].vval.v_list == NULL)
13357 {
13358 EMSG2(_(e_listarg), "inputlist()");
13359 return;
13360 }
13361
13362 msg_start();
Bram Moolenaar412f7442006-07-23 19:51:57 +000013363 msg_row = Rows - 1; /* for when 'cmdheight' > 1 */
Bram Moolenaar6efa2b32005-09-10 19:26:26 +000013364 lines_left = Rows; /* avoid more prompt */
13365 msg_scroll = TRUE;
13366 msg_clr_eos();
13367
13368 for (li = argvars[0].vval.v_list->lv_first; li != NULL; li = li->li_next)
13369 {
13370 msg_puts(get_tv_string(&li->li_tv));
13371 msg_putchar('\n');
13372 }
13373
13374 /* Ask for choice. */
13375 selected = prompt_for_number(&mouse_used);
13376 if (mouse_used)
13377 selected -= lines_left;
13378
13379 rettv->vval.v_number = selected;
13380}
13381
13382
Bram Moolenaar071d4272004-06-13 20:20:40 +000013383static garray_T ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL};
13384
13385/*
13386 * "inputrestore()" function
13387 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013388 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013389f_inputrestore(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000013390 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000013391 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013392{
13393 if (ga_userinput.ga_len > 0)
13394 {
13395 --ga_userinput.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013396 restore_typeahead((tasave_T *)(ga_userinput.ga_data)
13397 + ga_userinput.ga_len);
Bram Moolenaar798b30b2009-04-22 10:56:16 +000013398 /* default return is zero == OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013399 }
13400 else if (p_verbose > 1)
13401 {
Bram Moolenaar54ee7752005-05-31 22:22:17 +000013402 verb_msg((char_u *)_("called inputrestore() more often than inputsave()"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013403 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013404 }
13405}
13406
13407/*
13408 * "inputsave()" function
13409 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013410 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013411f_inputsave(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000013412 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000013413 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013414{
Bram Moolenaar8c8de832008-06-24 22:58:06 +000013415 /* Add an entry to the stack of typeahead storage. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013416 if (ga_grow(&ga_userinput, 1) == OK)
13417 {
13418 save_typeahead((tasave_T *)(ga_userinput.ga_data)
13419 + ga_userinput.ga_len);
13420 ++ga_userinput.ga_len;
Bram Moolenaar798b30b2009-04-22 10:56:16 +000013421 /* default return is zero == OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013422 }
13423 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013424 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013425}
13426
13427/*
13428 * "inputsecret()" function
13429 */
13430 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013431f_inputsecret(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013432 typval_T *argvars;
13433 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013434{
13435 ++cmdline_star;
13436 ++inputsecret_flag;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013437 f_input(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013438 --cmdline_star;
13439 --inputsecret_flag;
13440}
13441
13442/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013443 * "insert()" function
13444 */
13445 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013446f_insert(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013447 typval_T *argvars;
13448 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013449{
13450 long before = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000013451 listitem_T *item;
13452 list_T *l;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013453 int error = FALSE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013454
13455 if (argvars[0].v_type != VAR_LIST)
Bram Moolenaar0d660222005-01-07 21:51:51 +000013456 EMSG2(_(e_listarg), "insert()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000013457 else if ((l = argvars[0].vval.v_list) != NULL
Bram Moolenaar32f649e2011-04-11 13:46:13 +020013458 && !tv_check_lock(l->lv_lock, (char_u *)_("insert() argument")))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013459 {
13460 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013461 before = get_tv_number_chk(&argvars[2], &error);
13462 if (error)
13463 return; /* type error; errmsg already given */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013464
Bram Moolenaar758711c2005-02-02 23:11:38 +000013465 if (before == l->lv_len)
13466 item = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013467 else
13468 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000013469 item = list_find(l, before);
13470 if (item == NULL)
13471 {
13472 EMSGN(_(e_listidx), before);
13473 l = NULL;
13474 }
13475 }
13476 if (l != NULL)
13477 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013478 list_insert_tv(l, &argvars[1], item);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013479 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013480 }
13481 }
13482}
13483
13484/*
Bram Moolenaard6e256c2011-12-14 15:32:50 +010013485 * "invert(expr)" function
13486 */
13487 static void
13488f_invert(argvars, rettv)
13489 typval_T *argvars;
13490 typval_T *rettv;
13491{
13492 rettv->vval.v_number = ~get_tv_number_chk(&argvars[0], NULL);
13493}
13494
13495/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013496 * "isdirectory()" function
13497 */
13498 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013499f_isdirectory(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013500 typval_T *argvars;
13501 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013502{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013503 rettv->vval.v_number = mch_isdir(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000013504}
13505
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000013506/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000013507 * "islocked()" function
13508 */
13509 static void
13510f_islocked(argvars, rettv)
13511 typval_T *argvars;
13512 typval_T *rettv;
13513{
13514 lval_T lv;
13515 char_u *end;
13516 dictitem_T *di;
13517
13518 rettv->vval.v_number = -1;
Bram Moolenaar6d977d62014-01-14 15:24:39 +010013519 end = get_lval(get_tv_string(&argvars[0]), NULL, &lv, FALSE, FALSE,
13520 GLV_NO_AUTOLOAD, FNE_CHECK_START);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000013521 if (end != NULL && lv.ll_name != NULL)
13522 {
13523 if (*end != NUL)
13524 EMSG(_(e_trailing));
13525 else
13526 {
13527 if (lv.ll_tv == NULL)
13528 {
13529 if (check_changedtick(lv.ll_name))
13530 rettv->vval.v_number = 1; /* always locked */
13531 else
13532 {
Bram Moolenaar6d977d62014-01-14 15:24:39 +010013533 di = find_var(lv.ll_name, NULL, TRUE);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000013534 if (di != NULL)
13535 {
13536 /* Consider a variable locked when:
13537 * 1. the variable itself is locked
13538 * 2. the value of the variable is locked.
13539 * 3. the List or Dict value is locked.
13540 */
13541 rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK)
13542 || tv_islocked(&di->di_tv));
13543 }
13544 }
13545 }
13546 else if (lv.ll_range)
Bram Moolenaar910f66f2006-04-05 20:41:53 +000013547 EMSG(_("E786: Range not allowed"));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000013548 else if (lv.ll_newkey != NULL)
13549 EMSG2(_(e_dictkey), lv.ll_newkey);
13550 else if (lv.ll_list != NULL)
13551 /* List item. */
13552 rettv->vval.v_number = tv_islocked(&lv.ll_li->li_tv);
13553 else
13554 /* Dictionary item. */
13555 rettv->vval.v_number = tv_islocked(&lv.ll_di->di_tv);
13556 }
13557 }
13558
13559 clear_lval(&lv);
13560}
13561
Bram Moolenaar33570922005-01-25 22:26:29 +000013562static void dict_list __ARGS((typval_T *argvars, typval_T *rettv, int what));
Bram Moolenaar8c711452005-01-14 21:53:12 +000013563
13564/*
13565 * Turn a dict into a list:
13566 * "what" == 0: list of keys
13567 * "what" == 1: list of values
13568 * "what" == 2: list of items
13569 */
13570 static void
13571dict_list(argvars, rettv, what)
Bram Moolenaar33570922005-01-25 22:26:29 +000013572 typval_T *argvars;
13573 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000013574 int what;
13575{
Bram Moolenaar33570922005-01-25 22:26:29 +000013576 list_T *l2;
13577 dictitem_T *di;
13578 hashitem_T *hi;
13579 listitem_T *li;
13580 listitem_T *li2;
13581 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000013582 int todo;
Bram Moolenaar8c711452005-01-14 21:53:12 +000013583
Bram Moolenaar8c711452005-01-14 21:53:12 +000013584 if (argvars[0].v_type != VAR_DICT)
13585 {
13586 EMSG(_(e_dictreq));
13587 return;
13588 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000013589 if ((d = argvars[0].vval.v_dict) == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000013590 return;
13591
Bram Moolenaareddf53b2006-02-27 00:11:10 +000013592 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000013593 return;
Bram Moolenaar8c711452005-01-14 21:53:12 +000013594
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000013595 todo = (int)d->dv_hashtab.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +000013596 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +000013597 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000013598 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar8c711452005-01-14 21:53:12 +000013599 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000013600 --todo;
13601 di = HI2DI(hi);
Bram Moolenaar8c711452005-01-14 21:53:12 +000013602
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000013603 li = listitem_alloc();
13604 if (li == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000013605 break;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000013606 list_append(rettv->vval.v_list, li);
Bram Moolenaar8c711452005-01-14 21:53:12 +000013607
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000013608 if (what == 0)
13609 {
13610 /* keys() */
13611 li->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000013612 li->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000013613 li->li_tv.vval.v_string = vim_strsave(di->di_key);
13614 }
13615 else if (what == 1)
13616 {
13617 /* values() */
13618 copy_tv(&di->di_tv, &li->li_tv);
13619 }
13620 else
13621 {
13622 /* items() */
13623 l2 = list_alloc();
13624 li->li_tv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000013625 li->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000013626 li->li_tv.vval.v_list = l2;
13627 if (l2 == NULL)
13628 break;
13629 ++l2->lv_refcount;
13630
13631 li2 = listitem_alloc();
13632 if (li2 == NULL)
13633 break;
13634 list_append(l2, li2);
13635 li2->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000013636 li2->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000013637 li2->li_tv.vval.v_string = vim_strsave(di->di_key);
13638
13639 li2 = listitem_alloc();
13640 if (li2 == NULL)
13641 break;
13642 list_append(l2, li2);
13643 copy_tv(&di->di_tv, &li2->li_tv);
13644 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000013645 }
13646 }
13647}
13648
13649/*
13650 * "items(dict)" function
13651 */
13652 static void
13653f_items(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013654 typval_T *argvars;
13655 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000013656{
13657 dict_list(argvars, rettv, 2);
13658}
13659
Bram Moolenaar071d4272004-06-13 20:20:40 +000013660/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000013661 * "join()" function
13662 */
13663 static void
13664f_join(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013665 typval_T *argvars;
13666 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000013667{
13668 garray_T ga;
13669 char_u *sep;
13670
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000013671 if (argvars[0].v_type != VAR_LIST)
13672 {
13673 EMSG(_(e_listreq));
13674 return;
13675 }
13676 if (argvars[0].vval.v_list == NULL)
13677 return;
13678 if (argvars[1].v_type == VAR_UNKNOWN)
13679 sep = (char_u *)" ";
13680 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013681 sep = get_tv_string_chk(&argvars[1]);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000013682
13683 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013684
13685 if (sep != NULL)
13686 {
13687 ga_init2(&ga, (int)sizeof(char), 80);
Bram Moolenaarb71eaae2006-01-20 23:10:18 +000013688 list_join(&ga, argvars[0].vval.v_list, sep, TRUE, 0);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013689 ga_append(&ga, NUL);
13690 rettv->vval.v_string = (char_u *)ga.ga_data;
13691 }
13692 else
13693 rettv->vval.v_string = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000013694}
13695
13696/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000013697 * "keys()" function
13698 */
13699 static void
13700f_keys(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013701 typval_T *argvars;
13702 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000013703{
13704 dict_list(argvars, rettv, 0);
13705}
13706
13707/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013708 * "last_buffer_nr()" function.
13709 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013710 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013711f_last_buffer_nr(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000013712 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000013713 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013714{
13715 int n = 0;
13716 buf_T *buf;
13717
13718 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
13719 if (n < buf->b_fnum)
13720 n = buf->b_fnum;
13721
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013722 rettv->vval.v_number = n;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013723}
13724
13725/*
13726 * "len()" function
13727 */
13728 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013729f_len(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013730 typval_T *argvars;
13731 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013732{
13733 switch (argvars[0].v_type)
13734 {
13735 case VAR_STRING:
13736 case VAR_NUMBER:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013737 rettv->vval.v_number = (varnumber_T)STRLEN(
13738 get_tv_string(&argvars[0]));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013739 break;
13740 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013741 rettv->vval.v_number = list_len(argvars[0].vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013742 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +000013743 case VAR_DICT:
13744 rettv->vval.v_number = dict_len(argvars[0].vval.v_dict);
13745 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013746 default:
Bram Moolenaare49b69a2005-01-08 16:11:57 +000013747 EMSG(_("E701: Invalid type for len()"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013748 break;
13749 }
13750}
13751
Bram Moolenaar33570922005-01-25 22:26:29 +000013752static void libcall_common __ARGS((typval_T *argvars, typval_T *rettv, int type));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013753
13754 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013755libcall_common(argvars, rettv, type)
Bram Moolenaar33570922005-01-25 22:26:29 +000013756 typval_T *argvars;
13757 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013758 int type;
13759{
13760#ifdef FEAT_LIBCALL
13761 char_u *string_in;
13762 char_u **string_result;
13763 int nr_result;
13764#endif
13765
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013766 rettv->v_type = type;
Bram Moolenaar798b30b2009-04-22 10:56:16 +000013767 if (type != VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013768 rettv->vval.v_string = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013769
13770 if (check_restricted() || check_secure())
13771 return;
13772
13773#ifdef FEAT_LIBCALL
13774 /* The first two args must be strings, otherwise its meaningless */
13775 if (argvars[0].v_type == VAR_STRING && argvars[1].v_type == VAR_STRING)
13776 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000013777 string_in = NULL;
13778 if (argvars[2].v_type == VAR_STRING)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013779 string_in = argvars[2].vval.v_string;
13780 if (type == VAR_NUMBER)
13781 string_result = NULL;
13782 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013783 string_result = &rettv->vval.v_string;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013784 if (mch_libcall(argvars[0].vval.v_string,
13785 argvars[1].vval.v_string,
13786 string_in,
13787 argvars[2].vval.v_number,
13788 string_result,
13789 &nr_result) == OK
13790 && type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013791 rettv->vval.v_number = nr_result;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013792 }
13793#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000013794}
13795
13796/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000013797 * "libcall()" function
13798 */
13799 static void
13800f_libcall(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013801 typval_T *argvars;
13802 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013803{
13804 libcall_common(argvars, rettv, VAR_STRING);
13805}
13806
13807/*
13808 * "libcallnr()" function
13809 */
13810 static void
13811f_libcallnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013812 typval_T *argvars;
13813 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013814{
13815 libcall_common(argvars, rettv, VAR_NUMBER);
13816}
13817
13818/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013819 * "line(string)" function
13820 */
13821 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013822f_line(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013823 typval_T *argvars;
13824 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013825{
13826 linenr_T lnum = 0;
13827 pos_T *fp;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000013828 int fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013829
Bram Moolenaar0e34f622006-03-03 23:00:03 +000013830 fp = var2fpos(&argvars[0], TRUE, &fnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013831 if (fp != NULL)
13832 lnum = fp->lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013833 rettv->vval.v_number = lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013834}
13835
13836/*
13837 * "line2byte(lnum)" function
13838 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013839 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013840f_line2byte(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000013841 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000013842 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013843{
13844#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013845 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013846#else
13847 linenr_T lnum;
13848
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013849 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013850 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013851 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013852 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013853 rettv->vval.v_number = ml_find_line_or_offset(curbuf, lnum, NULL);
13854 if (rettv->vval.v_number >= 0)
13855 ++rettv->vval.v_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013856#endif
13857}
13858
13859/*
13860 * "lispindent(lnum)" function
13861 */
13862 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013863f_lispindent(argvars, rettv)
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +010013864 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000013865 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013866{
13867#ifdef FEAT_LISP
13868 pos_T pos;
13869 linenr_T lnum;
13870
13871 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013872 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013873 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
13874 {
13875 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013876 rettv->vval.v_number = get_lisp_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +000013877 curwin->w_cursor = pos;
13878 }
13879 else
13880#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013881 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013882}
13883
13884/*
13885 * "localtime()" function
13886 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013887 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013888f_localtime(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000013889 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000013890 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013891{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013892 rettv->vval.v_number = (varnumber_T)time(NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013893}
13894
Bram Moolenaar33570922005-01-25 22:26:29 +000013895static void get_maparg __ARGS((typval_T *argvars, typval_T *rettv, int exact));
Bram Moolenaar071d4272004-06-13 20:20:40 +000013896
13897 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013898get_maparg(argvars, rettv, exact)
Bram Moolenaar33570922005-01-25 22:26:29 +000013899 typval_T *argvars;
13900 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013901 int exact;
13902{
13903 char_u *keys;
13904 char_u *which;
13905 char_u buf[NUMBUFLEN];
13906 char_u *keys_buf = NULL;
13907 char_u *rhs;
13908 int mode;
Bram Moolenaar2c932302006-03-18 21:42:09 +000013909 int abbr = FALSE;
Bram Moolenaar3fe37d62012-02-06 00:13:22 +010013910 int get_dict = FALSE;
Bram Moolenaarbd743252010-10-20 21:23:33 +020013911 mapblock_T *mp;
13912 int buffer_local;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013913
13914 /* return empty string for failure */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013915 rettv->v_type = VAR_STRING;
13916 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013917
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013918 keys = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013919 if (*keys == NUL)
13920 return;
13921
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013922 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar2c932302006-03-18 21:42:09 +000013923 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013924 which = get_tv_string_buf_chk(&argvars[1], buf);
Bram Moolenaar2c932302006-03-18 21:42:09 +000013925 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarbd743252010-10-20 21:23:33 +020013926 {
Bram Moolenaar2c932302006-03-18 21:42:09 +000013927 abbr = get_tv_number(&argvars[2]);
Bram Moolenaarbd743252010-10-20 21:23:33 +020013928 if (argvars[3].v_type != VAR_UNKNOWN)
13929 get_dict = get_tv_number(&argvars[3]);
13930 }
Bram Moolenaar2c932302006-03-18 21:42:09 +000013931 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013932 else
13933 which = (char_u *)"";
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013934 if (which == NULL)
13935 return;
13936
Bram Moolenaar071d4272004-06-13 20:20:40 +000013937 mode = get_map_mode(&which, 0);
13938
Bram Moolenaar3fb9eda2006-05-03 21:29:58 +000013939 keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, FALSE);
Bram Moolenaarbd743252010-10-20 21:23:33 +020013940 rhs = check_map(keys, mode, exact, FALSE, abbr, &mp, &buffer_local);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013941 vim_free(keys_buf);
Bram Moolenaarbd743252010-10-20 21:23:33 +020013942
13943 if (!get_dict)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013944 {
Bram Moolenaarbd743252010-10-20 21:23:33 +020013945 /* Return a string. */
13946 if (rhs != NULL)
13947 rettv->vval.v_string = str2special_save(rhs, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013948
Bram Moolenaarbd743252010-10-20 21:23:33 +020013949 }
13950 else if (rettv_dict_alloc(rettv) != FAIL && rhs != NULL)
13951 {
13952 /* Return a dictionary. */
13953 char_u *lhs = str2special_save(mp->m_keys, TRUE);
13954 char_u *mapmode = map_mode_to_chars(mp->m_mode);
13955 dict_T *dict = rettv->vval.v_dict;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013956
Bram Moolenaarbd743252010-10-20 21:23:33 +020013957 dict_add_nr_str(dict, "lhs", 0L, lhs);
13958 dict_add_nr_str(dict, "rhs", 0L, mp->m_orig_str);
13959 dict_add_nr_str(dict, "noremap", mp->m_noremap ? 1L : 0L , NULL);
13960 dict_add_nr_str(dict, "expr", mp->m_expr ? 1L : 0L, NULL);
13961 dict_add_nr_str(dict, "silent", mp->m_silent ? 1L : 0L, NULL);
13962 dict_add_nr_str(dict, "sid", (long)mp->m_script_ID, NULL);
13963 dict_add_nr_str(dict, "buffer", (long)buffer_local, NULL);
Bram Moolenaar72179e12013-06-29 13:58:31 +020013964 dict_add_nr_str(dict, "nowait", mp->m_nowait ? 1L : 0L, NULL);
Bram Moolenaarbd743252010-10-20 21:23:33 +020013965 dict_add_nr_str(dict, "mode", 0L, mapmode);
13966
13967 vim_free(lhs);
13968 vim_free(mapmode);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013969 }
13970}
13971
Bram Moolenaar8c8de832008-06-24 22:58:06 +000013972#ifdef FEAT_FLOAT
13973/*
Bram Moolenaardb7c6862010-05-21 16:33:48 +020013974 * "log()" function
13975 */
13976 static void
13977f_log(argvars, rettv)
13978 typval_T *argvars;
13979 typval_T *rettv;
13980{
13981 float_T f;
13982
13983 rettv->v_type = VAR_FLOAT;
13984 if (get_float_arg(argvars, &f) == OK)
13985 rettv->vval.v_float = log(f);
13986 else
13987 rettv->vval.v_float = 0.0;
13988}
13989
13990/*
Bram Moolenaar8c8de832008-06-24 22:58:06 +000013991 * "log10()" function
13992 */
13993 static void
13994f_log10(argvars, rettv)
13995 typval_T *argvars;
13996 typval_T *rettv;
13997{
13998 float_T f;
13999
14000 rettv->v_type = VAR_FLOAT;
14001 if (get_float_arg(argvars, &f) == OK)
14002 rettv->vval.v_float = log10(f);
14003 else
14004 rettv->vval.v_float = 0.0;
14005}
14006#endif
14007
Bram Moolenaar1dced572012-04-05 16:54:08 +020014008#ifdef FEAT_LUA
14009/*
14010 * "luaeval()" function
14011 */
14012 static void
14013f_luaeval(argvars, rettv)
14014 typval_T *argvars;
14015 typval_T *rettv;
14016{
14017 char_u *str;
14018 char_u buf[NUMBUFLEN];
14019
14020 str = get_tv_string_buf(&argvars[0], buf);
14021 do_luaeval(str, argvars + 1, rettv);
14022}
14023#endif
14024
Bram Moolenaar071d4272004-06-13 20:20:40 +000014025/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014026 * "map()" function
14027 */
14028 static void
14029f_map(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014030 typval_T *argvars;
14031 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014032{
14033 filter_map(argvars, rettv, TRUE);
14034}
14035
14036/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000014037 * "maparg()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000014038 */
14039 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000014040f_maparg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014041 typval_T *argvars;
14042 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014043{
Bram Moolenaar0d660222005-01-07 21:51:51 +000014044 get_maparg(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014045}
14046
14047/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000014048 * "mapcheck()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000014049 */
14050 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000014051f_mapcheck(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014052 typval_T *argvars;
14053 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014054{
Bram Moolenaar0d660222005-01-07 21:51:51 +000014055 get_maparg(argvars, rettv, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014056}
14057
Bram Moolenaar33570922005-01-25 22:26:29 +000014058static void find_some_match __ARGS((typval_T *argvars, typval_T *rettv, int start));
Bram Moolenaar071d4272004-06-13 20:20:40 +000014059
14060 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014061find_some_match(argvars, rettv, type)
Bram Moolenaar33570922005-01-25 22:26:29 +000014062 typval_T *argvars;
14063 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014064 int type;
14065{
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014066 char_u *str = NULL;
Bram Moolenaar9feaf622014-02-22 22:18:47 +010014067 long len = 0;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014068 char_u *expr = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014069 char_u *pat;
14070 regmatch_T regmatch;
14071 char_u patbuf[NUMBUFLEN];
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014072 char_u strbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000014073 char_u *save_cpo;
14074 long start = 0;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000014075 long nth = 1;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000014076 colnr_T startcol = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014077 int match = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000014078 list_T *l = NULL;
14079 listitem_T *li = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014080 long idx = 0;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014081 char_u *tofree = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014082
14083 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
14084 save_cpo = p_cpo;
14085 p_cpo = (char_u *)"";
14086
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014087 rettv->vval.v_number = -1;
14088 if (type == 3)
14089 {
14090 /* return empty list when there are no matches */
Bram Moolenaareddf53b2006-02-27 00:11:10 +000014091 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014092 goto theend;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014093 }
14094 else if (type == 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014095 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014096 rettv->v_type = VAR_STRING;
14097 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014098 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014099
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014100 if (argvars[0].v_type == VAR_LIST)
14101 {
14102 if ((l = argvars[0].vval.v_list) == NULL)
14103 goto theend;
14104 li = l->lv_first;
14105 }
14106 else
Bram Moolenaar9feaf622014-02-22 22:18:47 +010014107 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014108 expr = str = get_tv_string(&argvars[0]);
Bram Moolenaar9feaf622014-02-22 22:18:47 +010014109 len = (long)STRLEN(str);
14110 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014111
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014112 pat = get_tv_string_buf_chk(&argvars[1], patbuf);
14113 if (pat == NULL)
14114 goto theend;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014115
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014116 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014117 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014118 int error = FALSE;
14119
14120 start = get_tv_number_chk(&argvars[2], &error);
14121 if (error)
14122 goto theend;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014123 if (l != NULL)
14124 {
14125 li = list_find(l, start);
14126 if (li == NULL)
14127 goto theend;
Bram Moolenaar758711c2005-02-02 23:11:38 +000014128 idx = l->lv_idx; /* use the cached index */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014129 }
14130 else
14131 {
14132 if (start < 0)
14133 start = 0;
Bram Moolenaar9feaf622014-02-22 22:18:47 +010014134 if (start > len)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014135 goto theend;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000014136 /* When "count" argument is there ignore matches before "start",
14137 * otherwise skip part of the string. Differs when pattern is "^"
14138 * or "\<". */
14139 if (argvars[3].v_type != VAR_UNKNOWN)
14140 startcol = start;
14141 else
Bram Moolenaar9feaf622014-02-22 22:18:47 +010014142 {
Bram Moolenaar0e34f622006-03-03 23:00:03 +000014143 str += start;
Bram Moolenaar9feaf622014-02-22 22:18:47 +010014144 len -= start;
14145 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014146 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000014147
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014148 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014149 nth = get_tv_number_chk(&argvars[3], &error);
14150 if (error)
14151 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014152 }
14153
14154 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
14155 if (regmatch.regprog != NULL)
14156 {
14157 regmatch.rm_ic = p_ic;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000014158
Bram Moolenaard8e9bb22005-07-09 21:14:46 +000014159 for (;;)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000014160 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014161 if (l != NULL)
14162 {
14163 if (li == NULL)
14164 {
14165 match = FALSE;
14166 break;
14167 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014168 vim_free(tofree);
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000014169 str = echo_string(&li->li_tv, &tofree, strbuf, 0);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014170 if (str == NULL)
14171 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014172 }
14173
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000014174 match = vim_regexec_nl(&regmatch, str, (colnr_T)startcol);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014175
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014176 if (match && --nth <= 0)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000014177 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014178 if (l == NULL && !match)
14179 break;
14180
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000014181 /* Advance to just after the match. */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014182 if (l != NULL)
14183 {
14184 li = li->li_next;
14185 ++idx;
14186 }
14187 else
14188 {
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000014189#ifdef FEAT_MBYTE
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000014190 startcol = (colnr_T)(regmatch.startp[0]
14191 + (*mb_ptr2len)(regmatch.startp[0]) - str);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000014192#else
Bram Moolenaar8765a4a2010-07-27 22:41:43 +020014193 startcol = (colnr_T)(regmatch.startp[0] + 1 - str);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000014194#endif
Bram Moolenaar9feaf622014-02-22 22:18:47 +010014195 if (startcol > (colnr_T)len
14196 || str + startcol <= regmatch.startp[0])
14197 {
14198 match = FALSE;
14199 break;
14200 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014201 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000014202 }
14203
14204 if (match)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014205 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014206 if (type == 3)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014207 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014208 int i;
14209
14210 /* return list with matched string and submatches */
14211 for (i = 0; i < NSUBEXP; ++i)
14212 {
14213 if (regmatch.endp[i] == NULL)
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000014214 {
14215 if (list_append_string(rettv->vval.v_list,
14216 (char_u *)"", 0) == FAIL)
14217 break;
14218 }
14219 else if (list_append_string(rettv->vval.v_list,
Bram Moolenaar4463f292005-09-25 22:20:24 +000014220 regmatch.startp[i],
14221 (int)(regmatch.endp[i] - regmatch.startp[i]))
14222 == FAIL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014223 break;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014224 }
14225 }
14226 else if (type == 2)
14227 {
14228 /* return matched string */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014229 if (l != NULL)
14230 copy_tv(&li->li_tv, rettv);
14231 else
14232 rettv->vval.v_string = vim_strnsave(regmatch.startp[0],
Bram Moolenaar071d4272004-06-13 20:20:40 +000014233 (int)(regmatch.endp[0] - regmatch.startp[0]));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014234 }
14235 else if (l != NULL)
14236 rettv->vval.v_number = idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014237 else
14238 {
14239 if (type != 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014240 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +000014241 (varnumber_T)(regmatch.startp[0] - str);
14242 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014243 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +000014244 (varnumber_T)(regmatch.endp[0] - str);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000014245 rettv->vval.v_number += (varnumber_T)(str - expr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014246 }
14247 }
Bram Moolenaar473de612013-06-08 18:19:48 +020014248 vim_regfree(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014249 }
14250
14251theend:
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014252 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014253 p_cpo = save_cpo;
14254}
14255
14256/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000014257 * "match()" function
14258 */
14259 static void
14260f_match(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014261 typval_T *argvars;
14262 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014263{
14264 find_some_match(argvars, rettv, 1);
14265}
14266
14267/*
Bram Moolenaar6ee10162007-07-26 20:58:42 +000014268 * "matchadd()" function
14269 */
14270 static void
14271f_matchadd(argvars, rettv)
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +010014272 typval_T *argvars UNUSED;
14273 typval_T *rettv UNUSED;
Bram Moolenaar6ee10162007-07-26 20:58:42 +000014274{
14275#ifdef FEAT_SEARCH_EXTRA
14276 char_u buf[NUMBUFLEN];
14277 char_u *grp = get_tv_string_buf_chk(&argvars[0], buf); /* group */
14278 char_u *pat = get_tv_string_buf_chk(&argvars[1], buf); /* pattern */
14279 int prio = 10; /* default priority */
14280 int id = -1;
14281 int error = FALSE;
14282
14283 rettv->vval.v_number = -1;
14284
14285 if (grp == NULL || pat == NULL)
14286 return;
14287 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar2240aeb2007-07-27 19:33:14 +000014288 {
Bram Moolenaar6ee10162007-07-26 20:58:42 +000014289 prio = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaar2240aeb2007-07-27 19:33:14 +000014290 if (argvars[3].v_type != VAR_UNKNOWN)
14291 id = get_tv_number_chk(&argvars[3], &error);
14292 }
Bram Moolenaar6ee10162007-07-26 20:58:42 +000014293 if (error == TRUE)
14294 return;
14295 if (id >= 1 && id <= 3)
14296 {
14297 EMSGN("E798: ID is reserved for \":match\": %ld", id);
14298 return;
14299 }
14300
14301 rettv->vval.v_number = match_add(curwin, grp, pat, prio, id);
14302#endif
14303}
14304
14305/*
Bram Moolenaar910f66f2006-04-05 20:41:53 +000014306 * "matcharg()" function
14307 */
14308 static void
14309f_matcharg(argvars, rettv)
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +010014310 typval_T *argvars UNUSED;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000014311 typval_T *rettv;
14312{
14313 if (rettv_list_alloc(rettv) == OK)
14314 {
14315#ifdef FEAT_SEARCH_EXTRA
Bram Moolenaar6ee10162007-07-26 20:58:42 +000014316 int id = get_tv_number(&argvars[0]);
14317 matchitem_T *m;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000014318
Bram Moolenaar6ee10162007-07-26 20:58:42 +000014319 if (id >= 1 && id <= 3)
Bram Moolenaar910f66f2006-04-05 20:41:53 +000014320 {
Bram Moolenaar6ee10162007-07-26 20:58:42 +000014321 if ((m = (matchitem_T *)get_match(curwin, id)) != NULL)
14322 {
14323 list_append_string(rettv->vval.v_list,
14324 syn_id2name(m->hlg_id), -1);
14325 list_append_string(rettv->vval.v_list, m->pattern, -1);
14326 }
14327 else
14328 {
Bram Moolenaar5f4c8402014-01-06 06:19:11 +010014329 list_append_string(rettv->vval.v_list, NULL, -1);
14330 list_append_string(rettv->vval.v_list, NULL, -1);
Bram Moolenaar6ee10162007-07-26 20:58:42 +000014331 }
Bram Moolenaar910f66f2006-04-05 20:41:53 +000014332 }
14333#endif
14334 }
14335}
14336
14337/*
Bram Moolenaar6ee10162007-07-26 20:58:42 +000014338 * "matchdelete()" function
14339 */
14340 static void
14341f_matchdelete(argvars, rettv)
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +010014342 typval_T *argvars UNUSED;
14343 typval_T *rettv UNUSED;
Bram Moolenaar6ee10162007-07-26 20:58:42 +000014344{
14345#ifdef FEAT_SEARCH_EXTRA
14346 rettv->vval.v_number = match_delete(curwin,
14347 (int)get_tv_number(&argvars[0]), TRUE);
14348#endif
14349}
14350
14351/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000014352 * "matchend()" function
14353 */
14354 static void
14355f_matchend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014356 typval_T *argvars;
14357 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014358{
14359 find_some_match(argvars, rettv, 0);
14360}
14361
14362/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014363 * "matchlist()" function
14364 */
14365 static void
14366f_matchlist(argvars, rettv)
14367 typval_T *argvars;
14368 typval_T *rettv;
14369{
14370 find_some_match(argvars, rettv, 3);
14371}
14372
14373/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000014374 * "matchstr()" function
14375 */
14376 static void
14377f_matchstr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014378 typval_T *argvars;
14379 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014380{
14381 find_some_match(argvars, rettv, 2);
14382}
14383
Bram Moolenaar33570922005-01-25 22:26:29 +000014384static void max_min __ARGS((typval_T *argvars, typval_T *rettv, int domax));
Bram Moolenaar6cc16192005-01-08 21:49:45 +000014385
14386 static void
14387max_min(argvars, rettv, domax)
Bram Moolenaar33570922005-01-25 22:26:29 +000014388 typval_T *argvars;
14389 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000014390 int domax;
14391{
Bram Moolenaar6cc16192005-01-08 21:49:45 +000014392 long n = 0;
14393 long i;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014394 int error = FALSE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000014395
14396 if (argvars[0].v_type == VAR_LIST)
14397 {
Bram Moolenaar33570922005-01-25 22:26:29 +000014398 list_T *l;
14399 listitem_T *li;
Bram Moolenaare9a41262005-01-15 22:18:47 +000014400
Bram Moolenaar6cc16192005-01-08 21:49:45 +000014401 l = argvars[0].vval.v_list;
14402 if (l != NULL)
14403 {
14404 li = l->lv_first;
14405 if (li != NULL)
14406 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014407 n = get_tv_number_chk(&li->li_tv, &error);
Bram Moolenaard8e9bb22005-07-09 21:14:46 +000014408 for (;;)
Bram Moolenaar6cc16192005-01-08 21:49:45 +000014409 {
14410 li = li->li_next;
14411 if (li == NULL)
14412 break;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014413 i = get_tv_number_chk(&li->li_tv, &error);
Bram Moolenaar6cc16192005-01-08 21:49:45 +000014414 if (domax ? i > n : i < n)
14415 n = i;
14416 }
14417 }
14418 }
14419 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000014420 else if (argvars[0].v_type == VAR_DICT)
14421 {
Bram Moolenaar33570922005-01-25 22:26:29 +000014422 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000014423 int first = TRUE;
Bram Moolenaar33570922005-01-25 22:26:29 +000014424 hashitem_T *hi;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000014425 int todo;
Bram Moolenaare9a41262005-01-15 22:18:47 +000014426
14427 d = argvars[0].vval.v_dict;
14428 if (d != NULL)
14429 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000014430 todo = (int)d->dv_hashtab.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +000014431 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaare9a41262005-01-15 22:18:47 +000014432 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000014433 if (!HASHITEM_EMPTY(hi))
Bram Moolenaare9a41262005-01-15 22:18:47 +000014434 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000014435 --todo;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014436 i = get_tv_number_chk(&HI2DI(hi)->di_tv, &error);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000014437 if (first)
14438 {
14439 n = i;
14440 first = FALSE;
14441 }
14442 else if (domax ? i > n : i < n)
Bram Moolenaare9a41262005-01-15 22:18:47 +000014443 n = i;
14444 }
14445 }
14446 }
14447 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +000014448 else
Bram Moolenaar758711c2005-02-02 23:11:38 +000014449 EMSG(_(e_listdictarg));
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014450 rettv->vval.v_number = error ? 0 : n;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000014451}
14452
14453/*
14454 * "max()" function
14455 */
14456 static void
14457f_max(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014458 typval_T *argvars;
14459 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000014460{
14461 max_min(argvars, rettv, TRUE);
14462}
14463
14464/*
14465 * "min()" function
14466 */
14467 static void
14468f_min(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014469 typval_T *argvars;
14470 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000014471{
14472 max_min(argvars, rettv, FALSE);
14473}
14474
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000014475static int mkdir_recurse __ARGS((char_u *dir, int prot));
14476
14477/*
14478 * Create the directory in which "dir" is located, and higher levels when
14479 * needed.
14480 */
14481 static int
14482mkdir_recurse(dir, prot)
14483 char_u *dir;
14484 int prot;
14485{
14486 char_u *p;
14487 char_u *updir;
14488 int r = FAIL;
14489
14490 /* Get end of directory name in "dir".
14491 * We're done when it's "/" or "c:/". */
14492 p = gettail_sep(dir);
14493 if (p <= get_past_head(dir))
14494 return OK;
14495
14496 /* If the directory exists we're done. Otherwise: create it.*/
14497 updir = vim_strnsave(dir, (int)(p - dir));
14498 if (updir == NULL)
14499 return FAIL;
14500 if (mch_isdir(updir))
14501 r = OK;
14502 else if (mkdir_recurse(updir, prot) == OK)
14503 r = vim_mkdir_emsg(updir, prot);
14504 vim_free(updir);
14505 return r;
14506}
14507
14508#ifdef vim_mkdir
14509/*
14510 * "mkdir()" function
14511 */
14512 static void
14513f_mkdir(argvars, rettv)
14514 typval_T *argvars;
14515 typval_T *rettv;
14516{
14517 char_u *dir;
14518 char_u buf[NUMBUFLEN];
14519 int prot = 0755;
14520
14521 rettv->vval.v_number = FAIL;
14522 if (check_restricted() || check_secure())
14523 return;
14524
14525 dir = get_tv_string_buf(&argvars[0], buf);
Bram Moolenaar195ef0c2013-08-30 16:00:08 +020014526 if (*dir == NUL)
14527 rettv->vval.v_number = FAIL;
14528 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000014529 {
Bram Moolenaar195ef0c2013-08-30 16:00:08 +020014530 if (*gettail(dir) == NUL)
14531 /* remove trailing slashes */
14532 *gettail_sep(dir) = NUL;
14533
14534 if (argvars[1].v_type != VAR_UNKNOWN)
14535 {
14536 if (argvars[2].v_type != VAR_UNKNOWN)
14537 prot = get_tv_number_chk(&argvars[2], NULL);
14538 if (prot != -1 && STRCMP(get_tv_string(&argvars[1]), "p") == 0)
14539 mkdir_recurse(dir, prot);
14540 }
14541 rettv->vval.v_number = prot == -1 ? FAIL : vim_mkdir_emsg(dir, prot);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000014542 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000014543}
14544#endif
14545
Bram Moolenaar0d660222005-01-07 21:51:51 +000014546/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014547 * "mode()" function
14548 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014549 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014550f_mode(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014551 typval_T *argvars;
14552 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014553{
Bram Moolenaar8c8de832008-06-24 22:58:06 +000014554 char_u buf[3];
14555
14556 buf[1] = NUL;
14557 buf[2] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014558
Bram Moolenaar071d4272004-06-13 20:20:40 +000014559 if (VIsual_active)
14560 {
14561 if (VIsual_select)
14562 buf[0] = VIsual_mode + 's' - 'v';
14563 else
14564 buf[0] = VIsual_mode;
14565 }
Bram Moolenaarf7ff6e82014-03-23 15:13:05 +010014566 else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE
Bram Moolenaar8c8de832008-06-24 22:58:06 +000014567 || State == CONFIRM)
14568 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000014569 buf[0] = 'r';
Bram Moolenaar8c8de832008-06-24 22:58:06 +000014570 if (State == ASKMORE)
14571 buf[1] = 'm';
14572 else if (State == CONFIRM)
14573 buf[1] = '?';
14574 }
14575 else if (State == EXTERNCMD)
14576 buf[0] = '!';
Bram Moolenaar071d4272004-06-13 20:20:40 +000014577 else if (State & INSERT)
14578 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +000014579#ifdef FEAT_VREPLACE
14580 if (State & VREPLACE_FLAG)
14581 {
14582 buf[0] = 'R';
14583 buf[1] = 'v';
14584 }
14585 else
14586#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000014587 if (State & REPLACE_FLAG)
14588 buf[0] = 'R';
14589 else
14590 buf[0] = 'i';
14591 }
14592 else if (State & CMDLINE)
Bram Moolenaar8c8de832008-06-24 22:58:06 +000014593 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000014594 buf[0] = 'c';
Bram Moolenaar8c8de832008-06-24 22:58:06 +000014595 if (exmode_active)
14596 buf[1] = 'v';
14597 }
14598 else if (exmode_active)
14599 {
14600 buf[0] = 'c';
14601 buf[1] = 'e';
14602 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014603 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +000014604 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000014605 buf[0] = 'n';
Bram Moolenaar8c8de832008-06-24 22:58:06 +000014606 if (finish_op)
14607 buf[1] = 'o';
14608 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014609
Bram Moolenaar05bb9532008-07-04 09:44:11 +000014610 /* Clear out the minor mode when the argument is not a non-zero number or
14611 * non-empty string. */
14612 if (!non_zero_arg(&argvars[0]))
Bram Moolenaar8c8de832008-06-24 22:58:06 +000014613 buf[1] = NUL;
14614
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014615 rettv->vval.v_string = vim_strsave(buf);
14616 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014617}
14618
Bram Moolenaar429fa852013-04-15 12:27:36 +020014619#if defined(FEAT_MZSCHEME) || defined(PROTO)
Bram Moolenaar7e506b62010-01-19 15:55:06 +010014620/*
14621 * "mzeval()" function
14622 */
14623 static void
14624f_mzeval(argvars, rettv)
14625 typval_T *argvars;
14626 typval_T *rettv;
14627{
14628 char_u *str;
14629 char_u buf[NUMBUFLEN];
14630
14631 str = get_tv_string_buf(&argvars[0], buf);
14632 do_mzeval(str, rettv);
14633}
Bram Moolenaar75676462013-01-30 14:55:42 +010014634
14635 void
14636mzscheme_call_vim(name, args, rettv)
14637 char_u *name;
14638 typval_T *args;
14639 typval_T *rettv;
14640{
14641 typval_T argvars[3];
14642
14643 argvars[0].v_type = VAR_STRING;
14644 argvars[0].vval.v_string = name;
14645 copy_tv(args, &argvars[1]);
14646 argvars[2].v_type = VAR_UNKNOWN;
14647 f_call(argvars, rettv);
14648 clear_tv(&argvars[1]);
14649}
Bram Moolenaar7e506b62010-01-19 15:55:06 +010014650#endif
14651
Bram Moolenaar071d4272004-06-13 20:20:40 +000014652/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000014653 * "nextnonblank()" function
14654 */
14655 static void
14656f_nextnonblank(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014657 typval_T *argvars;
14658 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014659{
14660 linenr_T lnum;
14661
14662 for (lnum = get_tv_lnum(argvars); ; ++lnum)
14663 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014664 if (lnum < 0 || lnum > curbuf->b_ml.ml_line_count)
Bram Moolenaar0d660222005-01-07 21:51:51 +000014665 {
14666 lnum = 0;
14667 break;
14668 }
14669 if (*skipwhite(ml_get(lnum)) != NUL)
14670 break;
14671 }
14672 rettv->vval.v_number = lnum;
14673}
14674
14675/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014676 * "nr2char()" function
14677 */
14678 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014679f_nr2char(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014680 typval_T *argvars;
14681 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014682{
14683 char_u buf[NUMBUFLEN];
14684
14685#ifdef FEAT_MBYTE
14686 if (has_mbyte)
Bram Moolenaard35d7842013-01-23 17:17:10 +010014687 {
14688 int utf8 = 0;
14689
14690 if (argvars[1].v_type != VAR_UNKNOWN)
14691 utf8 = get_tv_number_chk(&argvars[1], NULL);
14692 if (utf8)
14693 buf[(*utf_char2bytes)((int)get_tv_number(&argvars[0]), buf)] = NUL;
14694 else
14695 buf[(*mb_char2bytes)((int)get_tv_number(&argvars[0]), buf)] = NUL;
14696 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014697 else
14698#endif
14699 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014700 buf[0] = (char_u)get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014701 buf[1] = NUL;
14702 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014703 rettv->v_type = VAR_STRING;
14704 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014705}
14706
14707/*
Bram Moolenaard6e256c2011-12-14 15:32:50 +010014708 * "or(expr, expr)" function
14709 */
14710 static void
14711f_or(argvars, rettv)
14712 typval_T *argvars;
14713 typval_T *rettv;
14714{
14715 rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL)
14716 | get_tv_number_chk(&argvars[1], NULL);
14717}
14718
14719/*
Bram Moolenaar910f66f2006-04-05 20:41:53 +000014720 * "pathshorten()" function
14721 */
14722 static void
14723f_pathshorten(argvars, rettv)
14724 typval_T *argvars;
14725 typval_T *rettv;
14726{
14727 char_u *p;
14728
14729 rettv->v_type = VAR_STRING;
14730 p = get_tv_string_chk(&argvars[0]);
14731 if (p == NULL)
14732 rettv->vval.v_string = NULL;
14733 else
14734 {
14735 p = vim_strsave(p);
14736 rettv->vval.v_string = p;
14737 if (p != NULL)
14738 shorten_dir(p);
14739 }
14740}
14741
Bram Moolenaar8c8de832008-06-24 22:58:06 +000014742#ifdef FEAT_FLOAT
14743/*
14744 * "pow()" function
14745 */
14746 static void
14747f_pow(argvars, rettv)
14748 typval_T *argvars;
14749 typval_T *rettv;
14750{
14751 float_T fx, fy;
14752
14753 rettv->v_type = VAR_FLOAT;
14754 if (get_float_arg(argvars, &fx) == OK
14755 && get_float_arg(&argvars[1], &fy) == OK)
14756 rettv->vval.v_float = pow(fx, fy);
14757 else
14758 rettv->vval.v_float = 0.0;
14759}
14760#endif
14761
Bram Moolenaar910f66f2006-04-05 20:41:53 +000014762/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000014763 * "prevnonblank()" function
14764 */
14765 static void
14766f_prevnonblank(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014767 typval_T *argvars;
14768 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014769{
14770 linenr_T lnum;
14771
14772 lnum = get_tv_lnum(argvars);
14773 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
14774 lnum = 0;
14775 else
14776 while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL)
14777 --lnum;
14778 rettv->vval.v_number = lnum;
14779}
14780
Bram Moolenaara6c840d2005-08-22 22:59:46 +000014781#ifdef HAVE_STDARG_H
14782/* This dummy va_list is here because:
14783 * - passing a NULL pointer doesn't work when va_list isn't a pointer
14784 * - locally in the function results in a "used before set" warning
14785 * - using va_start() to initialize it gives "function with fixed args" error */
14786static va_list ap;
14787#endif
14788
Bram Moolenaar8c711452005-01-14 21:53:12 +000014789/*
Bram Moolenaar4be06f92005-07-29 22:36:03 +000014790 * "printf()" function
14791 */
14792 static void
14793f_printf(argvars, rettv)
14794 typval_T *argvars;
14795 typval_T *rettv;
14796{
14797 rettv->v_type = VAR_STRING;
14798 rettv->vval.v_string = NULL;
Bram Moolenaard52d9742005-08-21 22:20:28 +000014799#ifdef HAVE_STDARG_H /* only very old compilers can't do this */
Bram Moolenaar4be06f92005-07-29 22:36:03 +000014800 {
14801 char_u buf[NUMBUFLEN];
14802 int len;
14803 char_u *s;
14804 int saved_did_emsg = did_emsg;
14805 char *fmt;
14806
14807 /* Get the required length, allocate the buffer and do it for real. */
14808 did_emsg = FALSE;
14809 fmt = (char *)get_tv_string_buf(&argvars[0], buf);
Bram Moolenaar5b8d8fd2005-08-16 23:01:50 +000014810 len = vim_vsnprintf(NULL, 0, fmt, ap, argvars + 1);
Bram Moolenaar4be06f92005-07-29 22:36:03 +000014811 if (!did_emsg)
14812 {
14813 s = alloc(len + 1);
14814 if (s != NULL)
14815 {
14816 rettv->vval.v_string = s;
Bram Moolenaar5b8d8fd2005-08-16 23:01:50 +000014817 (void)vim_vsnprintf((char *)s, len + 1, fmt, ap, argvars + 1);
Bram Moolenaar4be06f92005-07-29 22:36:03 +000014818 }
14819 }
14820 did_emsg |= saved_did_emsg;
14821 }
14822#endif
14823}
14824
14825/*
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000014826 * "pumvisible()" function
14827 */
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000014828 static void
14829f_pumvisible(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000014830 typval_T *argvars UNUSED;
14831 typval_T *rettv UNUSED;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000014832{
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000014833#ifdef FEAT_INS_EXPAND
14834 if (pum_visible())
14835 rettv->vval.v_number = 1;
14836#endif
14837}
14838
Bram Moolenaardb913952012-06-29 12:54:53 +020014839#ifdef FEAT_PYTHON3
14840/*
14841 * "py3eval()" function
14842 */
14843 static void
14844f_py3eval(argvars, rettv)
14845 typval_T *argvars;
14846 typval_T *rettv;
14847{
14848 char_u *str;
14849 char_u buf[NUMBUFLEN];
14850
14851 str = get_tv_string_buf(&argvars[0], buf);
14852 do_py3eval(str, rettv);
14853}
14854#endif
14855
14856#ifdef FEAT_PYTHON
14857/*
14858 * "pyeval()" function
14859 */
14860 static void
14861f_pyeval(argvars, rettv)
14862 typval_T *argvars;
14863 typval_T *rettv;
14864{
14865 char_u *str;
14866 char_u buf[NUMBUFLEN];
14867
14868 str = get_tv_string_buf(&argvars[0], buf);
14869 do_pyeval(str, rettv);
14870}
14871#endif
14872
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000014873/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000014874 * "range()" function
14875 */
14876 static void
14877f_range(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014878 typval_T *argvars;
14879 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000014880{
14881 long start;
14882 long end;
14883 long stride = 1;
14884 long i;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014885 int error = FALSE;
Bram Moolenaar8c711452005-01-14 21:53:12 +000014886
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014887 start = get_tv_number_chk(&argvars[0], &error);
Bram Moolenaar8c711452005-01-14 21:53:12 +000014888 if (argvars[1].v_type == VAR_UNKNOWN)
14889 {
14890 end = start - 1;
14891 start = 0;
14892 }
14893 else
14894 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014895 end = get_tv_number_chk(&argvars[1], &error);
Bram Moolenaar8c711452005-01-14 21:53:12 +000014896 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014897 stride = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaar8c711452005-01-14 21:53:12 +000014898 }
14899
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014900 if (error)
14901 return; /* type error; errmsg already given */
Bram Moolenaar8c711452005-01-14 21:53:12 +000014902 if (stride == 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014903 EMSG(_("E726: Stride is zero"));
Bram Moolenaar92124a32005-06-17 22:03:40 +000014904 else if (stride > 0 ? end + 1 < start : end - 1 > start)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014905 EMSG(_("E727: Start past end"));
Bram Moolenaar8c711452005-01-14 21:53:12 +000014906 else
14907 {
Bram Moolenaareddf53b2006-02-27 00:11:10 +000014908 if (rettv_list_alloc(rettv) == OK)
Bram Moolenaar8c711452005-01-14 21:53:12 +000014909 for (i = start; stride > 0 ? i <= end : i >= end; i += stride)
Bram Moolenaareddf53b2006-02-27 00:11:10 +000014910 if (list_append_number(rettv->vval.v_list,
14911 (varnumber_T)i) == FAIL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000014912 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000014913 }
14914}
14915
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014916/*
14917 * "readfile()" function
14918 */
14919 static void
14920f_readfile(argvars, rettv)
14921 typval_T *argvars;
14922 typval_T *rettv;
14923{
14924 int binary = FALSE;
Bram Moolenaara489e1d2012-02-05 00:39:18 +010014925 int failed = FALSE;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014926 char_u *fname;
14927 FILE *fd;
Bram Moolenaara489e1d2012-02-05 00:39:18 +010014928 char_u buf[(IOSIZE/256)*256]; /* rounded to avoid odd + 1 */
14929 int io_size = sizeof(buf);
14930 int readlen; /* size of last fread() */
14931 char_u *prev = NULL; /* previously read bytes, if any */
14932 long prevlen = 0; /* length of data in prev */
14933 long prevsize = 0; /* size of prev buffer */
14934 long maxline = MAXLNUM;
14935 long cnt = 0;
14936 char_u *p; /* position in buf */
14937 char_u *start; /* start of current line */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014938
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000014939 if (argvars[1].v_type != VAR_UNKNOWN)
14940 {
14941 if (STRCMP(get_tv_string(&argvars[1]), "b") == 0)
14942 binary = TRUE;
14943 if (argvars[2].v_type != VAR_UNKNOWN)
14944 maxline = get_tv_number(&argvars[2]);
14945 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014946
Bram Moolenaareddf53b2006-02-27 00:11:10 +000014947 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014948 return;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014949
14950 /* Always open the file in binary mode, library functions have a mind of
14951 * their own about CR-LF conversion. */
14952 fname = get_tv_string(&argvars[0]);
14953 if (*fname == NUL || (fd = mch_fopen((char *)fname, READBIN)) == NULL)
14954 {
14955 EMSG2(_(e_notopen), *fname == NUL ? (char_u *)_("<empty>") : fname);
14956 return;
14957 }
14958
Bram Moolenaarb982ca52005-03-28 21:02:15 +000014959 while (cnt < maxline || maxline < 0)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014960 {
Bram Moolenaara489e1d2012-02-05 00:39:18 +010014961 readlen = (int)fread(buf, 1, io_size, fd);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014962
Bram Moolenaara489e1d2012-02-05 00:39:18 +010014963 /* This for loop processes what was read, but is also entered at end
14964 * of file so that either:
14965 * - an incomplete line gets written
14966 * - a "binary" file gets an empty line at the end if it ends in a
14967 * newline. */
14968 for (p = buf, start = buf;
14969 p < buf + readlen || (readlen <= 0 && (prevlen > 0 || binary));
14970 ++p)
14971 {
14972 if (*p == '\n' || readlen <= 0)
14973 {
14974 listitem_T *li;
14975 char_u *s = NULL;
14976 long_u len = p - start;
14977
14978 /* Finished a line. Remove CRs before NL. */
14979 if (readlen > 0 && !binary)
14980 {
14981 while (len > 0 && start[len - 1] == '\r')
14982 --len;
14983 /* removal may cross back to the "prev" string */
14984 if (len == 0)
14985 while (prevlen > 0 && prev[prevlen - 1] == '\r')
14986 --prevlen;
14987 }
14988 if (prevlen == 0)
Bram Moolenaar68ba0dd2012-02-11 20:44:10 +010014989 s = vim_strnsave(start, (int)len);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014990 else
14991 {
Bram Moolenaara489e1d2012-02-05 00:39:18 +010014992 /* Change "prev" buffer to be the right size. This way
14993 * the bytes are only copied once, and very long lines are
14994 * allocated only once. */
14995 if ((s = vim_realloc(prev, prevlen + len + 1)) != NULL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014996 {
Bram Moolenaara489e1d2012-02-05 00:39:18 +010014997 mch_memmove(s + prevlen, start, len);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014998 s[prevlen + len] = NUL;
Bram Moolenaara489e1d2012-02-05 00:39:18 +010014999 prev = NULL; /* the list will own the string */
15000 prevlen = prevsize = 0;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015001 }
15002 }
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015003 if (s == NULL)
15004 {
15005 do_outofmem_msg((long_u) prevlen + len + 1);
15006 failed = TRUE;
15007 break;
15008 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015009
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015010 if ((li = listitem_alloc()) == NULL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015011 {
15012 vim_free(s);
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015013 failed = TRUE;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015014 break;
15015 }
15016 li->li_tv.v_type = VAR_STRING;
15017 li->li_tv.v_lock = 0;
15018 li->li_tv.vval.v_string = s;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015019 list_append(rettv->vval.v_list, li);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015020
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015021 start = p + 1; /* step over newline */
15022 if ((++cnt >= maxline && maxline >= 0) || readlen <= 0)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015023 break;
15024 }
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015025 else if (*p == NUL)
15026 *p = '\n';
Bram Moolenaar06583f12010-08-07 20:30:49 +020015027#ifdef FEAT_MBYTE
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015028 /* Check for utf8 "bom"; U+FEFF is encoded as EF BB BF. Do this
15029 * when finding the BF and check the previous two bytes. */
15030 else if (*p == 0xbf && enc_utf8 && !binary)
Bram Moolenaar06583f12010-08-07 20:30:49 +020015031 {
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015032 /* Find the two bytes before the 0xbf. If p is at buf, or buf
15033 * + 1, these may be in the "prev" string. */
15034 char_u back1 = p >= buf + 1 ? p[-1]
15035 : prevlen >= 1 ? prev[prevlen - 1] : NUL;
15036 char_u back2 = p >= buf + 2 ? p[-2]
15037 : p == buf + 1 && prevlen >= 1 ? prev[prevlen - 1]
15038 : prevlen >= 2 ? prev[prevlen - 2] : NUL;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015039
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015040 if (back2 == 0xef && back1 == 0xbb)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015041 {
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015042 char_u *dest = p - 2;
15043
15044 /* Usually a BOM is at the beginning of a file, and so at
15045 * the beginning of a line; then we can just step over it.
15046 */
15047 if (start == dest)
15048 start = p + 1;
15049 else
Bram Moolenaar27b60562011-04-01 16:07:46 +020015050 {
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015051 /* have to shuffle buf to close gap */
15052 int adjust_prevlen = 0;
15053
15054 if (dest < buf)
15055 {
Bram Moolenaar68ba0dd2012-02-11 20:44:10 +010015056 adjust_prevlen = (int)(buf - dest); /* must be 1 or 2 */
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015057 dest = buf;
15058 }
15059 if (readlen > p - buf + 1)
15060 mch_memmove(dest, p + 1, readlen - (p - buf) - 1);
15061 readlen -= 3 - adjust_prevlen;
15062 prevlen -= adjust_prevlen;
15063 p = dest - 1;
Bram Moolenaar27b60562011-04-01 16:07:46 +020015064 }
15065 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015066 }
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015067#endif
15068 } /* for */
15069
15070 if (failed || (cnt >= maxline && maxline >= 0) || readlen <= 0)
15071 break;
15072 if (start < p)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015073 {
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015074 /* There's part of a line in buf, store it in "prev". */
15075 if (p - start + prevlen >= prevsize)
15076 {
15077 /* need bigger "prev" buffer */
15078 char_u *newprev;
15079
15080 /* A common use case is ordinary text files and "prev" gets a
15081 * fragment of a line, so the first allocation is made
15082 * small, to avoid repeatedly 'allocing' large and
15083 * 'reallocing' small. */
15084 if (prevsize == 0)
Bram Moolenaar68ba0dd2012-02-11 20:44:10 +010015085 prevsize = (long)(p - start);
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015086 else
15087 {
15088 long grow50pc = (prevsize * 3) / 2;
Bram Moolenaar68ba0dd2012-02-11 20:44:10 +010015089 long growmin = (long)((p - start) * 2 + prevlen);
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015090 prevsize = grow50pc > growmin ? grow50pc : growmin;
15091 }
Bram Moolenaar455981e2012-05-18 18:34:19 +020015092 newprev = prev == NULL ? alloc(prevsize)
15093 : vim_realloc(prev, prevsize);
15094 if (newprev == NULL)
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015095 {
15096 do_outofmem_msg((long_u)prevsize);
15097 failed = TRUE;
15098 break;
15099 }
15100 prev = newprev;
15101 }
15102 /* Add the line part to end of "prev". */
15103 mch_memmove(prev + prevlen, start, p - start);
Bram Moolenaar68ba0dd2012-02-11 20:44:10 +010015104 prevlen += (long)(p - start);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015105 }
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015106 } /* while */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015107
Bram Moolenaarb982ca52005-03-28 21:02:15 +000015108 /*
15109 * For a negative line count use only the lines at the end of the file,
15110 * free the rest.
15111 */
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015112 if (!failed && maxline < 0)
Bram Moolenaarb982ca52005-03-28 21:02:15 +000015113 while (cnt > -maxline)
15114 {
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015115 listitem_remove(rettv->vval.v_list, rettv->vval.v_list->lv_first);
Bram Moolenaarb982ca52005-03-28 21:02:15 +000015116 --cnt;
15117 }
15118
Bram Moolenaara489e1d2012-02-05 00:39:18 +010015119 if (failed)
15120 {
15121 list_free(rettv->vval.v_list, TRUE);
15122 /* readfile doc says an empty list is returned on error */
15123 rettv->vval.v_list = list_alloc();
15124 }
15125
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015126 vim_free(prev);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015127 fclose(fd);
15128}
15129
Bram Moolenaare580b0c2006-03-21 21:33:03 +000015130#if defined(FEAT_RELTIME)
15131static int list2proftime __ARGS((typval_T *arg, proftime_T *tm));
15132
15133/*
15134 * Convert a List to proftime_T.
15135 * Return FAIL when there is something wrong.
15136 */
15137 static int
15138list2proftime(arg, tm)
15139 typval_T *arg;
15140 proftime_T *tm;
15141{
15142 long n1, n2;
15143 int error = FALSE;
15144
15145 if (arg->v_type != VAR_LIST || arg->vval.v_list == NULL
15146 || arg->vval.v_list->lv_len != 2)
15147 return FAIL;
15148 n1 = list_find_nr(arg->vval.v_list, 0L, &error);
15149 n2 = list_find_nr(arg->vval.v_list, 1L, &error);
15150# ifdef WIN3264
Bram Moolenaardb552d602006-03-23 22:59:57 +000015151 tm->HighPart = n1;
15152 tm->LowPart = n2;
Bram Moolenaare580b0c2006-03-21 21:33:03 +000015153# else
15154 tm->tv_sec = n1;
15155 tm->tv_usec = n2;
15156# endif
15157 return error ? FAIL : OK;
15158}
15159#endif /* FEAT_RELTIME */
15160
15161/*
15162 * "reltime()" function
15163 */
15164 static void
15165f_reltime(argvars, rettv)
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +010015166 typval_T *argvars UNUSED;
15167 typval_T *rettv UNUSED;
Bram Moolenaare580b0c2006-03-21 21:33:03 +000015168{
15169#ifdef FEAT_RELTIME
15170 proftime_T res;
15171 proftime_T start;
15172
15173 if (argvars[0].v_type == VAR_UNKNOWN)
15174 {
15175 /* No arguments: get current time. */
15176 profile_start(&res);
15177 }
15178 else if (argvars[1].v_type == VAR_UNKNOWN)
15179 {
15180 if (list2proftime(&argvars[0], &res) == FAIL)
15181 return;
15182 profile_end(&res);
15183 }
15184 else
15185 {
15186 /* Two arguments: compute the difference. */
15187 if (list2proftime(&argvars[0], &start) == FAIL
15188 || list2proftime(&argvars[1], &res) == FAIL)
15189 return;
15190 profile_sub(&res, &start);
15191 }
15192
15193 if (rettv_list_alloc(rettv) == OK)
15194 {
15195 long n1, n2;
15196
15197# ifdef WIN3264
Bram Moolenaardb552d602006-03-23 22:59:57 +000015198 n1 = res.HighPart;
15199 n2 = res.LowPart;
Bram Moolenaare580b0c2006-03-21 21:33:03 +000015200# else
15201 n1 = res.tv_sec;
15202 n2 = res.tv_usec;
15203# endif
15204 list_append_number(rettv->vval.v_list, (varnumber_T)n1);
15205 list_append_number(rettv->vval.v_list, (varnumber_T)n2);
15206 }
15207#endif
15208}
15209
15210/*
15211 * "reltimestr()" function
15212 */
15213 static void
15214f_reltimestr(argvars, rettv)
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +010015215 typval_T *argvars UNUSED;
Bram Moolenaare580b0c2006-03-21 21:33:03 +000015216 typval_T *rettv;
15217{
15218#ifdef FEAT_RELTIME
15219 proftime_T tm;
15220#endif
15221
15222 rettv->v_type = VAR_STRING;
15223 rettv->vval.v_string = NULL;
15224#ifdef FEAT_RELTIME
15225 if (list2proftime(&argvars[0], &tm) == OK)
15226 rettv->vval.v_string = vim_strsave((char_u *)profile_msg(&tm));
15227#endif
15228}
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015229
Bram Moolenaar0d660222005-01-07 21:51:51 +000015230#if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
15231static void make_connection __ARGS((void));
15232static int check_connection __ARGS((void));
15233
15234 static void
15235make_connection()
15236{
15237 if (X_DISPLAY == NULL
15238# ifdef FEAT_GUI
15239 && !gui.in_use
15240# endif
15241 )
15242 {
15243 x_force_connect = TRUE;
15244 setup_term_clip();
15245 x_force_connect = FALSE;
15246 }
15247}
15248
15249 static int
15250check_connection()
15251{
15252 make_connection();
15253 if (X_DISPLAY == NULL)
15254 {
15255 EMSG(_("E240: No connection to Vim server"));
15256 return FAIL;
15257 }
15258 return OK;
15259}
15260#endif
15261
15262#ifdef FEAT_CLIENTSERVER
Bram Moolenaar33570922005-01-25 22:26:29 +000015263static void remote_common __ARGS((typval_T *argvars, typval_T *rettv, int expr));
Bram Moolenaar0d660222005-01-07 21:51:51 +000015264
15265 static void
15266remote_common(argvars, rettv, expr)
Bram Moolenaar33570922005-01-25 22:26:29 +000015267 typval_T *argvars;
15268 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015269 int expr;
15270{
15271 char_u *server_name;
15272 char_u *keys;
15273 char_u *r = NULL;
15274 char_u buf[NUMBUFLEN];
15275# ifdef WIN32
15276 HWND w;
15277# else
15278 Window w;
15279# endif
15280
15281 if (check_restricted() || check_secure())
15282 return;
15283
15284# ifdef FEAT_X11
15285 if (check_connection() == FAIL)
15286 return;
15287# endif
15288
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015289 server_name = get_tv_string_chk(&argvars[0]);
15290 if (server_name == NULL)
15291 return; /* type error; errmsg already given */
Bram Moolenaar0d660222005-01-07 21:51:51 +000015292 keys = get_tv_string_buf(&argvars[1], buf);
15293# ifdef WIN32
15294 if (serverSendToVim(server_name, keys, &r, &w, expr, TRUE) < 0)
15295# else
15296 if (serverSendToVim(X_DISPLAY, server_name, keys, &r, &w, expr, 0, TRUE)
15297 < 0)
15298# endif
15299 {
15300 if (r != NULL)
15301 EMSG(r); /* sending worked but evaluation failed */
15302 else
15303 EMSG2(_("E241: Unable to send to %s"), server_name);
15304 return;
15305 }
15306
15307 rettv->vval.v_string = r;
15308
15309 if (argvars[2].v_type != VAR_UNKNOWN)
15310 {
Bram Moolenaar33570922005-01-25 22:26:29 +000015311 dictitem_T v;
Bram Moolenaar555b2802005-05-19 21:08:39 +000015312 char_u str[30];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015313 char_u *idvar;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015314
Bram Moolenaareb3593b2006-04-22 22:33:57 +000015315 sprintf((char *)str, PRINTF_HEX_LONG_U, (long_u)w);
Bram Moolenaar33570922005-01-25 22:26:29 +000015316 v.di_tv.v_type = VAR_STRING;
15317 v.di_tv.vval.v_string = vim_strsave(str);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015318 idvar = get_tv_string_chk(&argvars[2]);
15319 if (idvar != NULL)
15320 set_var(idvar, &v.di_tv, FALSE);
Bram Moolenaar33570922005-01-25 22:26:29 +000015321 vim_free(v.di_tv.vval.v_string);
Bram Moolenaar0d660222005-01-07 21:51:51 +000015322 }
15323}
15324#endif
15325
15326/*
15327 * "remote_expr()" function
15328 */
Bram Moolenaar0d660222005-01-07 21:51:51 +000015329 static void
15330f_remote_expr(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000015331 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000015332 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015333{
15334 rettv->v_type = VAR_STRING;
15335 rettv->vval.v_string = NULL;
15336#ifdef FEAT_CLIENTSERVER
15337 remote_common(argvars, rettv, TRUE);
15338#endif
15339}
15340
15341/*
15342 * "remote_foreground()" function
15343 */
Bram Moolenaar0d660222005-01-07 21:51:51 +000015344 static void
15345f_remote_foreground(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000015346 typval_T *argvars UNUSED;
15347 typval_T *rettv UNUSED;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015348{
Bram Moolenaar0d660222005-01-07 21:51:51 +000015349#ifdef FEAT_CLIENTSERVER
15350# ifdef WIN32
15351 /* On Win32 it's done in this application. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015352 {
15353 char_u *server_name = get_tv_string_chk(&argvars[0]);
15354
15355 if (server_name != NULL)
15356 serverForeground(server_name);
15357 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000015358# else
15359 /* Send a foreground() expression to the server. */
15360 argvars[1].v_type = VAR_STRING;
15361 argvars[1].vval.v_string = vim_strsave((char_u *)"foreground()");
15362 argvars[2].v_type = VAR_UNKNOWN;
15363 remote_common(argvars, rettv, TRUE);
15364 vim_free(argvars[1].vval.v_string);
15365# endif
15366#endif
15367}
15368
Bram Moolenaar0d660222005-01-07 21:51:51 +000015369 static void
15370f_remote_peek(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000015371 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000015372 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015373{
15374#ifdef FEAT_CLIENTSERVER
Bram Moolenaar33570922005-01-25 22:26:29 +000015375 dictitem_T v;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015376 char_u *s = NULL;
15377# ifdef WIN32
Bram Moolenaareb3593b2006-04-22 22:33:57 +000015378 long_u n = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015379# endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015380 char_u *serverid;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015381
15382 if (check_restricted() || check_secure())
15383 {
15384 rettv->vval.v_number = -1;
15385 return;
15386 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015387 serverid = get_tv_string_chk(&argvars[0]);
15388 if (serverid == NULL)
15389 {
15390 rettv->vval.v_number = -1;
15391 return; /* type error; errmsg already given */
15392 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000015393# ifdef WIN32
Bram Moolenaareb3593b2006-04-22 22:33:57 +000015394 sscanf(serverid, SCANF_HEX_LONG_U, &n);
Bram Moolenaar0d660222005-01-07 21:51:51 +000015395 if (n == 0)
15396 rettv->vval.v_number = -1;
15397 else
15398 {
15399 s = serverGetReply((HWND)n, FALSE, FALSE, FALSE);
15400 rettv->vval.v_number = (s != NULL);
15401 }
15402# else
Bram Moolenaar0d660222005-01-07 21:51:51 +000015403 if (check_connection() == FAIL)
15404 return;
15405
15406 rettv->vval.v_number = serverPeekReply(X_DISPLAY,
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015407 serverStrToWin(serverid), &s);
Bram Moolenaar0d660222005-01-07 21:51:51 +000015408# endif
15409
15410 if (argvars[1].v_type != VAR_UNKNOWN && rettv->vval.v_number > 0)
15411 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015412 char_u *retvar;
15413
Bram Moolenaar33570922005-01-25 22:26:29 +000015414 v.di_tv.v_type = VAR_STRING;
15415 v.di_tv.vval.v_string = vim_strsave(s);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015416 retvar = get_tv_string_chk(&argvars[1]);
15417 if (retvar != NULL)
15418 set_var(retvar, &v.di_tv, FALSE);
Bram Moolenaar33570922005-01-25 22:26:29 +000015419 vim_free(v.di_tv.vval.v_string);
Bram Moolenaar0d660222005-01-07 21:51:51 +000015420 }
15421#else
15422 rettv->vval.v_number = -1;
15423#endif
15424}
15425
Bram Moolenaar0d660222005-01-07 21:51:51 +000015426 static void
15427f_remote_read(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000015428 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000015429 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015430{
15431 char_u *r = NULL;
15432
15433#ifdef FEAT_CLIENTSERVER
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015434 char_u *serverid = get_tv_string_chk(&argvars[0]);
15435
15436 if (serverid != NULL && !check_restricted() && !check_secure())
Bram Moolenaar0d660222005-01-07 21:51:51 +000015437 {
15438# ifdef WIN32
15439 /* The server's HWND is encoded in the 'id' parameter */
Bram Moolenaareb3593b2006-04-22 22:33:57 +000015440 long_u n = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015441
Bram Moolenaareb3593b2006-04-22 22:33:57 +000015442 sscanf(serverid, SCANF_HEX_LONG_U, &n);
Bram Moolenaar0d660222005-01-07 21:51:51 +000015443 if (n != 0)
15444 r = serverGetReply((HWND)n, FALSE, TRUE, TRUE);
15445 if (r == NULL)
15446# else
15447 if (check_connection() == FAIL || serverReadReply(X_DISPLAY,
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015448 serverStrToWin(serverid), &r, FALSE) < 0)
Bram Moolenaar0d660222005-01-07 21:51:51 +000015449# endif
15450 EMSG(_("E277: Unable to read a server reply"));
15451 }
15452#endif
15453 rettv->v_type = VAR_STRING;
15454 rettv->vval.v_string = r;
15455}
15456
15457/*
15458 * "remote_send()" function
15459 */
Bram Moolenaar0d660222005-01-07 21:51:51 +000015460 static void
15461f_remote_send(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000015462 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000015463 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015464{
15465 rettv->v_type = VAR_STRING;
15466 rettv->vval.v_string = NULL;
15467#ifdef FEAT_CLIENTSERVER
15468 remote_common(argvars, rettv, FALSE);
15469#endif
15470}
15471
15472/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000015473 * "remove()" function
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015474 */
15475 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015476f_remove(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015477 typval_T *argvars;
15478 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015479{
Bram Moolenaar33570922005-01-25 22:26:29 +000015480 list_T *l;
15481 listitem_T *item, *item2;
15482 listitem_T *li;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015483 long idx;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015484 long end;
Bram Moolenaar8c711452005-01-14 21:53:12 +000015485 char_u *key;
Bram Moolenaar33570922005-01-25 22:26:29 +000015486 dict_T *d;
15487 dictitem_T *di;
Bram Moolenaar32f649e2011-04-11 13:46:13 +020015488 char *arg_errmsg = N_("remove() argument");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015489
Bram Moolenaar8c711452005-01-14 21:53:12 +000015490 if (argvars[0].v_type == VAR_DICT)
15491 {
15492 if (argvars[2].v_type != VAR_UNKNOWN)
15493 EMSG2(_(e_toomanyarg), "remove()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015494 else if ((d = argvars[0].vval.v_dict) != NULL
Bram Moolenaar32f649e2011-04-11 13:46:13 +020015495 && !tv_check_lock(d->dv_lock, (char_u *)_(arg_errmsg)))
Bram Moolenaar8c711452005-01-14 21:53:12 +000015496 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015497 key = get_tv_string_chk(&argvars[1]);
15498 if (key != NULL)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015499 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015500 di = dict_find(d, key, -1);
15501 if (di == NULL)
15502 EMSG2(_(e_dictkey), key);
15503 else
15504 {
15505 *rettv = di->di_tv;
15506 init_tv(&di->di_tv);
15507 dictitem_remove(d, di);
15508 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015509 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000015510 }
15511 }
15512 else if (argvars[0].v_type != VAR_LIST)
15513 EMSG2(_(e_listdictarg), "remove()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015514 else if ((l = argvars[0].vval.v_list) != NULL
Bram Moolenaar32f649e2011-04-11 13:46:13 +020015515 && !tv_check_lock(l->lv_lock, (char_u *)_(arg_errmsg)))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015516 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015517 int error = FALSE;
15518
15519 idx = get_tv_number_chk(&argvars[1], &error);
15520 if (error)
15521 ; /* type error: do nothing, errmsg already given */
15522 else if ((item = list_find(l, idx)) == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015523 EMSGN(_(e_listidx), idx);
15524 else
15525 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015526 if (argvars[2].v_type == VAR_UNKNOWN)
15527 {
15528 /* Remove one item, return its value. */
Bram Moolenaar3ec7f4e2014-05-07 17:31:37 +020015529 vimlist_remove(l, item, item);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015530 *rettv = item->li_tv;
15531 vim_free(item);
15532 }
15533 else
15534 {
15535 /* Remove range of items, return list with values. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015536 end = get_tv_number_chk(&argvars[2], &error);
15537 if (error)
15538 ; /* type error: do nothing */
15539 else if ((item2 = list_find(l, end)) == NULL)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015540 EMSGN(_(e_listidx), end);
15541 else
15542 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000015543 int cnt = 0;
15544
15545 for (li = item; li != NULL; li = li->li_next)
15546 {
15547 ++cnt;
15548 if (li == item2)
15549 break;
15550 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015551 if (li == NULL) /* didn't find "item2" after "item" */
15552 EMSG(_(e_invrange));
15553 else
15554 {
Bram Moolenaar3ec7f4e2014-05-07 17:31:37 +020015555 vimlist_remove(l, item, item2);
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015556 if (rettv_list_alloc(rettv) == OK)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015557 {
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015558 l = rettv->vval.v_list;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015559 l->lv_first = item;
15560 l->lv_last = item2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015561 item->li_prev = NULL;
15562 item2->li_next = NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +000015563 l->lv_len = cnt;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015564 }
15565 }
15566 }
15567 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015568 }
15569 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015570}
15571
15572/*
15573 * "rename({from}, {to})" function
15574 */
15575 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015576f_rename(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015577 typval_T *argvars;
15578 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015579{
15580 char_u buf[NUMBUFLEN];
15581
15582 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015583 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015584 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015585 rettv->vval.v_number = vim_rename(get_tv_string(&argvars[0]),
15586 get_tv_string_buf(&argvars[1], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +000015587}
15588
15589/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015590 * "repeat()" function
15591 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015592 static void
15593f_repeat(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015594 typval_T *argvars;
15595 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015596{
15597 char_u *p;
15598 int n;
15599 int slen;
15600 int len;
15601 char_u *r;
15602 int i;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015603
15604 n = get_tv_number(&argvars[1]);
15605 if (argvars[0].v_type == VAR_LIST)
15606 {
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015607 if (rettv_list_alloc(rettv) == OK && argvars[0].vval.v_list != NULL)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015608 while (n-- > 0)
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015609 if (list_extend(rettv->vval.v_list,
15610 argvars[0].vval.v_list, NULL) == FAIL)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015611 break;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015612 }
15613 else
15614 {
15615 p = get_tv_string(&argvars[0]);
15616 rettv->v_type = VAR_STRING;
15617 rettv->vval.v_string = NULL;
15618
15619 slen = (int)STRLEN(p);
15620 len = slen * n;
15621 if (len <= 0)
15622 return;
15623
15624 r = alloc(len + 1);
15625 if (r != NULL)
15626 {
15627 for (i = 0; i < n; i++)
15628 mch_memmove(r + i * slen, p, (size_t)slen);
15629 r[len] = NUL;
15630 }
15631
15632 rettv->vval.v_string = r;
15633 }
15634}
15635
15636/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000015637 * "resolve()" function
15638 */
15639 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015640f_resolve(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015641 typval_T *argvars;
15642 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015643{
15644 char_u *p;
Bram Moolenaard9462e32011-04-11 21:35:11 +020015645#ifdef HAVE_READLINK
15646 char_u *buf = NULL;
15647#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000015648
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015649 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015650#ifdef FEAT_SHORTCUT
15651 {
15652 char_u *v = NULL;
15653
15654 v = mch_resolve_shortcut(p);
15655 if (v != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015656 rettv->vval.v_string = v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015657 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015658 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015659 }
15660#else
15661# ifdef HAVE_READLINK
15662 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000015663 char_u *cpy;
15664 int len;
15665 char_u *remain = NULL;
15666 char_u *q;
15667 int is_relative_to_current = FALSE;
15668 int has_trailing_pathsep = FALSE;
15669 int limit = 100;
15670
15671 p = vim_strsave(p);
15672
15673 if (p[0] == '.' && (vim_ispathsep(p[1])
15674 || (p[1] == '.' && (vim_ispathsep(p[2])))))
15675 is_relative_to_current = TRUE;
15676
15677 len = STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000015678 if (len > 0 && after_pathsep(p, p + len))
Bram Moolenaar1385c3e2011-05-19 14:59:10 +020015679 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000015680 has_trailing_pathsep = TRUE;
Bram Moolenaar1385c3e2011-05-19 14:59:10 +020015681 p[len - 1] = NUL; /* the trailing slash breaks readlink() */
15682 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015683
15684 q = getnextcomp(p);
15685 if (*q != NUL)
15686 {
15687 /* Separate the first path component in "p", and keep the
15688 * remainder (beginning with the path separator). */
15689 remain = vim_strsave(q - 1);
15690 q[-1] = NUL;
15691 }
15692
Bram Moolenaard9462e32011-04-11 21:35:11 +020015693 buf = alloc(MAXPATHL + 1);
15694 if (buf == NULL)
15695 goto fail;
15696
Bram Moolenaar071d4272004-06-13 20:20:40 +000015697 for (;;)
15698 {
15699 for (;;)
15700 {
15701 len = readlink((char *)p, (char *)buf, MAXPATHL);
15702 if (len <= 0)
15703 break;
15704 buf[len] = NUL;
15705
15706 if (limit-- == 0)
15707 {
15708 vim_free(p);
15709 vim_free(remain);
15710 EMSG(_("E655: Too many symbolic links (cycle?)"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015711 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015712 goto fail;
15713 }
15714
15715 /* Ensure that the result will have a trailing path separator
15716 * if the argument has one. */
15717 if (remain == NULL && has_trailing_pathsep)
15718 add_pathsep(buf);
15719
15720 /* Separate the first path component in the link value and
15721 * concatenate the remainders. */
15722 q = getnextcomp(vim_ispathsep(*buf) ? buf + 1 : buf);
15723 if (*q != NUL)
15724 {
15725 if (remain == NULL)
15726 remain = vim_strsave(q - 1);
15727 else
15728 {
Bram Moolenaar900b4d72005-12-12 22:05:50 +000015729 cpy = concat_str(q - 1, remain);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015730 if (cpy != NULL)
15731 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000015732 vim_free(remain);
15733 remain = cpy;
15734 }
15735 }
15736 q[-1] = NUL;
15737 }
15738
15739 q = gettail(p);
15740 if (q > p && *q == NUL)
15741 {
15742 /* Ignore trailing path separator. */
15743 q[-1] = NUL;
15744 q = gettail(p);
15745 }
15746 if (q > p && !mch_isFullName(buf))
15747 {
15748 /* symlink is relative to directory of argument */
15749 cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1));
15750 if (cpy != NULL)
15751 {
15752 STRCPY(cpy, p);
15753 STRCPY(gettail(cpy), buf);
15754 vim_free(p);
15755 p = cpy;
15756 }
15757 }
15758 else
15759 {
15760 vim_free(p);
15761 p = vim_strsave(buf);
15762 }
15763 }
15764
15765 if (remain == NULL)
15766 break;
15767
15768 /* Append the first path component of "remain" to "p". */
15769 q = getnextcomp(remain + 1);
15770 len = q - remain - (*q != NUL);
15771 cpy = vim_strnsave(p, STRLEN(p) + len);
15772 if (cpy != NULL)
15773 {
15774 STRNCAT(cpy, remain, len);
15775 vim_free(p);
15776 p = cpy;
15777 }
15778 /* Shorten "remain". */
15779 if (*q != NUL)
Bram Moolenaar8c8de832008-06-24 22:58:06 +000015780 STRMOVE(remain, q - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015781 else
15782 {
15783 vim_free(remain);
15784 remain = NULL;
15785 }
15786 }
15787
15788 /* If the result is a relative path name, make it explicitly relative to
15789 * the current directory if and only if the argument had this form. */
15790 if (!vim_ispathsep(*p))
15791 {
15792 if (is_relative_to_current
15793 && *p != NUL
15794 && !(p[0] == '.'
15795 && (p[1] == NUL
15796 || vim_ispathsep(p[1])
15797 || (p[1] == '.'
15798 && (p[2] == NUL
15799 || vim_ispathsep(p[2]))))))
15800 {
15801 /* Prepend "./". */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015802 cpy = concat_str((char_u *)"./", p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015803 if (cpy != NULL)
15804 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000015805 vim_free(p);
15806 p = cpy;
15807 }
15808 }
15809 else if (!is_relative_to_current)
15810 {
15811 /* Strip leading "./". */
15812 q = p;
15813 while (q[0] == '.' && vim_ispathsep(q[1]))
15814 q += 2;
15815 if (q > p)
Bram Moolenaar8c8de832008-06-24 22:58:06 +000015816 STRMOVE(p, p + 2);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015817 }
15818 }
15819
15820 /* Ensure that the result will have no trailing path separator
15821 * if the argument had none. But keep "/" or "//". */
15822 if (!has_trailing_pathsep)
15823 {
15824 q = p + STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000015825 if (after_pathsep(p, q))
15826 *gettail_sep(p) = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015827 }
15828
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015829 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015830 }
15831# else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015832 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015833# endif
15834#endif
15835
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015836 simplify_filename(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015837
15838#ifdef HAVE_READLINK
15839fail:
Bram Moolenaard9462e32011-04-11 21:35:11 +020015840 vim_free(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015841#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015842 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015843}
15844
15845/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000015846 * "reverse({list})" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000015847 */
15848 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000015849f_reverse(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015850 typval_T *argvars;
15851 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015852{
Bram Moolenaar33570922005-01-25 22:26:29 +000015853 list_T *l;
15854 listitem_T *li, *ni;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015855
Bram Moolenaar0d660222005-01-07 21:51:51 +000015856 if (argvars[0].v_type != VAR_LIST)
15857 EMSG2(_(e_listarg), "reverse()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015858 else if ((l = argvars[0].vval.v_list) != NULL
Bram Moolenaar32f649e2011-04-11 13:46:13 +020015859 && !tv_check_lock(l->lv_lock, (char_u *)_("reverse() argument")))
Bram Moolenaar0d660222005-01-07 21:51:51 +000015860 {
15861 li = l->lv_last;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015862 l->lv_first = l->lv_last = NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +000015863 l->lv_len = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015864 while (li != NULL)
15865 {
15866 ni = li->li_prev;
15867 list_append(l, li);
15868 li = ni;
15869 }
15870 rettv->vval.v_list = l;
15871 rettv->v_type = VAR_LIST;
15872 ++l->lv_refcount;
Bram Moolenaar52514562008-04-01 11:12:09 +000015873 l->lv_idx = l->lv_len - l->lv_idx - 1;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015874 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015875}
15876
Bram Moolenaar768b8c42006-03-04 21:58:33 +000015877#define SP_NOMOVE 0x01 /* don't move cursor */
15878#define SP_REPEAT 0x02 /* repeat to find outer pair */
15879#define SP_RETCOUNT 0x04 /* return matchcount */
15880#define SP_SETPCMARK 0x08 /* set previous context mark */
15881#define SP_START 0x10 /* accept match at start position */
15882#define SP_SUBPAT 0x20 /* return nr of matching sub-pattern */
15883#define SP_END 0x40 /* leave cursor at end of match */
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000015884
Bram Moolenaar33570922005-01-25 22:26:29 +000015885static int get_search_arg __ARGS((typval_T *varp, int *flagsp));
Bram Moolenaar0d660222005-01-07 21:51:51 +000015886
15887/*
15888 * Get flags for a search function.
15889 * Possibly sets "p_ws".
15890 * Returns BACKWARD, FORWARD or zero (for an error).
15891 */
15892 static int
15893get_search_arg(varp, flagsp)
Bram Moolenaar33570922005-01-25 22:26:29 +000015894 typval_T *varp;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015895 int *flagsp;
15896{
15897 int dir = FORWARD;
15898 char_u *flags;
15899 char_u nbuf[NUMBUFLEN];
15900 int mask;
15901
15902 if (varp->v_type != VAR_UNKNOWN)
15903 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015904 flags = get_tv_string_buf_chk(varp, nbuf);
15905 if (flags == NULL)
15906 return 0; /* type error; errmsg already given */
Bram Moolenaar0d660222005-01-07 21:51:51 +000015907 while (*flags != NUL)
15908 {
15909 switch (*flags)
15910 {
15911 case 'b': dir = BACKWARD; break;
15912 case 'w': p_ws = TRUE; break;
15913 case 'W': p_ws = FALSE; break;
15914 default: mask = 0;
15915 if (flagsp != NULL)
15916 switch (*flags)
15917 {
Bram Moolenaar0e34f622006-03-03 23:00:03 +000015918 case 'c': mask = SP_START; break;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000015919 case 'e': mask = SP_END; break;
15920 case 'm': mask = SP_RETCOUNT; break;
15921 case 'n': mask = SP_NOMOVE; break;
15922 case 'p': mask = SP_SUBPAT; break;
15923 case 'r': mask = SP_REPEAT; break;
15924 case 's': mask = SP_SETPCMARK; break;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015925 }
15926 if (mask == 0)
15927 {
15928 EMSG2(_(e_invarg2), flags);
15929 dir = 0;
15930 }
15931 else
15932 *flagsp |= mask;
15933 }
15934 if (dir == 0)
15935 break;
15936 ++flags;
15937 }
15938 }
15939 return dir;
15940}
15941
Bram Moolenaar071d4272004-06-13 20:20:40 +000015942/*
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000015943 * Shared by search() and searchpos() functions
Bram Moolenaar071d4272004-06-13 20:20:40 +000015944 */
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000015945 static int
Bram Moolenaar362e1a32006-03-06 23:29:24 +000015946search_cmn(argvars, match_pos, flagsp)
Bram Moolenaar33570922005-01-25 22:26:29 +000015947 typval_T *argvars;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015948 pos_T *match_pos;
Bram Moolenaar362e1a32006-03-06 23:29:24 +000015949 int *flagsp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015950{
Bram Moolenaar362e1a32006-03-06 23:29:24 +000015951 int flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015952 char_u *pat;
15953 pos_T pos;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000015954 pos_T save_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015955 int save_p_ws = p_ws;
15956 int dir;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000015957 int retval = 0; /* default: FAIL */
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015958 long lnum_stop = 0;
Bram Moolenaar76929292008-01-06 19:07:36 +000015959 proftime_T tm;
15960#ifdef FEAT_RELTIME
15961 long time_limit = 0;
15962#endif
Bram Moolenaar0e34f622006-03-03 23:00:03 +000015963 int options = SEARCH_KEEP;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000015964 int subpatnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015965
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015966 pat = get_tv_string(&argvars[0]);
Bram Moolenaar362e1a32006-03-06 23:29:24 +000015967 dir = get_search_arg(&argvars[1], flagsp); /* may set p_ws */
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000015968 if (dir == 0)
15969 goto theend;
Bram Moolenaar362e1a32006-03-06 23:29:24 +000015970 flags = *flagsp;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000015971 if (flags & SP_START)
15972 options |= SEARCH_START;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000015973 if (flags & SP_END)
15974 options |= SEARCH_END;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015975
Bram Moolenaar76929292008-01-06 19:07:36 +000015976 /* Optional arguments: line number to stop searching and timeout. */
15977 if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015978 {
15979 lnum_stop = get_tv_number_chk(&argvars[2], NULL);
15980 if (lnum_stop < 0)
15981 goto theend;
Bram Moolenaar76929292008-01-06 19:07:36 +000015982#ifdef FEAT_RELTIME
15983 if (argvars[3].v_type != VAR_UNKNOWN)
15984 {
15985 time_limit = get_tv_number_chk(&argvars[3], NULL);
15986 if (time_limit < 0)
15987 goto theend;
15988 }
15989#endif
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015990 }
15991
Bram Moolenaar76929292008-01-06 19:07:36 +000015992#ifdef FEAT_RELTIME
15993 /* Set the time limit, if there is one. */
15994 profile_setlimit(time_limit, &tm);
15995#endif
15996
Bram Moolenaar231334e2005-07-25 20:46:57 +000015997 /*
Bram Moolenaar768b8c42006-03-04 21:58:33 +000015998 * This function does not accept SP_REPEAT and SP_RETCOUNT flags.
Bram Moolenaar231334e2005-07-25 20:46:57 +000015999 * Check to make sure only those flags are set.
16000 * Also, Only the SP_NOMOVE or the SP_SETPCMARK flag can be set. Both
16001 * flags cannot be set. Check for that condition also.
16002 */
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016003 if (((flags & (SP_REPEAT | SP_RETCOUNT)) != 0)
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016004 || ((flags & SP_NOMOVE) && (flags & SP_SETPCMARK)))
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000016005 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016006 EMSG2(_(e_invarg2), get_tv_string(&argvars[1]));
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000016007 goto theend;
16008 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016009
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000016010 pos = save_cursor = curwin->w_cursor;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016011 subpatnum = searchit(curwin, curbuf, &pos, dir, pat, 1L,
Bram Moolenaar76929292008-01-06 19:07:36 +000016012 options, RE_SEARCH, (linenr_T)lnum_stop, &tm);
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016013 if (subpatnum != FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016014 {
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016015 if (flags & SP_SUBPAT)
16016 retval = subpatnum;
16017 else
16018 retval = pos.lnum;
Bram Moolenaar231334e2005-07-25 20:46:57 +000016019 if (flags & SP_SETPCMARK)
16020 setpcmark();
Bram Moolenaar071d4272004-06-13 20:20:40 +000016021 curwin->w_cursor = pos;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016022 if (match_pos != NULL)
16023 {
16024 /* Store the match cursor position */
16025 match_pos->lnum = pos.lnum;
16026 match_pos->col = pos.col + 1;
16027 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016028 /* "/$" will put the cursor after the end of the line, may need to
16029 * correct that here */
16030 check_cursor();
16031 }
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000016032
16033 /* If 'n' flag is used: restore cursor position. */
16034 if (flags & SP_NOMOVE)
16035 curwin->w_cursor = save_cursor;
Bram Moolenaar7a42fa32007-07-10 11:28:55 +000016036 else
16037 curwin->w_set_curswant = TRUE;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000016038theend:
Bram Moolenaar071d4272004-06-13 20:20:40 +000016039 p_ws = save_p_ws;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016040
16041 return retval;
16042}
16043
Bram Moolenaar8c8de832008-06-24 22:58:06 +000016044#ifdef FEAT_FLOAT
Bram Moolenaara2e14fc2013-06-10 20:10:44 +020016045
16046/*
16047 * round() is not in C90, use ceil() or floor() instead.
16048 */
16049 float_T
16050vim_round(f)
16051 float_T f;
16052{
16053 return f > 0 ? floor(f + 0.5) : ceil(f - 0.5);
16054}
16055
Bram Moolenaar8c8de832008-06-24 22:58:06 +000016056/*
16057 * "round({float})" function
16058 */
16059 static void
16060f_round(argvars, rettv)
16061 typval_T *argvars;
16062 typval_T *rettv;
16063{
16064 float_T f;
16065
16066 rettv->v_type = VAR_FLOAT;
16067 if (get_float_arg(argvars, &f) == OK)
Bram Moolenaara2e14fc2013-06-10 20:10:44 +020016068 rettv->vval.v_float = vim_round(f);
Bram Moolenaar8c8de832008-06-24 22:58:06 +000016069 else
16070 rettv->vval.v_float = 0.0;
16071}
16072#endif
16073
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016074/*
Bram Moolenaar9a773482013-06-11 18:40:13 +020016075 * "screenattr()" function
16076 */
16077 static void
16078f_screenattr(argvars, rettv)
16079 typval_T *argvars UNUSED;
16080 typval_T *rettv;
16081{
16082 int row;
16083 int col;
16084 int c;
16085
16086 row = get_tv_number_chk(&argvars[0], NULL) - 1;
16087 col = get_tv_number_chk(&argvars[1], NULL) - 1;
16088 if (row < 0 || row >= screen_Rows
16089 || col < 0 || col >= screen_Columns)
16090 c = -1;
16091 else
16092 c = ScreenAttrs[LineOffset[row] + col];
16093 rettv->vval.v_number = c;
16094}
16095
16096/*
16097 * "screenchar()" function
16098 */
16099 static void
16100f_screenchar(argvars, rettv)
16101 typval_T *argvars UNUSED;
16102 typval_T *rettv;
16103{
16104 int row;
16105 int col;
16106 int off;
16107 int c;
16108
16109 row = get_tv_number_chk(&argvars[0], NULL) - 1;
16110 col = get_tv_number_chk(&argvars[1], NULL) - 1;
16111 if (row < 0 || row >= screen_Rows
16112 || col < 0 || col >= screen_Columns)
16113 c = -1;
16114 else
16115 {
16116 off = LineOffset[row] + col;
16117#ifdef FEAT_MBYTE
16118 if (enc_utf8 && ScreenLinesUC[off] != 0)
16119 c = ScreenLinesUC[off];
16120 else
16121#endif
16122 c = ScreenLines[off];
16123 }
16124 rettv->vval.v_number = c;
16125}
16126
16127/*
Bram Moolenaar9750bb12012-12-05 16:10:42 +010016128 * "screencol()" function
16129 *
16130 * First column is 1 to be consistent with virtcol().
16131 */
16132 static void
16133f_screencol(argvars, rettv)
16134 typval_T *argvars UNUSED;
16135 typval_T *rettv;
16136{
16137 rettv->vval.v_number = screen_screencol() + 1;
16138}
16139
16140/*
16141 * "screenrow()" function
16142 */
16143 static void
16144f_screenrow(argvars, rettv)
16145 typval_T *argvars UNUSED;
16146 typval_T *rettv;
16147{
16148 rettv->vval.v_number = screen_screenrow() + 1;
16149}
16150
16151/*
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016152 * "search()" function
16153 */
16154 static void
16155f_search(argvars, rettv)
16156 typval_T *argvars;
16157 typval_T *rettv;
16158{
Bram Moolenaar362e1a32006-03-06 23:29:24 +000016159 int flags = 0;
16160
16161 rettv->vval.v_number = search_cmn(argvars, NULL, &flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016162}
16163
Bram Moolenaar071d4272004-06-13 20:20:40 +000016164/*
Bram Moolenaardd2436f2005-09-05 22:14:46 +000016165 * "searchdecl()" function
16166 */
16167 static void
16168f_searchdecl(argvars, rettv)
16169 typval_T *argvars;
16170 typval_T *rettv;
16171{
16172 int locally = 1;
Bram Moolenaare6facf92005-09-13 21:22:27 +000016173 int thisblock = 0;
Bram Moolenaardd2436f2005-09-05 22:14:46 +000016174 int error = FALSE;
16175 char_u *name;
16176
16177 rettv->vval.v_number = 1; /* default: FAIL */
16178
16179 name = get_tv_string_chk(&argvars[0]);
16180 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaare6facf92005-09-13 21:22:27 +000016181 {
Bram Moolenaardd2436f2005-09-05 22:14:46 +000016182 locally = get_tv_number_chk(&argvars[1], &error) == 0;
Bram Moolenaare6facf92005-09-13 21:22:27 +000016183 if (!error && argvars[2].v_type != VAR_UNKNOWN)
16184 thisblock = get_tv_number_chk(&argvars[2], &error) != 0;
16185 }
Bram Moolenaardd2436f2005-09-05 22:14:46 +000016186 if (!error && name != NULL)
16187 rettv->vval.v_number = find_decl(name, (int)STRLEN(name),
Bram Moolenaare6facf92005-09-13 21:22:27 +000016188 locally, thisblock, SEARCH_KEEP) == FAIL;
Bram Moolenaardd2436f2005-09-05 22:14:46 +000016189}
16190
16191/*
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016192 * Used by searchpair() and searchpairpos()
Bram Moolenaar071d4272004-06-13 20:20:40 +000016193 */
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016194 static int
16195searchpair_cmn(argvars, match_pos)
Bram Moolenaar33570922005-01-25 22:26:29 +000016196 typval_T *argvars;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016197 pos_T *match_pos;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016198{
16199 char_u *spat, *mpat, *epat;
16200 char_u *skip;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016201 int save_p_ws = p_ws;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016202 int dir;
16203 int flags = 0;
16204 char_u nbuf1[NUMBUFLEN];
16205 char_u nbuf2[NUMBUFLEN];
16206 char_u nbuf3[NUMBUFLEN];
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016207 int retval = 0; /* default: FAIL */
Bram Moolenaareddf53b2006-02-27 00:11:10 +000016208 long lnum_stop = 0;
Bram Moolenaar76929292008-01-06 19:07:36 +000016209 long time_limit = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016210
Bram Moolenaar071d4272004-06-13 20:20:40 +000016211 /* Get the three pattern arguments: start, middle, end. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016212 spat = get_tv_string_chk(&argvars[0]);
16213 mpat = get_tv_string_buf_chk(&argvars[1], nbuf1);
16214 epat = get_tv_string_buf_chk(&argvars[2], nbuf2);
16215 if (spat == NULL || mpat == NULL || epat == NULL)
16216 goto theend; /* type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016217
Bram Moolenaar071d4272004-06-13 20:20:40 +000016218 /* Handle the optional fourth argument: flags */
16219 dir = get_search_arg(&argvars[3], &flags); /* may set p_ws */
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000016220 if (dir == 0)
16221 goto theend;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016222
16223 /* Don't accept SP_END or SP_SUBPAT.
Bram Moolenaar231334e2005-07-25 20:46:57 +000016224 * Only one of the SP_NOMOVE or SP_SETPCMARK flags can be set.
16225 */
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016226 if ((flags & (SP_END | SP_SUBPAT)) != 0
16227 || ((flags & SP_NOMOVE) && (flags & SP_SETPCMARK)))
Bram Moolenaar231334e2005-07-25 20:46:57 +000016228 {
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016229 EMSG2(_(e_invarg2), get_tv_string(&argvars[3]));
Bram Moolenaar231334e2005-07-25 20:46:57 +000016230 goto theend;
16231 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016232
Bram Moolenaar92de73d2008-01-22 10:59:38 +000016233 /* Using 'r' implies 'W', otherwise it doesn't work. */
16234 if (flags & SP_REPEAT)
16235 p_ws = FALSE;
16236
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016237 /* Optional fifth argument: skip expression */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016238 if (argvars[3].v_type == VAR_UNKNOWN
16239 || argvars[4].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016240 skip = (char_u *)"";
16241 else
Bram Moolenaareddf53b2006-02-27 00:11:10 +000016242 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016243 skip = get_tv_string_buf_chk(&argvars[4], nbuf3);
Bram Moolenaareddf53b2006-02-27 00:11:10 +000016244 if (argvars[5].v_type != VAR_UNKNOWN)
16245 {
16246 lnum_stop = get_tv_number_chk(&argvars[5], NULL);
16247 if (lnum_stop < 0)
16248 goto theend;
Bram Moolenaar76929292008-01-06 19:07:36 +000016249#ifdef FEAT_RELTIME
16250 if (argvars[6].v_type != VAR_UNKNOWN)
16251 {
16252 time_limit = get_tv_number_chk(&argvars[6], NULL);
16253 if (time_limit < 0)
16254 goto theend;
16255 }
16256#endif
Bram Moolenaareddf53b2006-02-27 00:11:10 +000016257 }
16258 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016259 if (skip == NULL)
16260 goto theend; /* type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016261
Bram Moolenaareddf53b2006-02-27 00:11:10 +000016262 retval = do_searchpair(spat, mpat, epat, dir, skip, flags,
Bram Moolenaar76929292008-01-06 19:07:36 +000016263 match_pos, lnum_stop, time_limit);
Bram Moolenaar9fad3082005-07-19 22:22:13 +000016264
16265theend:
16266 p_ws = save_p_ws;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016267
16268 return retval;
16269}
16270
16271/*
16272 * "searchpair()" function
16273 */
16274 static void
16275f_searchpair(argvars, rettv)
16276 typval_T *argvars;
16277 typval_T *rettv;
16278{
16279 rettv->vval.v_number = searchpair_cmn(argvars, NULL);
16280}
16281
16282/*
16283 * "searchpairpos()" function
16284 */
16285 static void
16286f_searchpairpos(argvars, rettv)
16287 typval_T *argvars;
16288 typval_T *rettv;
16289{
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016290 pos_T match_pos;
16291 int lnum = 0;
16292 int col = 0;
16293
Bram Moolenaareddf53b2006-02-27 00:11:10 +000016294 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016295 return;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016296
16297 if (searchpair_cmn(argvars, &match_pos) > 0)
16298 {
16299 lnum = match_pos.lnum;
16300 col = match_pos.col;
16301 }
16302
Bram Moolenaareddf53b2006-02-27 00:11:10 +000016303 list_append_number(rettv->vval.v_list, (varnumber_T)lnum);
16304 list_append_number(rettv->vval.v_list, (varnumber_T)col);
Bram Moolenaar9fad3082005-07-19 22:22:13 +000016305}
16306
16307/*
16308 * Search for a start/middle/end thing.
16309 * Used by searchpair(), see its documentation for the details.
16310 * Returns 0 or -1 for no match,
16311 */
16312 long
Bram Moolenaar76929292008-01-06 19:07:36 +000016313do_searchpair(spat, mpat, epat, dir, skip, flags, match_pos,
16314 lnum_stop, time_limit)
Bram Moolenaar9fad3082005-07-19 22:22:13 +000016315 char_u *spat; /* start pattern */
16316 char_u *mpat; /* middle pattern */
16317 char_u *epat; /* end pattern */
16318 int dir; /* BACKWARD or FORWARD */
16319 char_u *skip; /* skip expression */
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016320 int flags; /* SP_SETPCMARK and other SP_ values */
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016321 pos_T *match_pos;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000016322 linenr_T lnum_stop; /* stop at this line if not zero */
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +010016323 long time_limit UNUSED; /* stop after this many msec */
Bram Moolenaar9fad3082005-07-19 22:22:13 +000016324{
16325 char_u *save_cpo;
16326 char_u *pat, *pat2 = NULL, *pat3 = NULL;
16327 long retval = 0;
16328 pos_T pos;
16329 pos_T firstpos;
16330 pos_T foundpos;
16331 pos_T save_cursor;
16332 pos_T save_pos;
16333 int n;
16334 int r;
16335 int nest = 1;
16336 int err;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016337 int options = SEARCH_KEEP;
Bram Moolenaar76929292008-01-06 19:07:36 +000016338 proftime_T tm;
Bram Moolenaar9fad3082005-07-19 22:22:13 +000016339
16340 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
16341 save_cpo = p_cpo;
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +000016342 p_cpo = empty_option;
Bram Moolenaar9fad3082005-07-19 22:22:13 +000016343
Bram Moolenaar76929292008-01-06 19:07:36 +000016344#ifdef FEAT_RELTIME
16345 /* Set the time limit, if there is one. */
16346 profile_setlimit(time_limit, &tm);
16347#endif
16348
Bram Moolenaar9fad3082005-07-19 22:22:13 +000016349 /* Make two search patterns: start/end (pat2, for in nested pairs) and
16350 * start/middle/end (pat3, for the top pair). */
16351 pat2 = alloc((unsigned)(STRLEN(spat) + STRLEN(epat) + 15));
16352 pat3 = alloc((unsigned)(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 23));
16353 if (pat2 == NULL || pat3 == NULL)
16354 goto theend;
16355 sprintf((char *)pat2, "\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat);
16356 if (*mpat == NUL)
16357 STRCPY(pat3, pat2);
16358 else
16359 sprintf((char *)pat3, "\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)",
16360 spat, epat, mpat);
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016361 if (flags & SP_START)
16362 options |= SEARCH_START;
Bram Moolenaar9fad3082005-07-19 22:22:13 +000016363
Bram Moolenaar071d4272004-06-13 20:20:40 +000016364 save_cursor = curwin->w_cursor;
16365 pos = curwin->w_cursor;
Bram Moolenaar261bfea2006-03-01 22:12:31 +000016366 clearpos(&firstpos);
16367 clearpos(&foundpos);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016368 pat = pat3;
16369 for (;;)
16370 {
16371 n = searchit(curwin, curbuf, &pos, dir, pat, 1L,
Bram Moolenaar76929292008-01-06 19:07:36 +000016372 options, RE_SEARCH, lnum_stop, &tm);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016373 if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos)))
16374 /* didn't find it or found the first match again: FAIL */
16375 break;
16376
16377 if (firstpos.lnum == 0)
16378 firstpos = pos;
Bram Moolenaarc9a2d2e2005-04-24 22:09:56 +000016379 if (equalpos(pos, foundpos))
16380 {
16381 /* Found the same position again. Can happen with a pattern that
16382 * has "\zs" at the end and searching backwards. Advance one
16383 * character and try again. */
16384 if (dir == BACKWARD)
16385 decl(&pos);
16386 else
16387 incl(&pos);
16388 }
16389 foundpos = pos;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016390
Bram Moolenaar92de73d2008-01-22 10:59:38 +000016391 /* clear the start flag to avoid getting stuck here */
16392 options &= ~SEARCH_START;
16393
Bram Moolenaar071d4272004-06-13 20:20:40 +000016394 /* If the skip pattern matches, ignore this match. */
16395 if (*skip != NUL)
16396 {
16397 save_pos = curwin->w_cursor;
16398 curwin->w_cursor = pos;
16399 r = eval_to_bool(skip, &err, NULL, FALSE);
16400 curwin->w_cursor = save_pos;
16401 if (err)
16402 {
16403 /* Evaluating {skip} caused an error, break here. */
16404 curwin->w_cursor = save_cursor;
Bram Moolenaar9fad3082005-07-19 22:22:13 +000016405 retval = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016406 break;
16407 }
16408 if (r)
16409 continue;
16410 }
16411
16412 if ((dir == BACKWARD && n == 3) || (dir == FORWARD && n == 2))
16413 {
16414 /* Found end when searching backwards or start when searching
16415 * forward: nested pair. */
16416 ++nest;
16417 pat = pat2; /* nested, don't search for middle */
16418 }
16419 else
16420 {
16421 /* Found end when searching forward or start when searching
16422 * backward: end of (nested) pair; or found middle in outer pair. */
16423 if (--nest == 1)
16424 pat = pat3; /* outer level, search for middle */
16425 }
16426
16427 if (nest == 0)
16428 {
16429 /* Found the match: return matchcount or line number. */
16430 if (flags & SP_RETCOUNT)
Bram Moolenaar9fad3082005-07-19 22:22:13 +000016431 ++retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016432 else
Bram Moolenaar9fad3082005-07-19 22:22:13 +000016433 retval = pos.lnum;
Bram Moolenaar231334e2005-07-25 20:46:57 +000016434 if (flags & SP_SETPCMARK)
16435 setpcmark();
Bram Moolenaar071d4272004-06-13 20:20:40 +000016436 curwin->w_cursor = pos;
16437 if (!(flags & SP_REPEAT))
16438 break;
16439 nest = 1; /* search for next unmatched */
16440 }
16441 }
16442
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016443 if (match_pos != NULL)
16444 {
16445 /* Store the match cursor position */
16446 match_pos->lnum = curwin->w_cursor.lnum;
16447 match_pos->col = curwin->w_cursor.col + 1;
16448 }
16449
Bram Moolenaar071d4272004-06-13 20:20:40 +000016450 /* If 'n' flag is used or search failed: restore cursor position. */
Bram Moolenaar9fad3082005-07-19 22:22:13 +000016451 if ((flags & SP_NOMOVE) || retval == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016452 curwin->w_cursor = save_cursor;
16453
16454theend:
16455 vim_free(pat2);
16456 vim_free(pat3);
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +000016457 if (p_cpo == empty_option)
16458 p_cpo = save_cpo;
16459 else
16460 /* Darn, evaluating the {skip} expression changed the value. */
16461 free_string_option(save_cpo);
Bram Moolenaar9fad3082005-07-19 22:22:13 +000016462
16463 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016464}
16465
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016466/*
16467 * "searchpos()" function
16468 */
16469 static void
16470f_searchpos(argvars, rettv)
16471 typval_T *argvars;
16472 typval_T *rettv;
16473{
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016474 pos_T match_pos;
16475 int lnum = 0;
16476 int col = 0;
Bram Moolenaar362e1a32006-03-06 23:29:24 +000016477 int n;
16478 int flags = 0;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016479
Bram Moolenaareddf53b2006-02-27 00:11:10 +000016480 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016481 return;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016482
Bram Moolenaar362e1a32006-03-06 23:29:24 +000016483 n = search_cmn(argvars, &match_pos, &flags);
16484 if (n > 0)
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016485 {
16486 lnum = match_pos.lnum;
16487 col = match_pos.col;
16488 }
16489
Bram Moolenaareddf53b2006-02-27 00:11:10 +000016490 list_append_number(rettv->vval.v_list, (varnumber_T)lnum);
16491 list_append_number(rettv->vval.v_list, (varnumber_T)col);
Bram Moolenaar362e1a32006-03-06 23:29:24 +000016492 if (flags & SP_SUBPAT)
16493 list_append_number(rettv->vval.v_list, (varnumber_T)n);
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000016494}
16495
16496
Bram Moolenaar0d660222005-01-07 21:51:51 +000016497 static void
16498f_server2client(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000016499 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000016500 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016501{
Bram Moolenaar0d660222005-01-07 21:51:51 +000016502#ifdef FEAT_CLIENTSERVER
16503 char_u buf[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016504 char_u *server = get_tv_string_chk(&argvars[0]);
16505 char_u *reply = get_tv_string_buf_chk(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016506
Bram Moolenaar0d660222005-01-07 21:51:51 +000016507 rettv->vval.v_number = -1;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016508 if (server == NULL || reply == NULL)
16509 return;
Bram Moolenaar0d660222005-01-07 21:51:51 +000016510 if (check_restricted() || check_secure())
16511 return;
16512# ifdef FEAT_X11
16513 if (check_connection() == FAIL)
16514 return;
16515# endif
16516
16517 if (serverSendReply(server, reply) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016518 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000016519 EMSG(_("E258: Unable to send to client"));
16520 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016521 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000016522 rettv->vval.v_number = 0;
16523#else
16524 rettv->vval.v_number = -1;
16525#endif
16526}
16527
Bram Moolenaar0d660222005-01-07 21:51:51 +000016528 static void
16529f_serverlist(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000016530 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000016531 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000016532{
16533 char_u *r = NULL;
16534
16535#ifdef FEAT_CLIENTSERVER
16536# ifdef WIN32
16537 r = serverGetVimNames();
16538# else
16539 make_connection();
16540 if (X_DISPLAY != NULL)
16541 r = serverGetVimNames(X_DISPLAY);
16542# endif
16543#endif
16544 rettv->v_type = VAR_STRING;
16545 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016546}
16547
16548/*
16549 * "setbufvar()" function
16550 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016551 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016552f_setbufvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000016553 typval_T *argvars;
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000016554 typval_T *rettv UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016555{
16556 buf_T *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016557 aco_save_T aco;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016558 char_u *varname, *bufvarname;
Bram Moolenaar33570922005-01-25 22:26:29 +000016559 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016560 char_u nbuf[NUMBUFLEN];
16561
16562 if (check_restricted() || check_secure())
16563 return;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016564 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
16565 varname = get_tv_string_chk(&argvars[1]);
Bram Moolenaar0c279bb2013-03-19 14:25:54 +010016566 buf = get_buf_tv(&argvars[0], FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016567 varp = &argvars[2];
16568
16569 if (buf != NULL && varname != NULL && varp != NULL)
16570 {
16571 /* set curbuf to be our buf, temporarily */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016572 aucmd_prepbuf(&aco, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016573
16574 if (*varname == '&')
16575 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016576 long numval;
16577 char_u *strval;
16578 int error = FALSE;
16579
Bram Moolenaar071d4272004-06-13 20:20:40 +000016580 ++varname;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016581 numval = get_tv_number_chk(varp, &error);
16582 strval = get_tv_string_buf_chk(varp, nbuf);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016583 if (!error && strval != NULL)
16584 set_option_value(varname, numval, strval, OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016585 }
16586 else
16587 {
16588 bufvarname = alloc((unsigned)STRLEN(varname) + 3);
16589 if (bufvarname != NULL)
16590 {
16591 STRCPY(bufvarname, "b:");
16592 STRCPY(bufvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000016593 set_var(bufvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016594 vim_free(bufvarname);
16595 }
16596 }
16597
16598 /* reset notion of buffer */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016599 aucmd_restbuf(&aco);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016600 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016601}
16602
16603/*
16604 * "setcmdpos()" function
16605 */
16606 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016607f_setcmdpos(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000016608 typval_T *argvars;
16609 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016610{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016611 int pos = (int)get_tv_number(&argvars[0]) - 1;
16612
16613 if (pos >= 0)
16614 rettv->vval.v_number = set_cmdline_pos(pos);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016615}
16616
16617/*
16618 * "setline()" function
16619 */
16620 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016621f_setline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000016622 typval_T *argvars;
16623 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016624{
16625 linenr_T lnum;
Bram Moolenaar0e6830e2005-05-27 20:23:44 +000016626 char_u *line = NULL;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000016627 list_T *l = NULL;
16628 listitem_T *li = NULL;
16629 long added = 0;
16630 linenr_T lcount = curbuf->b_ml.ml_line_count;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016631
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000016632 lnum = get_tv_lnum(&argvars[0]);
16633 if (argvars[1].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016634 {
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000016635 l = argvars[1].vval.v_list;
16636 li = l->lv_first;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016637 }
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000016638 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016639 line = get_tv_string_chk(&argvars[1]);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000016640
Bram Moolenaar798b30b2009-04-22 10:56:16 +000016641 /* default result is zero == OK */
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000016642 for (;;)
16643 {
16644 if (l != NULL)
16645 {
16646 /* list argument, get next string */
16647 if (li == NULL)
16648 break;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016649 line = get_tv_string_chk(&li->li_tv);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000016650 li = li->li_next;
16651 }
16652
16653 rettv->vval.v_number = 1; /* FAIL */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016654 if (line == NULL || lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000016655 break;
Bram Moolenaar3c1e9c22013-07-04 20:25:41 +020016656
16657 /* When coming here from Insert mode, sync undo, so that this can be
16658 * undone separately from what was previously inserted. */
16659 if (u_sync_once == 2)
16660 {
16661 u_sync_once = 1; /* notify that u_sync() was called */
16662 u_sync(TRUE);
16663 }
16664
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000016665 if (lnum <= curbuf->b_ml.ml_line_count)
16666 {
16667 /* existing line, replace it */
16668 if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK)
16669 {
16670 changed_bytes(lnum, 0);
Bram Moolenaar87c19962007-04-26 08:54:21 +000016671 if (lnum == curwin->w_cursor.lnum)
16672 check_cursor_col();
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000016673 rettv->vval.v_number = 0; /* OK */
16674 }
16675 }
16676 else if (added > 0 || u_save(lnum - 1, lnum) == OK)
16677 {
16678 /* lnum is one past the last line, append the line */
16679 ++added;
16680 if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK)
16681 rettv->vval.v_number = 0; /* OK */
16682 }
16683
16684 if (l == NULL) /* only one string argument */
16685 break;
16686 ++lnum;
16687 }
16688
16689 if (added > 0)
16690 appended_lines_mark(lcount, added);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016691}
16692
Bram Moolenaard9ff7d52008-03-20 12:23:49 +000016693static void set_qf_ll_list __ARGS((win_T *wp, typval_T *list_arg, typval_T *action_arg, typval_T *rettv));
16694
Bram Moolenaar071d4272004-06-13 20:20:40 +000016695/*
Bram Moolenaar17c7c012006-01-26 22:25:15 +000016696 * Used by "setqflist()" and "setloclist()" functions
Bram Moolenaar2641f772005-03-25 21:58:17 +000016697 */
Bram Moolenaar2641f772005-03-25 21:58:17 +000016698 static void
Bram Moolenaar17c7c012006-01-26 22:25:15 +000016699set_qf_ll_list(wp, list_arg, action_arg, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000016700 win_T *wp UNUSED;
16701 typval_T *list_arg UNUSED;
16702 typval_T *action_arg UNUSED;
Bram Moolenaar2641f772005-03-25 21:58:17 +000016703 typval_T *rettv;
16704{
Bram Moolenaar0ac93792006-01-21 22:16:51 +000016705#ifdef FEAT_QUICKFIX
Bram Moolenaarf4630b62005-05-20 21:31:17 +000016706 char_u *act;
16707 int action = ' ';
Bram Moolenaar0ac93792006-01-21 22:16:51 +000016708#endif
Bram Moolenaarf4630b62005-05-20 21:31:17 +000016709
Bram Moolenaar2641f772005-03-25 21:58:17 +000016710 rettv->vval.v_number = -1;
16711
16712#ifdef FEAT_QUICKFIX
Bram Moolenaar17c7c012006-01-26 22:25:15 +000016713 if (list_arg->v_type != VAR_LIST)
Bram Moolenaar2641f772005-03-25 21:58:17 +000016714 EMSG(_(e_listreq));
16715 else
16716 {
Bram Moolenaar17c7c012006-01-26 22:25:15 +000016717 list_T *l = list_arg->vval.v_list;
Bram Moolenaar2641f772005-03-25 21:58:17 +000016718
Bram Moolenaar17c7c012006-01-26 22:25:15 +000016719 if (action_arg->v_type == VAR_STRING)
Bram Moolenaarf4630b62005-05-20 21:31:17 +000016720 {
Bram Moolenaar17c7c012006-01-26 22:25:15 +000016721 act = get_tv_string_chk(action_arg);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016722 if (act == NULL)
16723 return; /* type error; errmsg already given */
Bram Moolenaarf4630b62005-05-20 21:31:17 +000016724 if (*act == 'a' || *act == 'r')
16725 action = *act;
16726 }
16727
Bram Moolenaar81484f42012-12-05 15:16:47 +010016728 if (l != NULL && set_errorlist(wp, l, action,
16729 (char_u *)(wp == NULL ? "setqflist()" : "setloclist()")) == OK)
Bram Moolenaar2641f772005-03-25 21:58:17 +000016730 rettv->vval.v_number = 0;
16731 }
16732#endif
16733}
16734
16735/*
Bram Moolenaar17c7c012006-01-26 22:25:15 +000016736 * "setloclist()" function
16737 */
Bram Moolenaar17c7c012006-01-26 22:25:15 +000016738 static void
16739f_setloclist(argvars, rettv)
16740 typval_T *argvars;
16741 typval_T *rettv;
16742{
16743 win_T *win;
16744
16745 rettv->vval.v_number = -1;
16746
Bram Moolenaar99ebf042006-04-15 20:28:54 +000016747 win = find_win_by_nr(&argvars[0], NULL);
Bram Moolenaar17c7c012006-01-26 22:25:15 +000016748 if (win != NULL)
16749 set_qf_ll_list(win, &argvars[1], &argvars[2], rettv);
16750}
16751
16752/*
Bram Moolenaar6ee10162007-07-26 20:58:42 +000016753 * "setmatches()" function
16754 */
16755 static void
16756f_setmatches(argvars, rettv)
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +010016757 typval_T *argvars UNUSED;
16758 typval_T *rettv UNUSED;
Bram Moolenaar6ee10162007-07-26 20:58:42 +000016759{
16760#ifdef FEAT_SEARCH_EXTRA
16761 list_T *l;
16762 listitem_T *li;
16763 dict_T *d;
16764
16765 rettv->vval.v_number = -1;
16766 if (argvars[0].v_type != VAR_LIST)
16767 {
16768 EMSG(_(e_listreq));
16769 return;
16770 }
16771 if ((l = argvars[0].vval.v_list) != NULL)
16772 {
16773
16774 /* To some extent make sure that we are dealing with a list from
16775 * "getmatches()". */
16776 li = l->lv_first;
16777 while (li != NULL)
16778 {
16779 if (li->li_tv.v_type != VAR_DICT
16780 || (d = li->li_tv.vval.v_dict) == NULL)
16781 {
16782 EMSG(_(e_invarg));
16783 return;
16784 }
16785 if (!(dict_find(d, (char_u *)"group", -1) != NULL
16786 && dict_find(d, (char_u *)"pattern", -1) != NULL
16787 && dict_find(d, (char_u *)"priority", -1) != NULL
16788 && dict_find(d, (char_u *)"id", -1) != NULL))
16789 {
16790 EMSG(_(e_invarg));
16791 return;
16792 }
16793 li = li->li_next;
16794 }
16795
16796 clear_matches(curwin);
16797 li = l->lv_first;
16798 while (li != NULL)
16799 {
16800 d = li->li_tv.vval.v_dict;
16801 match_add(curwin, get_dict_string(d, (char_u *)"group", FALSE),
16802 get_dict_string(d, (char_u *)"pattern", FALSE),
16803 (int)get_dict_number(d, (char_u *)"priority"),
16804 (int)get_dict_number(d, (char_u *)"id"));
16805 li = li->li_next;
16806 }
16807 rettv->vval.v_number = 0;
16808 }
16809#endif
16810}
16811
16812/*
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016813 * "setpos()" function
16814 */
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016815 static void
16816f_setpos(argvars, rettv)
16817 typval_T *argvars;
16818 typval_T *rettv;
16819{
16820 pos_T pos;
16821 int fnum;
16822 char_u *name;
Bram Moolenaar493c1782014-05-28 14:34:46 +020016823 colnr_T curswant = -1;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016824
Bram Moolenaar08250432008-02-13 11:42:46 +000016825 rettv->vval.v_number = -1;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016826 name = get_tv_string_chk(argvars);
16827 if (name != NULL)
16828 {
Bram Moolenaar493c1782014-05-28 14:34:46 +020016829 if (list2fpos(&argvars[1], &pos, &fnum, &curswant) == OK)
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016830 {
Bram Moolenaar742d1ec2009-12-31 12:18:30 +000016831 if (--pos.col < 0)
16832 pos.col = 0;
Bram Moolenaar08250432008-02-13 11:42:46 +000016833 if (name[0] == '.' && name[1] == NUL)
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016834 {
Bram Moolenaar08250432008-02-13 11:42:46 +000016835 /* set cursor */
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016836 if (fnum == curbuf->b_fnum)
16837 {
16838 curwin->w_cursor = pos;
Bram Moolenaar493c1782014-05-28 14:34:46 +020016839 if (curswant >= 0)
16840 curwin->w_curswant = curswant - 1;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016841 check_cursor();
Bram Moolenaar08250432008-02-13 11:42:46 +000016842 rettv->vval.v_number = 0;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016843 }
16844 else
16845 EMSG(_(e_invarg));
16846 }
Bram Moolenaar08250432008-02-13 11:42:46 +000016847 else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL)
16848 {
16849 /* set mark */
16850 if (setmark_pos(name[1], &pos, fnum) == OK)
16851 rettv->vval.v_number = 0;
16852 }
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016853 else
16854 EMSG(_(e_invarg));
16855 }
16856 }
16857}
16858
16859/*
Bram Moolenaar17c7c012006-01-26 22:25:15 +000016860 * "setqflist()" function
16861 */
Bram Moolenaar17c7c012006-01-26 22:25:15 +000016862 static void
16863f_setqflist(argvars, rettv)
16864 typval_T *argvars;
16865 typval_T *rettv;
16866{
16867 set_qf_ll_list(NULL, &argvars[0], &argvars[1], rettv);
16868}
16869
16870/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000016871 * "setreg()" function
16872 */
16873 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016874f_setreg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000016875 typval_T *argvars;
16876 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016877{
16878 int regname;
16879 char_u *strregname;
16880 char_u *stropt;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016881 char_u *strval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016882 int append;
16883 char_u yank_type;
16884 long block_len;
16885
16886 block_len = -1;
16887 yank_type = MAUTO;
16888 append = FALSE;
16889
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016890 strregname = get_tv_string_chk(argvars);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016891 rettv->vval.v_number = 1; /* FAIL is default */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016892
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016893 if (strregname == NULL)
16894 return; /* type error; errmsg already given */
16895 regname = *strregname;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016896 if (regname == 0 || regname == '@')
16897 regname = '"';
Bram Moolenaar071d4272004-06-13 20:20:40 +000016898
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016899 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016900 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016901 stropt = get_tv_string_chk(&argvars[2]);
16902 if (stropt == NULL)
16903 return; /* type error */
16904 for (; *stropt != NUL; ++stropt)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016905 switch (*stropt)
16906 {
16907 case 'a': case 'A': /* append */
16908 append = TRUE;
16909 break;
16910 case 'v': case 'c': /* character-wise selection */
16911 yank_type = MCHAR;
16912 break;
16913 case 'V': case 'l': /* line-wise selection */
16914 yank_type = MLINE;
16915 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016916 case 'b': case Ctrl_V: /* block-wise selection */
16917 yank_type = MBLOCK;
16918 if (VIM_ISDIGIT(stropt[1]))
16919 {
16920 ++stropt;
16921 block_len = getdigits(&stropt) - 1;
16922 --stropt;
16923 }
16924 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016925 }
16926 }
16927
Bram Moolenaar5a50c222014-04-02 22:17:10 +020016928 if (argvars[1].v_type == VAR_LIST)
16929 {
16930 char_u **lstval;
Bram Moolenaar7d647822014-04-05 21:28:56 +020016931 char_u **allocval;
16932 char_u buf[NUMBUFLEN];
Bram Moolenaar5a50c222014-04-02 22:17:10 +020016933 char_u **curval;
Bram Moolenaar7d647822014-04-05 21:28:56 +020016934 char_u **curallocval;
Bram Moolenaar5a50c222014-04-02 22:17:10 +020016935 int len = argvars[1].vval.v_list->lv_len;
16936 listitem_T *li;
16937
Bram Moolenaar7d647822014-04-05 21:28:56 +020016938 /* First half: use for pointers to result lines; second half: use for
16939 * pointers to allocated copies. */
16940 lstval = (char_u **)alloc(sizeof(char_u *) * ((len + 1) * 2));
Bram Moolenaar5a50c222014-04-02 22:17:10 +020016941 if (lstval == NULL)
16942 return;
16943 curval = lstval;
Bram Moolenaar7d647822014-04-05 21:28:56 +020016944 allocval = lstval + len + 2;
16945 curallocval = allocval;
Bram Moolenaar5a50c222014-04-02 22:17:10 +020016946
16947 for (li = argvars[1].vval.v_list->lv_first; li != NULL;
16948 li = li->li_next)
16949 {
Bram Moolenaar7d647822014-04-05 21:28:56 +020016950 strval = get_tv_string_buf_chk(&li->li_tv, buf);
Bram Moolenaar5a50c222014-04-02 22:17:10 +020016951 if (strval == NULL)
Bram Moolenaar7d647822014-04-05 21:28:56 +020016952 goto free_lstval;
16953 if (strval == buf)
Bram Moolenaar5a50c222014-04-02 22:17:10 +020016954 {
Bram Moolenaar7d647822014-04-05 21:28:56 +020016955 /* Need to make a copy, next get_tv_string_buf_chk() will
16956 * overwrite the string. */
16957 strval = vim_strsave(buf);
16958 if (strval == NULL)
16959 goto free_lstval;
16960 *curallocval++ = strval;
Bram Moolenaar5a50c222014-04-02 22:17:10 +020016961 }
16962 *curval++ = strval;
16963 }
16964 *curval++ = NULL;
16965
16966 write_reg_contents_lst(regname, lstval, -1,
16967 append, yank_type, block_len);
Bram Moolenaar7d647822014-04-05 21:28:56 +020016968free_lstval:
16969 while (curallocval > allocval)
16970 vim_free(*--curallocval);
Bram Moolenaar5a50c222014-04-02 22:17:10 +020016971 vim_free(lstval);
16972 }
16973 else
16974 {
16975 strval = get_tv_string_chk(&argvars[1]);
16976 if (strval == NULL)
16977 return;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016978 write_reg_contents_ex(regname, strval, -1,
Bram Moolenaar071d4272004-06-13 20:20:40 +000016979 append, yank_type, block_len);
Bram Moolenaar5a50c222014-04-02 22:17:10 +020016980 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016981 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016982}
16983
Bram Moolenaar99ebf042006-04-15 20:28:54 +000016984/*
Bram Moolenaar06b5d512010-05-22 15:37:44 +020016985 * "settabvar()" function
16986 */
16987 static void
16988f_settabvar(argvars, rettv)
16989 typval_T *argvars;
16990 typval_T *rettv;
16991{
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020016992#ifdef FEAT_WINDOWS
Bram Moolenaar06b5d512010-05-22 15:37:44 +020016993 tabpage_T *save_curtab;
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020016994 tabpage_T *tp;
16995#endif
Bram Moolenaar06b5d512010-05-22 15:37:44 +020016996 char_u *varname, *tabvarname;
16997 typval_T *varp;
Bram Moolenaar06b5d512010-05-22 15:37:44 +020016998
16999 rettv->vval.v_number = 0;
17000
17001 if (check_restricted() || check_secure())
17002 return;
17003
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020017004#ifdef FEAT_WINDOWS
Bram Moolenaar06b5d512010-05-22 15:37:44 +020017005 tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL));
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020017006#endif
Bram Moolenaar06b5d512010-05-22 15:37:44 +020017007 varname = get_tv_string_chk(&argvars[1]);
17008 varp = &argvars[2];
17009
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020017010 if (varname != NULL && varp != NULL
17011#ifdef FEAT_WINDOWS
17012 && tp != NULL
17013#endif
17014 )
Bram Moolenaar06b5d512010-05-22 15:37:44 +020017015 {
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020017016#ifdef FEAT_WINDOWS
Bram Moolenaar06b5d512010-05-22 15:37:44 +020017017 save_curtab = curtab;
Bram Moolenaar49e649f2013-05-06 04:50:35 +020017018 goto_tabpage_tp(tp, FALSE, FALSE);
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020017019#endif
Bram Moolenaar06b5d512010-05-22 15:37:44 +020017020
17021 tabvarname = alloc((unsigned)STRLEN(varname) + 3);
17022 if (tabvarname != NULL)
17023 {
17024 STRCPY(tabvarname, "t:");
17025 STRCPY(tabvarname + 2, varname);
17026 set_var(tabvarname, varp, TRUE);
17027 vim_free(tabvarname);
17028 }
17029
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020017030#ifdef FEAT_WINDOWS
Bram Moolenaar06b5d512010-05-22 15:37:44 +020017031 /* Restore current tabpage */
17032 if (valid_tabpage(save_curtab))
Bram Moolenaar49e649f2013-05-06 04:50:35 +020017033 goto_tabpage_tp(save_curtab, FALSE, FALSE);
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020017034#endif
Bram Moolenaar06b5d512010-05-22 15:37:44 +020017035 }
17036}
17037
17038/*
Bram Moolenaar99ebf042006-04-15 20:28:54 +000017039 * "settabwinvar()" function
17040 */
17041 static void
17042f_settabwinvar(argvars, rettv)
17043 typval_T *argvars;
17044 typval_T *rettv;
17045{
17046 setwinvar(argvars, rettv, 1);
17047}
Bram Moolenaar071d4272004-06-13 20:20:40 +000017048
17049/*
Bram Moolenaar99ebf042006-04-15 20:28:54 +000017050 * "setwinvar()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000017051 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017052 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017053f_setwinvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000017054 typval_T *argvars;
17055 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017056{
Bram Moolenaar99ebf042006-04-15 20:28:54 +000017057 setwinvar(argvars, rettv, 0);
17058}
17059
17060/*
17061 * "setwinvar()" and "settabwinvar()" functions
17062 */
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +020017063
Bram Moolenaar99ebf042006-04-15 20:28:54 +000017064 static void
17065setwinvar(argvars, rettv, off)
17066 typval_T *argvars;
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000017067 typval_T *rettv UNUSED;
Bram Moolenaar99ebf042006-04-15 20:28:54 +000017068 int off;
17069{
Bram Moolenaar071d4272004-06-13 20:20:40 +000017070 win_T *win;
17071#ifdef FEAT_WINDOWS
17072 win_T *save_curwin;
Bram Moolenaar99ebf042006-04-15 20:28:54 +000017073 tabpage_T *save_curtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017074#endif
17075 char_u *varname, *winvarname;
Bram Moolenaar33570922005-01-25 22:26:29 +000017076 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017077 char_u nbuf[NUMBUFLEN];
Bram Moolenaar8c0e3222013-06-16 17:32:40 +020017078 tabpage_T *tp = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017079
17080 if (check_restricted() || check_secure())
17081 return;
Bram Moolenaar99ebf042006-04-15 20:28:54 +000017082
17083#ifdef FEAT_WINDOWS
17084 if (off == 1)
17085 tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL));
17086 else
17087 tp = curtab;
17088#endif
17089 win = find_win_by_nr(&argvars[off], tp);
17090 varname = get_tv_string_chk(&argvars[off + 1]);
17091 varp = &argvars[off + 2];
Bram Moolenaar071d4272004-06-13 20:20:40 +000017092
17093 if (win != NULL && varname != NULL && varp != NULL)
17094 {
17095#ifdef FEAT_WINDOWS
Bram Moolenaard6949742013-06-16 14:18:28 +020017096 if (switch_win(&save_curwin, &save_curtab, win, tp, TRUE) == FAIL)
Bram Moolenaar99ebf042006-04-15 20:28:54 +000017097 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017098#endif
17099
17100 if (*varname == '&')
17101 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017102 long numval;
17103 char_u *strval;
17104 int error = FALSE;
17105
Bram Moolenaar071d4272004-06-13 20:20:40 +000017106 ++varname;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017107 numval = get_tv_number_chk(varp, &error);
17108 strval = get_tv_string_buf_chk(varp, nbuf);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017109 if (!error && strval != NULL)
17110 set_option_value(varname, numval, strval, OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017111 }
17112 else
17113 {
17114 winvarname = alloc((unsigned)STRLEN(varname) + 3);
17115 if (winvarname != NULL)
17116 {
17117 STRCPY(winvarname, "w:");
17118 STRCPY(winvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000017119 set_var(winvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017120 vim_free(winvarname);
17121 }
17122 }
17123
17124#ifdef FEAT_WINDOWS
Bram Moolenaard6949742013-06-16 14:18:28 +020017125 restore_win(save_curwin, save_curtab, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017126#endif
17127 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017128}
17129
Bram Moolenaaraf9aeb92013-02-13 17:35:04 +010017130#ifdef FEAT_CRYPT
17131/*
17132 * "sha256({string})" function
17133 */
17134 static void
17135f_sha256(argvars, rettv)
17136 typval_T *argvars;
17137 typval_T *rettv;
17138{
17139 char_u *p;
17140
17141 p = get_tv_string(&argvars[0]);
17142 rettv->vval.v_string = vim_strsave(
17143 sha256_bytes(p, (int)STRLEN(p), NULL, 0));
17144 rettv->v_type = VAR_STRING;
17145}
17146#endif /* FEAT_CRYPT */
17147
Bram Moolenaar071d4272004-06-13 20:20:40 +000017148/*
Bram Moolenaar60a495f2006-10-03 12:44:42 +000017149 * "shellescape({string})" function
17150 */
17151 static void
17152f_shellescape(argvars, rettv)
17153 typval_T *argvars;
17154 typval_T *rettv;
17155{
Bram Moolenaar05bb9532008-07-04 09:44:11 +000017156 rettv->vval.v_string = vim_strsave_shellescape(
Bram Moolenaar26df0922014-02-23 23:39:13 +010017157 get_tv_string(&argvars[0]), non_zero_arg(&argvars[1]), TRUE);
Bram Moolenaar60a495f2006-10-03 12:44:42 +000017158 rettv->v_type = VAR_STRING;
17159}
17160
17161/*
Bram Moolenaar2d17fa32012-10-21 00:45:18 +020017162 * shiftwidth() function
17163 */
17164 static void
17165f_shiftwidth(argvars, rettv)
Bram Moolenaar95e09ea2012-10-21 23:56:05 +020017166 typval_T *argvars UNUSED;
Bram Moolenaar2d17fa32012-10-21 00:45:18 +020017167 typval_T *rettv;
17168{
Bram Moolenaar6bcbcc52013-11-05 07:13:41 +010017169 rettv->vval.v_number = get_sw_value(curbuf);
Bram Moolenaar2d17fa32012-10-21 00:45:18 +020017170}
17171
17172/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000017173 * "simplify()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000017174 */
17175 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000017176f_simplify(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000017177 typval_T *argvars;
17178 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017179{
Bram Moolenaar0d660222005-01-07 21:51:51 +000017180 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017181
Bram Moolenaar0d660222005-01-07 21:51:51 +000017182 p = get_tv_string(&argvars[0]);
17183 rettv->vval.v_string = vim_strsave(p);
17184 simplify_filename(rettv->vval.v_string); /* simplify in place */
17185 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017186}
17187
Bram Moolenaar8c8de832008-06-24 22:58:06 +000017188#ifdef FEAT_FLOAT
17189/*
17190 * "sin()" function
17191 */
17192 static void
17193f_sin(argvars, rettv)
17194 typval_T *argvars;
17195 typval_T *rettv;
17196{
17197 float_T f;
17198
17199 rettv->v_type = VAR_FLOAT;
17200 if (get_float_arg(argvars, &f) == OK)
17201 rettv->vval.v_float = sin(f);
17202 else
17203 rettv->vval.v_float = 0.0;
17204}
Bram Moolenaardb7c6862010-05-21 16:33:48 +020017205
17206/*
17207 * "sinh()" function
17208 */
17209 static void
17210f_sinh(argvars, rettv)
17211 typval_T *argvars;
17212 typval_T *rettv;
17213{
17214 float_T f;
17215
17216 rettv->v_type = VAR_FLOAT;
17217 if (get_float_arg(argvars, &f) == OK)
17218 rettv->vval.v_float = sinh(f);
17219 else
17220 rettv->vval.v_float = 0.0;
17221}
Bram Moolenaar8c8de832008-06-24 22:58:06 +000017222#endif
17223
Bram Moolenaar0d660222005-01-07 21:51:51 +000017224static int
17225#ifdef __BORLANDC__
17226 _RTLENTRYF
17227#endif
17228 item_compare __ARGS((const void *s1, const void *s2));
17229static int
17230#ifdef __BORLANDC__
17231 _RTLENTRYF
17232#endif
17233 item_compare2 __ARGS((const void *s1, const void *s2));
17234
17235static int item_compare_ic;
17236static char_u *item_compare_func;
Bram Moolenaar5f894962011-06-19 02:55:37 +020017237static dict_T *item_compare_selfdict;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017238static int item_compare_func_err;
Bram Moolenaar327aa022014-03-25 18:24:23 +010017239static void do_sort_uniq __ARGS((typval_T *argvars, typval_T *rettv, int sort));
Bram Moolenaar0d660222005-01-07 21:51:51 +000017240#define ITEM_COMPARE_FAIL 999
17241
Bram Moolenaar071d4272004-06-13 20:20:40 +000017242/*
Bram Moolenaar327aa022014-03-25 18:24:23 +010017243 * Compare functions for f_sort() and f_uniq() below.
Bram Moolenaar071d4272004-06-13 20:20:40 +000017244 */
Bram Moolenaar0d660222005-01-07 21:51:51 +000017245 static int
17246#ifdef __BORLANDC__
17247_RTLENTRYF
17248#endif
17249item_compare(s1, s2)
17250 const void *s1;
17251 const void *s2;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017252{
Bram Moolenaar0d660222005-01-07 21:51:51 +000017253 char_u *p1, *p2;
17254 char_u *tofree1, *tofree2;
17255 int res;
17256 char_u numbuf1[NUMBUFLEN];
17257 char_u numbuf2[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000017258
Bram Moolenaarb71eaae2006-01-20 23:10:18 +000017259 p1 = tv2string(&(*(listitem_T **)s1)->li_tv, &tofree1, numbuf1, 0);
17260 p2 = tv2string(&(*(listitem_T **)s2)->li_tv, &tofree2, numbuf2, 0);
Bram Moolenaar92c5aba2007-08-14 20:29:31 +000017261 if (p1 == NULL)
17262 p1 = (char_u *)"";
17263 if (p2 == NULL)
17264 p2 = (char_u *)"";
Bram Moolenaar0d660222005-01-07 21:51:51 +000017265 if (item_compare_ic)
17266 res = STRICMP(p1, p2);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017267 else
Bram Moolenaar0d660222005-01-07 21:51:51 +000017268 res = STRCMP(p1, p2);
17269 vim_free(tofree1);
17270 vim_free(tofree2);
17271 return res;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017272}
17273
17274 static int
Bram Moolenaar0d660222005-01-07 21:51:51 +000017275#ifdef __BORLANDC__
17276_RTLENTRYF
Bram Moolenaar071d4272004-06-13 20:20:40 +000017277#endif
Bram Moolenaar0d660222005-01-07 21:51:51 +000017278item_compare2(s1, s2)
17279 const void *s1;
17280 const void *s2;
17281{
17282 int res;
Bram Moolenaar33570922005-01-25 22:26:29 +000017283 typval_T rettv;
Bram Moolenaareb3593b2006-04-22 22:33:57 +000017284 typval_T argv[3];
Bram Moolenaar0d660222005-01-07 21:51:51 +000017285 int dummy;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017286
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017287 /* shortcut after failure in previous call; compare all items equal */
17288 if (item_compare_func_err)
17289 return 0;
17290
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017291 /* copy the values. This is needed to be able to set v_lock to VAR_FIXED
17292 * in the copy without changing the original list items. */
Bram Moolenaar33570922005-01-25 22:26:29 +000017293 copy_tv(&(*(listitem_T **)s1)->li_tv, &argv[0]);
17294 copy_tv(&(*(listitem_T **)s2)->li_tv, &argv[1]);
Bram Moolenaar0d660222005-01-07 21:51:51 +000017295
17296 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000017297 res = call_func(item_compare_func, (int)STRLEN(item_compare_func),
Bram Moolenaar5f894962011-06-19 02:55:37 +020017298 &rettv, 2, argv, 0L, 0L, &dummy, TRUE,
17299 item_compare_selfdict);
Bram Moolenaar0d660222005-01-07 21:51:51 +000017300 clear_tv(&argv[0]);
17301 clear_tv(&argv[1]);
17302
17303 if (res == FAIL)
17304 res = ITEM_COMPARE_FAIL;
17305 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017306 res = get_tv_number_chk(&rettv, &item_compare_func_err);
17307 if (item_compare_func_err)
Bram Moolenaar61c4e2c2008-08-25 02:49:18 +000017308 res = ITEM_COMPARE_FAIL; /* return value has wrong type */
Bram Moolenaar0d660222005-01-07 21:51:51 +000017309 clear_tv(&rettv);
17310 return res;
17311}
17312
17313/*
17314 * "sort({list})" function
17315 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017316 static void
Bram Moolenaar327aa022014-03-25 18:24:23 +010017317do_sort_uniq(argvars, rettv, sort)
Bram Moolenaar33570922005-01-25 22:26:29 +000017318 typval_T *argvars;
17319 typval_T *rettv;
Bram Moolenaar327aa022014-03-25 18:24:23 +010017320 int sort;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017321{
Bram Moolenaar33570922005-01-25 22:26:29 +000017322 list_T *l;
17323 listitem_T *li;
17324 listitem_T **ptrs;
Bram Moolenaar0d660222005-01-07 21:51:51 +000017325 long len;
17326 long i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017327
Bram Moolenaar0d660222005-01-07 21:51:51 +000017328 if (argvars[0].v_type != VAR_LIST)
Bram Moolenaar327aa022014-03-25 18:24:23 +010017329 EMSG2(_(e_listarg), sort ? "sort()" : "uniq()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000017330 else
17331 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000017332 l = argvars[0].vval.v_list;
Bram Moolenaar32f649e2011-04-11 13:46:13 +020017333 if (l == NULL || tv_check_lock(l->lv_lock,
Bram Moolenaar327aa022014-03-25 18:24:23 +010017334 (char_u *)(sort ? _("sort() argument") : _("uniq() argument"))))
Bram Moolenaar0d660222005-01-07 21:51:51 +000017335 return;
17336 rettv->vval.v_list = l;
17337 rettv->v_type = VAR_LIST;
17338 ++l->lv_refcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017339
Bram Moolenaar0d660222005-01-07 21:51:51 +000017340 len = list_len(l);
17341 if (len <= 1)
17342 return; /* short list sorts pretty quickly */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017343
Bram Moolenaar0d660222005-01-07 21:51:51 +000017344 item_compare_ic = FALSE;
17345 item_compare_func = NULL;
Bram Moolenaar5f894962011-06-19 02:55:37 +020017346 item_compare_selfdict = NULL;
Bram Moolenaar0d660222005-01-07 21:51:51 +000017347 if (argvars[1].v_type != VAR_UNKNOWN)
17348 {
Bram Moolenaar5f894962011-06-19 02:55:37 +020017349 /* optional second argument: {func} */
Bram Moolenaar0d660222005-01-07 21:51:51 +000017350 if (argvars[1].v_type == VAR_FUNC)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017351 item_compare_func = argvars[1].vval.v_string;
Bram Moolenaar0d660222005-01-07 21:51:51 +000017352 else
17353 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017354 int error = FALSE;
17355
17356 i = get_tv_number_chk(&argvars[1], &error);
17357 if (error)
17358 return; /* type error; errmsg already given */
Bram Moolenaar0d660222005-01-07 21:51:51 +000017359 if (i == 1)
17360 item_compare_ic = TRUE;
17361 else
17362 item_compare_func = get_tv_string(&argvars[1]);
17363 }
Bram Moolenaar5f894962011-06-19 02:55:37 +020017364
17365 if (argvars[2].v_type != VAR_UNKNOWN)
17366 {
17367 /* optional third argument: {dict} */
17368 if (argvars[2].v_type != VAR_DICT)
17369 {
17370 EMSG(_(e_dictreq));
17371 return;
17372 }
17373 item_compare_selfdict = argvars[2].vval.v_dict;
17374 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000017375 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017376
Bram Moolenaar0d660222005-01-07 21:51:51 +000017377 /* Make an array with each entry pointing to an item in the List. */
Bram Moolenaar33570922005-01-25 22:26:29 +000017378 ptrs = (listitem_T **)alloc((int)(len * sizeof(listitem_T *)));
Bram Moolenaar0d660222005-01-07 21:51:51 +000017379 if (ptrs == NULL)
17380 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017381
Bram Moolenaar327aa022014-03-25 18:24:23 +010017382 i = 0;
17383 if (sort)
17384 {
17385 /* sort(): ptrs will be the list to sort */
17386 for (li = l->lv_first; li != NULL; li = li->li_next)
17387 ptrs[i++] = li;
17388
17389 item_compare_func_err = FALSE;
17390 /* test the compare function */
17391 if (item_compare_func != NULL
17392 && item_compare2((void *)&ptrs[0], (void *)&ptrs[1])
Bram Moolenaar0d660222005-01-07 21:51:51 +000017393 == ITEM_COMPARE_FAIL)
Bram Moolenaar327aa022014-03-25 18:24:23 +010017394 EMSG(_("E702: Sort compare function failed"));
17395 else
17396 {
17397 /* Sort the array with item pointers. */
17398 qsort((void *)ptrs, (size_t)len, sizeof(listitem_T *),
17399 item_compare_func == NULL ? item_compare : item_compare2);
17400
17401 if (!item_compare_func_err)
17402 {
17403 /* Clear the List and append the items in sorted order. */
17404 l->lv_first = l->lv_last = l->lv_idx_item = NULL;
17405 l->lv_len = 0;
17406 for (i = 0; i < len; ++i)
17407 list_append(l, ptrs[i]);
17408 }
17409 }
17410 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017411 else
Bram Moolenaar0d660222005-01-07 21:51:51 +000017412 {
Bram Moolenaar327aa022014-03-25 18:24:23 +010017413 int (*item_compare_func_ptr)__ARGS((const void *, const void *));
17414
17415 /* f_uniq(): ptrs will be a stack of items to remove */
17416 item_compare_func_err = FALSE;
17417 item_compare_func_ptr = item_compare_func
17418 ? item_compare2 : item_compare;
17419
17420 for (li = l->lv_first; li != NULL && li->li_next != NULL;
17421 li = li->li_next)
17422 {
17423 if (item_compare_func_ptr((void *)&li, (void *)&li->li_next)
17424 == 0)
17425 ptrs[i++] = li;
17426 if (item_compare_func_err)
17427 {
17428 EMSG(_("E882: Uniq compare function failed"));
17429 break;
17430 }
17431 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000017432
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017433 if (!item_compare_func_err)
17434 {
Bram Moolenaar327aa022014-03-25 18:24:23 +010017435 while (--i >= 0)
17436 {
17437 li = ptrs[i]->li_next;
17438 ptrs[i]->li_next = li->li_next;
17439 if (li->li_next != NULL)
17440 li->li_next->li_prev = ptrs[i];
17441 else
17442 l->lv_last = ptrs[i];
17443 list_fix_watch(l, li);
17444 listitem_free(li);
17445 l->lv_len--;
17446 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017447 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000017448 }
17449
17450 vim_free(ptrs);
17451 }
17452}
17453
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017454/*
Bram Moolenaar327aa022014-03-25 18:24:23 +010017455 * "sort({list})" function
17456 */
17457 static void
17458f_sort(argvars, rettv)
17459 typval_T *argvars;
17460 typval_T *rettv;
17461{
17462 do_sort_uniq(argvars, rettv, TRUE);
17463}
17464
17465/*
17466 * "uniq({list})" function
17467 */
17468 static void
17469f_uniq(argvars, rettv)
17470 typval_T *argvars;
17471 typval_T *rettv;
17472{
17473 do_sort_uniq(argvars, rettv, FALSE);
17474}
17475
17476/*
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +000017477 * "soundfold({word})" function
17478 */
17479 static void
17480f_soundfold(argvars, rettv)
17481 typval_T *argvars;
17482 typval_T *rettv;
17483{
17484 char_u *s;
17485
17486 rettv->v_type = VAR_STRING;
17487 s = get_tv_string(&argvars[0]);
Bram Moolenaar3c56a962006-03-12 22:19:04 +000017488#ifdef FEAT_SPELL
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +000017489 rettv->vval.v_string = eval_soundfold(s);
17490#else
17491 rettv->vval.v_string = vim_strsave(s);
17492#endif
17493}
17494
17495/*
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017496 * "spellbadword()" function
17497 */
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017498 static void
17499f_spellbadword(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000017500 typval_T *argvars UNUSED;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017501 typval_T *rettv;
17502{
Bram Moolenaar4463f292005-09-25 22:20:24 +000017503 char_u *word = (char_u *)"";
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000017504 hlf_T attr = HLF_COUNT;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000017505 int len = 0;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017506
Bram Moolenaareddf53b2006-02-27 00:11:10 +000017507 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar4463f292005-09-25 22:20:24 +000017508 return;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017509
Bram Moolenaar3c56a962006-03-12 22:19:04 +000017510#ifdef FEAT_SPELL
Bram Moolenaar4463f292005-09-25 22:20:24 +000017511 if (argvars[0].v_type == VAR_UNKNOWN)
17512 {
17513 /* Find the start and length of the badly spelled word. */
17514 len = spell_move_to(curwin, FORWARD, TRUE, TRUE, &attr);
17515 if (len != 0)
17516 word = ml_get_cursor();
17517 }
Bram Moolenaar860cae12010-06-05 23:22:07 +020017518 else if (curwin->w_p_spell && *curbuf->b_s.b_p_spl != NUL)
Bram Moolenaar4463f292005-09-25 22:20:24 +000017519 {
17520 char_u *str = get_tv_string_chk(&argvars[0]);
17521 int capcol = -1;
17522
17523 if (str != NULL)
17524 {
17525 /* Check the argument for spelling. */
17526 while (*str != NUL)
17527 {
Bram Moolenaar4770d092006-01-12 23:22:24 +000017528 len = spell_check(curwin, str, &attr, &capcol, FALSE);
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000017529 if (attr != HLF_COUNT)
Bram Moolenaar4463f292005-09-25 22:20:24 +000017530 {
17531 word = str;
17532 break;
17533 }
17534 str += len;
17535 }
17536 }
17537 }
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017538#endif
Bram Moolenaar4463f292005-09-25 22:20:24 +000017539
Bram Moolenaareddf53b2006-02-27 00:11:10 +000017540 list_append_string(rettv->vval.v_list, word, len);
17541 list_append_string(rettv->vval.v_list, (char_u *)(
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000017542 attr == HLF_SPB ? "bad" :
17543 attr == HLF_SPR ? "rare" :
17544 attr == HLF_SPL ? "local" :
17545 attr == HLF_SPC ? "caps" :
17546 ""), -1);
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017547}
17548
17549/*
17550 * "spellsuggest()" function
17551 */
17552 static void
17553f_spellsuggest(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000017554 typval_T *argvars UNUSED;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017555 typval_T *rettv;
17556{
Bram Moolenaar3c56a962006-03-12 22:19:04 +000017557#ifdef FEAT_SPELL
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017558 char_u *str;
Bram Moolenaar69e0ff92005-09-30 21:23:56 +000017559 int typeerr = FALSE;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017560 int maxcount;
17561 garray_T ga;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017562 int i;
Bram Moolenaar69e0ff92005-09-30 21:23:56 +000017563 listitem_T *li;
17564 int need_capital = FALSE;
17565#endif
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017566
Bram Moolenaareddf53b2006-02-27 00:11:10 +000017567 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017568 return;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017569
Bram Moolenaar3c56a962006-03-12 22:19:04 +000017570#ifdef FEAT_SPELL
Bram Moolenaar860cae12010-06-05 23:22:07 +020017571 if (curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL)
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017572 {
17573 str = get_tv_string(&argvars[0]);
17574 if (argvars[1].v_type != VAR_UNKNOWN)
17575 {
Bram Moolenaar69e0ff92005-09-30 21:23:56 +000017576 maxcount = get_tv_number_chk(&argvars[1], &typeerr);
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017577 if (maxcount <= 0)
17578 return;
Bram Moolenaar69e0ff92005-09-30 21:23:56 +000017579 if (argvars[2].v_type != VAR_UNKNOWN)
17580 {
17581 need_capital = get_tv_number_chk(&argvars[2], &typeerr);
17582 if (typeerr)
17583 return;
17584 }
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017585 }
17586 else
17587 maxcount = 25;
17588
Bram Moolenaar4770d092006-01-12 23:22:24 +000017589 spell_suggest_list(&ga, str, maxcount, need_capital, FALSE);
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017590
17591 for (i = 0; i < ga.ga_len; ++i)
17592 {
17593 str = ((char_u **)ga.ga_data)[i];
17594
17595 li = listitem_alloc();
17596 if (li == NULL)
17597 vim_free(str);
17598 else
17599 {
17600 li->li_tv.v_type = VAR_STRING;
17601 li->li_tv.v_lock = 0;
17602 li->li_tv.vval.v_string = str;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000017603 list_append(rettv->vval.v_list, li);
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017604 }
17605 }
17606 ga_clear(&ga);
17607 }
17608#endif
17609}
17610
Bram Moolenaar0d660222005-01-07 21:51:51 +000017611 static void
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000017612f_split(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000017613 typval_T *argvars;
17614 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000017615{
17616 char_u *str;
17617 char_u *end;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000017618 char_u *pat = NULL;
Bram Moolenaar0d660222005-01-07 21:51:51 +000017619 regmatch_T regmatch;
17620 char_u patbuf[NUMBUFLEN];
17621 char_u *save_cpo;
17622 int match;
Bram Moolenaar0d660222005-01-07 21:51:51 +000017623 colnr_T col = 0;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000017624 int keepempty = FALSE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017625 int typeerr = FALSE;
Bram Moolenaar0d660222005-01-07 21:51:51 +000017626
17627 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
17628 save_cpo = p_cpo;
17629 p_cpo = (char_u *)"";
17630
17631 str = get_tv_string(&argvars[0]);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000017632 if (argvars[1].v_type != VAR_UNKNOWN)
17633 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017634 pat = get_tv_string_buf_chk(&argvars[1], patbuf);
17635 if (pat == NULL)
17636 typeerr = TRUE;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000017637 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017638 keepempty = get_tv_number_chk(&argvars[2], &typeerr);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000017639 }
17640 if (pat == NULL || *pat == NUL)
17641 pat = (char_u *)"[\\x01- ]\\+";
Bram Moolenaar0d660222005-01-07 21:51:51 +000017642
Bram Moolenaareddf53b2006-02-27 00:11:10 +000017643 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017644 return;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017645 if (typeerr)
17646 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017647
Bram Moolenaar0d660222005-01-07 21:51:51 +000017648 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
17649 if (regmatch.regprog != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017650 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000017651 regmatch.rm_ic = FALSE;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000017652 while (*str != NUL || keepempty)
Bram Moolenaar0d660222005-01-07 21:51:51 +000017653 {
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000017654 if (*str == NUL)
17655 match = FALSE; /* empty item at the end */
17656 else
17657 match = vim_regexec_nl(&regmatch, str, col);
Bram Moolenaar0d660222005-01-07 21:51:51 +000017658 if (match)
17659 end = regmatch.startp[0];
17660 else
17661 end = str + STRLEN(str);
Bram Moolenaareddf53b2006-02-27 00:11:10 +000017662 if (keepempty || end > str || (rettv->vval.v_list->lv_len > 0
17663 && *str != NUL && match && end < regmatch.endp[0]))
Bram Moolenaar0d660222005-01-07 21:51:51 +000017664 {
Bram Moolenaareddf53b2006-02-27 00:11:10 +000017665 if (list_append_string(rettv->vval.v_list, str,
17666 (int)(end - str)) == FAIL)
Bram Moolenaar0d660222005-01-07 21:51:51 +000017667 break;
Bram Moolenaar0d660222005-01-07 21:51:51 +000017668 }
17669 if (!match)
17670 break;
17671 /* Advance to just after the match. */
17672 if (regmatch.endp[0] > str)
17673 col = 0;
17674 else
17675 {
17676 /* Don't get stuck at the same match. */
17677#ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000017678 col = (*mb_ptr2len)(regmatch.endp[0]);
Bram Moolenaar0d660222005-01-07 21:51:51 +000017679#else
17680 col = 1;
17681#endif
17682 }
17683 str = regmatch.endp[0];
17684 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017685
Bram Moolenaar473de612013-06-08 18:19:48 +020017686 vim_regfree(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017687 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017688
Bram Moolenaar0d660222005-01-07 21:51:51 +000017689 p_cpo = save_cpo;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017690}
17691
Bram Moolenaar8c8de832008-06-24 22:58:06 +000017692#ifdef FEAT_FLOAT
17693/*
17694 * "sqrt()" function
17695 */
17696 static void
17697f_sqrt(argvars, rettv)
17698 typval_T *argvars;
17699 typval_T *rettv;
17700{
17701 float_T f;
17702
17703 rettv->v_type = VAR_FLOAT;
17704 if (get_float_arg(argvars, &f) == OK)
17705 rettv->vval.v_float = sqrt(f);
17706 else
17707 rettv->vval.v_float = 0.0;
17708}
17709
17710/*
17711 * "str2float()" function
17712 */
17713 static void
17714f_str2float(argvars, rettv)
17715 typval_T *argvars;
17716 typval_T *rettv;
17717{
17718 char_u *p = skipwhite(get_tv_string(&argvars[0]));
17719
17720 if (*p == '+')
17721 p = skipwhite(p + 1);
17722 (void)string2float(p, &rettv->vval.v_float);
17723 rettv->v_type = VAR_FLOAT;
17724}
17725#endif
17726
Bram Moolenaar2c932302006-03-18 21:42:09 +000017727/*
17728 * "str2nr()" function
17729 */
17730 static void
17731f_str2nr(argvars, rettv)
17732 typval_T *argvars;
17733 typval_T *rettv;
17734{
17735 int base = 10;
17736 char_u *p;
17737 long n;
17738
17739 if (argvars[1].v_type != VAR_UNKNOWN)
17740 {
17741 base = get_tv_number(&argvars[1]);
17742 if (base != 8 && base != 10 && base != 16)
17743 {
17744 EMSG(_(e_invarg));
17745 return;
17746 }
17747 }
17748
17749 p = skipwhite(get_tv_string(&argvars[0]));
Bram Moolenaar8c8de832008-06-24 22:58:06 +000017750 if (*p == '+')
17751 p = skipwhite(p + 1);
Bram Moolenaar2c932302006-03-18 21:42:09 +000017752 vim_str2nr(p, NULL, NULL, base == 8 ? 2 : 0, base == 16 ? 2 : 0, &n, NULL);
17753 rettv->vval.v_number = n;
17754}
17755
Bram Moolenaar071d4272004-06-13 20:20:40 +000017756#ifdef HAVE_STRFTIME
17757/*
17758 * "strftime({format}[, {time}])" function
17759 */
17760 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017761f_strftime(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000017762 typval_T *argvars;
17763 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017764{
17765 char_u result_buf[256];
17766 struct tm *curtime;
17767 time_t seconds;
17768 char_u *p;
17769
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017770 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017771
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017772 p = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017773 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017774 seconds = time(NULL);
17775 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017776 seconds = (time_t)get_tv_number(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017777 curtime = localtime(&seconds);
17778 /* MSVC returns NULL for an invalid value of seconds. */
17779 if (curtime == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017780 rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
Bram Moolenaar071d4272004-06-13 20:20:40 +000017781 else
17782 {
17783# ifdef FEAT_MBYTE
17784 vimconv_T conv;
17785 char_u *enc;
17786
17787 conv.vc_type = CONV_NONE;
17788 enc = enc_locale();
17789 convert_setup(&conv, p_enc, enc);
17790 if (conv.vc_type != CONV_NONE)
17791 p = string_convert(&conv, p, NULL);
17792# endif
17793 if (p != NULL)
17794 (void)strftime((char *)result_buf, sizeof(result_buf),
17795 (char *)p, curtime);
17796 else
17797 result_buf[0] = NUL;
17798
17799# ifdef FEAT_MBYTE
17800 if (conv.vc_type != CONV_NONE)
17801 vim_free(p);
17802 convert_setup(&conv, enc, p_enc);
17803 if (conv.vc_type != CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017804 rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017805 else
17806# endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017807 rettv->vval.v_string = vim_strsave(result_buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017808
17809# ifdef FEAT_MBYTE
17810 /* Release conversion descriptors */
17811 convert_setup(&conv, NULL, NULL);
17812 vim_free(enc);
17813# endif
17814 }
17815}
17816#endif
17817
17818/*
17819 * "stridx()" function
17820 */
17821 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017822f_stridx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000017823 typval_T *argvars;
17824 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017825{
17826 char_u buf[NUMBUFLEN];
17827 char_u *needle;
17828 char_u *haystack;
Bram Moolenaar33570922005-01-25 22:26:29 +000017829 char_u *save_haystack;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017830 char_u *pos;
Bram Moolenaar33570922005-01-25 22:26:29 +000017831 int start_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017832
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017833 needle = get_tv_string_chk(&argvars[1]);
17834 save_haystack = haystack = get_tv_string_buf_chk(&argvars[0], buf);
Bram Moolenaar33570922005-01-25 22:26:29 +000017835 rettv->vval.v_number = -1;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017836 if (needle == NULL || haystack == NULL)
17837 return; /* type error; errmsg already given */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017838
Bram Moolenaar33570922005-01-25 22:26:29 +000017839 if (argvars[2].v_type != VAR_UNKNOWN)
17840 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017841 int error = FALSE;
17842
17843 start_idx = get_tv_number_chk(&argvars[2], &error);
17844 if (error || start_idx >= (int)STRLEN(haystack))
Bram Moolenaar33570922005-01-25 22:26:29 +000017845 return;
Bram Moolenaar532c7802005-01-27 14:44:31 +000017846 if (start_idx >= 0)
17847 haystack += start_idx;
Bram Moolenaar33570922005-01-25 22:26:29 +000017848 }
17849
17850 pos = (char_u *)strstr((char *)haystack, (char *)needle);
17851 if (pos != NULL)
17852 rettv->vval.v_number = (varnumber_T)(pos - save_haystack);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017853}
17854
17855/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017856 * "string()" function
17857 */
17858 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017859f_string(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000017860 typval_T *argvars;
17861 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017862{
17863 char_u *tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000017864 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017865
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017866 rettv->v_type = VAR_STRING;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +000017867 rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf, 0);
Bram Moolenaar8c8de832008-06-24 22:58:06 +000017868 /* Make a copy if we have a value but it's not in allocated memory. */
Bram Moolenaar92c5aba2007-08-14 20:29:31 +000017869 if (rettv->vval.v_string != NULL && tofree == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017870 rettv->vval.v_string = vim_strsave(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017871}
17872
17873/*
17874 * "strlen()" function
17875 */
17876 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017877f_strlen(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000017878 typval_T *argvars;
17879 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017880{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017881 rettv->vval.v_number = (varnumber_T)(STRLEN(
17882 get_tv_string(&argvars[0])));
Bram Moolenaar071d4272004-06-13 20:20:40 +000017883}
17884
17885/*
Bram Moolenaar72597a52010-07-18 15:31:08 +020017886 * "strchars()" function
17887 */
17888 static void
17889f_strchars(argvars, rettv)
17890 typval_T *argvars;
17891 typval_T *rettv;
17892{
17893 char_u *s = get_tv_string(&argvars[0]);
17894#ifdef FEAT_MBYTE
17895 varnumber_T len = 0;
17896
17897 while (*s != NUL)
17898 {
17899 mb_cptr2char_adv(&s);
17900 ++len;
17901 }
17902 rettv->vval.v_number = len;
17903#else
17904 rettv->vval.v_number = (varnumber_T)(STRLEN(s));
17905#endif
17906}
17907
17908/*
Bram Moolenaardc536092010-07-18 15:45:49 +020017909 * "strdisplaywidth()" function
17910 */
17911 static void
17912f_strdisplaywidth(argvars, rettv)
17913 typval_T *argvars;
17914 typval_T *rettv;
17915{
17916 char_u *s = get_tv_string(&argvars[0]);
17917 int col = 0;
17918
17919 if (argvars[1].v_type != VAR_UNKNOWN)
17920 col = get_tv_number(&argvars[1]);
17921
Bram Moolenaar8a09b982010-07-22 22:20:57 +020017922 rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, s) - col);
Bram Moolenaardc536092010-07-18 15:45:49 +020017923}
17924
17925/*
Bram Moolenaar72597a52010-07-18 15:31:08 +020017926 * "strwidth()" function
17927 */
17928 static void
17929f_strwidth(argvars, rettv)
17930 typval_T *argvars;
17931 typval_T *rettv;
17932{
17933 char_u *s = get_tv_string(&argvars[0]);
17934
17935 rettv->vval.v_number = (varnumber_T)(
17936#ifdef FEAT_MBYTE
17937 mb_string2cells(s, -1)
17938#else
17939 STRLEN(s)
17940#endif
17941 );
17942}
17943
17944/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000017945 * "strpart()" function
17946 */
17947 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017948f_strpart(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000017949 typval_T *argvars;
17950 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017951{
17952 char_u *p;
17953 int n;
17954 int len;
17955 int slen;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017956 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017957
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017958 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017959 slen = (int)STRLEN(p);
17960
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017961 n = get_tv_number_chk(&argvars[1], &error);
17962 if (error)
17963 len = 0;
17964 else if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017965 len = get_tv_number(&argvars[2]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017966 else
17967 len = slen - n; /* default len: all bytes that are available. */
17968
17969 /*
17970 * Only return the overlap between the specified part and the actual
17971 * string.
17972 */
17973 if (n < 0)
17974 {
17975 len += n;
17976 n = 0;
17977 }
17978 else if (n > slen)
17979 n = slen;
17980 if (len < 0)
17981 len = 0;
17982 else if (n + len > slen)
17983 len = slen - n;
17984
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017985 rettv->v_type = VAR_STRING;
17986 rettv->vval.v_string = vim_strnsave(p + n, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017987}
17988
17989/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000017990 * "strridx()" function
17991 */
17992 static void
17993f_strridx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000017994 typval_T *argvars;
17995 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000017996{
17997 char_u buf[NUMBUFLEN];
17998 char_u *needle;
17999 char_u *haystack;
18000 char_u *rest;
18001 char_u *lastmatch = NULL;
Bram Moolenaar532c7802005-01-27 14:44:31 +000018002 int haystack_len, end_idx;
Bram Moolenaar0d660222005-01-07 21:51:51 +000018003
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018004 needle = get_tv_string_chk(&argvars[1]);
18005 haystack = get_tv_string_buf_chk(&argvars[0], buf);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018006
18007 rettv->vval.v_number = -1;
18008 if (needle == NULL || haystack == NULL)
18009 return; /* type error; errmsg already given */
Bram Moolenaareb3593b2006-04-22 22:33:57 +000018010
18011 haystack_len = (int)STRLEN(haystack);
Bram Moolenaar05159a02005-02-26 23:04:13 +000018012 if (argvars[2].v_type != VAR_UNKNOWN)
18013 {
18014 /* Third argument: upper limit for index */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018015 end_idx = get_tv_number_chk(&argvars[2], NULL);
Bram Moolenaar05159a02005-02-26 23:04:13 +000018016 if (end_idx < 0)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018017 return; /* can never find a match */
Bram Moolenaar05159a02005-02-26 23:04:13 +000018018 }
18019 else
18020 end_idx = haystack_len;
18021
Bram Moolenaar0d660222005-01-07 21:51:51 +000018022 if (*needle == NUL)
Bram Moolenaar05159a02005-02-26 23:04:13 +000018023 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000018024 /* Empty string matches past the end. */
Bram Moolenaar05159a02005-02-26 23:04:13 +000018025 lastmatch = haystack + end_idx;
18026 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000018027 else
Bram Moolenaar532c7802005-01-27 14:44:31 +000018028 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000018029 for (rest = haystack; *rest != '\0'; ++rest)
18030 {
18031 rest = (char_u *)strstr((char *)rest, (char *)needle);
Bram Moolenaar532c7802005-01-27 14:44:31 +000018032 if (rest == NULL || rest > haystack + end_idx)
Bram Moolenaar0d660222005-01-07 21:51:51 +000018033 break;
18034 lastmatch = rest;
18035 }
Bram Moolenaar532c7802005-01-27 14:44:31 +000018036 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000018037
18038 if (lastmatch == NULL)
18039 rettv->vval.v_number = -1;
18040 else
18041 rettv->vval.v_number = (varnumber_T)(lastmatch - haystack);
18042}
18043
18044/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000018045 * "strtrans()" function
18046 */
18047 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018048f_strtrans(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000018049 typval_T *argvars;
18050 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018051{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018052 rettv->v_type = VAR_STRING;
18053 rettv->vval.v_string = transstr(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000018054}
18055
18056/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000018057 * "submatch()" function
18058 */
18059 static void
18060f_submatch(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000018061 typval_T *argvars;
18062 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000018063{
Bram Moolenaar41571762014-04-02 19:00:58 +020018064 int error = FALSE;
Bram Moolenaar41571762014-04-02 19:00:58 +020018065 int no;
18066 int retList = 0;
18067
18068 no = (int)get_tv_number_chk(&argvars[0], &error);
18069 if (error)
18070 return;
18071 error = FALSE;
18072 if (argvars[1].v_type != VAR_UNKNOWN)
18073 retList = get_tv_number_chk(&argvars[1], &error);
18074 if (error)
18075 return;
18076
18077 if (retList == 0)
18078 {
18079 rettv->v_type = VAR_STRING;
18080 rettv->vval.v_string = reg_submatch(no);
18081 }
18082 else
18083 {
18084 rettv->v_type = VAR_LIST;
18085 rettv->vval.v_list = reg_submatch_list(no);
18086 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000018087}
18088
18089/*
18090 * "substitute()" function
18091 */
18092 static void
18093f_substitute(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000018094 typval_T *argvars;
18095 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000018096{
18097 char_u patbuf[NUMBUFLEN];
18098 char_u subbuf[NUMBUFLEN];
18099 char_u flagsbuf[NUMBUFLEN];
18100
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018101 char_u *str = get_tv_string_chk(&argvars[0]);
18102 char_u *pat = get_tv_string_buf_chk(&argvars[1], patbuf);
18103 char_u *sub = get_tv_string_buf_chk(&argvars[2], subbuf);
18104 char_u *flg = get_tv_string_buf_chk(&argvars[3], flagsbuf);
18105
Bram Moolenaar0d660222005-01-07 21:51:51 +000018106 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018107 if (str == NULL || pat == NULL || sub == NULL || flg == NULL)
18108 rettv->vval.v_string = NULL;
18109 else
18110 rettv->vval.v_string = do_string_sub(str, pat, sub, flg);
Bram Moolenaar0d660222005-01-07 21:51:51 +000018111}
18112
18113/*
Bram Moolenaar54ff3412005-04-20 19:48:33 +000018114 * "synID(lnum, col, trans)" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000018115 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018116 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018117f_synID(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000018118 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000018119 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018120{
18121 int id = 0;
18122#ifdef FEAT_SYN_HL
Bram Moolenaar54ff3412005-04-20 19:48:33 +000018123 long lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018124 long col;
18125 int trans;
Bram Moolenaar92124a32005-06-17 22:03:40 +000018126 int transerr = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018127
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018128 lnum = get_tv_lnum(argvars); /* -1 on type error */
18129 col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */
18130 trans = get_tv_number_chk(&argvars[2], &transerr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018131
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018132 if (!transerr && lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
Bram Moolenaar54ff3412005-04-20 19:48:33 +000018133 && col >= 0 && col < (long)STRLEN(ml_get(lnum)))
Bram Moolenaar56cefaf2008-01-12 15:47:10 +000018134 id = syn_get_id(curwin, lnum, (colnr_T)col, trans, NULL, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018135#endif
18136
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018137 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018138}
18139
18140/*
18141 * "synIDattr(id, what [, mode])" function
18142 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018143 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018144f_synIDattr(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000018145 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000018146 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018147{
18148 char_u *p = NULL;
18149#ifdef FEAT_SYN_HL
18150 int id;
18151 char_u *what;
18152 char_u *mode;
18153 char_u modebuf[NUMBUFLEN];
18154 int modec;
18155
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018156 id = get_tv_number(&argvars[0]);
18157 what = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000018158 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018159 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018160 mode = get_tv_string_buf(&argvars[2], modebuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018161 modec = TOLOWER_ASC(mode[0]);
Bram Moolenaar61623362010-07-14 22:04:22 +020018162 if (modec != 't' && modec != 'c' && modec != 'g')
Bram Moolenaar071d4272004-06-13 20:20:40 +000018163 modec = 0; /* replace invalid with current */
18164 }
18165 else
18166 {
18167#ifdef FEAT_GUI
18168 if (gui.in_use)
18169 modec = 'g';
18170 else
18171#endif
18172 if (t_colors > 1)
18173 modec = 'c';
18174 else
18175 modec = 't';
18176 }
18177
18178
18179 switch (TOLOWER_ASC(what[0]))
18180 {
18181 case 'b':
18182 if (TOLOWER_ASC(what[1]) == 'g') /* bg[#] */
18183 p = highlight_color(id, what, modec);
18184 else /* bold */
18185 p = highlight_has_attr(id, HL_BOLD, modec);
18186 break;
18187
Bram Moolenaar12682fd2010-03-10 13:43:49 +010018188 case 'f': /* fg[#] or font */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018189 p = highlight_color(id, what, modec);
18190 break;
18191
18192 case 'i':
18193 if (TOLOWER_ASC(what[1]) == 'n') /* inverse */
18194 p = highlight_has_attr(id, HL_INVERSE, modec);
18195 else /* italic */
18196 p = highlight_has_attr(id, HL_ITALIC, modec);
18197 break;
18198
18199 case 'n': /* name */
18200 p = get_highlight_name(NULL, id - 1);
18201 break;
18202
18203 case 'r': /* reverse */
18204 p = highlight_has_attr(id, HL_INVERSE, modec);
18205 break;
18206
Bram Moolenaar6f507d62008-11-28 10:16:05 +000018207 case 's':
18208 if (TOLOWER_ASC(what[1]) == 'p') /* sp[#] */
18209 p = highlight_color(id, what, modec);
18210 else /* standout */
18211 p = highlight_has_attr(id, HL_STANDOUT, modec);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018212 break;
18213
Bram Moolenaar5b743bf2005-03-15 22:50:43 +000018214 case 'u':
18215 if (STRLEN(what) <= 5 || TOLOWER_ASC(what[5]) != 'c')
18216 /* underline */
18217 p = highlight_has_attr(id, HL_UNDERLINE, modec);
18218 else
18219 /* undercurl */
18220 p = highlight_has_attr(id, HL_UNDERCURL, modec);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018221 break;
18222 }
18223
18224 if (p != NULL)
18225 p = vim_strsave(p);
18226#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018227 rettv->v_type = VAR_STRING;
18228 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018229}
18230
18231/*
18232 * "synIDtrans(id)" function
18233 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018234 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018235f_synIDtrans(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000018236 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000018237 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018238{
18239 int id;
18240
18241#ifdef FEAT_SYN_HL
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018242 id = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018243
18244 if (id > 0)
18245 id = syn_get_final_id(id);
18246 else
18247#endif
18248 id = 0;
18249
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018250 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018251}
18252
18253/*
Bram Moolenaar7510fe72010-07-25 12:46:44 +020018254 * "synconcealed(lnum, col)" function
18255 */
18256 static void
18257f_synconcealed(argvars, rettv)
18258 typval_T *argvars UNUSED;
18259 typval_T *rettv;
18260{
18261#if defined(FEAT_SYN_HL) && defined(FEAT_CONCEAL)
18262 long lnum;
18263 long col;
18264 int syntax_flags = 0;
18265 int cchar;
18266 int matchid = 0;
18267 char_u str[NUMBUFLEN];
18268#endif
18269
18270 rettv->v_type = VAR_LIST;
18271 rettv->vval.v_list = NULL;
18272
18273#if defined(FEAT_SYN_HL) && defined(FEAT_CONCEAL)
18274 lnum = get_tv_lnum(argvars); /* -1 on type error */
18275 col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */
18276
18277 vim_memset(str, NUL, sizeof(str));
18278
18279 if (rettv_list_alloc(rettv) != FAIL)
18280 {
18281 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
18282 && col >= 0 && col <= (long)STRLEN(ml_get(lnum))
18283 && curwin->w_p_cole > 0)
18284 {
18285 (void)syn_get_id(curwin, lnum, col, FALSE, NULL, FALSE);
18286 syntax_flags = get_syntax_info(&matchid);
18287
18288 /* get the conceal character */
18289 if ((syntax_flags & HL_CONCEAL) && curwin->w_p_cole < 3)
18290 {
18291 cchar = syn_get_sub_char();
18292 if (cchar == NUL && curwin->w_p_cole == 1 && lcs_conceal != NUL)
18293 cchar = lcs_conceal;
18294 if (cchar != NUL)
18295 {
18296# ifdef FEAT_MBYTE
18297 if (has_mbyte)
18298 (*mb_char2bytes)(cchar, str);
18299 else
18300# endif
18301 str[0] = cchar;
18302 }
18303 }
18304 }
18305
18306 list_append_number(rettv->vval.v_list,
18307 (syntax_flags & HL_CONCEAL) != 0);
18308 /* -1 to auto-determine strlen */
18309 list_append_string(rettv->vval.v_list, str, -1);
18310 list_append_number(rettv->vval.v_list, matchid);
18311 }
18312#endif
18313}
18314
18315/*
Bram Moolenaar9d188ab2008-01-10 21:24:39 +000018316 * "synstack(lnum, col)" function
18317 */
Bram Moolenaar9d188ab2008-01-10 21:24:39 +000018318 static void
18319f_synstack(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000018320 typval_T *argvars UNUSED;
Bram Moolenaar9d188ab2008-01-10 21:24:39 +000018321 typval_T *rettv;
18322{
18323#ifdef FEAT_SYN_HL
18324 long lnum;
18325 long col;
18326 int i;
18327 int id;
18328#endif
18329
18330 rettv->v_type = VAR_LIST;
18331 rettv->vval.v_list = NULL;
18332
18333#ifdef FEAT_SYN_HL
18334 lnum = get_tv_lnum(argvars); /* -1 on type error */
18335 col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */
18336
18337 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
Bram Moolenaard04b7502010-07-08 22:27:55 +020018338 && col >= 0 && col <= (long)STRLEN(ml_get(lnum))
Bram Moolenaar9d188ab2008-01-10 21:24:39 +000018339 && rettv_list_alloc(rettv) != FAIL)
18340 {
Bram Moolenaar56cefaf2008-01-12 15:47:10 +000018341 (void)syn_get_id(curwin, lnum, (colnr_T)col, FALSE, NULL, TRUE);
Bram Moolenaar9d188ab2008-01-10 21:24:39 +000018342 for (i = 0; ; ++i)
18343 {
18344 id = syn_get_stack_item(i);
18345 if (id < 0)
18346 break;
18347 if (list_append_number(rettv->vval.v_list, id) == FAIL)
18348 break;
18349 }
18350 }
18351#endif
18352}
18353
Bram Moolenaar071d4272004-06-13 20:20:40 +000018354 static void
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018355get_cmd_output_as_rettv(argvars, rettv, retlist)
Bram Moolenaar33570922005-01-25 22:26:29 +000018356 typval_T *argvars;
18357 typval_T *rettv;
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018358 int retlist;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018359{
Bram Moolenaarc0197e22004-09-13 20:26:32 +000018360 char_u *res = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018361 char_u *p;
Bram Moolenaarc0197e22004-09-13 20:26:32 +000018362 char_u *infile = NULL;
18363 char_u buf[NUMBUFLEN];
18364 int err = FALSE;
18365 FILE *fd;
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018366 list_T *list = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018367
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018368 rettv->v_type = VAR_STRING;
18369 rettv->vval.v_string = NULL;
Bram Moolenaard9fe7c42007-04-29 11:53:56 +000018370 if (check_restricted() || check_secure())
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018371 goto errret;
Bram Moolenaard9fe7c42007-04-29 11:53:56 +000018372
Bram Moolenaar49cd9572005-01-03 21:06:01 +000018373 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc0197e22004-09-13 20:26:32 +000018374 {
18375 /*
18376 * Write the string to a temp file, to be used for input of the shell
18377 * command.
18378 */
18379 if ((infile = vim_tempname('i')) == NULL)
18380 {
18381 EMSG(_(e_notmp));
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018382 goto errret;
Bram Moolenaarc0197e22004-09-13 20:26:32 +000018383 }
18384
18385 fd = mch_fopen((char *)infile, WRITEBIN);
18386 if (fd == NULL)
18387 {
18388 EMSG2(_(e_notopen), infile);
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018389 goto errret;
Bram Moolenaarc0197e22004-09-13 20:26:32 +000018390 }
Bram Moolenaar57ebe6e2014-04-05 18:55:46 +020018391 if (argvars[1].v_type == VAR_LIST)
Bram Moolenaareb3593b2006-04-22 22:33:57 +000018392 {
Bram Moolenaar57ebe6e2014-04-05 18:55:46 +020018393 if (write_list(fd, argvars[1].vval.v_list, TRUE) == FAIL)
18394 err = TRUE;
Bram Moolenaareb3593b2006-04-22 22:33:57 +000018395 }
Bram Moolenaar57ebe6e2014-04-05 18:55:46 +020018396 else
18397 {
18398 p = get_tv_string_buf_chk(&argvars[1], buf);
18399 if (p == NULL)
18400 {
18401 fclose(fd);
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018402 goto errret; /* type error; errmsg already given */
Bram Moolenaar57ebe6e2014-04-05 18:55:46 +020018403 }
18404 if (fwrite(p, STRLEN(p), 1, fd) != 1)
18405 err = TRUE;
18406 }
Bram Moolenaarc0197e22004-09-13 20:26:32 +000018407 if (fclose(fd) != 0)
18408 err = TRUE;
18409 if (err)
18410 {
18411 EMSG(_("E677: Error writing temp file"));
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018412 goto errret;
Bram Moolenaarc0197e22004-09-13 20:26:32 +000018413 }
18414 }
18415
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018416 if (retlist)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018417 {
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018418 int len;
18419 listitem_T *li;
18420 char_u *s = NULL;
18421 char_u *start;
18422 char_u *end;
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018423 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018424
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018425 res = get_cmd_output(get_tv_string(&argvars[0]), infile,
18426 SHELL_SILENT | SHELL_COOKED, &len);
18427 if (res == NULL)
18428 goto errret;
18429
18430 list = list_alloc();
18431 if (list == NULL)
18432 goto errret;
18433
18434 for (i = 0; i < len; ++i)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018435 {
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018436 start = res + i;
Bram Moolenaarb21a29b2014-04-11 10:22:53 +020018437 while (i < len && res[i] != NL)
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018438 ++i;
Bram Moolenaarb21a29b2014-04-11 10:22:53 +020018439 end = res + i;
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018440
Bram Moolenaarb21a29b2014-04-11 10:22:53 +020018441 s = alloc((unsigned)(end - start + 1));
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018442 if (s == NULL)
18443 goto errret;
18444
Bram Moolenaarb21a29b2014-04-11 10:22:53 +020018445 for (p = s; start < end; ++p, ++start)
18446 *p = *start == NUL ? NL : *start;
18447 *p = NUL;
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018448
18449 li = listitem_alloc();
18450 if (li == NULL)
18451 {
18452 vim_free(s);
18453 goto errret;
18454 }
18455 li->li_tv.v_type = VAR_STRING;
18456 li->li_tv.vval.v_string = s;
18457 list_append(list, li);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018458 }
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018459
Bram Moolenaarb21a29b2014-04-11 10:22:53 +020018460 ++list->lv_refcount;
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018461 rettv->v_type = VAR_LIST;
18462 rettv->vval.v_list = list;
18463 list = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018464 }
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018465 else
18466 {
18467 res = get_cmd_output(get_tv_string(&argvars[0]), infile,
18468 SHELL_SILENT | SHELL_COOKED, NULL);
18469#ifdef USE_CR
18470 /* translate <CR> into <NL> */
18471 if (res != NULL)
18472 {
18473 char_u *s;
18474
18475 for (s = res; *s; ++s)
18476 {
18477 if (*s == CAR)
18478 *s = NL;
18479 }
18480 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018481#else
18482# ifdef USE_CRNL
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018483 /* translate <CR><NL> into <NL> */
18484 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018485 {
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018486 char_u *s, *d;
18487
18488 d = res;
18489 for (s = res; *s; ++s)
18490 {
18491 if (s[0] == CAR && s[1] == NL)
18492 ++s;
18493 *d++ = *s;
18494 }
18495 *d = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018496 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018497# endif
18498#endif
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018499 rettv->vval.v_string = res;
18500 res = NULL;
18501 }
Bram Moolenaarc0197e22004-09-13 20:26:32 +000018502
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018503errret:
Bram Moolenaarc0197e22004-09-13 20:26:32 +000018504 if (infile != NULL)
18505 {
18506 mch_remove(infile);
18507 vim_free(infile);
18508 }
Bram Moolenaar39c29ed2014-04-05 19:44:40 +020018509 if (res != NULL)
18510 vim_free(res);
18511 if (list != NULL)
18512 list_free(list, TRUE);
18513}
18514
18515/*
18516 * "system()" function
18517 */
18518 static void
18519f_system(argvars, rettv)
18520 typval_T *argvars;
18521 typval_T *rettv;
18522{
18523 get_cmd_output_as_rettv(argvars, rettv, FALSE);
18524}
18525
18526/*
18527 * "systemlist()" function
18528 */
18529 static void
18530f_systemlist(argvars, rettv)
18531 typval_T *argvars;
18532 typval_T *rettv;
18533{
18534 get_cmd_output_as_rettv(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018535}
18536
18537/*
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000018538 * "tabpagebuflist()" function
18539 */
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000018540 static void
18541f_tabpagebuflist(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000018542 typval_T *argvars UNUSED;
18543 typval_T *rettv UNUSED;
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000018544{
Bram Moolenaar798b30b2009-04-22 10:56:16 +000018545#ifdef FEAT_WINDOWS
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000018546 tabpage_T *tp;
18547 win_T *wp = NULL;
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000018548
18549 if (argvars[0].v_type == VAR_UNKNOWN)
18550 wp = firstwin;
18551 else
18552 {
18553 tp = find_tabpage((int)get_tv_number(&argvars[0]));
18554 if (tp != NULL)
Bram Moolenaar238a5642006-02-21 22:12:05 +000018555 wp = (tp == curtab) ? firstwin : tp->tp_firstwin;
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000018556 }
Bram Moolenaar798b30b2009-04-22 10:56:16 +000018557 if (wp != NULL && rettv_list_alloc(rettv) != FAIL)
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000018558 {
Bram Moolenaar798b30b2009-04-22 10:56:16 +000018559 for (; wp != NULL; wp = wp->w_next)
18560 if (list_append_number(rettv->vval.v_list,
Bram Moolenaareddf53b2006-02-27 00:11:10 +000018561 wp->w_buffer->b_fnum) == FAIL)
Bram Moolenaar798b30b2009-04-22 10:56:16 +000018562 break;
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000018563 }
18564#endif
18565}
18566
18567
18568/*
Bram Moolenaar7e8fd632006-02-18 22:14:51 +000018569 * "tabpagenr()" function
18570 */
Bram Moolenaar7e8fd632006-02-18 22:14:51 +000018571 static void
18572f_tabpagenr(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000018573 typval_T *argvars UNUSED;
Bram Moolenaar7e8fd632006-02-18 22:14:51 +000018574 typval_T *rettv;
18575{
18576 int nr = 1;
18577#ifdef FEAT_WINDOWS
Bram Moolenaar7e8fd632006-02-18 22:14:51 +000018578 char_u *arg;
18579
18580 if (argvars[0].v_type != VAR_UNKNOWN)
18581 {
18582 arg = get_tv_string_chk(&argvars[0]);
18583 nr = 0;
18584 if (arg != NULL)
18585 {
18586 if (STRCMP(arg, "$") == 0)
Bram Moolenaara5621492006-02-25 21:55:24 +000018587 nr = tabpage_index(NULL) - 1;
Bram Moolenaar7e8fd632006-02-18 22:14:51 +000018588 else
18589 EMSG2(_(e_invexpr2), arg);
18590 }
18591 }
18592 else
Bram Moolenaar32466aa2006-02-24 23:53:04 +000018593 nr = tabpage_index(curtab);
Bram Moolenaar7e8fd632006-02-18 22:14:51 +000018594#endif
18595 rettv->vval.v_number = nr;
18596}
18597
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000018598
18599#ifdef FEAT_WINDOWS
18600static int get_winnr __ARGS((tabpage_T *tp, typval_T *argvar));
18601
18602/*
18603 * Common code for tabpagewinnr() and winnr().
18604 */
18605 static int
18606get_winnr(tp, argvar)
18607 tabpage_T *tp;
18608 typval_T *argvar;
18609{
18610 win_T *twin;
18611 int nr = 1;
18612 win_T *wp;
18613 char_u *arg;
18614
18615 twin = (tp == curtab) ? curwin : tp->tp_curwin;
18616 if (argvar->v_type != VAR_UNKNOWN)
18617 {
18618 arg = get_tv_string_chk(argvar);
18619 if (arg == NULL)
18620 nr = 0; /* type error; errmsg already given */
18621 else if (STRCMP(arg, "$") == 0)
18622 twin = (tp == curtab) ? lastwin : tp->tp_lastwin;
18623 else if (STRCMP(arg, "#") == 0)
18624 {
18625 twin = (tp == curtab) ? prevwin : tp->tp_prevwin;
18626 if (twin == NULL)
18627 nr = 0;
18628 }
18629 else
18630 {
18631 EMSG2(_(e_invexpr2), arg);
18632 nr = 0;
18633 }
18634 }
18635
18636 if (nr > 0)
18637 for (wp = (tp == curtab) ? firstwin : tp->tp_firstwin;
18638 wp != twin; wp = wp->w_next)
Bram Moolenaar4940e3f2007-03-25 15:49:08 +000018639 {
18640 if (wp == NULL)
18641 {
18642 /* didn't find it in this tabpage */
18643 nr = 0;
18644 break;
18645 }
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000018646 ++nr;
Bram Moolenaar4940e3f2007-03-25 15:49:08 +000018647 }
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000018648 return nr;
18649}
18650#endif
18651
18652/*
18653 * "tabpagewinnr()" function
18654 */
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000018655 static void
18656f_tabpagewinnr(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000018657 typval_T *argvars UNUSED;
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000018658 typval_T *rettv;
18659{
18660 int nr = 1;
18661#ifdef FEAT_WINDOWS
18662 tabpage_T *tp;
18663
18664 tp = find_tabpage((int)get_tv_number(&argvars[0]));
18665 if (tp == NULL)
18666 nr = 0;
18667 else
18668 nr = get_winnr(tp, &argvars[1]);
18669#endif
18670 rettv->vval.v_number = nr;
18671}
18672
18673
Bram Moolenaar7e8fd632006-02-18 22:14:51 +000018674/*
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000018675 * "tagfiles()" function
18676 */
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000018677 static void
18678f_tagfiles(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000018679 typval_T *argvars UNUSED;
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000018680 typval_T *rettv;
18681{
Bram Moolenaard9462e32011-04-11 21:35:11 +020018682 char_u *fname;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000018683 tagname_T tn;
18684 int first;
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000018685
Bram Moolenaareddf53b2006-02-27 00:11:10 +000018686 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000018687 return;
Bram Moolenaard9462e32011-04-11 21:35:11 +020018688 fname = alloc(MAXPATHL);
18689 if (fname == NULL)
18690 return;
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000018691
Bram Moolenaareddf53b2006-02-27 00:11:10 +000018692 for (first = TRUE; ; first = FALSE)
18693 if (get_tagfname(&tn, first, fname) == FAIL
18694 || list_append_string(rettv->vval.v_list, fname, -1) == FAIL)
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000018695 break;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000018696 tagname_free(&tn);
Bram Moolenaard9462e32011-04-11 21:35:11 +020018697 vim_free(fname);
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000018698}
18699
18700/*
Bram Moolenaare2ac10d2005-03-07 23:26:06 +000018701 * "taglist()" function
Bram Moolenaar19a09a12005-03-04 23:39:37 +000018702 */
18703 static void
18704f_taglist(argvars, rettv)
18705 typval_T *argvars;
18706 typval_T *rettv;
18707{
18708 char_u *tag_pattern;
Bram Moolenaar19a09a12005-03-04 23:39:37 +000018709
18710 tag_pattern = get_tv_string(&argvars[0]);
18711
18712 rettv->vval.v_number = FALSE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018713 if (*tag_pattern == NUL)
18714 return;
Bram Moolenaar19a09a12005-03-04 23:39:37 +000018715
Bram Moolenaareddf53b2006-02-27 00:11:10 +000018716 if (rettv_list_alloc(rettv) == OK)
18717 (void)get_tags(rettv->vval.v_list, tag_pattern);
Bram Moolenaar19a09a12005-03-04 23:39:37 +000018718}
18719
18720/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000018721 * "tempname()" function
18722 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018723 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018724f_tempname(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000018725 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000018726 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018727{
18728 static int x = 'A';
18729
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018730 rettv->v_type = VAR_STRING;
18731 rettv->vval.v_string = vim_tempname(x);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018732
18733 /* Advance 'x' to use A-Z and 0-9, so that there are at least 34 different
18734 * names. Skip 'I' and 'O', they are used for shell redirection. */
18735 do
18736 {
18737 if (x == 'Z')
18738 x = '0';
18739 else if (x == '9')
18740 x = 'A';
18741 else
18742 {
18743#ifdef EBCDIC
18744 if (x == 'I')
18745 x = 'J';
18746 else if (x == 'R')
18747 x = 'S';
18748 else
18749#endif
18750 ++x;
18751 }
18752 } while (x == 'I' || x == 'O');
18753}
18754
18755/*
Bram Moolenaard52d9742005-08-21 22:20:28 +000018756 * "test(list)" function: Just checking the walls...
18757 */
Bram Moolenaard52d9742005-08-21 22:20:28 +000018758 static void
18759f_test(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000018760 typval_T *argvars UNUSED;
18761 typval_T *rettv UNUSED;
Bram Moolenaard52d9742005-08-21 22:20:28 +000018762{
18763 /* Used for unit testing. Change the code below to your liking. */
18764#if 0
18765 listitem_T *li;
18766 list_T *l;
18767 char_u *bad, *good;
18768
18769 if (argvars[0].v_type != VAR_LIST)
18770 return;
18771 l = argvars[0].vval.v_list;
18772 if (l == NULL)
18773 return;
18774 li = l->lv_first;
18775 if (li == NULL)
18776 return;
18777 bad = get_tv_string(&li->li_tv);
18778 li = li->li_next;
18779 if (li == NULL)
18780 return;
18781 good = get_tv_string(&li->li_tv);
18782 rettv->vval.v_number = test_edit_score(bad, good);
18783#endif
18784}
18785
Bram Moolenaardb7c6862010-05-21 16:33:48 +020018786#ifdef FEAT_FLOAT
18787/*
18788 * "tan()" function
18789 */
18790 static void
18791f_tan(argvars, rettv)
18792 typval_T *argvars;
18793 typval_T *rettv;
18794{
18795 float_T f;
18796
18797 rettv->v_type = VAR_FLOAT;
18798 if (get_float_arg(argvars, &f) == OK)
18799 rettv->vval.v_float = tan(f);
18800 else
18801 rettv->vval.v_float = 0.0;
18802}
18803
18804/*
18805 * "tanh()" function
18806 */
18807 static void
18808f_tanh(argvars, rettv)
18809 typval_T *argvars;
18810 typval_T *rettv;
18811{
18812 float_T f;
18813
18814 rettv->v_type = VAR_FLOAT;
18815 if (get_float_arg(argvars, &f) == OK)
18816 rettv->vval.v_float = tanh(f);
18817 else
18818 rettv->vval.v_float = 0.0;
18819}
18820#endif
18821
Bram Moolenaard52d9742005-08-21 22:20:28 +000018822/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000018823 * "tolower(string)" function
18824 */
18825 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018826f_tolower(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000018827 typval_T *argvars;
18828 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018829{
18830 char_u *p;
18831
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018832 p = vim_strsave(get_tv_string(&argvars[0]));
18833 rettv->v_type = VAR_STRING;
18834 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018835
18836 if (p != NULL)
18837 while (*p != NUL)
18838 {
18839#ifdef FEAT_MBYTE
18840 int l;
18841
18842 if (enc_utf8)
18843 {
18844 int c, lc;
18845
18846 c = utf_ptr2char(p);
18847 lc = utf_tolower(c);
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000018848 l = utf_ptr2len(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018849 /* TODO: reallocate string when byte count changes. */
18850 if (utf_char2len(lc) == l)
18851 utf_char2bytes(lc, p);
18852 p += l;
18853 }
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000018854 else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018855 p += l; /* skip multi-byte character */
18856 else
18857#endif
18858 {
18859 *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */
18860 ++p;
18861 }
18862 }
18863}
18864
18865/*
18866 * "toupper(string)" function
18867 */
18868 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018869f_toupper(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000018870 typval_T *argvars;
18871 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018872{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018873 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018874 rettv->vval.v_string = strup_save(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000018875}
18876
18877/*
Bram Moolenaar8299df92004-07-10 09:47:34 +000018878 * "tr(string, fromstr, tostr)" function
18879 */
18880 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018881f_tr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000018882 typval_T *argvars;
18883 typval_T *rettv;
Bram Moolenaar8299df92004-07-10 09:47:34 +000018884{
Bram Moolenaar70b2a562012-01-10 22:26:17 +010018885 char_u *in_str;
Bram Moolenaar8299df92004-07-10 09:47:34 +000018886 char_u *fromstr;
18887 char_u *tostr;
18888 char_u *p;
18889#ifdef FEAT_MBYTE
Bram Moolenaar342337a2005-07-21 21:11:17 +000018890 int inlen;
18891 int fromlen;
18892 int tolen;
Bram Moolenaar8299df92004-07-10 09:47:34 +000018893 int idx;
18894 char_u *cpstr;
18895 int cplen;
18896 int first = TRUE;
18897#endif
18898 char_u buf[NUMBUFLEN];
18899 char_u buf2[NUMBUFLEN];
18900 garray_T ga;
18901
Bram Moolenaar70b2a562012-01-10 22:26:17 +010018902 in_str = get_tv_string(&argvars[0]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018903 fromstr = get_tv_string_buf_chk(&argvars[1], buf);
18904 tostr = get_tv_string_buf_chk(&argvars[2], buf2);
Bram Moolenaar8299df92004-07-10 09:47:34 +000018905
18906 /* Default return value: empty string. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018907 rettv->v_type = VAR_STRING;
18908 rettv->vval.v_string = NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000018909 if (fromstr == NULL || tostr == NULL)
18910 return; /* type error; errmsg already given */
Bram Moolenaar8299df92004-07-10 09:47:34 +000018911 ga_init2(&ga, (int)sizeof(char), 80);
18912
18913#ifdef FEAT_MBYTE
18914 if (!has_mbyte)
18915#endif
18916 /* not multi-byte: fromstr and tostr must be the same length */
18917 if (STRLEN(fromstr) != STRLEN(tostr))
18918 {
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000018919#ifdef FEAT_MBYTE
Bram Moolenaar8299df92004-07-10 09:47:34 +000018920error:
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000018921#endif
Bram Moolenaar8299df92004-07-10 09:47:34 +000018922 EMSG2(_(e_invarg2), fromstr);
18923 ga_clear(&ga);
18924 return;
18925 }
18926
18927 /* fromstr and tostr have to contain the same number of chars */
Bram Moolenaar70b2a562012-01-10 22:26:17 +010018928 while (*in_str != NUL)
Bram Moolenaar8299df92004-07-10 09:47:34 +000018929 {
18930#ifdef FEAT_MBYTE
18931 if (has_mbyte)
18932 {
Bram Moolenaar70b2a562012-01-10 22:26:17 +010018933 inlen = (*mb_ptr2len)(in_str);
18934 cpstr = in_str;
Bram Moolenaar8299df92004-07-10 09:47:34 +000018935 cplen = inlen;
18936 idx = 0;
18937 for (p = fromstr; *p != NUL; p += fromlen)
18938 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000018939 fromlen = (*mb_ptr2len)(p);
Bram Moolenaar70b2a562012-01-10 22:26:17 +010018940 if (fromlen == inlen && STRNCMP(in_str, p, inlen) == 0)
Bram Moolenaar8299df92004-07-10 09:47:34 +000018941 {
18942 for (p = tostr; *p != NUL; p += tolen)
18943 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000018944 tolen = (*mb_ptr2len)(p);
Bram Moolenaar8299df92004-07-10 09:47:34 +000018945 if (idx-- == 0)
18946 {
18947 cplen = tolen;
18948 cpstr = p;
18949 break;
18950 }
18951 }
18952 if (*p == NUL) /* tostr is shorter than fromstr */
18953 goto error;
18954 break;
18955 }
18956 ++idx;
18957 }
18958
Bram Moolenaar70b2a562012-01-10 22:26:17 +010018959 if (first && cpstr == in_str)
Bram Moolenaar8299df92004-07-10 09:47:34 +000018960 {
18961 /* Check that fromstr and tostr have the same number of
18962 * (multi-byte) characters. Done only once when a character
Bram Moolenaar70b2a562012-01-10 22:26:17 +010018963 * of in_str doesn't appear in fromstr. */
Bram Moolenaar8299df92004-07-10 09:47:34 +000018964 first = FALSE;
18965 for (p = tostr; *p != NUL; p += tolen)
18966 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000018967 tolen = (*mb_ptr2len)(p);
Bram Moolenaar8299df92004-07-10 09:47:34 +000018968 --idx;
18969 }
18970 if (idx != 0)
18971 goto error;
18972 }
18973
18974 ga_grow(&ga, cplen);
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +000018975 mch_memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen);
Bram Moolenaar8299df92004-07-10 09:47:34 +000018976 ga.ga_len += cplen;
Bram Moolenaar8299df92004-07-10 09:47:34 +000018977
Bram Moolenaar70b2a562012-01-10 22:26:17 +010018978 in_str += inlen;
Bram Moolenaar8299df92004-07-10 09:47:34 +000018979 }
18980 else
18981#endif
18982 {
18983 /* When not using multi-byte chars we can do it faster. */
Bram Moolenaar70b2a562012-01-10 22:26:17 +010018984 p = vim_strchr(fromstr, *in_str);
Bram Moolenaar8299df92004-07-10 09:47:34 +000018985 if (p != NULL)
18986 ga_append(&ga, tostr[p - fromstr]);
18987 else
Bram Moolenaar70b2a562012-01-10 22:26:17 +010018988 ga_append(&ga, *in_str);
18989 ++in_str;
Bram Moolenaar8299df92004-07-10 09:47:34 +000018990 }
18991 }
18992
Bram Moolenaar61b974b2006-12-05 09:32:29 +000018993 /* add a terminating NUL */
18994 ga_grow(&ga, 1);
18995 ga_append(&ga, NUL);
18996
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018997 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar8299df92004-07-10 09:47:34 +000018998}
18999
Bram Moolenaar8c8de832008-06-24 22:58:06 +000019000#ifdef FEAT_FLOAT
19001/*
19002 * "trunc({float})" function
19003 */
19004 static void
19005f_trunc(argvars, rettv)
19006 typval_T *argvars;
19007 typval_T *rettv;
19008{
19009 float_T f;
19010
19011 rettv->v_type = VAR_FLOAT;
19012 if (get_float_arg(argvars, &f) == OK)
19013 /* trunc() is not in C90, use floor() or ceil() instead. */
19014 rettv->vval.v_float = f > 0 ? floor(f) : ceil(f);
19015 else
19016 rettv->vval.v_float = 0.0;
19017}
19018#endif
19019
Bram Moolenaar8299df92004-07-10 09:47:34 +000019020/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000019021 * "type(expr)" function
19022 */
19023 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019024f_type(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000019025 typval_T *argvars;
19026 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019027{
Bram Moolenaar6cc16192005-01-08 21:49:45 +000019028 int n;
19029
19030 switch (argvars[0].v_type)
19031 {
19032 case VAR_NUMBER: n = 0; break;
19033 case VAR_STRING: n = 1; break;
19034 case VAR_FUNC: n = 2; break;
19035 case VAR_LIST: n = 3; break;
Bram Moolenaar758711c2005-02-02 23:11:38 +000019036 case VAR_DICT: n = 4; break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000019037#ifdef FEAT_FLOAT
19038 case VAR_FLOAT: n = 5; break;
19039#endif
Bram Moolenaar6cc16192005-01-08 21:49:45 +000019040 default: EMSG2(_(e_intern2), "f_type()"); n = 0; break;
19041 }
19042 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019043}
19044
19045/*
Bram Moolenaara17d4c12010-05-30 18:30:36 +020019046 * "undofile(name)" function
19047 */
19048 static void
19049f_undofile(argvars, rettv)
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +010019050 typval_T *argvars UNUSED;
Bram Moolenaara17d4c12010-05-30 18:30:36 +020019051 typval_T *rettv;
19052{
19053 rettv->v_type = VAR_STRING;
19054#ifdef FEAT_PERSISTENT_UNDO
Bram Moolenaar945e2db2010-06-05 17:43:32 +020019055 {
Bram Moolenaarb41d9682012-04-30 17:35:48 +020019056 char_u *fname = get_tv_string(&argvars[0]);
Bram Moolenaar945e2db2010-06-05 17:43:32 +020019057
Bram Moolenaarb41d9682012-04-30 17:35:48 +020019058 if (*fname == NUL)
19059 {
19060 /* If there is no file name there will be no undo file. */
19061 rettv->vval.v_string = NULL;
19062 }
19063 else
19064 {
19065 char_u *ffname = FullName_save(fname, FALSE);
19066
19067 if (ffname != NULL)
19068 rettv->vval.v_string = u_get_undo_file_name(ffname, FALSE);
19069 vim_free(ffname);
19070 }
Bram Moolenaar945e2db2010-06-05 17:43:32 +020019071 }
Bram Moolenaara17d4c12010-05-30 18:30:36 +020019072#else
19073 rettv->vval.v_string = NULL;
19074#endif
19075}
19076
19077/*
Bram Moolenaara800b422010-06-27 01:15:55 +020019078 * "undotree()" function
19079 */
19080 static void
19081f_undotree(argvars, rettv)
19082 typval_T *argvars UNUSED;
19083 typval_T *rettv;
19084{
19085 if (rettv_dict_alloc(rettv) == OK)
19086 {
19087 dict_T *dict = rettv->vval.v_dict;
19088 list_T *list;
19089
Bram Moolenaar730cde92010-06-27 05:18:54 +020019090 dict_add_nr_str(dict, "synced", (long)curbuf->b_u_synced, NULL);
Bram Moolenaara800b422010-06-27 01:15:55 +020019091 dict_add_nr_str(dict, "seq_last", curbuf->b_u_seq_last, NULL);
Bram Moolenaar730cde92010-06-27 05:18:54 +020019092 dict_add_nr_str(dict, "save_last",
19093 (long)curbuf->b_u_save_nr_last, NULL);
Bram Moolenaara800b422010-06-27 01:15:55 +020019094 dict_add_nr_str(dict, "seq_cur", curbuf->b_u_seq_cur, NULL);
19095 dict_add_nr_str(dict, "time_cur", (long)curbuf->b_u_time_cur, NULL);
Bram Moolenaar730cde92010-06-27 05:18:54 +020019096 dict_add_nr_str(dict, "save_cur", (long)curbuf->b_u_save_nr_cur, NULL);
Bram Moolenaara800b422010-06-27 01:15:55 +020019097
19098 list = list_alloc();
19099 if (list != NULL)
19100 {
19101 u_eval_tree(curbuf->b_u_oldhead, list);
19102 dict_add_list(dict, "entries", list);
19103 }
19104 }
19105}
19106
19107/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000019108 * "values(dict)" function
19109 */
19110 static void
19111f_values(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000019112 typval_T *argvars;
19113 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000019114{
19115 dict_list(argvars, rettv, 1);
19116}
19117
19118/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000019119 * "virtcol(string)" function
19120 */
19121 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019122f_virtcol(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000019123 typval_T *argvars;
19124 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019125{
19126 colnr_T vcol = 0;
19127 pos_T *fp;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000019128 int fnum = curbuf->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019129
Bram Moolenaar0e34f622006-03-03 23:00:03 +000019130 fp = var2fpos(&argvars[0], FALSE, &fnum);
19131 if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count
19132 && fnum == curbuf->b_fnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019133 {
19134 getvvcol(curwin, fp, NULL, NULL, &vcol);
19135 ++vcol;
19136 }
19137
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019138 rettv->vval.v_number = vcol;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019139}
19140
19141/*
19142 * "visualmode()" function
19143 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000019144 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019145f_visualmode(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000019146 typval_T *argvars UNUSED;
19147 typval_T *rettv UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019148{
Bram Moolenaar071d4272004-06-13 20:20:40 +000019149 char_u str[2];
19150
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019151 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019152 str[0] = curbuf->b_visual_mode_eval;
19153 str[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019154 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019155
19156 /* A non-zero number or non-empty string argument: reset mode. */
Bram Moolenaar05bb9532008-07-04 09:44:11 +000019157 if (non_zero_arg(&argvars[0]))
Bram Moolenaar071d4272004-06-13 20:20:40 +000019158 curbuf->b_visual_mode_eval = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019159}
19160
19161/*
Bram Moolenaar8738fc12013-02-20 17:59:11 +010019162 * "wildmenumode()" function
19163 */
19164 static void
19165f_wildmenumode(argvars, rettv)
19166 typval_T *argvars UNUSED;
19167 typval_T *rettv UNUSED;
19168{
19169#ifdef FEAT_WILDMENU
19170 if (wild_menu_showing)
19171 rettv->vval.v_number = 1;
19172#endif
19173}
19174
19175/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000019176 * "winbufnr(nr)" function
19177 */
19178 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019179f_winbufnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000019180 typval_T *argvars;
19181 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019182{
19183 win_T *wp;
19184
Bram Moolenaar99ebf042006-04-15 20:28:54 +000019185 wp = find_win_by_nr(&argvars[0], NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019186 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019187 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019188 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019189 rettv->vval.v_number = wp->w_buffer->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019190}
19191
19192/*
19193 * "wincol()" function
19194 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000019195 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019196f_wincol(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000019197 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000019198 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019199{
19200 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019201 rettv->vval.v_number = curwin->w_wcol + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019202}
19203
19204/*
19205 * "winheight(nr)" function
19206 */
19207 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019208f_winheight(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000019209 typval_T *argvars;
19210 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019211{
19212 win_T *wp;
19213
Bram Moolenaar99ebf042006-04-15 20:28:54 +000019214 wp = find_win_by_nr(&argvars[0], NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019215 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019216 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019217 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019218 rettv->vval.v_number = wp->w_height;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019219}
19220
19221/*
19222 * "winline()" function
19223 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000019224 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019225f_winline(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000019226 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000019227 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019228{
19229 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019230 rettv->vval.v_number = curwin->w_wrow + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019231}
19232
19233/*
19234 * "winnr()" function
19235 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000019236 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019237f_winnr(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000019238 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000019239 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019240{
19241 int nr = 1;
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000019242
Bram Moolenaar071d4272004-06-13 20:20:40 +000019243#ifdef FEAT_WINDOWS
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000019244 nr = get_winnr(curtab, &argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019245#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019246 rettv->vval.v_number = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019247}
19248
19249/*
19250 * "winrestcmd()" function
19251 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000019252 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019253f_winrestcmd(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000019254 typval_T *argvars UNUSED;
Bram Moolenaar33570922005-01-25 22:26:29 +000019255 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019256{
19257#ifdef FEAT_WINDOWS
19258 win_T *wp;
19259 int winnr = 1;
19260 garray_T ga;
19261 char_u buf[50];
19262
19263 ga_init2(&ga, (int)sizeof(char), 70);
19264 for (wp = firstwin; wp != NULL; wp = wp->w_next)
19265 {
19266 sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height);
19267 ga_concat(&ga, buf);
19268# ifdef FEAT_VERTSPLIT
19269 sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width);
19270 ga_concat(&ga, buf);
19271# endif
19272 ++winnr;
19273 }
Bram Moolenaar269ec652004-07-29 08:43:53 +000019274 ga_append(&ga, NUL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019275
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019276 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019277#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019278 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019279#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019280 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019281}
19282
19283/*
Bram Moolenaar768b8c42006-03-04 21:58:33 +000019284 * "winrestview()" function
19285 */
Bram Moolenaar768b8c42006-03-04 21:58:33 +000019286 static void
19287f_winrestview(argvars, rettv)
19288 typval_T *argvars;
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000019289 typval_T *rettv UNUSED;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000019290{
19291 dict_T *dict;
19292
19293 if (argvars[0].v_type != VAR_DICT
19294 || (dict = argvars[0].vval.v_dict) == NULL)
19295 EMSG(_(e_invarg));
19296 else
19297 {
Bram Moolenaar82c25852014-05-28 16:47:16 +020019298 if (dict_find(dict, (char_u *)"lnum", -1) != NULL)
19299 curwin->w_cursor.lnum = get_dict_number(dict, (char_u *)"lnum");
19300 if (dict_find(dict, (char_u *)"col", -1) != NULL)
19301 curwin->w_cursor.col = get_dict_number(dict, (char_u *)"col");
Bram Moolenaar768b8c42006-03-04 21:58:33 +000019302#ifdef FEAT_VIRTUALEDIT
Bram Moolenaar82c25852014-05-28 16:47:16 +020019303 if (dict_find(dict, (char_u *)"coladd", -1) != NULL)
19304 curwin->w_cursor.coladd = get_dict_number(dict, (char_u *)"coladd");
Bram Moolenaar768b8c42006-03-04 21:58:33 +000019305#endif
Bram Moolenaar82c25852014-05-28 16:47:16 +020019306 if (dict_find(dict, (char_u *)"curswant", -1) != NULL)
19307 {
19308 curwin->w_curswant = get_dict_number(dict, (char_u *)"curswant");
19309 curwin->w_set_curswant = FALSE;
19310 }
Bram Moolenaar768b8c42006-03-04 21:58:33 +000019311
Bram Moolenaar82c25852014-05-28 16:47:16 +020019312 if (dict_find(dict, (char_u *)"topline", -1) != NULL)
19313 set_topline(curwin, get_dict_number(dict, (char_u *)"topline"));
Bram Moolenaar768b8c42006-03-04 21:58:33 +000019314#ifdef FEAT_DIFF
Bram Moolenaar82c25852014-05-28 16:47:16 +020019315 if (dict_find(dict, (char_u *)"topfill", -1) != NULL)
19316 curwin->w_topfill = get_dict_number(dict, (char_u *)"topfill");
Bram Moolenaar768b8c42006-03-04 21:58:33 +000019317#endif
Bram Moolenaar82c25852014-05-28 16:47:16 +020019318 if (dict_find(dict, (char_u *)"leftcol", -1) != NULL)
19319 curwin->w_leftcol = get_dict_number(dict, (char_u *)"leftcol");
19320 if (dict_find(dict, (char_u *)"skipcol", -1) != NULL)
19321 curwin->w_skipcol = get_dict_number(dict, (char_u *)"skipcol");
Bram Moolenaar768b8c42006-03-04 21:58:33 +000019322
19323 check_cursor();
Bram Moolenaar6763c142012-07-19 18:05:44 +020019324 win_new_height(curwin, curwin->w_height);
19325# ifdef FEAT_VERTSPLIT
19326 win_new_width(curwin, W_WIDTH(curwin));
19327# endif
Bram Moolenaarab984db2012-06-06 16:29:10 +020019328 changed_window_setting();
Bram Moolenaar768b8c42006-03-04 21:58:33 +000019329
19330 if (curwin->w_topline == 0)
19331 curwin->w_topline = 1;
19332 if (curwin->w_topline > curbuf->b_ml.ml_line_count)
19333 curwin->w_topline = curbuf->b_ml.ml_line_count;
19334#ifdef FEAT_DIFF
19335 check_topfill(curwin, TRUE);
19336#endif
19337 }
19338}
19339
19340/*
19341 * "winsaveview()" function
19342 */
Bram Moolenaar768b8c42006-03-04 21:58:33 +000019343 static void
19344f_winsaveview(argvars, rettv)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000019345 typval_T *argvars UNUSED;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000019346 typval_T *rettv;
19347{
19348 dict_T *dict;
19349
Bram Moolenaara800b422010-06-27 01:15:55 +020019350 if (rettv_dict_alloc(rettv) == FAIL)
Bram Moolenaar768b8c42006-03-04 21:58:33 +000019351 return;
Bram Moolenaara800b422010-06-27 01:15:55 +020019352 dict = rettv->vval.v_dict;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000019353
19354 dict_add_nr_str(dict, "lnum", (long)curwin->w_cursor.lnum, NULL);
19355 dict_add_nr_str(dict, "col", (long)curwin->w_cursor.col, NULL);
19356#ifdef FEAT_VIRTUALEDIT
19357 dict_add_nr_str(dict, "coladd", (long)curwin->w_cursor.coladd, NULL);
19358#endif
Bram Moolenaar9af1ba92006-08-29 19:55:53 +000019359 update_curswant();
Bram Moolenaar768b8c42006-03-04 21:58:33 +000019360 dict_add_nr_str(dict, "curswant", (long)curwin->w_curswant, NULL);
19361
19362 dict_add_nr_str(dict, "topline", (long)curwin->w_topline, NULL);
19363#ifdef FEAT_DIFF
19364 dict_add_nr_str(dict, "topfill", (long)curwin->w_topfill, NULL);
19365#endif
19366 dict_add_nr_str(dict, "leftcol", (long)curwin->w_leftcol, NULL);
19367 dict_add_nr_str(dict, "skipcol", (long)curwin->w_skipcol, NULL);
19368}
19369
19370/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000019371 * "winwidth(nr)" function
19372 */
19373 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019374f_winwidth(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000019375 typval_T *argvars;
19376 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019377{
19378 win_T *wp;
19379
Bram Moolenaar99ebf042006-04-15 20:28:54 +000019380 wp = find_win_by_nr(&argvars[0], NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019381 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019382 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019383 else
19384#ifdef FEAT_VERTSPLIT
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019385 rettv->vval.v_number = wp->w_width;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019386#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019387 rettv->vval.v_number = Columns;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019388#endif
19389}
19390
Bram Moolenaar071d4272004-06-13 20:20:40 +000019391/*
Bram Moolenaar57ebe6e2014-04-05 18:55:46 +020019392 * Write list of strings to file
19393 */
19394 static int
19395write_list(fd, list, binary)
19396 FILE *fd;
19397 list_T *list;
19398 int binary;
19399{
19400 listitem_T *li;
19401 int c;
19402 int ret = OK;
19403 char_u *s;
19404
19405 for (li = list->lv_first; li != NULL; li = li->li_next)
19406 {
19407 for (s = get_tv_string(&li->li_tv); *s != NUL; ++s)
19408 {
19409 if (*s == '\n')
19410 c = putc(NUL, fd);
19411 else
19412 c = putc(*s, fd);
19413 if (c == EOF)
19414 {
19415 ret = FAIL;
19416 break;
19417 }
19418 }
19419 if (!binary || li->li_next != NULL)
19420 if (putc('\n', fd) == EOF)
19421 {
19422 ret = FAIL;
19423 break;
19424 }
19425 if (ret == FAIL)
19426 {
19427 EMSG(_(e_write));
19428 break;
19429 }
19430 }
19431 return ret;
19432}
19433
19434/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000019435 * "writefile()" function
19436 */
19437 static void
19438f_writefile(argvars, rettv)
19439 typval_T *argvars;
19440 typval_T *rettv;
19441{
19442 int binary = FALSE;
19443 char_u *fname;
19444 FILE *fd;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000019445 int ret = 0;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000019446
Bram Moolenaard9fe7c42007-04-29 11:53:56 +000019447 if (check_restricted() || check_secure())
19448 return;
19449
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000019450 if (argvars[0].v_type != VAR_LIST)
19451 {
19452 EMSG2(_(e_listarg), "writefile()");
19453 return;
19454 }
19455 if (argvars[0].vval.v_list == NULL)
19456 return;
19457
19458 if (argvars[2].v_type != VAR_UNKNOWN
19459 && STRCMP(get_tv_string(&argvars[2]), "b") == 0)
19460 binary = TRUE;
19461
19462 /* Always open the file in binary mode, library functions have a mind of
19463 * their own about CR-LF conversion. */
19464 fname = get_tv_string(&argvars[1]);
19465 if (*fname == NUL || (fd = mch_fopen((char *)fname, WRITEBIN)) == NULL)
19466 {
19467 EMSG2(_(e_notcreate), *fname == NUL ? (char_u *)_("<empty>") : fname);
19468 ret = -1;
19469 }
19470 else
19471 {
Bram Moolenaar57ebe6e2014-04-05 18:55:46 +020019472 if (write_list(fd, argvars[0].vval.v_list, binary) == FAIL)
19473 ret = -1;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000019474 fclose(fd);
19475 }
19476
19477 rettv->vval.v_number = ret;
19478}
19479
19480/*
Bram Moolenaard6e256c2011-12-14 15:32:50 +010019481 * "xor(expr, expr)" function
19482 */
19483 static void
19484f_xor(argvars, rettv)
19485 typval_T *argvars;
19486 typval_T *rettv;
19487{
19488 rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL)
19489 ^ get_tv_number_chk(&argvars[1], NULL);
19490}
19491
19492
19493/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000019494 * Translate a String variable into a position.
Bram Moolenaar32466aa2006-02-24 23:53:04 +000019495 * Returns NULL when there is an error.
Bram Moolenaar071d4272004-06-13 20:20:40 +000019496 */
19497 static pos_T *
Bram Moolenaar477933c2007-07-17 14:32:23 +000019498var2fpos(varp, dollar_lnum, fnum)
Bram Moolenaar33570922005-01-25 22:26:29 +000019499 typval_T *varp;
Bram Moolenaar477933c2007-07-17 14:32:23 +000019500 int dollar_lnum; /* TRUE when $ is last line */
Bram Moolenaar0e34f622006-03-03 23:00:03 +000019501 int *fnum; /* set to fnum for '0, 'A, etc. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000019502{
Bram Moolenaar261bfea2006-03-01 22:12:31 +000019503 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019504 static pos_T pos;
Bram Moolenaar261bfea2006-03-01 22:12:31 +000019505 pos_T *pp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019506
Bram Moolenaara5525202006-03-02 22:52:09 +000019507 /* Argument can be [lnum, col, coladd]. */
Bram Moolenaar32466aa2006-02-24 23:53:04 +000019508 if (varp->v_type == VAR_LIST)
19509 {
19510 list_T *l;
Bram Moolenaar32466aa2006-02-24 23:53:04 +000019511 int len;
Bram Moolenaara5525202006-03-02 22:52:09 +000019512 int error = FALSE;
Bram Moolenaar477933c2007-07-17 14:32:23 +000019513 listitem_T *li;
Bram Moolenaar32466aa2006-02-24 23:53:04 +000019514
19515 l = varp->vval.v_list;
19516 if (l == NULL)
19517 return NULL;
19518
19519 /* Get the line number */
Bram Moolenaara5525202006-03-02 22:52:09 +000019520 pos.lnum = list_find_nr(l, 0L, &error);
19521 if (error || pos.lnum <= 0 || pos.lnum > curbuf->b_ml.ml_line_count)
Bram Moolenaar32466aa2006-02-24 23:53:04 +000019522 return NULL; /* invalid line number */
19523
19524 /* Get the column number */
Bram Moolenaara5525202006-03-02 22:52:09 +000019525 pos.col = list_find_nr(l, 1L, &error);
19526 if (error)
Bram Moolenaar32466aa2006-02-24 23:53:04 +000019527 return NULL;
Bram Moolenaar32466aa2006-02-24 23:53:04 +000019528 len = (long)STRLEN(ml_get(pos.lnum));
Bram Moolenaar477933c2007-07-17 14:32:23 +000019529
19530 /* We accept "$" for the column number: last column. */
19531 li = list_find(l, 1L);
19532 if (li != NULL && li->li_tv.v_type == VAR_STRING
19533 && li->li_tv.vval.v_string != NULL
19534 && STRCMP(li->li_tv.vval.v_string, "$") == 0)
19535 pos.col = len + 1;
19536
Bram Moolenaara5525202006-03-02 22:52:09 +000019537 /* Accept a position up to the NUL after the line. */
Bram Moolenaar4c3f5362006-04-11 21:38:50 +000019538 if (pos.col == 0 || (int)pos.col > len + 1)
Bram Moolenaar32466aa2006-02-24 23:53:04 +000019539 return NULL; /* invalid column number */
Bram Moolenaara5525202006-03-02 22:52:09 +000019540 --pos.col;
Bram Moolenaar32466aa2006-02-24 23:53:04 +000019541
Bram Moolenaara5525202006-03-02 22:52:09 +000019542#ifdef FEAT_VIRTUALEDIT
19543 /* Get the virtual offset. Defaults to zero. */
19544 pos.coladd = list_find_nr(l, 2L, &error);
19545 if (error)
19546 pos.coladd = 0;
19547#endif
19548
Bram Moolenaar32466aa2006-02-24 23:53:04 +000019549 return &pos;
19550 }
19551
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000019552 name = get_tv_string_chk(varp);
19553 if (name == NULL)
19554 return NULL;
Bram Moolenaar9ecd0232008-06-20 15:31:51 +000019555 if (name[0] == '.') /* cursor */
Bram Moolenaar071d4272004-06-13 20:20:40 +000019556 return &curwin->w_cursor;
Bram Moolenaar9ecd0232008-06-20 15:31:51 +000019557 if (name[0] == 'v' && name[1] == NUL) /* Visual start */
19558 {
19559 if (VIsual_active)
19560 return &VIsual;
19561 return &curwin->w_cursor;
19562 }
Bram Moolenaar9ecd0232008-06-20 15:31:51 +000019563 if (name[0] == '\'') /* mark */
Bram Moolenaar071d4272004-06-13 20:20:40 +000019564 {
Bram Moolenaar9d182dd2013-01-23 15:53:15 +010019565 pp = getmark_buf_fnum(curbuf, name[1], FALSE, fnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019566 if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
19567 return NULL;
19568 return pp;
19569 }
Bram Moolenaara5525202006-03-02 22:52:09 +000019570
19571#ifdef FEAT_VIRTUALEDIT
19572 pos.coladd = 0;
19573#endif
19574
Bram Moolenaar477933c2007-07-17 14:32:23 +000019575 if (name[0] == 'w' && dollar_lnum)
Bram Moolenaarf52c7252006-02-10 23:23:57 +000019576 {
19577 pos.col = 0;
19578 if (name[1] == '0') /* "w0": first visible line */
19579 {
Bram Moolenaarf740b292006-02-16 22:11:02 +000019580 update_topline();
Bram Moolenaarf52c7252006-02-10 23:23:57 +000019581 pos.lnum = curwin->w_topline;
19582 return &pos;
19583 }
19584 else if (name[1] == '$') /* "w$": last visible line */
19585 {
Bram Moolenaarf740b292006-02-16 22:11:02 +000019586 validate_botline();
Bram Moolenaarf52c7252006-02-10 23:23:57 +000019587 pos.lnum = curwin->w_botline - 1;
19588 return &pos;
19589 }
19590 }
19591 else if (name[0] == '$') /* last column or line */
Bram Moolenaar071d4272004-06-13 20:20:40 +000019592 {
Bram Moolenaar477933c2007-07-17 14:32:23 +000019593 if (dollar_lnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019594 {
19595 pos.lnum = curbuf->b_ml.ml_line_count;
19596 pos.col = 0;
19597 }
19598 else
19599 {
19600 pos.lnum = curwin->w_cursor.lnum;
19601 pos.col = (colnr_T)STRLEN(ml_get_curline());
19602 }
19603 return &pos;
19604 }
19605 return NULL;
19606}
19607
19608/*
Bram Moolenaar0e34f622006-03-03 23:00:03 +000019609 * Convert list in "arg" into a position and optional file number.
19610 * When "fnump" is NULL there is no file number, only 3 items.
19611 * Note that the column is passed on as-is, the caller may want to decrement
19612 * it to use 1 for the first column.
19613 * Return FAIL when conversion is not possible, doesn't check the position for
19614 * validity.
19615 */
19616 static int
Bram Moolenaar493c1782014-05-28 14:34:46 +020019617list2fpos(arg, posp, fnump, curswantp)
Bram Moolenaar0e34f622006-03-03 23:00:03 +000019618 typval_T *arg;
19619 pos_T *posp;
19620 int *fnump;
Bram Moolenaar493c1782014-05-28 14:34:46 +020019621 colnr_T *curswantp;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000019622{
19623 list_T *l = arg->vval.v_list;
19624 long i = 0;
19625 long n;
19626
Bram Moolenaar493c1782014-05-28 14:34:46 +020019627 /* List must be: [fnum, lnum, col, coladd, curswant], where "fnum" is only
19628 * there when "fnump" isn't NULL; "coladd" and "curswant" are optional. */
Bram Moolenaarbde35262006-07-23 20:12:24 +000019629 if (arg->v_type != VAR_LIST
19630 || l == NULL
19631 || l->lv_len < (fnump == NULL ? 2 : 3)
Bram Moolenaar493c1782014-05-28 14:34:46 +020019632 || l->lv_len > (fnump == NULL ? 4 : 5))
Bram Moolenaar0e34f622006-03-03 23:00:03 +000019633 return FAIL;
19634
19635 if (fnump != NULL)
19636 {
19637 n = list_find_nr(l, i++, NULL); /* fnum */
19638 if (n < 0)
19639 return FAIL;
19640 if (n == 0)
19641 n = curbuf->b_fnum; /* current buffer */
19642 *fnump = n;
19643 }
19644
19645 n = list_find_nr(l, i++, NULL); /* lnum */
19646 if (n < 0)
19647 return FAIL;
19648 posp->lnum = n;
19649
19650 n = list_find_nr(l, i++, NULL); /* col */
19651 if (n < 0)
19652 return FAIL;
19653 posp->col = n;
19654
19655#ifdef FEAT_VIRTUALEDIT
Bram Moolenaar493c1782014-05-28 14:34:46 +020019656 n = list_find_nr(l, i, NULL); /* off */
Bram Moolenaar0e34f622006-03-03 23:00:03 +000019657 if (n < 0)
Bram Moolenaarbde35262006-07-23 20:12:24 +000019658 posp->coladd = 0;
19659 else
19660 posp->coladd = n;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000019661#endif
19662
Bram Moolenaar493c1782014-05-28 14:34:46 +020019663 if (curswantp != NULL)
19664 *curswantp = list_find_nr(l, i + 1, NULL); /* curswant */
19665
Bram Moolenaar0e34f622006-03-03 23:00:03 +000019666 return OK;
19667}
19668
19669/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000019670 * Get the length of an environment variable name.
19671 * Advance "arg" to the first character after the name.
19672 * Return 0 for error.
19673 */
19674 static int
19675get_env_len(arg)
19676 char_u **arg;
19677{
19678 char_u *p;
19679 int len;
19680
19681 for (p = *arg; vim_isIDc(*p); ++p)
19682 ;
19683 if (p == *arg) /* no name found */
19684 return 0;
19685
19686 len = (int)(p - *arg);
19687 *arg = p;
19688 return len;
19689}
19690
19691/*
19692 * Get the length of the name of a function or internal variable.
19693 * "arg" is advanced to the first non-white character after the name.
19694 * Return 0 if something is wrong.
19695 */
19696 static int
19697get_id_len(arg)
19698 char_u **arg;
19699{
19700 char_u *p;
19701 int len;
19702
19703 /* Find the end of the name. */
19704 for (p = *arg; eval_isnamec(*p); ++p)
19705 ;
19706 if (p == *arg) /* no name found */
19707 return 0;
19708
19709 len = (int)(p - *arg);
19710 *arg = skipwhite(p);
19711
19712 return len;
19713}
19714
19715/*
Bram Moolenaara7043832005-01-21 11:56:39 +000019716 * Get the length of the name of a variable or function.
19717 * Only the name is recognized, does not handle ".key" or "[idx]".
Bram Moolenaar071d4272004-06-13 20:20:40 +000019718 * "arg" is advanced to the first non-white character after the name.
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000019719 * Return -1 if curly braces expansion failed.
19720 * Return 0 if something else is wrong.
Bram Moolenaar071d4272004-06-13 20:20:40 +000019721 * If the name contains 'magic' {}'s, expand them and return the
19722 * expanded name in an allocated string via 'alias' - caller must free.
19723 */
19724 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000019725get_name_len(arg, alias, evaluate, verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019726 char_u **arg;
19727 char_u **alias;
19728 int evaluate;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000019729 int verbose;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019730{
19731 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019732 char_u *p;
19733 char_u *expr_start;
19734 char_u *expr_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019735
19736 *alias = NULL; /* default to no alias */
19737
19738 if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
19739 && (*arg)[2] == (int)KE_SNR)
19740 {
19741 /* hard coded <SNR>, already translated */
19742 *arg += 3;
19743 return get_id_len(arg) + 3;
19744 }
19745 len = eval_fname_script(*arg);
19746 if (len > 0)
19747 {
19748 /* literal "<SID>", "s:" or "<SNR>" */
19749 *arg += len;
19750 }
19751
Bram Moolenaar071d4272004-06-13 20:20:40 +000019752 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019753 * Find the end of the name; check for {} construction.
Bram Moolenaar071d4272004-06-13 20:20:40 +000019754 */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000019755 p = find_name_end(*arg, &expr_start, &expr_end,
19756 len > 0 ? 0 : FNE_CHECK_START);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019757 if (expr_start != NULL)
19758 {
19759 char_u *temp_string;
19760
19761 if (!evaluate)
19762 {
19763 len += (int)(p - *arg);
19764 *arg = skipwhite(p);
19765 return len;
19766 }
19767
19768 /*
19769 * Include any <SID> etc in the expanded string:
19770 * Thus the -len here.
19771 */
19772 temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
19773 if (temp_string == NULL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000019774 return -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019775 *alias = temp_string;
19776 *arg = skipwhite(p);
19777 return (int)STRLEN(temp_string);
19778 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000019779
19780 len += get_id_len(arg);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000019781 if (len == 0 && verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019782 EMSG2(_(e_invexpr2), *arg);
19783
19784 return len;
19785}
19786
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019787/*
19788 * Find the end of a variable or function name, taking care of magic braces.
19789 * If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the
19790 * start and end of the first magic braces item.
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000019791 * "flags" can have FNE_INCL_BR and FNE_CHECK_START.
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019792 * Return a pointer to just after the name. Equal to "arg" if there is no
19793 * valid name.
19794 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000019795 static char_u *
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000019796find_name_end(arg, expr_start, expr_end, flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019797 char_u *arg;
19798 char_u **expr_start;
19799 char_u **expr_end;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000019800 int flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019801{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019802 int mb_nest = 0;
19803 int br_nest = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019804 char_u *p;
19805
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019806 if (expr_start != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019807 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019808 *expr_start = NULL;
19809 *expr_end = NULL;
19810 }
19811
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000019812 /* Quick check for valid starting character. */
19813 if ((flags & FNE_CHECK_START) && !eval_isnamec1(*arg) && *arg != '{')
19814 return arg;
19815
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019816 for (p = arg; *p != NUL
19817 && (eval_isnamec(*p)
Bram Moolenaare9a41262005-01-15 22:18:47 +000019818 || *p == '{'
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000019819 || ((flags & FNE_INCL_BR) && (*p == '[' || *p == '.'))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019820 || mb_nest != 0
Bram Moolenaar8af24422005-08-08 22:06:28 +000019821 || br_nest != 0); mb_ptr_adv(p))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019822 {
Bram Moolenaar8af24422005-08-08 22:06:28 +000019823 if (*p == '\'')
19824 {
19825 /* skip over 'string' to avoid counting [ and ] inside it. */
19826 for (p = p + 1; *p != NUL && *p != '\''; mb_ptr_adv(p))
19827 ;
19828 if (*p == NUL)
19829 break;
19830 }
19831 else if (*p == '"')
19832 {
19833 /* skip over "str\"ing" to avoid counting [ and ] inside it. */
19834 for (p = p + 1; *p != NUL && *p != '"'; mb_ptr_adv(p))
19835 if (*p == '\\' && p[1] != NUL)
19836 ++p;
19837 if (*p == NUL)
19838 break;
19839 }
19840
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019841 if (mb_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019842 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019843 if (*p == '[')
19844 ++br_nest;
19845 else if (*p == ']')
19846 --br_nest;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019847 }
Bram Moolenaar8af24422005-08-08 22:06:28 +000019848
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019849 if (br_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019850 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019851 if (*p == '{')
19852 {
19853 mb_nest++;
19854 if (expr_start != NULL && *expr_start == NULL)
19855 *expr_start = p;
19856 }
19857 else if (*p == '}')
19858 {
19859 mb_nest--;
19860 if (expr_start != NULL && mb_nest == 0 && *expr_end == NULL)
19861 *expr_end = p;
19862 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000019863 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000019864 }
19865
19866 return p;
19867}
19868
19869/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000019870 * Expands out the 'magic' {}'s in a variable/function name.
19871 * Note that this can call itself recursively, to deal with
19872 * constructs like foo{bar}{baz}{bam}
19873 * The four pointer arguments point to "foo{expre}ss{ion}bar"
19874 * "in_start" ^
19875 * "expr_start" ^
19876 * "expr_end" ^
19877 * "in_end" ^
19878 *
19879 * Returns a new allocated string, which the caller must free.
19880 * Returns NULL for failure.
19881 */
19882 static char_u *
19883make_expanded_name(in_start, expr_start, expr_end, in_end)
19884 char_u *in_start;
19885 char_u *expr_start;
19886 char_u *expr_end;
19887 char_u *in_end;
19888{
19889 char_u c1;
19890 char_u *retval = NULL;
19891 char_u *temp_result;
19892 char_u *nextcmd = NULL;
19893
19894 if (expr_end == NULL || in_end == NULL)
19895 return NULL;
19896 *expr_start = NUL;
19897 *expr_end = NUL;
19898 c1 = *in_end;
19899 *in_end = NUL;
19900
Bram Moolenaar362e1a32006-03-06 23:29:24 +000019901 temp_result = eval_to_string(expr_start + 1, &nextcmd, FALSE);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000019902 if (temp_result != NULL && nextcmd == NULL)
19903 {
19904 retval = alloc((unsigned)(STRLEN(temp_result) + (expr_start - in_start)
19905 + (in_end - expr_end) + 1));
19906 if (retval != NULL)
19907 {
19908 STRCPY(retval, in_start);
19909 STRCAT(retval, temp_result);
19910 STRCAT(retval, expr_end + 1);
19911 }
19912 }
19913 vim_free(temp_result);
19914
19915 *in_end = c1; /* put char back for error messages */
19916 *expr_start = '{';
19917 *expr_end = '}';
19918
19919 if (retval != NULL)
19920 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000019921 temp_result = find_name_end(retval, &expr_start, &expr_end, 0);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000019922 if (expr_start != NULL)
19923 {
19924 /* Further expansion! */
19925 temp_result = make_expanded_name(retval, expr_start,
19926 expr_end, temp_result);
19927 vim_free(retval);
19928 retval = temp_result;
19929 }
19930 }
19931
19932 return retval;
19933}
19934
19935/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000019936 * Return TRUE if character "c" can be used in a variable or function name.
Bram Moolenaare9a41262005-01-15 22:18:47 +000019937 * Does not include '{' or '}' for magic braces.
Bram Moolenaar071d4272004-06-13 20:20:40 +000019938 */
19939 static int
19940eval_isnamec(c)
19941 int c;
19942{
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000019943 return (ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR);
19944}
19945
19946/*
19947 * Return TRUE if character "c" can be used as the first character in a
19948 * variable or function name (excluding '{' and '}').
19949 */
19950 static int
19951eval_isnamec1(c)
19952 int c;
19953{
19954 return (ASCII_ISALPHA(c) || c == '_');
Bram Moolenaar071d4272004-06-13 20:20:40 +000019955}
19956
19957/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000019958 * Set number v: variable to "val".
19959 */
19960 void
19961set_vim_var_nr(idx, val)
19962 int idx;
19963 long val;
19964{
Bram Moolenaare9a41262005-01-15 22:18:47 +000019965 vimvars[idx].vv_nr = val;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019966}
19967
19968/*
Bram Moolenaar19a09a12005-03-04 23:39:37 +000019969 * Get number v: variable value.
Bram Moolenaar071d4272004-06-13 20:20:40 +000019970 */
19971 long
19972get_vim_var_nr(idx)
19973 int idx;
19974{
Bram Moolenaare9a41262005-01-15 22:18:47 +000019975 return vimvars[idx].vv_nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019976}
19977
Bram Moolenaar19a09a12005-03-04 23:39:37 +000019978/*
19979 * Get string v: variable value. Uses a static buffer, can only be used once.
19980 */
19981 char_u *
19982get_vim_var_str(idx)
19983 int idx;
19984{
19985 return get_tv_string(&vimvars[idx].vv_tv);
19986}
Bram Moolenaar19a09a12005-03-04 23:39:37 +000019987
Bram Moolenaar071d4272004-06-13 20:20:40 +000019988/*
Bram Moolenaard812df62008-11-09 12:46:09 +000019989 * Get List v: variable value. Caller must take care of reference count when
19990 * needed.
19991 */
19992 list_T *
19993get_vim_var_list(idx)
19994 int idx;
19995{
19996 return vimvars[idx].vv_list;
19997}
19998
19999/*
Bram Moolenaarda9591e2009-09-30 13:17:02 +000020000 * Set v:char to character "c".
20001 */
20002 void
20003set_vim_var_char(c)
20004 int c;
20005{
Bram Moolenaar9a920d82012-06-01 15:21:02 +020020006 char_u buf[MB_MAXBYTES + 1];
Bram Moolenaarda9591e2009-09-30 13:17:02 +000020007
20008#ifdef FEAT_MBYTE
20009 if (has_mbyte)
20010 buf[(*mb_char2bytes)(c, buf)] = NUL;
20011 else
20012#endif
20013 {
20014 buf[0] = c;
20015 buf[1] = NUL;
20016 }
20017 set_vim_var_string(VV_CHAR, buf, -1);
20018}
20019
20020/*
Bram Moolenaar8df74be2008-11-20 15:12:02 +000020021 * Set v:count to "count" and v:count1 to "count1".
20022 * When "set_prevcount" is TRUE first set v:prevcount from v:count.
Bram Moolenaar071d4272004-06-13 20:20:40 +000020023 */
20024 void
Bram Moolenaar8df74be2008-11-20 15:12:02 +000020025set_vcount(count, count1, set_prevcount)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020026 long count;
20027 long count1;
Bram Moolenaar8df74be2008-11-20 15:12:02 +000020028 int set_prevcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020029{
Bram Moolenaar8df74be2008-11-20 15:12:02 +000020030 if (set_prevcount)
20031 vimvars[VV_PREVCOUNT].vv_nr = vimvars[VV_COUNT].vv_nr;
Bram Moolenaare9a41262005-01-15 22:18:47 +000020032 vimvars[VV_COUNT].vv_nr = count;
20033 vimvars[VV_COUNT1].vv_nr = count1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020034}
20035
20036/*
20037 * Set string v: variable to a copy of "val".
20038 */
20039 void
20040set_vim_var_string(idx, val, len)
20041 int idx;
20042 char_u *val;
20043 int len; /* length of "val" to use or -1 (whole string) */
20044{
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000020045 /* Need to do this (at least) once, since we can't initialize a union.
20046 * Will always be invoked when "v:progname" is set. */
20047 vimvars[VV_VERSION].vv_nr = VIM_VERSION_100;
20048
Bram Moolenaare9a41262005-01-15 22:18:47 +000020049 vim_free(vimvars[idx].vv_str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020050 if (val == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000020051 vimvars[idx].vv_str = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020052 else if (len == -1)
Bram Moolenaare9a41262005-01-15 22:18:47 +000020053 vimvars[idx].vv_str = vim_strsave(val);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020054 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000020055 vimvars[idx].vv_str = vim_strnsave(val, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020056}
20057
20058/*
Bram Moolenaard812df62008-11-09 12:46:09 +000020059 * Set List v: variable to "val".
20060 */
20061 void
20062set_vim_var_list(idx, val)
20063 int idx;
20064 list_T *val;
20065{
20066 list_unref(vimvars[idx].vv_list);
20067 vimvars[idx].vv_list = val;
20068 if (val != NULL)
20069 ++val->lv_refcount;
20070}
20071
20072/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000020073 * Set v:register if needed.
20074 */
20075 void
20076set_reg_var(c)
20077 int c;
20078{
20079 char_u regname;
20080
20081 if (c == 0 || c == ' ')
20082 regname = '"';
20083 else
20084 regname = c;
20085 /* Avoid free/alloc when the value is already right. */
Bram Moolenaare9a41262005-01-15 22:18:47 +000020086 if (vimvars[VV_REG].vv_str == NULL || vimvars[VV_REG].vv_str[0] != c)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020087 set_vim_var_string(VV_REG, &regname, 1);
20088}
20089
20090/*
20091 * Get or set v:exception. If "oldval" == NULL, return the current value.
20092 * Otherwise, restore the value to "oldval" and return NULL.
20093 * Must always be called in pairs to save and restore v:exception! Does not
20094 * take care of memory allocations.
20095 */
20096 char_u *
20097v_exception(oldval)
20098 char_u *oldval;
20099{
20100 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000020101 return vimvars[VV_EXCEPTION].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020102
Bram Moolenaare9a41262005-01-15 22:18:47 +000020103 vimvars[VV_EXCEPTION].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020104 return NULL;
20105}
20106
20107/*
20108 * Get or set v:throwpoint. If "oldval" == NULL, return the current value.
20109 * Otherwise, restore the value to "oldval" and return NULL.
20110 * Must always be called in pairs to save and restore v:throwpoint! Does not
20111 * take care of memory allocations.
20112 */
20113 char_u *
20114v_throwpoint(oldval)
20115 char_u *oldval;
20116{
20117 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000020118 return vimvars[VV_THROWPOINT].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020119
Bram Moolenaare9a41262005-01-15 22:18:47 +000020120 vimvars[VV_THROWPOINT].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020121 return NULL;
20122}
20123
20124#if defined(FEAT_AUTOCMD) || defined(PROTO)
20125/*
20126 * Set v:cmdarg.
20127 * If "eap" != NULL, use "eap" to generate the value and return the old value.
20128 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
20129 * Must always be called in pairs!
20130 */
20131 char_u *
20132set_cmdarg(eap, oldarg)
20133 exarg_T *eap;
20134 char_u *oldarg;
20135{
20136 char_u *oldval;
20137 char_u *newval;
20138 unsigned len;
20139
Bram Moolenaare9a41262005-01-15 22:18:47 +000020140 oldval = vimvars[VV_CMDARG].vv_str;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000020141 if (eap == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020142 {
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000020143 vim_free(oldval);
Bram Moolenaare9a41262005-01-15 22:18:47 +000020144 vimvars[VV_CMDARG].vv_str = oldarg;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000020145 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020146 }
20147
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000020148 if (eap->force_bin == FORCE_BIN)
20149 len = 6;
20150 else if (eap->force_bin == FORCE_NOBIN)
20151 len = 8;
20152 else
20153 len = 0;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000020154
20155 if (eap->read_edit)
20156 len += 7;
20157
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000020158 if (eap->force_ff != 0)
20159 len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6;
20160# ifdef FEAT_MBYTE
20161 if (eap->force_enc != 0)
20162 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
Bram Moolenaar34b4daf2010-05-16 13:26:25 +020020163 if (eap->bad_char != 0)
20164 len += 7 + 4; /* " ++bad=" + "keep" or "drop" */
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000020165# endif
20166
20167 newval = alloc(len + 1);
20168 if (newval == NULL)
20169 return NULL;
20170
20171 if (eap->force_bin == FORCE_BIN)
20172 sprintf((char *)newval, " ++bin");
20173 else if (eap->force_bin == FORCE_NOBIN)
20174 sprintf((char *)newval, " ++nobin");
20175 else
20176 *newval = NUL;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000020177
20178 if (eap->read_edit)
20179 STRCAT(newval, " ++edit");
20180
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000020181 if (eap->force_ff != 0)
20182 sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
20183 eap->cmd + eap->force_ff);
20184# ifdef FEAT_MBYTE
20185 if (eap->force_enc != 0)
20186 sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
20187 eap->cmd + eap->force_enc);
Bram Moolenaar34b4daf2010-05-16 13:26:25 +020020188 if (eap->bad_char == BAD_KEEP)
20189 STRCPY(newval + STRLEN(newval), " ++bad=keep");
20190 else if (eap->bad_char == BAD_DROP)
20191 STRCPY(newval + STRLEN(newval), " ++bad=drop");
20192 else if (eap->bad_char != 0)
20193 sprintf((char *)newval + STRLEN(newval), " ++bad=%c", eap->bad_char);
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000020194# endif
Bram Moolenaare9a41262005-01-15 22:18:47 +000020195 vimvars[VV_CMDARG].vv_str = newval;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000020196 return oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020197}
20198#endif
20199
20200/*
20201 * Get the value of internal variable "name".
20202 * Return OK or FAIL.
20203 */
20204 static int
Bram Moolenaar6d977d62014-01-14 15:24:39 +010020205get_var_tv(name, len, rettv, verbose, no_autoload)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020206 char_u *name;
20207 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +000020208 typval_T *rettv; /* NULL when only checking existence */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020209 int verbose; /* may give error message */
Bram Moolenaar6d977d62014-01-14 15:24:39 +010020210 int no_autoload; /* do not use script autoloading */
Bram Moolenaar071d4272004-06-13 20:20:40 +000020211{
20212 int ret = OK;
Bram Moolenaar33570922005-01-25 22:26:29 +000020213 typval_T *tv = NULL;
20214 typval_T atv;
20215 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020216 int cc;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020217
20218 /* truncate the name, so that we can use strcmp() */
20219 cc = name[len];
20220 name[len] = NUL;
20221
20222 /*
20223 * Check for "b:changedtick".
20224 */
20225 if (STRCMP(name, "b:changedtick") == 0)
20226 {
Bram Moolenaare9a41262005-01-15 22:18:47 +000020227 atv.v_type = VAR_NUMBER;
20228 atv.vval.v_number = curbuf->b_changedtick;
20229 tv = &atv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020230 }
20231
20232 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +000020233 * Check for user-defined variables.
20234 */
20235 else
20236 {
Bram Moolenaar6d977d62014-01-14 15:24:39 +010020237 v = find_var(name, NULL, no_autoload);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020238 if (v != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000020239 tv = &v->di_tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020240 }
20241
Bram Moolenaare9a41262005-01-15 22:18:47 +000020242 if (tv == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020243 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020244 if (rettv != NULL && verbose)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020245 EMSG2(_(e_undefvar), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020246 ret = FAIL;
20247 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020248 else if (rettv != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000020249 copy_tv(tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020250
20251 name[len] = cc;
20252
20253 return ret;
20254}
20255
20256/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020257 * Handle expr[expr], expr[expr:expr] subscript and .name lookup.
20258 * Also handle function call with Funcref variable: func(expr)
20259 * Can all be combined: dict.func(expr)[idx]['func'](expr)
20260 */
20261 static int
20262handle_subscript(arg, rettv, evaluate, verbose)
20263 char_u **arg;
20264 typval_T *rettv;
20265 int evaluate; /* do more than finding the end */
20266 int verbose; /* give error messages */
20267{
20268 int ret = OK;
20269 dict_T *selfdict = NULL;
20270 char_u *s;
20271 int len;
Bram Moolenaard9fba312005-06-26 22:34:35 +000020272 typval_T functv;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020273
20274 while (ret == OK
20275 && (**arg == '['
20276 || (**arg == '.' && rettv->v_type == VAR_DICT)
Bram Moolenaar0f8de8d2013-11-11 04:25:53 +010020277 || (**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC)))
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020278 && !vim_iswhite(*(*arg - 1)))
20279 {
20280 if (**arg == '(')
20281 {
Bram Moolenaard9fba312005-06-26 22:34:35 +000020282 /* need to copy the funcref so that we can clear rettv */
Bram Moolenaar0f8de8d2013-11-11 04:25:53 +010020283 if (evaluate)
20284 {
20285 functv = *rettv;
20286 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020287
Bram Moolenaar0f8de8d2013-11-11 04:25:53 +010020288 /* Invoke the function. Recursive! */
20289 s = functv.vval.v_string;
20290 }
20291 else
20292 s = (char_u *)"";
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000020293 ret = get_func_tv(s, (int)STRLEN(s), rettv, arg,
Bram Moolenaard9fba312005-06-26 22:34:35 +000020294 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
20295 &len, evaluate, selfdict);
20296
20297 /* Clear the funcref afterwards, so that deleting it while
20298 * evaluating the arguments is possible (see test55). */
Bram Moolenaar0f8de8d2013-11-11 04:25:53 +010020299 if (evaluate)
20300 clear_tv(&functv);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000020301
20302 /* Stop the expression evaluation when immediately aborting on
20303 * error, or when an interrupt occurred or an exception was thrown
20304 * but not caught. */
20305 if (aborting())
20306 {
20307 if (ret == OK)
20308 clear_tv(rettv);
20309 ret = FAIL;
20310 }
20311 dict_unref(selfdict);
20312 selfdict = NULL;
20313 }
20314 else /* **arg == '[' || **arg == '.' */
20315 {
20316 dict_unref(selfdict);
20317 if (rettv->v_type == VAR_DICT)
20318 {
20319 selfdict = rettv->vval.v_dict;
20320 if (selfdict != NULL)
20321 ++selfdict->dv_refcount;
20322 }
20323 else
20324 selfdict = NULL;
20325 if (eval_index(arg, rettv, evaluate, verbose) == FAIL)
20326 {
20327 clear_tv(rettv);
20328 ret = FAIL;
20329 }
20330 }
20331 }
20332 dict_unref(selfdict);
20333 return ret;
20334}
20335
20336/*
Bram Moolenaar8c8de832008-06-24 22:58:06 +000020337 * Allocate memory for a variable type-value, and make it empty (0 or NULL
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020338 * value).
20339 */
Bram Moolenaar33570922005-01-25 22:26:29 +000020340 static typval_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020341alloc_tv()
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020342{
Bram Moolenaar33570922005-01-25 22:26:29 +000020343 return (typval_T *)alloc_clear((unsigned)sizeof(typval_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020344}
20345
20346/*
20347 * Allocate memory for a variable type-value, and assign a string to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000020348 * The string "s" must have been allocated, it is consumed.
20349 * Return NULL for out of memory, the variable otherwise.
20350 */
Bram Moolenaar33570922005-01-25 22:26:29 +000020351 static typval_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020352alloc_string_tv(s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020353 char_u *s;
20354{
Bram Moolenaar33570922005-01-25 22:26:29 +000020355 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020356
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020357 rettv = alloc_tv();
20358 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020359 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020360 rettv->v_type = VAR_STRING;
20361 rettv->vval.v_string = s;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020362 }
20363 else
20364 vim_free(s);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020365 return rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020366}
20367
20368/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020369 * Free the memory for a variable type-value.
Bram Moolenaar071d4272004-06-13 20:20:40 +000020370 */
Bram Moolenaar4770d092006-01-12 23:22:24 +000020371 void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020372free_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000020373 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020374{
20375 if (varp != NULL)
20376 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020377 switch (varp->v_type)
20378 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020379 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000020380 func_unref(varp->vval.v_string);
20381 /*FALLTHROUGH*/
20382 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020383 vim_free(varp->vval.v_string);
20384 break;
20385 case VAR_LIST:
20386 list_unref(varp->vval.v_list);
20387 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000020388 case VAR_DICT:
20389 dict_unref(varp->vval.v_dict);
20390 break;
Bram Moolenaar758711c2005-02-02 23:11:38 +000020391 case VAR_NUMBER:
Bram Moolenaar8c8de832008-06-24 22:58:06 +000020392#ifdef FEAT_FLOAT
20393 case VAR_FLOAT:
20394#endif
Bram Moolenaar758711c2005-02-02 23:11:38 +000020395 case VAR_UNKNOWN:
20396 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020397 default:
Bram Moolenaar758711c2005-02-02 23:11:38 +000020398 EMSG2(_(e_intern2), "free_tv()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020399 break;
20400 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000020401 vim_free(varp);
20402 }
20403}
20404
20405/*
20406 * Free the memory for a variable value and set the value to NULL or 0.
20407 */
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000020408 void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020409clear_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000020410 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020411{
20412 if (varp != NULL)
20413 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020414 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020415 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020416 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000020417 func_unref(varp->vval.v_string);
20418 /*FALLTHROUGH*/
20419 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020420 vim_free(varp->vval.v_string);
20421 varp->vval.v_string = NULL;
20422 break;
20423 case VAR_LIST:
20424 list_unref(varp->vval.v_list);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000020425 varp->vval.v_list = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020426 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000020427 case VAR_DICT:
20428 dict_unref(varp->vval.v_dict);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000020429 varp->vval.v_dict = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +000020430 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020431 case VAR_NUMBER:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020432 varp->vval.v_number = 0;
20433 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000020434#ifdef FEAT_FLOAT
20435 case VAR_FLOAT:
20436 varp->vval.v_float = 0.0;
20437 break;
20438#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020439 case VAR_UNKNOWN:
20440 break;
20441 default:
20442 EMSG2(_(e_intern2), "clear_tv()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000020443 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000020444 varp->v_lock = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020445 }
20446}
20447
20448/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020449 * Set the value of a variable to NULL without freeing items.
20450 */
20451 static void
20452init_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000020453 typval_T *varp;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020454{
20455 if (varp != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000020456 vim_memset(varp, 0, sizeof(typval_T));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020457}
20458
20459/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000020460 * Get the number value of a variable.
20461 * If it is a String variable, uses vim_str2nr().
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000020462 * For incompatible types, return 0.
20463 * get_tv_number_chk() is similar to get_tv_number(), but informs the
20464 * caller of incompatible types: it sets *denote to TRUE if "denote"
20465 * is not NULL or returns -1 otherwise.
Bram Moolenaar071d4272004-06-13 20:20:40 +000020466 */
20467 static long
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020468get_tv_number(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000020469 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020470{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000020471 int error = FALSE;
20472
20473 return get_tv_number_chk(varp, &error); /* return 0L on error */
20474}
20475
Bram Moolenaar4be06f92005-07-29 22:36:03 +000020476 long
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000020477get_tv_number_chk(varp, denote)
20478 typval_T *varp;
20479 int *denote;
20480{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020481 long n = 0L;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020482
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020483 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020484 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020485 case VAR_NUMBER:
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000020486 return (long)(varp->vval.v_number);
Bram Moolenaar8c8de832008-06-24 22:58:06 +000020487#ifdef FEAT_FLOAT
20488 case VAR_FLOAT:
Bram Moolenaared0e7452008-06-27 19:17:34 +000020489 EMSG(_("E805: Using a Float as a Number"));
Bram Moolenaar8c8de832008-06-24 22:58:06 +000020490 break;
20491#endif
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020492 case VAR_FUNC:
Bram Moolenaared0e7452008-06-27 19:17:34 +000020493 EMSG(_("E703: Using a Funcref as a Number"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020494 break;
20495 case VAR_STRING:
20496 if (varp->vval.v_string != NULL)
20497 vim_str2nr(varp->vval.v_string, NULL, NULL,
20498 TRUE, TRUE, &n, NULL);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000020499 return n;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000020500 case VAR_LIST:
Bram Moolenaared0e7452008-06-27 19:17:34 +000020501 EMSG(_("E745: Using a List as a Number"));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000020502 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000020503 case VAR_DICT:
Bram Moolenaared0e7452008-06-27 19:17:34 +000020504 EMSG(_("E728: Using a Dictionary as a Number"));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000020505 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020506 default:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000020507 EMSG2(_(e_intern2), "get_tv_number()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020508 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020509 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000020510 if (denote == NULL) /* useful for values that must be unsigned */
20511 n = -1;
20512 else
20513 *denote = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020514 return n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020515}
20516
20517/*
Bram Moolenaar661b1822005-07-28 22:36:45 +000020518 * Get the lnum from the first argument.
20519 * Also accepts ".", "$", etc., but that only works for the current buffer.
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000020520 * Returns -1 on error.
Bram Moolenaar071d4272004-06-13 20:20:40 +000020521 */
20522 static linenr_T
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020523get_tv_lnum(argvars)
Bram Moolenaar33570922005-01-25 22:26:29 +000020524 typval_T *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020525{
Bram Moolenaar33570922005-01-25 22:26:29 +000020526 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020527 linenr_T lnum;
20528
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000020529 lnum = get_tv_number_chk(&argvars[0], NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020530 if (lnum == 0) /* no valid number, try using line() */
20531 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020532 rettv.v_type = VAR_NUMBER;
20533 f_line(argvars, &rettv);
20534 lnum = rettv.vval.v_number;
20535 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020536 }
20537 return lnum;
20538}
20539
20540/*
Bram Moolenaar661b1822005-07-28 22:36:45 +000020541 * Get the lnum from the first argument.
20542 * Also accepts "$", then "buf" is used.
20543 * Returns 0 on error.
20544 */
20545 static linenr_T
20546get_tv_lnum_buf(argvars, buf)
20547 typval_T *argvars;
20548 buf_T *buf;
20549{
20550 if (argvars[0].v_type == VAR_STRING
20551 && argvars[0].vval.v_string != NULL
20552 && argvars[0].vval.v_string[0] == '$'
20553 && buf != NULL)
20554 return buf->b_ml.ml_line_count;
20555 return get_tv_number_chk(&argvars[0], NULL);
20556}
20557
20558/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000020559 * Get the string value of a variable.
20560 * If it is a Number variable, the number is converted into a string.
Bram Moolenaara7043832005-01-21 11:56:39 +000020561 * get_tv_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
20562 * get_tv_string_buf() uses a given buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +000020563 * If the String variable has never been set, return an empty string.
20564 * Never returns NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000020565 * get_tv_string_chk() and get_tv_string_buf_chk() are similar, but return
20566 * NULL on error.
Bram Moolenaar071d4272004-06-13 20:20:40 +000020567 */
20568 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020569get_tv_string(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000020570 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020571{
20572 static char_u mybuf[NUMBUFLEN];
20573
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020574 return get_tv_string_buf(varp, mybuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020575}
20576
20577 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020578get_tv_string_buf(varp, buf)
Bram Moolenaar33570922005-01-25 22:26:29 +000020579 typval_T *varp;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020580 char_u *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020581{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000020582 char_u *res = get_tv_string_buf_chk(varp, buf);
20583
20584 return res != NULL ? res : (char_u *)"";
20585}
20586
Bram Moolenaar7d647822014-04-05 21:28:56 +020020587/*
20588 * Careful: This uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
20589 */
Bram Moolenaar4be06f92005-07-29 22:36:03 +000020590 char_u *
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000020591get_tv_string_chk(varp)
20592 typval_T *varp;
20593{
20594 static char_u mybuf[NUMBUFLEN];
20595
20596 return get_tv_string_buf_chk(varp, mybuf);
20597}
20598
20599 static char_u *
20600get_tv_string_buf_chk(varp, buf)
20601 typval_T *varp;
20602 char_u *buf;
20603{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020604 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020605 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020606 case VAR_NUMBER:
20607 sprintf((char *)buf, "%ld", (long)varp->vval.v_number);
20608 return buf;
20609 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000020610 EMSG(_("E729: using Funcref as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020611 break;
20612 case VAR_LIST:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000020613 EMSG(_("E730: using List as a String"));
Bram Moolenaar8c711452005-01-14 21:53:12 +000020614 break;
20615 case VAR_DICT:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000020616 EMSG(_("E731: using Dictionary as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020617 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000020618#ifdef FEAT_FLOAT
20619 case VAR_FLOAT:
Bram Moolenaar2a876e42013-06-12 22:08:58 +020020620 EMSG(_(e_float_as_string));
Bram Moolenaar8c8de832008-06-24 22:58:06 +000020621 break;
20622#endif
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020623 case VAR_STRING:
20624 if (varp->vval.v_string != NULL)
20625 return varp->vval.v_string;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000020626 return (char_u *)"";
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020627 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020628 EMSG2(_(e_intern2), "get_tv_string_buf()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020629 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020630 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000020631 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020632}
20633
20634/*
20635 * Find variable "name" in the list of variables.
20636 * Return a pointer to it if found, NULL if not found.
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020637 * Careful: "a:0" variables don't have a name.
Bram Moolenaara7043832005-01-21 11:56:39 +000020638 * When "htp" is not NULL we are writing to the variable, set "htp" to the
Bram Moolenaar33570922005-01-25 22:26:29 +000020639 * hashtab_T used.
Bram Moolenaar071d4272004-06-13 20:20:40 +000020640 */
Bram Moolenaar33570922005-01-25 22:26:29 +000020641 static dictitem_T *
Bram Moolenaar6d977d62014-01-14 15:24:39 +010020642find_var(name, htp, no_autoload)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020643 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000020644 hashtab_T **htp;
Bram Moolenaar6d977d62014-01-14 15:24:39 +010020645 int no_autoload;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020646{
Bram Moolenaar071d4272004-06-13 20:20:40 +000020647 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000020648 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020649
Bram Moolenaara7043832005-01-21 11:56:39 +000020650 ht = find_var_ht(name, &varname);
20651 if (htp != NULL)
20652 *htp = ht;
20653 if (ht == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020654 return NULL;
Bram Moolenaar6d977d62014-01-14 15:24:39 +010020655 return find_var_in_ht(ht, *name, varname, no_autoload || htp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020656}
20657
20658/*
Bram Moolenaar332ac062013-04-15 13:06:21 +020020659 * Find variable "varname" in hashtab "ht" with name "htname".
Bram Moolenaara7043832005-01-21 11:56:39 +000020660 * Returns NULL if not found.
Bram Moolenaar071d4272004-06-13 20:20:40 +000020661 */
Bram Moolenaar33570922005-01-25 22:26:29 +000020662 static dictitem_T *
Bram Moolenaar6d977d62014-01-14 15:24:39 +010020663find_var_in_ht(ht, htname, varname, no_autoload)
Bram Moolenaar33570922005-01-25 22:26:29 +000020664 hashtab_T *ht;
Bram Moolenaar332ac062013-04-15 13:06:21 +020020665 int htname;
Bram Moolenaara7043832005-01-21 11:56:39 +000020666 char_u *varname;
Bram Moolenaar6d977d62014-01-14 15:24:39 +010020667 int no_autoload;
Bram Moolenaara7043832005-01-21 11:56:39 +000020668{
Bram Moolenaar33570922005-01-25 22:26:29 +000020669 hashitem_T *hi;
20670
20671 if (*varname == NUL)
20672 {
20673 /* Must be something like "s:", otherwise "ht" would be NULL. */
Bram Moolenaar332ac062013-04-15 13:06:21 +020020674 switch (htname)
Bram Moolenaar33570922005-01-25 22:26:29 +000020675 {
Bram Moolenaar9577c3e2010-05-14 12:16:25 +020020676 case 's': return &SCRIPT_SV(current_SID)->sv_var;
Bram Moolenaar33570922005-01-25 22:26:29 +000020677 case 'g': return &globvars_var;
20678 case 'v': return &vimvars_var;
20679 case 'b': return &curbuf->b_bufvar;
20680 case 'w': return &curwin->w_winvar;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000020681#ifdef FEAT_WINDOWS
20682 case 't': return &curtab->tp_winvar;
20683#endif
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000020684 case 'l': return current_funccal == NULL
20685 ? NULL : &current_funccal->l_vars_var;
20686 case 'a': return current_funccal == NULL
20687 ? NULL : &current_funccal->l_avars_var;
Bram Moolenaar33570922005-01-25 22:26:29 +000020688 }
20689 return NULL;
20690 }
Bram Moolenaara7043832005-01-21 11:56:39 +000020691
20692 hi = hash_find(ht, varname);
20693 if (HASHITEM_EMPTY(hi))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000020694 {
20695 /* For global variables we may try auto-loading the script. If it
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000020696 * worked find the variable again. Don't auto-load a script if it was
20697 * loaded already, otherwise it would be loaded every time when
20698 * checking if a function name is a Funcref variable. */
Bram Moolenaar6d977d62014-01-14 15:24:39 +010020699 if (ht == &globvarht && !no_autoload)
Bram Moolenaar8000baf2011-11-30 15:19:28 +010020700 {
20701 /* Note: script_autoload() may make "hi" invalid. It must either
20702 * be obtained again or not used. */
20703 if (!script_autoload(varname, FALSE) || aborting())
20704 return NULL;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000020705 hi = hash_find(ht, varname);
Bram Moolenaar8000baf2011-11-30 15:19:28 +010020706 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000020707 if (HASHITEM_EMPTY(hi))
20708 return NULL;
20709 }
Bram Moolenaar33570922005-01-25 22:26:29 +000020710 return HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +000020711}
20712
20713/*
Bram Moolenaar33570922005-01-25 22:26:29 +000020714 * Find the hashtab used for a variable name.
Bram Moolenaara7043832005-01-21 11:56:39 +000020715 * Set "varname" to the start of name without ':'.
20716 */
Bram Moolenaar33570922005-01-25 22:26:29 +000020717 static hashtab_T *
Bram Moolenaara7043832005-01-21 11:56:39 +000020718find_var_ht(name, varname)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020719 char_u *name;
20720 char_u **varname;
20721{
Bram Moolenaar75c50c42005-06-04 22:06:24 +000020722 hashitem_T *hi;
20723
Bram Moolenaar071d4272004-06-13 20:20:40 +000020724 if (name[1] != ':')
20725 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000020726 /* The name must not start with a colon or #. */
20727 if (name[0] == ':' || name[0] == AUTOLOAD_CHAR)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020728 return NULL;
20729 *varname = name;
Bram Moolenaar532c7802005-01-27 14:44:31 +000020730
20731 /* "version" is "v:version" in all scopes */
Bram Moolenaar75c50c42005-06-04 22:06:24 +000020732 hi = hash_find(&compat_hashtab, name);
20733 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar532c7802005-01-27 14:44:31 +000020734 return &compat_hashtab;
20735
Bram Moolenaar071d4272004-06-13 20:20:40 +000020736 if (current_funccal == NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000020737 return &globvarht; /* global variable */
20738 return &current_funccal->l_vars.dv_hashtab; /* l: variable */
Bram Moolenaar071d4272004-06-13 20:20:40 +000020739 }
20740 *varname = name + 2;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000020741 if (*name == 'g') /* global variable */
20742 return &globvarht;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000020743 /* There must be no ':' or '#' in the rest of the name, unless g: is used
20744 */
20745 if (vim_strchr(name + 2, ':') != NULL
20746 || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000020747 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020748 if (*name == 'b') /* buffer variable */
Bram Moolenaar429fa852013-04-15 12:27:36 +020020749 return &curbuf->b_vars->dv_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020750 if (*name == 'w') /* window variable */
Bram Moolenaar429fa852013-04-15 12:27:36 +020020751 return &curwin->w_vars->dv_hashtab;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000020752#ifdef FEAT_WINDOWS
20753 if (*name == 't') /* tab page variable */
Bram Moolenaar429fa852013-04-15 12:27:36 +020020754 return &curtab->tp_vars->dv_hashtab;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000020755#endif
Bram Moolenaar33570922005-01-25 22:26:29 +000020756 if (*name == 'v') /* v: variable */
20757 return &vimvarht;
20758 if (*name == 'a' && current_funccal != NULL) /* function argument */
20759 return &current_funccal->l_avars.dv_hashtab;
20760 if (*name == 'l' && current_funccal != NULL) /* local function variable */
20761 return &current_funccal->l_vars.dv_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020762 if (*name == 's' /* script variable */
20763 && current_SID > 0 && current_SID <= ga_scripts.ga_len)
20764 return &SCRIPT_VARS(current_SID);
20765 return NULL;
20766}
20767
20768/*
20769 * Get the string value of a (global/local) variable.
Bram Moolenaar1950c352010-06-06 15:21:10 +020020770 * Note: see get_tv_string() for how long the pointer remains valid.
Bram Moolenaar071d4272004-06-13 20:20:40 +000020771 * Returns NULL when it doesn't exist.
20772 */
20773 char_u *
20774get_var_value(name)
20775 char_u *name;
20776{
Bram Moolenaar33570922005-01-25 22:26:29 +000020777 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020778
Bram Moolenaar6d977d62014-01-14 15:24:39 +010020779 v = find_var(name, NULL, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020780 if (v == NULL)
20781 return NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +000020782 return get_tv_string(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020783}
20784
20785/*
Bram Moolenaar33570922005-01-25 22:26:29 +000020786 * Allocate a new hashtab for a sourced script. It will be used while
Bram Moolenaar071d4272004-06-13 20:20:40 +000020787 * sourcing this script and when executing functions defined in the script.
20788 */
20789 void
20790new_script_vars(id)
20791 scid_T id;
20792{
Bram Moolenaara7043832005-01-21 11:56:39 +000020793 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +000020794 hashtab_T *ht;
20795 scriptvar_T *sv;
Bram Moolenaara7043832005-01-21 11:56:39 +000020796
Bram Moolenaar071d4272004-06-13 20:20:40 +000020797 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
20798 {
Bram Moolenaara7043832005-01-21 11:56:39 +000020799 /* Re-allocating ga_data means that an ht_array pointing to
20800 * ht_smallarray becomes invalid. We can recognize this: ht_mask is
Bram Moolenaar33570922005-01-25 22:26:29 +000020801 * at its init value. Also reset "v_dict", it's always the same. */
Bram Moolenaara7043832005-01-21 11:56:39 +000020802 for (i = 1; i <= ga_scripts.ga_len; ++i)
20803 {
20804 ht = &SCRIPT_VARS(i);
20805 if (ht->ht_mask == HT_INIT_SIZE - 1)
20806 ht->ht_array = ht->ht_smallarray;
Bram Moolenaar9577c3e2010-05-14 12:16:25 +020020807 sv = SCRIPT_SV(i);
Bram Moolenaar33570922005-01-25 22:26:29 +000020808 sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict;
Bram Moolenaara7043832005-01-21 11:56:39 +000020809 }
20810
Bram Moolenaar071d4272004-06-13 20:20:40 +000020811 while (ga_scripts.ga_len < id)
20812 {
Bram Moolenaar2c704a72010-06-03 21:17:25 +020020813 sv = SCRIPT_SV(ga_scripts.ga_len + 1) =
Bram Moolenaar9577c3e2010-05-14 12:16:25 +020020814 (scriptvar_T *)alloc_clear(sizeof(scriptvar_T));
Bram Moolenaarbdb62052012-07-16 17:31:53 +020020815 init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020816 ++ga_scripts.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020817 }
20818 }
20819}
20820
20821/*
Bram Moolenaar33570922005-01-25 22:26:29 +000020822 * Initialize dictionary "dict" as a scope and set variable "dict_var" to
20823 * point to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000020824 */
20825 void
Bram Moolenaarbdb62052012-07-16 17:31:53 +020020826init_var_dict(dict, dict_var, scope)
Bram Moolenaar33570922005-01-25 22:26:29 +000020827 dict_T *dict;
20828 dictitem_T *dict_var;
Bram Moolenaarbdb62052012-07-16 17:31:53 +020020829 int scope;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020830{
Bram Moolenaar33570922005-01-25 22:26:29 +000020831 hash_init(&dict->dv_hashtab);
Bram Moolenaared465602012-06-20 14:13:06 +020020832 dict->dv_lock = 0;
Bram Moolenaarbdb62052012-07-16 17:31:53 +020020833 dict->dv_scope = scope;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000020834 dict->dv_refcount = DO_NOT_FREE_CNT;
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +000020835 dict->dv_copyID = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000020836 dict_var->di_tv.vval.v_dict = dict;
20837 dict_var->di_tv.v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000020838 dict_var->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000020839 dict_var->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
20840 dict_var->di_key[0] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020841}
20842
20843/*
Bram Moolenaar429fa852013-04-15 12:27:36 +020020844 * Unreference a dictionary initialized by init_var_dict().
20845 */
20846 void
20847unref_var_dict(dict)
20848 dict_T *dict;
20849{
20850 /* Now the dict needs to be freed if no one else is using it, go back to
20851 * normal reference counting. */
20852 dict->dv_refcount -= DO_NOT_FREE_CNT - 1;
20853 dict_unref(dict);
20854}
20855
20856/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000020857 * Clean up a list of internal variables.
Bram Moolenaar33570922005-01-25 22:26:29 +000020858 * Frees all allocated variables and the value they contain.
20859 * Clears hashtab "ht", does not free it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000020860 */
20861 void
Bram Moolenaara7043832005-01-21 11:56:39 +000020862vars_clear(ht)
Bram Moolenaar33570922005-01-25 22:26:29 +000020863 hashtab_T *ht;
20864{
20865 vars_clear_ext(ht, TRUE);
20866}
20867
20868/*
20869 * Like vars_clear(), but only free the value if "free_val" is TRUE.
20870 */
20871 static void
20872vars_clear_ext(ht, free_val)
20873 hashtab_T *ht;
20874 int free_val;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020875{
Bram Moolenaara7043832005-01-21 11:56:39 +000020876 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000020877 hashitem_T *hi;
20878 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020879
Bram Moolenaar33570922005-01-25 22:26:29 +000020880 hash_lock(ht);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000020881 todo = (int)ht->ht_used;
Bram Moolenaara7043832005-01-21 11:56:39 +000020882 for (hi = ht->ht_array; todo > 0; ++hi)
20883 {
20884 if (!HASHITEM_EMPTY(hi))
20885 {
20886 --todo;
20887
Bram Moolenaar33570922005-01-25 22:26:29 +000020888 /* Free the variable. Don't remove it from the hashtab,
Bram Moolenaara7043832005-01-21 11:56:39 +000020889 * ht_array might change then. hash_clear() takes care of it
20890 * later. */
Bram Moolenaar33570922005-01-25 22:26:29 +000020891 v = HI2DI(hi);
20892 if (free_val)
20893 clear_tv(&v->di_tv);
20894 if ((v->di_flags & DI_FLAGS_FIX) == 0)
20895 vim_free(v);
Bram Moolenaara7043832005-01-21 11:56:39 +000020896 }
20897 }
20898 hash_clear(ht);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000020899 ht->ht_used = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020900}
20901
Bram Moolenaara7043832005-01-21 11:56:39 +000020902/*
Bram Moolenaar33570922005-01-25 22:26:29 +000020903 * Delete a variable from hashtab "ht" at item "hi".
20904 * Clear the variable value and free the dictitem.
Bram Moolenaara7043832005-01-21 11:56:39 +000020905 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000020906 static void
Bram Moolenaara7043832005-01-21 11:56:39 +000020907delete_var(ht, hi)
Bram Moolenaar33570922005-01-25 22:26:29 +000020908 hashtab_T *ht;
20909 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020910{
Bram Moolenaar33570922005-01-25 22:26:29 +000020911 dictitem_T *di = HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +000020912
20913 hash_remove(ht, hi);
Bram Moolenaar33570922005-01-25 22:26:29 +000020914 clear_tv(&di->di_tv);
20915 vim_free(di);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020916}
20917
20918/*
20919 * List the value of one internal variable.
20920 */
20921 static void
Bram Moolenaar7d61a922007-08-30 09:12:23 +000020922list_one_var(v, prefix, first)
Bram Moolenaar33570922005-01-25 22:26:29 +000020923 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020924 char_u *prefix;
Bram Moolenaar7d61a922007-08-30 09:12:23 +000020925 int *first;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020926{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020927 char_u *tofree;
20928 char_u *s;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000020929 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020930
Bram Moolenaar2c2398c2009-06-03 11:22:45 +000020931 current_copyID += COPYID_INC;
20932 s = echo_string(&v->di_tv, &tofree, numbuf, current_copyID);
Bram Moolenaar33570922005-01-25 22:26:29 +000020933 list_one_var_a(prefix, v->di_key, v->di_tv.v_type,
Bram Moolenaar7d61a922007-08-30 09:12:23 +000020934 s == NULL ? (char_u *)"" : s, first);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020935 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020936}
20937
Bram Moolenaar071d4272004-06-13 20:20:40 +000020938 static void
Bram Moolenaar7d61a922007-08-30 09:12:23 +000020939list_one_var_a(prefix, name, type, string, first)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020940 char_u *prefix;
20941 char_u *name;
20942 int type;
20943 char_u *string;
Bram Moolenaar7d61a922007-08-30 09:12:23 +000020944 int *first; /* when TRUE clear rest of screen and set to FALSE */
Bram Moolenaar071d4272004-06-13 20:20:40 +000020945{
Bram Moolenaar31859182007-08-14 20:41:13 +000020946 /* don't use msg() or msg_attr() to avoid overwriting "v:statusmsg" */
20947 msg_start();
20948 msg_puts(prefix);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020949 if (name != NULL) /* "a:" vars don't have a name stored */
20950 msg_puts(name);
20951 msg_putchar(' ');
20952 msg_advance(22);
20953 if (type == VAR_NUMBER)
20954 msg_putchar('#');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020955 else if (type == VAR_FUNC)
20956 msg_putchar('*');
20957 else if (type == VAR_LIST)
20958 {
20959 msg_putchar('[');
20960 if (*string == '[')
20961 ++string;
20962 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000020963 else if (type == VAR_DICT)
20964 {
20965 msg_putchar('{');
20966 if (*string == '{')
20967 ++string;
20968 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000020969 else
20970 msg_putchar(' ');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020971
Bram Moolenaar071d4272004-06-13 20:20:40 +000020972 msg_outtrans(string);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000020973
20974 if (type == VAR_FUNC)
20975 msg_puts((char_u *)"()");
Bram Moolenaar7d61a922007-08-30 09:12:23 +000020976 if (*first)
20977 {
20978 msg_clr_eos();
20979 *first = FALSE;
20980 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000020981}
20982
20983/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020984 * Set variable "name" to value in "tv".
Bram Moolenaar071d4272004-06-13 20:20:40 +000020985 * If the variable already exists, the value is updated.
20986 * Otherwise the variable is created.
20987 */
20988 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020989set_var(name, tv, copy)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020990 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000020991 typval_T *tv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020992 int copy; /* make copy of value in "tv" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000020993{
Bram Moolenaar33570922005-01-25 22:26:29 +000020994 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020995 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000020996 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020997
Bram Moolenaarbaff0fe2010-03-17 19:53:49 +010020998 ht = find_var_ht(name, &varname);
20999 if (ht == NULL || *varname == NUL)
21000 {
21001 EMSG2(_(e_illvar), name);
21002 return;
21003 }
Bram Moolenaar332ac062013-04-15 13:06:21 +020021004 v = find_var_in_ht(ht, 0, varname, TRUE);
Bram Moolenaarbaff0fe2010-03-17 19:53:49 +010021005
Bram Moolenaar4228bec2011-03-27 16:03:15 +020021006 if (tv->v_type == VAR_FUNC && var_check_func_name(name, v == NULL))
21007 return;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021008
Bram Moolenaar33570922005-01-25 22:26:29 +000021009 if (v != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021010 {
Bram Moolenaar33570922005-01-25 22:26:29 +000021011 /* existing variable, need to clear the value */
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000021012 if (var_check_ro(v->di_flags, name)
21013 || tv_check_lock(v->di_tv.v_lock, name))
Bram Moolenaar33570922005-01-25 22:26:29 +000021014 return;
21015 if (v->di_tv.v_type != tv->v_type
21016 && !((v->di_tv.v_type == VAR_STRING
21017 || v->di_tv.v_type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021018 && (tv->v_type == VAR_STRING
Bram Moolenaar8c8de832008-06-24 22:58:06 +000021019 || tv->v_type == VAR_NUMBER))
21020#ifdef FEAT_FLOAT
21021 && !((v->di_tv.v_type == VAR_NUMBER
21022 || v->di_tv.v_type == VAR_FLOAT)
21023 && (tv->v_type == VAR_NUMBER
21024 || tv->v_type == VAR_FLOAT))
21025#endif
21026 )
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021027 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +000021028 EMSG2(_("E706: Variable type mismatch for: %s"), name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021029 return;
21030 }
Bram Moolenaar33570922005-01-25 22:26:29 +000021031
21032 /*
Bram Moolenaar758711c2005-02-02 23:11:38 +000021033 * Handle setting internal v: variables separately: we don't change
21034 * the type.
Bram Moolenaar33570922005-01-25 22:26:29 +000021035 */
21036 if (ht == &vimvarht)
21037 {
21038 if (v->di_tv.v_type == VAR_STRING)
21039 {
21040 vim_free(v->di_tv.vval.v_string);
21041 if (copy || tv->v_type != VAR_STRING)
21042 v->di_tv.vval.v_string = vim_strsave(get_tv_string(tv));
21043 else
21044 {
21045 /* Take over the string to avoid an extra alloc/free. */
21046 v->di_tv.vval.v_string = tv->vval.v_string;
21047 tv->vval.v_string = NULL;
21048 }
21049 }
21050 else if (v->di_tv.v_type != VAR_NUMBER)
21051 EMSG2(_(e_intern2), "set_var()");
21052 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +000021053 {
Bram Moolenaar33570922005-01-25 22:26:29 +000021054 v->di_tv.vval.v_number = get_tv_number(tv);
Bram Moolenaar8c8de832008-06-24 22:58:06 +000021055 if (STRCMP(varname, "searchforward") == 0)
21056 set_search_direction(v->di_tv.vval.v_number ? '/' : '?');
Bram Moolenaar8050efa2013-11-08 04:30:20 +010021057#ifdef FEAT_SEARCH_EXTRA
21058 else if (STRCMP(varname, "hlsearch") == 0)
21059 {
21060 no_hlsearch = !v->di_tv.vval.v_number;
21061 redraw_all_later(SOME_VALID);
21062 }
21063#endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +000021064 }
Bram Moolenaar33570922005-01-25 22:26:29 +000021065 return;
21066 }
21067
21068 clear_tv(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021069 }
21070 else /* add a new variable */
21071 {
Bram Moolenaar5fcc3fe2006-06-22 15:35:14 +000021072 /* Can't add "v:" variable. */
21073 if (ht == &vimvarht)
21074 {
21075 EMSG2(_(e_illvar), name);
21076 return;
21077 }
21078
Bram Moolenaar92124a32005-06-17 22:03:40 +000021079 /* Make sure the variable name is valid. */
Bram Moolenaar4228bec2011-03-27 16:03:15 +020021080 if (!valid_varname(varname))
21081 return;
Bram Moolenaar92124a32005-06-17 22:03:40 +000021082
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000021083 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
21084 + STRLEN(varname)));
Bram Moolenaara7043832005-01-21 11:56:39 +000021085 if (v == NULL)
21086 return;
Bram Moolenaar33570922005-01-25 22:26:29 +000021087 STRCPY(v->di_key, varname);
Bram Moolenaar33570922005-01-25 22:26:29 +000021088 if (hash_add(ht, DI2HIKEY(v)) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021089 {
Bram Moolenaara7043832005-01-21 11:56:39 +000021090 vim_free(v);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021091 return;
21092 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000021093 v->di_flags = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021094 }
Bram Moolenaara7043832005-01-21 11:56:39 +000021095
Bram Moolenaar8c8de832008-06-24 22:58:06 +000021096 if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT)
Bram Moolenaar33570922005-01-25 22:26:29 +000021097 copy_tv(tv, &v->di_tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000021098 else
21099 {
Bram Moolenaar33570922005-01-25 22:26:29 +000021100 v->di_tv = *tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000021101 v->di_tv.v_lock = 0;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021102 init_tv(tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000021103 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000021104}
21105
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021106/*
Bram Moolenaar4e957af2006-09-02 11:41:07 +000021107 * Return TRUE if di_flags "flags" indicates variable "name" is read-only.
Bram Moolenaar33570922005-01-25 22:26:29 +000021108 * Also give an error message.
21109 */
21110 static int
21111var_check_ro(flags, name)
21112 int flags;
21113 char_u *name;
21114{
21115 if (flags & DI_FLAGS_RO)
21116 {
21117 EMSG2(_(e_readonlyvar), name);
21118 return TRUE;
21119 }
21120 if ((flags & DI_FLAGS_RO_SBX) && sandbox)
21121 {
21122 EMSG2(_(e_readonlysbx), name);
21123 return TRUE;
21124 }
21125 return FALSE;
21126}
21127
21128/*
Bram Moolenaar4e957af2006-09-02 11:41:07 +000021129 * Return TRUE if di_flags "flags" indicates variable "name" is fixed.
21130 * Also give an error message.
21131 */
21132 static int
21133var_check_fixed(flags, name)
21134 int flags;
21135 char_u *name;
21136{
21137 if (flags & DI_FLAGS_FIX)
21138 {
21139 EMSG2(_("E795: Cannot delete variable %s"), name);
21140 return TRUE;
21141 }
21142 return FALSE;
21143}
21144
21145/*
Bram Moolenaar4228bec2011-03-27 16:03:15 +020021146 * Check if a funcref is assigned to a valid variable name.
21147 * Return TRUE and give an error if not.
21148 */
21149 static int
21150var_check_func_name(name, new_var)
21151 char_u *name; /* points to start of variable name */
21152 int new_var; /* TRUE when creating the variable */
21153{
Bram Moolenaarcbc67722014-05-22 14:19:56 +020021154 /* Allow for w: b: s: and t:. */
21155 if (!(vim_strchr((char_u *)"wbst", name[0]) != NULL && name[1] == ':')
Bram Moolenaar4228bec2011-03-27 16:03:15 +020021156 && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
21157 ? name[2] : name[0]))
21158 {
21159 EMSG2(_("E704: Funcref variable name must start with a capital: %s"),
21160 name);
21161 return TRUE;
21162 }
21163 /* Don't allow hiding a function. When "v" is not NULL we might be
21164 * assigning another function to the same var, the type is checked
21165 * below. */
21166 if (new_var && function_exists(name))
21167 {
21168 EMSG2(_("E705: Variable name conflicts with existing function: %s"),
21169 name);
21170 return TRUE;
21171 }
21172 return FALSE;
21173}
21174
21175/*
21176 * Check if a variable name is valid.
21177 * Return FALSE and give an error if not.
21178 */
21179 static int
21180valid_varname(varname)
21181 char_u *varname;
21182{
21183 char_u *p;
21184
21185 for (p = varname; *p != NUL; ++p)
21186 if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p))
21187 && *p != AUTOLOAD_CHAR)
21188 {
21189 EMSG2(_(e_illvar), varname);
21190 return FALSE;
21191 }
21192 return TRUE;
21193}
21194
21195/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000021196 * Return TRUE if typeval "tv" is set to be locked (immutable).
21197 * Also give an error message, using "name".
21198 */
21199 static int
21200tv_check_lock(lock, name)
21201 int lock;
21202 char_u *name;
21203{
21204 if (lock & VAR_LOCKED)
21205 {
21206 EMSG2(_("E741: Value is locked: %s"),
21207 name == NULL ? (char_u *)_("Unknown") : name);
21208 return TRUE;
21209 }
21210 if (lock & VAR_FIXED)
21211 {
21212 EMSG2(_("E742: Cannot change value of %s"),
21213 name == NULL ? (char_u *)_("Unknown") : name);
21214 return TRUE;
21215 }
21216 return FALSE;
21217}
21218
21219/*
Bram Moolenaar33570922005-01-25 22:26:29 +000021220 * Copy the values from typval_T "from" to typval_T "to".
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021221 * When needed allocates string or increases reference count.
Bram Moolenaare9a41262005-01-15 22:18:47 +000021222 * Does not make a copy of a list or dict but copies the reference!
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000021223 * It is OK for "from" and "to" to point to the same item. This is used to
21224 * make a copy later.
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021225 */
Bram Moolenaar7e506b62010-01-19 15:55:06 +010021226 void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021227copy_tv(from, to)
Bram Moolenaar33570922005-01-25 22:26:29 +000021228 typval_T *from;
21229 typval_T *to;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021230{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021231 to->v_type = from->v_type;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000021232 to->v_lock = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021233 switch (from->v_type)
21234 {
21235 case VAR_NUMBER:
21236 to->vval.v_number = from->vval.v_number;
21237 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000021238#ifdef FEAT_FLOAT
21239 case VAR_FLOAT:
21240 to->vval.v_float = from->vval.v_float;
21241 break;
21242#endif
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021243 case VAR_STRING:
21244 case VAR_FUNC:
21245 if (from->vval.v_string == NULL)
21246 to->vval.v_string = NULL;
21247 else
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021248 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021249 to->vval.v_string = vim_strsave(from->vval.v_string);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021250 if (from->v_type == VAR_FUNC)
21251 func_ref(to->vval.v_string);
21252 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021253 break;
21254 case VAR_LIST:
21255 if (from->vval.v_list == NULL)
21256 to->vval.v_list = NULL;
21257 else
21258 {
21259 to->vval.v_list = from->vval.v_list;
21260 ++to->vval.v_list->lv_refcount;
21261 }
21262 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000021263 case VAR_DICT:
21264 if (from->vval.v_dict == NULL)
21265 to->vval.v_dict = NULL;
21266 else
21267 {
21268 to->vval.v_dict = from->vval.v_dict;
21269 ++to->vval.v_dict->dv_refcount;
21270 }
21271 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021272 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021273 EMSG2(_(e_intern2), "copy_tv()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021274 break;
21275 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000021276}
21277
21278/*
Bram Moolenaare9a41262005-01-15 22:18:47 +000021279 * Make a copy of an item.
21280 * Lists and Dictionaries are also copied. A deep copy if "deep" is set.
Bram Moolenaar81bf7082005-02-12 14:31:42 +000021281 * For deepcopy() "copyID" is zero for a full copy or the ID for when a
21282 * reference to an already copied list/dict can be used.
21283 * Returns FAIL or OK.
Bram Moolenaare9a41262005-01-15 22:18:47 +000021284 */
Bram Moolenaar81bf7082005-02-12 14:31:42 +000021285 static int
21286item_copy(from, to, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +000021287 typval_T *from;
21288 typval_T *to;
Bram Moolenaare9a41262005-01-15 22:18:47 +000021289 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000021290 int copyID;
Bram Moolenaare9a41262005-01-15 22:18:47 +000021291{
21292 static int recurse = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000021293 int ret = OK;
Bram Moolenaare9a41262005-01-15 22:18:47 +000021294
Bram Moolenaar33570922005-01-25 22:26:29 +000021295 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +000021296 {
21297 EMSG(_("E698: variable nested too deep for making a copy"));
Bram Moolenaar81bf7082005-02-12 14:31:42 +000021298 return FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000021299 }
21300 ++recurse;
21301
21302 switch (from->v_type)
21303 {
21304 case VAR_NUMBER:
Bram Moolenaar8c8de832008-06-24 22:58:06 +000021305#ifdef FEAT_FLOAT
21306 case VAR_FLOAT:
21307#endif
Bram Moolenaare9a41262005-01-15 22:18:47 +000021308 case VAR_STRING:
21309 case VAR_FUNC:
21310 copy_tv(from, to);
21311 break;
21312 case VAR_LIST:
21313 to->v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000021314 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000021315 if (from->vval.v_list == NULL)
21316 to->vval.v_list = NULL;
21317 else if (copyID != 0 && from->vval.v_list->lv_copyID == copyID)
21318 {
21319 /* use the copy made earlier */
21320 to->vval.v_list = from->vval.v_list->lv_copylist;
21321 ++to->vval.v_list->lv_refcount;
21322 }
21323 else
21324 to->vval.v_list = list_copy(from->vval.v_list, deep, copyID);
21325 if (to->vval.v_list == NULL)
21326 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000021327 break;
21328 case VAR_DICT:
21329 to->v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000021330 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000021331 if (from->vval.v_dict == NULL)
21332 to->vval.v_dict = NULL;
21333 else if (copyID != 0 && from->vval.v_dict->dv_copyID == copyID)
21334 {
21335 /* use the copy made earlier */
21336 to->vval.v_dict = from->vval.v_dict->dv_copydict;
21337 ++to->vval.v_dict->dv_refcount;
21338 }
21339 else
21340 to->vval.v_dict = dict_copy(from->vval.v_dict, deep, copyID);
21341 if (to->vval.v_dict == NULL)
21342 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000021343 break;
21344 default:
21345 EMSG2(_(e_intern2), "item_copy()");
Bram Moolenaar81bf7082005-02-12 14:31:42 +000021346 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000021347 }
21348 --recurse;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000021349 return ret;
Bram Moolenaare9a41262005-01-15 22:18:47 +000021350}
21351
21352/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000021353 * ":echo expr1 ..." print each argument separated with a space, add a
21354 * newline at the end.
21355 * ":echon expr1 ..." print each argument plain.
21356 */
21357 void
21358ex_echo(eap)
21359 exarg_T *eap;
21360{
21361 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000021362 typval_T rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021363 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021364 char_u *p;
21365 int needclr = TRUE;
21366 int atstart = TRUE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000021367 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000021368
21369 if (eap->skip)
21370 ++emsg_skip;
21371 while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int)
21372 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +000021373 /* If eval1() causes an error message the text from the command may
21374 * still need to be cleared. E.g., "echo 22,44". */
21375 need_clr_eos = needclr;
21376
Bram Moolenaar071d4272004-06-13 20:20:40 +000021377 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021378 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021379 {
21380 /*
21381 * Report the invalid expression unless the expression evaluation
21382 * has been cancelled due to an aborting error, an interrupt, or an
21383 * exception.
21384 */
21385 if (!aborting())
21386 EMSG2(_(e_invexpr2), p);
Bram Moolenaar8c8de832008-06-24 22:58:06 +000021387 need_clr_eos = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021388 break;
21389 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +000021390 need_clr_eos = FALSE;
21391
Bram Moolenaar071d4272004-06-13 20:20:40 +000021392 if (!eap->skip)
21393 {
21394 if (atstart)
21395 {
21396 atstart = FALSE;
21397 /* Call msg_start() after eval1(), evaluating the expression
21398 * may cause a message to appear. */
21399 if (eap->cmdidx == CMD_echo)
Bram Moolenaar12b02902012-03-23 15:18:24 +010021400 {
Bram Moolenaar6df5e5a2012-03-28 16:49:29 +020021401 /* Mark the saved text as finishing the line, so that what
21402 * follows is displayed on a new line when scrolling back
21403 * at the more prompt. */
21404 msg_sb_eol();
Bram Moolenaar071d4272004-06-13 20:20:40 +000021405 msg_start();
Bram Moolenaar12b02902012-03-23 15:18:24 +010021406 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000021407 }
21408 else if (eap->cmdidx == CMD_echo)
21409 msg_puts_attr((char_u *)" ", echo_attr);
Bram Moolenaar2c2398c2009-06-03 11:22:45 +000021410 current_copyID += COPYID_INC;
21411 p = echo_string(&rettv, &tofree, numbuf, current_copyID);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000021412 if (p != NULL)
21413 for ( ; *p != NUL && !got_int; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021414 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000021415 if (*p == '\n' || *p == '\r' || *p == TAB)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021416 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000021417 if (*p != TAB && needclr)
21418 {
21419 /* remove any text still there from the command */
21420 msg_clr_eos();
21421 needclr = FALSE;
21422 }
21423 msg_putchar_attr(*p, echo_attr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021424 }
21425 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +000021426 {
21427#ifdef FEAT_MBYTE
21428 if (has_mbyte)
21429 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000021430 int i = (*mb_ptr2len)(p);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000021431
21432 (void)msg_outtrans_len_attr(p, i, echo_attr);
21433 p += i - 1;
21434 }
21435 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000021436#endif
Bram Moolenaar81bf7082005-02-12 14:31:42 +000021437 (void)msg_outtrans_len_attr(p, 1, echo_attr);
21438 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000021439 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000021440 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021441 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021442 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021443 arg = skipwhite(arg);
21444 }
21445 eap->nextcmd = check_nextcmd(arg);
21446
21447 if (eap->skip)
21448 --emsg_skip;
21449 else
21450 {
21451 /* remove text that may still be there from the command */
21452 if (needclr)
21453 msg_clr_eos();
21454 if (eap->cmdidx == CMD_echo)
21455 msg_end();
21456 }
21457}
21458
21459/*
21460 * ":echohl {name}".
21461 */
21462 void
21463ex_echohl(eap)
21464 exarg_T *eap;
21465{
21466 int id;
21467
21468 id = syn_name2id(eap->arg);
21469 if (id == 0)
21470 echo_attr = 0;
21471 else
21472 echo_attr = syn_id2attr(id);
21473}
21474
21475/*
21476 * ":execute expr1 ..." execute the result of an expression.
21477 * ":echomsg expr1 ..." Print a message
21478 * ":echoerr expr1 ..." Print an error
21479 * Each gets spaces around each argument and a newline at the end for
21480 * echo commands
21481 */
21482 void
21483ex_execute(eap)
21484 exarg_T *eap;
21485{
21486 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000021487 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021488 int ret = OK;
21489 char_u *p;
21490 garray_T ga;
21491 int len;
21492 int save_did_emsg;
21493
21494 ga_init2(&ga, 1, 80);
21495
21496 if (eap->skip)
21497 ++emsg_skip;
21498 while (*arg != NUL && *arg != '|' && *arg != '\n')
21499 {
21500 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021501 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021502 {
21503 /*
21504 * Report the invalid expression unless the expression evaluation
21505 * has been cancelled due to an aborting error, an interrupt, or an
21506 * exception.
21507 */
21508 if (!aborting())
21509 EMSG2(_(e_invexpr2), p);
21510 ret = FAIL;
21511 break;
21512 }
21513
21514 if (!eap->skip)
21515 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021516 p = get_tv_string(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021517 len = (int)STRLEN(p);
21518 if (ga_grow(&ga, len + 2) == FAIL)
21519 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021520 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021521 ret = FAIL;
21522 break;
21523 }
21524 if (ga.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021525 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
Bram Moolenaar071d4272004-06-13 20:20:40 +000021526 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021527 ga.ga_len += len;
21528 }
21529
Bram Moolenaarc70646c2005-01-04 21:52:38 +000021530 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021531 arg = skipwhite(arg);
21532 }
21533
21534 if (ret != FAIL && ga.ga_data != NULL)
21535 {
21536 if (eap->cmdidx == CMD_echomsg)
Bram Moolenaar4770d092006-01-12 23:22:24 +000021537 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000021538 MSG_ATTR(ga.ga_data, echo_attr);
Bram Moolenaar4770d092006-01-12 23:22:24 +000021539 out_flush();
21540 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000021541 else if (eap->cmdidx == CMD_echoerr)
21542 {
21543 /* We don't want to abort following commands, restore did_emsg. */
21544 save_did_emsg = did_emsg;
21545 EMSG((char_u *)ga.ga_data);
21546 if (!force_abort)
21547 did_emsg = save_did_emsg;
21548 }
21549 else if (eap->cmdidx == CMD_execute)
21550 do_cmdline((char_u *)ga.ga_data,
21551 eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE);
21552 }
21553
21554 ga_clear(&ga);
21555
21556 if (eap->skip)
21557 --emsg_skip;
21558
21559 eap->nextcmd = check_nextcmd(arg);
21560}
21561
21562/*
21563 * Skip over the name of an option: "&option", "&g:option" or "&l:option".
21564 * "arg" points to the "&" or '+' when called, to "option" when returning.
21565 * Returns NULL when no option name found. Otherwise pointer to the char
21566 * after the option name.
21567 */
21568 static char_u *
21569find_option_end(arg, opt_flags)
21570 char_u **arg;
21571 int *opt_flags;
21572{
21573 char_u *p = *arg;
21574
21575 ++p;
21576 if (*p == 'g' && p[1] == ':')
21577 {
21578 *opt_flags = OPT_GLOBAL;
21579 p += 2;
21580 }
21581 else if (*p == 'l' && p[1] == ':')
21582 {
21583 *opt_flags = OPT_LOCAL;
21584 p += 2;
21585 }
21586 else
21587 *opt_flags = 0;
21588
21589 if (!ASCII_ISALPHA(*p))
21590 return NULL;
21591 *arg = p;
21592
21593 if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL)
21594 p += 4; /* termcap option */
21595 else
21596 while (ASCII_ISALPHA(*p))
21597 ++p;
21598 return p;
21599}
21600
21601/*
21602 * ":function"
21603 */
21604 void
21605ex_function(eap)
21606 exarg_T *eap;
21607{
21608 char_u *theline;
Bram Moolenaaracd6a042011-09-30 16:39:48 +020021609 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021610 int j;
21611 int c;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021612 int saved_did_emsg;
Bram Moolenaarccf623f2013-07-05 18:29:48 +020021613 int saved_wait_return = need_wait_return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021614 char_u *name = NULL;
21615 char_u *p;
21616 char_u *arg;
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000021617 char_u *line_arg = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021618 garray_T newargs;
21619 garray_T newlines;
21620 int varargs = FALSE;
21621 int mustend = FALSE;
21622 int flags = 0;
21623 ufunc_T *fp;
21624 int indent;
21625 int nesting;
21626 char_u *skip_until = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +000021627 dictitem_T *v;
21628 funcdict_T fudi;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021629 static int func_nr = 0; /* number for nameless function */
21630 int paren;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000021631 hashtab_T *ht;
21632 int todo;
21633 hashitem_T *hi;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000021634 int sourcing_lnum_off;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021635
21636 /*
21637 * ":function" without argument: list functions.
21638 */
21639 if (ends_excmd(*eap->arg))
21640 {
21641 if (!eap->skip)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000021642 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000021643 todo = (int)func_hashtab.ht_used;
Bram Moolenaar038eb0e2005-02-27 22:43:26 +000021644 for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000021645 {
21646 if (!HASHITEM_EMPTY(hi))
21647 {
21648 --todo;
21649 fp = HI2UF(hi);
21650 if (!isdigit(*fp->uf_name))
21651 list_func_head(fp, FALSE);
21652 }
21653 }
21654 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000021655 eap->nextcmd = check_nextcmd(eap->arg);
21656 return;
21657 }
21658
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021659 /*
Bram Moolenaardd2436f2005-09-05 22:14:46 +000021660 * ":function /pat": list functions matching pattern.
21661 */
21662 if (*eap->arg == '/')
21663 {
21664 p = skip_regexp(eap->arg + 1, '/', TRUE, NULL);
21665 if (!eap->skip)
21666 {
21667 regmatch_T regmatch;
21668
21669 c = *p;
21670 *p = NUL;
21671 regmatch.regprog = vim_regcomp(eap->arg + 1, RE_MAGIC);
21672 *p = c;
21673 if (regmatch.regprog != NULL)
21674 {
21675 regmatch.rm_ic = p_ic;
21676
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000021677 todo = (int)func_hashtab.ht_used;
Bram Moolenaardd2436f2005-09-05 22:14:46 +000021678 for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
21679 {
21680 if (!HASHITEM_EMPTY(hi))
21681 {
21682 --todo;
21683 fp = HI2UF(hi);
21684 if (!isdigit(*fp->uf_name)
21685 && vim_regexec(&regmatch, fp->uf_name, 0))
21686 list_func_head(fp, FALSE);
21687 }
21688 }
Bram Moolenaar473de612013-06-08 18:19:48 +020021689 vim_regfree(regmatch.regprog);
Bram Moolenaardd2436f2005-09-05 22:14:46 +000021690 }
21691 }
21692 if (*p == '/')
21693 ++p;
21694 eap->nextcmd = check_nextcmd(p);
21695 return;
21696 }
21697
21698 /*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021699 * Get the function name. There are these situations:
21700 * func normal function name
21701 * "name" == func, "fudi.fd_dict" == NULL
21702 * dict.func new dictionary entry
21703 * "name" == NULL, "fudi.fd_dict" set,
21704 * "fudi.fd_di" == NULL, "fudi.fd_newkey" == func
21705 * dict.func existing dict entry with a Funcref
Bram Moolenaard857f0e2005-06-21 22:37:39 +000021706 * "name" == func, "fudi.fd_dict" set,
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021707 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL
21708 * dict.func existing dict entry that's not a Funcref
21709 * "name" == NULL, "fudi.fd_dict" set,
21710 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL
Bram Moolenaareccb7fc2014-04-23 20:43:41 +020021711 * s:func script-local function name
21712 * g:func global function name, same as "func"
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021713 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000021714 p = eap->arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021715 name = trans_function_name(&p, eap->skip, 0, &fudi);
21716 paren = (vim_strchr(p, '(') != NULL);
21717 if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021718 {
21719 /*
21720 * Return on an invalid expression in braces, unless the expression
21721 * evaluation has been cancelled due to an aborting error, an
21722 * interrupt, or an exception.
21723 */
21724 if (!aborting())
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021725 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000021726 if (!eap->skip && fudi.fd_newkey != NULL)
21727 EMSG2(_(e_dictkey), fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021728 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021729 return;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021730 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000021731 else
21732 eap->skip = TRUE;
21733 }
Bram Moolenaar1f35bf92006-03-07 22:38:47 +000021734
Bram Moolenaar071d4272004-06-13 20:20:40 +000021735 /* An error in a function call during evaluation of an expression in magic
21736 * braces should not cause the function not to be defined. */
21737 saved_did_emsg = did_emsg;
21738 did_emsg = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021739
21740 /*
21741 * ":function func" with only function name: list function.
21742 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021743 if (!paren)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021744 {
21745 if (!ends_excmd(*skipwhite(p)))
21746 {
21747 EMSG(_(e_trailing));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021748 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021749 }
21750 eap->nextcmd = check_nextcmd(p);
21751 if (eap->nextcmd != NULL)
21752 *p = NUL;
21753 if (!eap->skip && !got_int)
21754 {
21755 fp = find_func(name);
21756 if (fp != NULL)
21757 {
21758 list_func_head(fp, TRUE);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000021759 for (j = 0; j < fp->uf_lines.ga_len && !got_int; ++j)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021760 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000021761 if (FUNCLINE(fp, j) == NULL)
21762 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021763 msg_putchar('\n');
21764 msg_outnum((long)(j + 1));
21765 if (j < 9)
21766 msg_putchar(' ');
21767 if (j < 99)
21768 msg_putchar(' ');
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000021769 msg_prt_line(FUNCLINE(fp, j), FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021770 out_flush(); /* show a line at a time */
21771 ui_breakcheck();
21772 }
21773 if (!got_int)
21774 {
21775 msg_putchar('\n');
21776 msg_puts((char_u *)" endfunction");
21777 }
21778 }
21779 else
Bram Moolenaar7b76b0a2009-01-28 18:09:38 +000021780 emsg_funcname(N_("E123: Undefined function: %s"), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000021781 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021782 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021783 }
21784
21785 /*
21786 * ":function name(arg1, arg2)" Define function.
21787 */
21788 p = skipwhite(p);
21789 if (*p != '(')
21790 {
21791 if (!eap->skip)
21792 {
21793 EMSG2(_("E124: Missing '(': %s"), eap->arg);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021794 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021795 }
21796 /* attempt to continue by skipping some text */
21797 if (vim_strchr(p, '(') != NULL)
21798 p = vim_strchr(p, '(');
21799 }
21800 p = skipwhite(p + 1);
21801
21802 ga_init2(&newargs, (int)sizeof(char_u *), 3);
21803 ga_init2(&newlines, (int)sizeof(char_u *), 3);
21804
Bram Moolenaard857f0e2005-06-21 22:37:39 +000021805 if (!eap->skip)
21806 {
Bram Moolenaarb42dc232006-11-21 18:36:05 +000021807 /* Check the name of the function. Unless it's a dictionary function
21808 * (that we are overwriting). */
Bram Moolenaard857f0e2005-06-21 22:37:39 +000021809 if (name != NULL)
21810 arg = name;
21811 else
21812 arg = fudi.fd_newkey;
Bram Moolenaarb42dc232006-11-21 18:36:05 +000021813 if (arg != NULL && (fudi.fd_di == NULL
21814 || fudi.fd_di->di_tv.v_type != VAR_FUNC))
Bram Moolenaard857f0e2005-06-21 22:37:39 +000021815 {
21816 if (*arg == K_SPECIAL)
21817 j = 3;
21818 else
21819 j = 0;
21820 while (arg[j] != NUL && (j == 0 ? eval_isnamec1(arg[j])
21821 : eval_isnamec(arg[j])))
21822 ++j;
21823 if (arg[j] != NUL)
Bram Moolenaarb67cc162009-02-04 15:27:06 +000021824 emsg_funcname((char *)e_invarg2, arg);
Bram Moolenaard857f0e2005-06-21 22:37:39 +000021825 }
Bram Moolenaar2142e5d2013-02-20 15:19:43 +010021826 /* Disallow using the g: dict. */
21827 if (fudi.fd_dict != NULL && fudi.fd_dict->dv_scope == VAR_DEF_SCOPE)
21828 EMSG(_("E862: Cannot use g: here"));
Bram Moolenaard857f0e2005-06-21 22:37:39 +000021829 }
21830
Bram Moolenaar071d4272004-06-13 20:20:40 +000021831 /*
21832 * Isolate the arguments: "arg1, arg2, ...)"
21833 */
21834 while (*p != ')')
21835 {
21836 if (p[0] == '.' && p[1] == '.' && p[2] == '.')
21837 {
21838 varargs = TRUE;
21839 p += 3;
21840 mustend = TRUE;
21841 }
21842 else
21843 {
21844 arg = p;
21845 while (ASCII_ISALNUM(*p) || *p == '_')
21846 ++p;
21847 if (arg == p || isdigit(*arg)
21848 || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0)
21849 || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0))
21850 {
21851 if (!eap->skip)
21852 EMSG2(_("E125: Illegal argument: %s"), arg);
21853 break;
21854 }
21855 if (ga_grow(&newargs, 1) == FAIL)
21856 goto erret;
21857 c = *p;
21858 *p = NUL;
21859 arg = vim_strsave(arg);
21860 if (arg == NULL)
21861 goto erret;
Bram Moolenaaracd6a042011-09-30 16:39:48 +020021862
21863 /* Check for duplicate argument name. */
21864 for (i = 0; i < newargs.ga_len; ++i)
21865 if (STRCMP(((char_u **)(newargs.ga_data))[i], arg) == 0)
21866 {
21867 EMSG2(_("E853: Duplicate argument name: %s"), arg);
Bram Moolenaar47b83422014-02-24 03:32:00 +010021868 vim_free(arg);
Bram Moolenaaracd6a042011-09-30 16:39:48 +020021869 goto erret;
21870 }
21871
Bram Moolenaar071d4272004-06-13 20:20:40 +000021872 ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg;
21873 *p = c;
21874 newargs.ga_len++;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021875 if (*p == ',')
21876 ++p;
21877 else
21878 mustend = TRUE;
21879 }
21880 p = skipwhite(p);
21881 if (mustend && *p != ')')
21882 {
21883 if (!eap->skip)
21884 EMSG2(_(e_invarg2), eap->arg);
21885 break;
21886 }
21887 }
21888 ++p; /* skip the ')' */
21889
Bram Moolenaare9a41262005-01-15 22:18:47 +000021890 /* find extra arguments "range", "dict" and "abort" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000021891 for (;;)
21892 {
21893 p = skipwhite(p);
21894 if (STRNCMP(p, "range", 5) == 0)
21895 {
21896 flags |= FC_RANGE;
21897 p += 5;
21898 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000021899 else if (STRNCMP(p, "dict", 4) == 0)
21900 {
21901 flags |= FC_DICT;
21902 p += 4;
21903 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000021904 else if (STRNCMP(p, "abort", 5) == 0)
21905 {
21906 flags |= FC_ABORT;
21907 p += 5;
21908 }
21909 else
21910 break;
21911 }
21912
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000021913 /* When there is a line break use what follows for the function body.
21914 * Makes 'exe "func Test()\n...\nendfunc"' work. */
21915 if (*p == '\n')
21916 line_arg = p + 1;
21917 else if (*p != NUL && *p != '"' && !eap->skip && !did_emsg)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021918 EMSG(_(e_trailing));
21919
21920 /*
21921 * Read the body of the function, until ":endfunction" is found.
21922 */
21923 if (KeyTyped)
21924 {
21925 /* Check if the function already exists, don't let the user type the
21926 * whole function before telling him it doesn't work! For a script we
21927 * need to skip the body to be able to find what follows. */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021928 if (!eap->skip && !eap->forceit)
21929 {
21930 if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL)
21931 EMSG(_(e_funcdict));
21932 else if (name != NULL && find_func(name) != NULL)
Bram Moolenaar81bf7082005-02-12 14:31:42 +000021933 emsg_funcname(e_funcexts, name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000021934 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000021935
Bram Moolenaard857f0e2005-06-21 22:37:39 +000021936 if (!eap->skip && did_emsg)
21937 goto erret;
21938
Bram Moolenaar071d4272004-06-13 20:20:40 +000021939 msg_putchar('\n'); /* don't overwrite the function name */
21940 cmdline_row = msg_row;
21941 }
21942
21943 indent = 2;
21944 nesting = 0;
21945 for (;;)
21946 {
Bram Moolenaar52af9652011-09-14 14:33:51 +020021947 if (KeyTyped)
Bram Moolenaarccf623f2013-07-05 18:29:48 +020021948 {
Bram Moolenaar52af9652011-09-14 14:33:51 +020021949 msg_scroll = TRUE;
Bram Moolenaarccf623f2013-07-05 18:29:48 +020021950 saved_wait_return = FALSE;
21951 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000021952 need_wait_return = FALSE;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000021953 sourcing_lnum_off = sourcing_lnum;
21954
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000021955 if (line_arg != NULL)
21956 {
21957 /* Use eap->arg, split up in parts by line breaks. */
21958 theline = line_arg;
21959 p = vim_strchr(theline, '\n');
21960 if (p == NULL)
21961 line_arg += STRLEN(line_arg);
21962 else
21963 {
21964 *p = NUL;
21965 line_arg = p + 1;
21966 }
21967 }
21968 else if (eap->getline == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021969 theline = getcmdline(':', 0L, indent);
21970 else
21971 theline = eap->getline(':', eap->cookie, indent);
21972 if (KeyTyped)
21973 lines_left = Rows - 1;
21974 if (theline == NULL)
21975 {
21976 EMSG(_("E126: Missing :endfunction"));
21977 goto erret;
21978 }
21979
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000021980 /* Detect line continuation: sourcing_lnum increased more than one. */
21981 if (sourcing_lnum > sourcing_lnum_off + 1)
21982 sourcing_lnum_off = sourcing_lnum - sourcing_lnum_off - 1;
21983 else
21984 sourcing_lnum_off = 0;
21985
Bram Moolenaar071d4272004-06-13 20:20:40 +000021986 if (skip_until != NULL)
21987 {
21988 /* between ":append" and "." and between ":python <<EOF" and "EOF"
21989 * don't check for ":endfunc". */
21990 if (STRCMP(theline, skip_until) == 0)
21991 {
21992 vim_free(skip_until);
21993 skip_until = NULL;
21994 }
21995 }
21996 else
21997 {
21998 /* skip ':' and blanks*/
21999 for (p = theline; vim_iswhite(*p) || *p == ':'; ++p)
22000 ;
22001
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000022002 /* Check for "endfunction". */
22003 if (checkforcmd(&p, "endfunction", 4) && nesting-- == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022004 {
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000022005 if (line_arg == NULL)
22006 vim_free(theline);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022007 break;
22008 }
22009
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000022010 /* Increase indent inside "if", "while", "for" and "try", decrease
Bram Moolenaar071d4272004-06-13 20:20:40 +000022011 * at "end". */
22012 if (indent > 2 && STRNCMP(p, "end", 3) == 0)
22013 indent -= 2;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000022014 else if (STRNCMP(p, "if", 2) == 0
22015 || STRNCMP(p, "wh", 2) == 0
22016 || STRNCMP(p, "for", 3) == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +000022017 || STRNCMP(p, "try", 3) == 0)
22018 indent += 2;
22019
22020 /* Check for defining a function inside this function. */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000022021 if (checkforcmd(&p, "function", 2))
Bram Moolenaar071d4272004-06-13 20:20:40 +000022022 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000022023 if (*p == '!')
22024 p = skipwhite(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022025 p += eval_fname_script(p);
22026 if (ASCII_ISALPHA(*p))
22027 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022028 vim_free(trans_function_name(&p, TRUE, 0, NULL));
Bram Moolenaar071d4272004-06-13 20:20:40 +000022029 if (*skipwhite(p) == '(')
22030 {
22031 ++nesting;
22032 indent += 2;
22033 }
22034 }
22035 }
22036
22037 /* Check for ":append" or ":insert". */
22038 p = skip_range(p, NULL);
22039 if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
22040 || (p[0] == 'i'
22041 && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
22042 && (!ASCII_ISALPHA(p[2]) || (p[2] == 's'))))))
22043 skip_until = vim_strsave((char_u *)".");
22044
22045 /* Check for ":python <<EOF", ":tcl <<EOF", etc. */
22046 arg = skipwhite(skiptowhite(p));
22047 if (arg[0] == '<' && arg[1] =='<'
22048 && ((p[0] == 'p' && p[1] == 'y'
22049 && (!ASCII_ISALPHA(p[2]) || p[2] == 't'))
22050 || (p[0] == 'p' && p[1] == 'e'
22051 && (!ASCII_ISALPHA(p[2]) || p[2] == 'r'))
22052 || (p[0] == 't' && p[1] == 'c'
22053 && (!ASCII_ISALPHA(p[2]) || p[2] == 'l'))
Bram Moolenaar50bfb322011-10-26 13:19:27 +020022054 || (p[0] == 'l' && p[1] == 'u' && p[2] == 'a'
22055 && !ASCII_ISALPHA(p[3]))
Bram Moolenaar071d4272004-06-13 20:20:40 +000022056 || (p[0] == 'r' && p[1] == 'u' && p[2] == 'b'
22057 && (!ASCII_ISALPHA(p[3]) || p[3] == 'y'))
Bram Moolenaar325b7a22004-07-05 15:58:32 +000022058 || (p[0] == 'm' && p[1] == 'z'
22059 && (!ASCII_ISALPHA(p[2]) || p[2] == 's'))
Bram Moolenaar071d4272004-06-13 20:20:40 +000022060 ))
22061 {
22062 /* ":python <<" continues until a dot, like ":append" */
22063 p = skipwhite(arg + 2);
22064 if (*p == NUL)
22065 skip_until = vim_strsave((char_u *)".");
22066 else
22067 skip_until = vim_strsave(p);
22068 }
22069 }
22070
22071 /* Add the line to the function. */
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000022072 if (ga_grow(&newlines, 1 + sourcing_lnum_off) == FAIL)
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000022073 {
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000022074 if (line_arg == NULL)
22075 vim_free(theline);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022076 goto erret;
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000022077 }
22078
22079 /* Copy the line to newly allocated memory. get_one_sourceline()
22080 * allocates 250 bytes per line, this saves 80% on average. The cost
22081 * is an extra alloc/free. */
22082 p = vim_strsave(theline);
22083 if (p != NULL)
22084 {
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000022085 if (line_arg == NULL)
22086 vim_free(theline);
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000022087 theline = p;
22088 }
22089
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000022090 ((char_u **)(newlines.ga_data))[newlines.ga_len++] = theline;
22091
22092 /* Add NULL lines for continuation lines, so that the line count is
22093 * equal to the index in the growarray. */
22094 while (sourcing_lnum_off-- > 0)
22095 ((char_u **)(newlines.ga_data))[newlines.ga_len++] = NULL;
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000022096
22097 /* Check for end of eap->arg. */
22098 if (line_arg != NULL && *line_arg == NUL)
22099 line_arg = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022100 }
22101
22102 /* Don't define the function when skipping commands or when an error was
22103 * detected. */
22104 if (eap->skip || did_emsg)
22105 goto erret;
22106
22107 /*
22108 * If there are no errors, add the function
22109 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022110 if (fudi.fd_dict == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022111 {
Bram Moolenaar6d977d62014-01-14 15:24:39 +010022112 v = find_var(name, &ht, FALSE);
Bram Moolenaar33570922005-01-25 22:26:29 +000022113 if (v != NULL && v->di_tv.v_type == VAR_FUNC)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022114 {
Bram Moolenaar7b76b0a2009-01-28 18:09:38 +000022115 emsg_funcname(N_("E707: Function name conflicts with variable: %s"),
Bram Moolenaar81bf7082005-02-12 14:31:42 +000022116 name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022117 goto erret;
22118 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022119
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022120 fp = find_func(name);
22121 if (fp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022122 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022123 if (!eap->forceit)
22124 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000022125 emsg_funcname(e_funcexts, name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022126 goto erret;
22127 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022128 if (fp->uf_calls > 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022129 {
Bram Moolenaar7b76b0a2009-01-28 18:09:38 +000022130 emsg_funcname(N_("E127: Cannot redefine function %s: It is in use"),
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022131 name);
22132 goto erret;
22133 }
22134 /* redefine existing function */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022135 ga_clear_strings(&(fp->uf_args));
22136 ga_clear_strings(&(fp->uf_lines));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022137 vim_free(name);
22138 name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022139 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000022140 }
22141 else
22142 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022143 char numbuf[20];
22144
22145 fp = NULL;
22146 if (fudi.fd_newkey == NULL && !eap->forceit)
22147 {
22148 EMSG(_(e_funcdict));
22149 goto erret;
22150 }
Bram Moolenaar758711c2005-02-02 23:11:38 +000022151 if (fudi.fd_di == NULL)
22152 {
22153 /* Can't add a function to a locked dictionary */
22154 if (tv_check_lock(fudi.fd_dict->dv_lock, eap->arg))
22155 goto erret;
22156 }
22157 /* Can't change an existing function if it is locked */
22158 else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg))
22159 goto erret;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022160
22161 /* Give the function a sequential number. Can only be used with a
22162 * Funcref! */
22163 vim_free(name);
22164 sprintf(numbuf, "%d", ++func_nr);
22165 name = vim_strsave((char_u *)numbuf);
22166 if (name == NULL)
22167 goto erret;
22168 }
22169
22170 if (fp == NULL)
22171 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000022172 if (fudi.fd_dict == NULL && vim_strchr(name, AUTOLOAD_CHAR) != NULL)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022173 {
22174 int slen, plen;
22175 char_u *scriptname;
22176
22177 /* Check that the autoload name matches the script name. */
22178 j = FAIL;
22179 if (sourcing_name != NULL)
22180 {
22181 scriptname = autoload_name(name);
22182 if (scriptname != NULL)
22183 {
22184 p = vim_strchr(scriptname, '/');
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000022185 plen = (int)STRLEN(p);
22186 slen = (int)STRLEN(sourcing_name);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022187 if (slen > plen && fnamecmp(p,
22188 sourcing_name + slen - plen) == 0)
22189 j = OK;
22190 vim_free(scriptname);
22191 }
22192 }
22193 if (j == FAIL)
22194 {
22195 EMSG2(_("E746: Function name does not match script file name: %s"), name);
22196 goto erret;
22197 }
22198 }
22199
22200 fp = (ufunc_T *)alloc((unsigned)(sizeof(ufunc_T) + STRLEN(name)));
Bram Moolenaar071d4272004-06-13 20:20:40 +000022201 if (fp == NULL)
22202 goto erret;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022203
22204 if (fudi.fd_dict != NULL)
22205 {
22206 if (fudi.fd_di == NULL)
22207 {
22208 /* add new dict entry */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000022209 fudi.fd_di = dictitem_alloc(fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022210 if (fudi.fd_di == NULL)
22211 {
22212 vim_free(fp);
22213 goto erret;
22214 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000022215 if (dict_add(fudi.fd_dict, fudi.fd_di) == FAIL)
22216 {
22217 vim_free(fudi.fd_di);
Bram Moolenaar0a5fd8b2006-08-16 20:02:22 +000022218 vim_free(fp);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000022219 goto erret;
22220 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022221 }
22222 else
22223 /* overwrite existing dict entry */
22224 clear_tv(&fudi.fd_di->di_tv);
22225 fudi.fd_di->di_tv.v_type = VAR_FUNC;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000022226 fudi.fd_di->di_tv.v_lock = 0;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022227 fudi.fd_di->di_tv.vval.v_string = vim_strsave(name);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022228 fp->uf_refcount = 1;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000022229
22230 /* behave like "dict" was used */
22231 flags |= FC_DICT;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022232 }
22233
Bram Moolenaar071d4272004-06-13 20:20:40 +000022234 /* insert the new function in the function list */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022235 STRCPY(fp->uf_name, name);
22236 hash_add(&func_hashtab, UF2HIKEY(fp));
Bram Moolenaar071d4272004-06-13 20:20:40 +000022237 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022238 fp->uf_args = newargs;
22239 fp->uf_lines = newlines;
Bram Moolenaar05159a02005-02-26 23:04:13 +000022240#ifdef FEAT_PROFILE
22241 fp->uf_tml_count = NULL;
22242 fp->uf_tml_total = NULL;
22243 fp->uf_tml_self = NULL;
22244 fp->uf_profiling = FALSE;
22245 if (prof_def_func())
22246 func_do_profile(fp);
22247#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022248 fp->uf_varargs = varargs;
22249 fp->uf_flags = flags;
22250 fp->uf_calls = 0;
22251 fp->uf_script_ID = current_SID;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022252 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022253
22254erret:
Bram Moolenaar071d4272004-06-13 20:20:40 +000022255 ga_clear_strings(&newargs);
22256 ga_clear_strings(&newlines);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022257ret_free:
22258 vim_free(skip_until);
22259 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022260 vim_free(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022261 did_emsg |= saved_did_emsg;
Bram Moolenaarccf623f2013-07-05 18:29:48 +020022262 need_wait_return |= saved_wait_return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022263}
22264
22265/*
22266 * Get a function name, translating "<SID>" and "<SNR>".
Bram Moolenaara7043832005-01-21 11:56:39 +000022267 * Also handles a Funcref in a List or Dictionary.
Bram Moolenaar071d4272004-06-13 20:20:40 +000022268 * Returns the function name in allocated memory, or NULL for failure.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022269 * flags:
Bram Moolenaar6d977d62014-01-14 15:24:39 +010022270 * TFN_INT: internal function name OK
22271 * TFN_QUIET: be quiet
22272 * TFN_NO_AUTOLOAD: do not use script autoloading
Bram Moolenaar071d4272004-06-13 20:20:40 +000022273 * Advances "pp" to just after the function name (if no error).
22274 */
22275 static char_u *
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022276trans_function_name(pp, skip, flags, fdp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022277 char_u **pp;
22278 int skip; /* only find the end, don't evaluate */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022279 int flags;
Bram Moolenaar33570922005-01-25 22:26:29 +000022280 funcdict_T *fdp; /* return: info about dictionary used */
Bram Moolenaar071d4272004-06-13 20:20:40 +000022281{
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000022282 char_u *name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022283 char_u *start;
22284 char_u *end;
22285 int lead;
22286 char_u sid_buf[20];
Bram Moolenaar071d4272004-06-13 20:20:40 +000022287 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +000022288 lval_T lv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022289
22290 if (fdp != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000022291 vim_memset(fdp, 0, sizeof(funcdict_T));
Bram Moolenaar071d4272004-06-13 20:20:40 +000022292 start = *pp;
Bram Moolenaara7043832005-01-21 11:56:39 +000022293
22294 /* Check for hard coded <SNR>: already translated function ID (from a user
22295 * command). */
22296 if ((*pp)[0] == K_SPECIAL && (*pp)[1] == KS_EXTRA
22297 && (*pp)[2] == (int)KE_SNR)
22298 {
22299 *pp += 3;
22300 len = get_id_len(pp) + 3;
22301 return vim_strnsave(start, len);
22302 }
22303
22304 /* A name starting with "<SID>" or "<SNR>" is local to a script. But
22305 * don't skip over "s:", get_lval() needs it for "s:dict.func". */
Bram Moolenaar071d4272004-06-13 20:20:40 +000022306 lead = eval_fname_script(start);
Bram Moolenaara7043832005-01-21 11:56:39 +000022307 if (lead > 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022308 start += lead;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000022309
Bram Moolenaar6d977d62014-01-14 15:24:39 +010022310 /* Note that TFN_ flags use the same values as GLV_ flags. */
22311 end = get_lval(start, NULL, &lv, FALSE, skip, flags,
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000022312 lead > 2 ? 0 : FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000022313 if (end == start)
22314 {
22315 if (!skip)
22316 EMSG(_("E129: Function name required"));
22317 goto theend;
22318 }
Bram Moolenaara7043832005-01-21 11:56:39 +000022319 if (end == NULL || (lv.ll_tv != NULL && (lead > 2 || lv.ll_range)))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000022320 {
22321 /*
22322 * Report an invalid expression in braces, unless the expression
22323 * evaluation has been cancelled due to an aborting error, an
22324 * interrupt, or an exception.
22325 */
22326 if (!aborting())
22327 {
22328 if (end != NULL)
22329 EMSG2(_(e_invarg2), start);
22330 }
22331 else
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000022332 *pp = find_name_end(start, NULL, NULL, FNE_INCL_BR);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000022333 goto theend;
22334 }
22335
22336 if (lv.ll_tv != NULL)
22337 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022338 if (fdp != NULL)
22339 {
22340 fdp->fd_dict = lv.ll_dict;
22341 fdp->fd_newkey = lv.ll_newkey;
22342 lv.ll_newkey = NULL;
22343 fdp->fd_di = lv.ll_di;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022344 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000022345 if (lv.ll_tv->v_type == VAR_FUNC && lv.ll_tv->vval.v_string != NULL)
22346 {
22347 name = vim_strsave(lv.ll_tv->vval.v_string);
22348 *pp = end;
22349 }
22350 else
22351 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000022352 if (!skip && !(flags & TFN_QUIET) && (fdp == NULL
22353 || lv.ll_dict == NULL || fdp->fd_newkey == NULL))
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022354 EMSG(_(e_funcref));
22355 else
22356 *pp = end;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000022357 name = NULL;
22358 }
22359 goto theend;
22360 }
22361
22362 if (lv.ll_name == NULL)
22363 {
22364 /* Error found, but continue after the function name. */
22365 *pp = end;
22366 goto theend;
22367 }
22368
Bram Moolenaar33e1a802007-09-06 12:26:44 +000022369 /* Check if the name is a Funcref. If so, use the value. */
22370 if (lv.ll_exp_name != NULL)
22371 {
22372 len = (int)STRLEN(lv.ll_exp_name);
Bram Moolenaar8822a9c2014-01-14 19:44:34 +010022373 name = deref_func_name(lv.ll_exp_name, &len, flags & TFN_NO_AUTOLOAD);
Bram Moolenaar33e1a802007-09-06 12:26:44 +000022374 if (name == lv.ll_exp_name)
22375 name = NULL;
22376 }
22377 else
22378 {
22379 len = (int)(end - *pp);
Bram Moolenaar8822a9c2014-01-14 19:44:34 +010022380 name = deref_func_name(*pp, &len, flags & TFN_NO_AUTOLOAD);
Bram Moolenaar33e1a802007-09-06 12:26:44 +000022381 if (name == *pp)
22382 name = NULL;
22383 }
22384 if (name != NULL)
22385 {
22386 name = vim_strsave(name);
22387 *pp = end;
Bram Moolenaar355a95a2014-04-29 14:03:02 +020022388 if (STRNCMP(name, "<SNR>", 5) == 0)
22389 {
22390 /* Change "<SNR>" to the byte sequence. */
22391 name[0] = K_SPECIAL;
22392 name[1] = KS_EXTRA;
22393 name[2] = (int)KE_SNR;
22394 mch_memmove(name + 3, name + 5, STRLEN(name + 5) + 1);
22395 }
Bram Moolenaar33e1a802007-09-06 12:26:44 +000022396 goto theend;
22397 }
22398
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000022399 if (lv.ll_exp_name != NULL)
Bram Moolenaarc32840f2006-01-14 21:23:38 +000022400 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000022401 len = (int)STRLEN(lv.ll_exp_name);
Bram Moolenaarc32840f2006-01-14 21:23:38 +000022402 if (lead <= 2 && lv.ll_name == lv.ll_exp_name
22403 && STRNCMP(lv.ll_name, "s:", 2) == 0)
22404 {
22405 /* When there was "s:" already or the name expanded to get a
22406 * leading "s:" then remove it. */
22407 lv.ll_name += 2;
22408 len -= 2;
22409 lead = 2;
22410 }
22411 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000022412 else
Bram Moolenaara7043832005-01-21 11:56:39 +000022413 {
Bram Moolenaareccb7fc2014-04-23 20:43:41 +020022414 /* skip over "s:" and "g:" */
22415 if (lead == 2 || (lv.ll_name[0] == 'g' && lv.ll_name[1] == ':'))
Bram Moolenaara7043832005-01-21 11:56:39 +000022416 lv.ll_name += 2;
22417 len = (int)(end - lv.ll_name);
22418 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000022419
22420 /*
22421 * Copy the function name to allocated memory.
22422 * Accept <SID>name() inside a script, translate into <SNR>123_name().
22423 * Accept <SNR>123_name() outside a script.
22424 */
22425 if (skip)
22426 lead = 0; /* do nothing */
22427 else if (lead > 0)
22428 {
22429 lead = 3;
Bram Moolenaar86c9ee22006-05-13 11:33:27 +000022430 if ((lv.ll_exp_name != NULL && eval_fname_sid(lv.ll_exp_name))
22431 || eval_fname_sid(*pp))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000022432 {
Bram Moolenaar899dddf2006-03-26 21:06:50 +000022433 /* It's "s:" or "<SID>" */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000022434 if (current_SID <= 0)
22435 {
22436 EMSG(_(e_usingsid));
22437 goto theend;
22438 }
22439 sprintf((char *)sid_buf, "%ld_", (long)current_SID);
22440 lead += (int)STRLEN(sid_buf);
22441 }
22442 }
Bram Moolenaar9bdfb002014-04-23 17:43:42 +020022443 else if (!(flags & TFN_INT) && builtin_function(lv.ll_name, len))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000022444 {
Bram Moolenaar9bdfb002014-04-23 17:43:42 +020022445 EMSG2(_("E128: Function name must start with a capital or \"s:\": %s"),
Bram Moolenaareccb7fc2014-04-23 20:43:41 +020022446 start);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000022447 goto theend;
22448 }
Bram Moolenaareccb7fc2014-04-23 20:43:41 +020022449 if (!skip && !(flags & TFN_QUIET))
Bram Moolenaar9bdfb002014-04-23 17:43:42 +020022450 {
22451 char_u *cp = vim_strchr(lv.ll_name, ':');
22452
22453 if (cp != NULL && cp < end)
22454 {
Bram Moolenaareccb7fc2014-04-23 20:43:41 +020022455 EMSG2(_("E884: Function name cannot contain a colon: %s"), start);
Bram Moolenaar9bdfb002014-04-23 17:43:42 +020022456 goto theend;
22457 }
22458 }
22459
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000022460 name = alloc((unsigned)(len + lead + 1));
22461 if (name != NULL)
22462 {
22463 if (lead > 0)
22464 {
22465 name[0] = K_SPECIAL;
22466 name[1] = KS_EXTRA;
22467 name[2] = (int)KE_SNR;
Bram Moolenaara7043832005-01-21 11:56:39 +000022468 if (lead > 3) /* If it's "<SID>" */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000022469 STRCPY(name + 3, sid_buf);
22470 }
22471 mch_memmove(name + lead, lv.ll_name, (size_t)len);
Bram Moolenaar9bdfb002014-04-23 17:43:42 +020022472 name[lead + len] = NUL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000022473 }
22474 *pp = end;
22475
22476theend:
22477 clear_lval(&lv);
22478 return name;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022479}
22480
22481/*
22482 * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case).
22483 * Return 2 if "p" starts with "s:".
22484 * Return 0 otherwise.
22485 */
22486 static int
22487eval_fname_script(p)
22488 char_u *p;
22489{
22490 if (p[0] == '<' && (STRNICMP(p + 1, "SID>", 4) == 0
22491 || STRNICMP(p + 1, "SNR>", 4) == 0))
22492 return 5;
22493 if (p[0] == 's' && p[1] == ':')
22494 return 2;
22495 return 0;
22496}
22497
22498/*
22499 * Return TRUE if "p" starts with "<SID>" or "s:".
22500 * Only works if eval_fname_script() returned non-zero for "p"!
22501 */
22502 static int
22503eval_fname_sid(p)
22504 char_u *p;
22505{
22506 return (*p == 's' || TOUPPER_ASC(p[2]) == 'I');
22507}
22508
22509/*
22510 * List the head of the function: "name(arg1, arg2)".
22511 */
22512 static void
22513list_func_head(fp, indent)
22514 ufunc_T *fp;
22515 int indent;
22516{
22517 int j;
22518
22519 msg_start();
22520 if (indent)
22521 MSG_PUTS(" ");
22522 MSG_PUTS("function ");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022523 if (fp->uf_name[0] == K_SPECIAL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022524 {
22525 MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022526 msg_puts(fp->uf_name + 3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022527 }
22528 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022529 msg_puts(fp->uf_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022530 msg_putchar('(');
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022531 for (j = 0; j < fp->uf_args.ga_len; ++j)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022532 {
22533 if (j)
22534 MSG_PUTS(", ");
22535 msg_puts(FUNCARG(fp, j));
22536 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022537 if (fp->uf_varargs)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022538 {
22539 if (j)
22540 MSG_PUTS(", ");
22541 MSG_PUTS("...");
22542 }
22543 msg_putchar(')');
Bram Moolenaar4cd92d52013-06-06 21:31:06 +020022544 if (fp->uf_flags & FC_ABORT)
22545 MSG_PUTS(" abort");
22546 if (fp->uf_flags & FC_RANGE)
22547 MSG_PUTS(" range");
22548 if (fp->uf_flags & FC_DICT)
22549 MSG_PUTS(" dict");
Bram Moolenaarcafda4f2005-09-06 19:25:11 +000022550 msg_clr_eos();
Bram Moolenaar5b8d8fd2005-08-16 23:01:50 +000022551 if (p_verbose > 0)
22552 last_set_msg(fp->uf_script_ID);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022553}
22554
22555/*
22556 * Find a function by name, return pointer to it in ufuncs.
22557 * Return NULL for unknown function.
22558 */
22559 static ufunc_T *
22560find_func(name)
22561 char_u *name;
22562{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022563 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022564
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022565 hi = hash_find(&func_hashtab, name);
22566 if (!HASHITEM_EMPTY(hi))
22567 return HI2UF(hi);
22568 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022569}
22570
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000022571#if defined(EXITFREE) || defined(PROTO)
22572 void
22573free_all_functions()
22574{
22575 hashitem_T *hi;
22576
22577 /* Need to start all over every time, because func_free() may change the
22578 * hash table. */
22579 while (func_hashtab.ht_used > 0)
22580 for (hi = func_hashtab.ht_array; ; ++hi)
22581 if (!HASHITEM_EMPTY(hi))
22582 {
22583 func_free(HI2UF(hi));
22584 break;
22585 }
22586}
22587#endif
22588
Bram Moolenaar355fd9b2013-05-30 13:14:13 +020022589 int
22590translated_function_exists(name)
22591 char_u *name;
22592{
Bram Moolenaar9bdfb002014-04-23 17:43:42 +020022593 if (builtin_function(name, -1))
Bram Moolenaar355fd9b2013-05-30 13:14:13 +020022594 return find_internal_func(name) >= 0;
22595 return find_func(name) != NULL;
22596}
22597
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022598/*
22599 * Return TRUE if a function "name" exists.
22600 */
22601 static int
22602function_exists(name)
22603 char_u *name;
22604{
Bram Moolenaaraa35dd12006-04-29 22:03:41 +000022605 char_u *nm = name;
22606 char_u *p;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022607 int n = FALSE;
22608
Bram Moolenaar6d977d62014-01-14 15:24:39 +010022609 p = trans_function_name(&nm, FALSE, TFN_INT|TFN_QUIET|TFN_NO_AUTOLOAD,
22610 NULL);
Bram Moolenaar79783442006-05-05 21:18:03 +000022611 nm = skipwhite(nm);
22612
22613 /* Only accept "funcname", "funcname ", "funcname (..." and
22614 * "funcname(...", not "funcname!...". */
22615 if (p != NULL && (*nm == NUL || *nm == '('))
Bram Moolenaar355fd9b2013-05-30 13:14:13 +020022616 n = translated_function_exists(p);
Bram Moolenaar79783442006-05-05 21:18:03 +000022617 vim_free(p);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000022618 return n;
22619}
22620
Bram Moolenaara1544c02013-05-30 12:35:52 +020022621 char_u *
22622get_expanded_name(name, check)
22623 char_u *name;
22624 int check;
22625{
22626 char_u *nm = name;
22627 char_u *p;
22628
22629 p = trans_function_name(&nm, FALSE, TFN_INT|TFN_QUIET, NULL);
22630
22631 if (p != NULL && *nm == NUL)
Bram Moolenaar355fd9b2013-05-30 13:14:13 +020022632 if (!check || translated_function_exists(p))
Bram Moolenaara1544c02013-05-30 12:35:52 +020022633 return p;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +020022634
Bram Moolenaara1544c02013-05-30 12:35:52 +020022635 vim_free(p);
22636 return NULL;
22637}
22638
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000022639/*
22640 * Return TRUE if "name" looks like a builtin function name: starts with a
Bram Moolenaar9bdfb002014-04-23 17:43:42 +020022641 * lower case letter and doesn't contain AUTOLOAD_CHAR.
22642 * "len" is the length of "name", or -1 for NUL terminated.
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000022643 */
22644 static int
Bram Moolenaar9bdfb002014-04-23 17:43:42 +020022645builtin_function(name, len)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000022646 char_u *name;
Bram Moolenaar9bdfb002014-04-23 17:43:42 +020022647 int len;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000022648{
Bram Moolenaar9bdfb002014-04-23 17:43:42 +020022649 char_u *p;
22650
22651 if (!ASCII_ISLOWER(name[0]))
22652 return FALSE;
22653 p = vim_strchr(name, AUTOLOAD_CHAR);
22654 return p == NULL || (len > 0 && p > name + len);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000022655}
22656
Bram Moolenaar05159a02005-02-26 23:04:13 +000022657#if defined(FEAT_PROFILE) || defined(PROTO)
22658/*
22659 * Start profiling function "fp".
22660 */
22661 static void
22662func_do_profile(fp)
22663 ufunc_T *fp;
22664{
Bram Moolenaar904c6222010-07-24 16:57:39 +020022665 int len = fp->uf_lines.ga_len;
22666
22667 if (len == 0)
22668 len = 1; /* avoid getting error for allocating zero bytes */
Bram Moolenaar05159a02005-02-26 23:04:13 +000022669 fp->uf_tm_count = 0;
22670 profile_zero(&fp->uf_tm_self);
22671 profile_zero(&fp->uf_tm_total);
22672 if (fp->uf_tml_count == NULL)
Bram Moolenaar904c6222010-07-24 16:57:39 +020022673 fp->uf_tml_count = (int *)alloc_clear((unsigned) (sizeof(int) * len));
Bram Moolenaar05159a02005-02-26 23:04:13 +000022674 if (fp->uf_tml_total == NULL)
22675 fp->uf_tml_total = (proftime_T *)alloc_clear((unsigned)
Bram Moolenaar904c6222010-07-24 16:57:39 +020022676 (sizeof(proftime_T) * len));
Bram Moolenaar05159a02005-02-26 23:04:13 +000022677 if (fp->uf_tml_self == NULL)
22678 fp->uf_tml_self = (proftime_T *)alloc_clear((unsigned)
Bram Moolenaar904c6222010-07-24 16:57:39 +020022679 (sizeof(proftime_T) * len));
Bram Moolenaar05159a02005-02-26 23:04:13 +000022680 fp->uf_tml_idx = -1;
22681 if (fp->uf_tml_count == NULL || fp->uf_tml_total == NULL
22682 || fp->uf_tml_self == NULL)
22683 return; /* out of memory */
22684
22685 fp->uf_profiling = TRUE;
22686}
22687
22688/*
22689 * Dump the profiling results for all functions in file "fd".
22690 */
22691 void
22692func_dump_profile(fd)
22693 FILE *fd;
22694{
22695 hashitem_T *hi;
22696 int todo;
22697 ufunc_T *fp;
22698 int i;
Bram Moolenaar73830342005-02-28 22:48:19 +000022699 ufunc_T **sorttab;
22700 int st_len = 0;
Bram Moolenaar05159a02005-02-26 23:04:13 +000022701
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000022702 todo = (int)func_hashtab.ht_used;
Bram Moolenaar61c4e2c2008-08-25 02:49:18 +000022703 if (todo == 0)
22704 return; /* nothing to dump */
22705
Bram Moolenaar73830342005-02-28 22:48:19 +000022706 sorttab = (ufunc_T **)alloc((unsigned)(sizeof(ufunc_T) * todo));
22707
Bram Moolenaar05159a02005-02-26 23:04:13 +000022708 for (hi = func_hashtab.ht_array; todo > 0; ++hi)
22709 {
22710 if (!HASHITEM_EMPTY(hi))
22711 {
22712 --todo;
22713 fp = HI2UF(hi);
22714 if (fp->uf_profiling)
22715 {
Bram Moolenaar73830342005-02-28 22:48:19 +000022716 if (sorttab != NULL)
22717 sorttab[st_len++] = fp;
22718
Bram Moolenaar05159a02005-02-26 23:04:13 +000022719 if (fp->uf_name[0] == K_SPECIAL)
22720 fprintf(fd, "FUNCTION <SNR>%s()\n", fp->uf_name + 3);
22721 else
22722 fprintf(fd, "FUNCTION %s()\n", fp->uf_name);
22723 if (fp->uf_tm_count == 1)
22724 fprintf(fd, "Called 1 time\n");
22725 else
22726 fprintf(fd, "Called %d times\n", fp->uf_tm_count);
22727 fprintf(fd, "Total time: %s\n", profile_msg(&fp->uf_tm_total));
22728 fprintf(fd, " Self time: %s\n", profile_msg(&fp->uf_tm_self));
22729 fprintf(fd, "\n");
22730 fprintf(fd, "count total (s) self (s)\n");
22731
22732 for (i = 0; i < fp->uf_lines.ga_len; ++i)
22733 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000022734 if (FUNCLINE(fp, i) == NULL)
22735 continue;
Bram Moolenaar73830342005-02-28 22:48:19 +000022736 prof_func_line(fd, fp->uf_tml_count[i],
22737 &fp->uf_tml_total[i], &fp->uf_tml_self[i], TRUE);
Bram Moolenaar05159a02005-02-26 23:04:13 +000022738 fprintf(fd, "%s\n", FUNCLINE(fp, i));
22739 }
22740 fprintf(fd, "\n");
22741 }
22742 }
22743 }
Bram Moolenaar73830342005-02-28 22:48:19 +000022744
22745 if (sorttab != NULL && st_len > 0)
22746 {
22747 qsort((void *)sorttab, (size_t)st_len, sizeof(ufunc_T *),
22748 prof_total_cmp);
22749 prof_sort_list(fd, sorttab, st_len, "TOTAL", FALSE);
22750 qsort((void *)sorttab, (size_t)st_len, sizeof(ufunc_T *),
22751 prof_self_cmp);
22752 prof_sort_list(fd, sorttab, st_len, "SELF", TRUE);
22753 }
Bram Moolenaar61c4e2c2008-08-25 02:49:18 +000022754
22755 vim_free(sorttab);
Bram Moolenaar05159a02005-02-26 23:04:13 +000022756}
Bram Moolenaar73830342005-02-28 22:48:19 +000022757
22758 static void
22759prof_sort_list(fd, sorttab, st_len, title, prefer_self)
22760 FILE *fd;
22761 ufunc_T **sorttab;
22762 int st_len;
22763 char *title;
22764 int prefer_self; /* when equal print only self time */
22765{
22766 int i;
22767 ufunc_T *fp;
22768
22769 fprintf(fd, "FUNCTIONS SORTED ON %s TIME\n", title);
22770 fprintf(fd, "count total (s) self (s) function\n");
22771 for (i = 0; i < 20 && i < st_len; ++i)
22772 {
22773 fp = sorttab[i];
22774 prof_func_line(fd, fp->uf_tm_count, &fp->uf_tm_total, &fp->uf_tm_self,
22775 prefer_self);
22776 if (fp->uf_name[0] == K_SPECIAL)
22777 fprintf(fd, " <SNR>%s()\n", fp->uf_name + 3);
22778 else
22779 fprintf(fd, " %s()\n", fp->uf_name);
22780 }
22781 fprintf(fd, "\n");
22782}
22783
22784/*
22785 * Print the count and times for one function or function line.
22786 */
22787 static void
22788prof_func_line(fd, count, total, self, prefer_self)
22789 FILE *fd;
22790 int count;
22791 proftime_T *total;
22792 proftime_T *self;
22793 int prefer_self; /* when equal print only self time */
22794{
22795 if (count > 0)
22796 {
22797 fprintf(fd, "%5d ", count);
22798 if (prefer_self && profile_equal(total, self))
22799 fprintf(fd, " ");
22800 else
22801 fprintf(fd, "%s ", profile_msg(total));
22802 if (!prefer_self && profile_equal(total, self))
22803 fprintf(fd, " ");
22804 else
22805 fprintf(fd, "%s ", profile_msg(self));
22806 }
22807 else
22808 fprintf(fd, " ");
22809}
22810
22811/*
22812 * Compare function for total time sorting.
22813 */
22814 static int
22815#ifdef __BORLANDC__
22816_RTLENTRYF
22817#endif
22818prof_total_cmp(s1, s2)
22819 const void *s1;
22820 const void *s2;
22821{
22822 ufunc_T *p1, *p2;
22823
22824 p1 = *(ufunc_T **)s1;
22825 p2 = *(ufunc_T **)s2;
22826 return profile_cmp(&p1->uf_tm_total, &p2->uf_tm_total);
22827}
22828
22829/*
22830 * Compare function for self time sorting.
22831 */
22832 static int
22833#ifdef __BORLANDC__
22834_RTLENTRYF
22835#endif
22836prof_self_cmp(s1, s2)
22837 const void *s1;
22838 const void *s2;
22839{
22840 ufunc_T *p1, *p2;
22841
22842 p1 = *(ufunc_T **)s1;
22843 p2 = *(ufunc_T **)s2;
22844 return profile_cmp(&p1->uf_tm_self, &p2->uf_tm_self);
22845}
22846
Bram Moolenaar05159a02005-02-26 23:04:13 +000022847#endif
22848
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000022849/*
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022850 * If "name" has a package name try autoloading the script for it.
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000022851 * Return TRUE if a package was loaded.
22852 */
Bram Moolenaar018acca2013-05-30 13:37:28 +020022853 static int
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000022854script_autoload(name, reload)
22855 char_u *name;
22856 int reload; /* load script again when already loaded */
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000022857{
22858 char_u *p;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000022859 char_u *scriptname, *tofree;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000022860 int ret = FALSE;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000022861 int i;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000022862
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000022863 /* If there is no '#' after name[0] there is no package name. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000022864 p = vim_strchr(name, AUTOLOAD_CHAR);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000022865 if (p == NULL || p == name)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000022866 return FALSE;
22867
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000022868 tofree = scriptname = autoload_name(name);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022869
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000022870 /* Find the name in the list of previously loaded package names. Skip
22871 * "autoload/", it's always the same. */
22872 for (i = 0; i < ga_loaded.ga_len; ++i)
22873 if (STRCMP(((char_u **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0)
22874 break;
22875 if (!reload && i < ga_loaded.ga_len)
22876 ret = FALSE; /* was loaded already */
22877 else
22878 {
22879 /* Remember the name if it wasn't loaded already. */
22880 if (i == ga_loaded.ga_len && ga_grow(&ga_loaded, 1) == OK)
22881 {
22882 ((char_u **)ga_loaded.ga_data)[ga_loaded.ga_len++] = scriptname;
22883 tofree = NULL;
22884 }
22885
22886 /* Try loading the package from $VIMRUNTIME/autoload/<name>.vim */
Bram Moolenaar90cfdbe2005-08-12 19:59:19 +000022887 if (source_runtime(scriptname, FALSE) == OK)
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000022888 ret = TRUE;
22889 }
22890
22891 vim_free(tofree);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022892 return ret;
22893}
22894
22895/*
22896 * Return the autoload script name for a function or variable name.
22897 * Returns NULL when out of memory.
22898 */
22899 static char_u *
22900autoload_name(name)
22901 char_u *name;
22902{
22903 char_u *p;
22904 char_u *scriptname;
22905
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000022906 /* Get the script file name: replace '#' with '/', append ".vim". */
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000022907 scriptname = alloc((unsigned)(STRLEN(name) + 14));
22908 if (scriptname == NULL)
22909 return FALSE;
22910 STRCPY(scriptname, "autoload/");
22911 STRCAT(scriptname, name);
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000022912 *vim_strrchr(scriptname, AUTOLOAD_CHAR) = NUL;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000022913 STRCAT(scriptname, ".vim");
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000022914 while ((p = vim_strchr(scriptname, AUTOLOAD_CHAR)) != NULL)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000022915 *p = '/';
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022916 return scriptname;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000022917}
22918
Bram Moolenaar071d4272004-06-13 20:20:40 +000022919#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
22920
22921/*
22922 * Function given to ExpandGeneric() to obtain the list of user defined
22923 * function names.
22924 */
22925 char_u *
22926get_user_func_name(xp, idx)
22927 expand_T *xp;
22928 int idx;
22929{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022930 static long_u done;
22931 static hashitem_T *hi;
22932 ufunc_T *fp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022933
22934 if (idx == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022935 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022936 done = 0;
22937 hi = func_hashtab.ht_array;
22938 }
22939 if (done < func_hashtab.ht_used)
22940 {
22941 if (done++ > 0)
22942 ++hi;
22943 while (HASHITEM_EMPTY(hi))
22944 ++hi;
22945 fp = HI2UF(hi);
22946
Bram Moolenaar195ea0f2011-11-30 14:57:31 +010022947 if (fp->uf_flags & FC_DICT)
Bram Moolenaar975261e2012-01-26 18:52:06 +010022948 return (char_u *)""; /* don't show dict functions */
Bram Moolenaar195ea0f2011-11-30 14:57:31 +010022949
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022950 if (STRLEN(fp->uf_name) + 4 >= IOSIZE)
22951 return fp->uf_name; /* prevents overflow */
Bram Moolenaar071d4272004-06-13 20:20:40 +000022952
22953 cat_func_name(IObuff, fp);
22954 if (xp->xp_context != EXPAND_USER_FUNC)
22955 {
22956 STRCAT(IObuff, "(");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022957 if (!fp->uf_varargs && fp->uf_args.ga_len == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022958 STRCAT(IObuff, ")");
22959 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000022960 return IObuff;
22961 }
22962 return NULL;
22963}
22964
22965#endif /* FEAT_CMDL_COMPL */
22966
22967/*
22968 * Copy the function name of "fp" to buffer "buf".
22969 * "buf" must be able to hold the function name plus three bytes.
22970 * Takes care of script-local function names.
22971 */
22972 static void
22973cat_func_name(buf, fp)
22974 char_u *buf;
22975 ufunc_T *fp;
22976{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022977 if (fp->uf_name[0] == K_SPECIAL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022978 {
22979 STRCPY(buf, "<SNR>");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022980 STRCAT(buf, fp->uf_name + 3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022981 }
22982 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000022983 STRCPY(buf, fp->uf_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000022984}
22985
22986/*
22987 * ":delfunction {name}"
22988 */
22989 void
22990ex_delfunction(eap)
22991 exarg_T *eap;
22992{
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022993 ufunc_T *fp = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022994 char_u *p;
22995 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000022996 funcdict_T fudi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000022997
22998 p = eap->arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000022999 name = trans_function_name(&p, eap->skip, 0, &fudi);
23000 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023001 if (name == NULL)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023002 {
23003 if (fudi.fd_dict != NULL && !eap->skip)
23004 EMSG(_(e_funcref));
Bram Moolenaar071d4272004-06-13 20:20:40 +000023005 return;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023006 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000023007 if (!ends_excmd(*skipwhite(p)))
23008 {
23009 vim_free(name);
23010 EMSG(_(e_trailing));
23011 return;
23012 }
23013 eap->nextcmd = check_nextcmd(p);
23014 if (eap->nextcmd != NULL)
23015 *p = NUL;
23016
23017 if (!eap->skip)
23018 fp = find_func(name);
23019 vim_free(name);
23020
23021 if (!eap->skip)
23022 {
23023 if (fp == NULL)
23024 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000023025 EMSG2(_(e_nofunc), eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023026 return;
23027 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023028 if (fp->uf_calls > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023029 {
23030 EMSG2(_("E131: Cannot delete function %s: It is in use"), eap->arg);
23031 return;
23032 }
23033
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023034 if (fudi.fd_dict != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023035 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023036 /* Delete the dict item that refers to the function, it will
23037 * invoke func_unref() and possibly delete the function. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000023038 dictitem_remove(fudi.fd_dict, fudi.fd_di);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023039 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023040 else
23041 func_free(fp);
23042 }
23043}
23044
23045/*
23046 * Free a function and remove it from the list of functions.
23047 */
23048 static void
23049func_free(fp)
23050 ufunc_T *fp;
23051{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023052 hashitem_T *hi;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023053
23054 /* clear this function */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023055 ga_clear_strings(&(fp->uf_args));
23056 ga_clear_strings(&(fp->uf_lines));
Bram Moolenaar05159a02005-02-26 23:04:13 +000023057#ifdef FEAT_PROFILE
23058 vim_free(fp->uf_tml_count);
23059 vim_free(fp->uf_tml_total);
23060 vim_free(fp->uf_tml_self);
23061#endif
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023062
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023063 /* remove the function from the function hashtable */
23064 hi = hash_find(&func_hashtab, UF2HIKEY(fp));
23065 if (HASHITEM_EMPTY(hi))
23066 EMSG2(_(e_intern2), "func_free()");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023067 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023068 hash_remove(&func_hashtab, hi);
23069
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023070 vim_free(fp);
23071}
23072
23073/*
23074 * Unreference a Function: decrement the reference count and free it when it
23075 * becomes zero. Only for numbered functions.
23076 */
Bram Moolenaardb913952012-06-29 12:54:53 +020023077 void
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023078func_unref(name)
23079 char_u *name;
23080{
23081 ufunc_T *fp;
23082
23083 if (name != NULL && isdigit(*name))
23084 {
23085 fp = find_func(name);
23086 if (fp == NULL)
23087 EMSG2(_(e_intern2), "func_unref()");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023088 else if (--fp->uf_refcount <= 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023089 {
23090 /* Only delete it when it's not being used. Otherwise it's done
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023091 * when "uf_calls" becomes zero. */
23092 if (fp->uf_calls == 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023093 func_free(fp);
23094 }
23095 }
23096}
23097
23098/*
23099 * Count a reference to a Function.
23100 */
Bram Moolenaardb913952012-06-29 12:54:53 +020023101 void
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000023102func_ref(name)
23103 char_u *name;
23104{
23105 ufunc_T *fp;
23106
23107 if (name != NULL && isdigit(*name))
23108 {
23109 fp = find_func(name);
23110 if (fp == NULL)
23111 EMSG2(_(e_intern2), "func_ref()");
23112 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023113 ++fp->uf_refcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023114 }
23115}
23116
23117/*
23118 * Call a user function.
23119 */
23120 static void
Bram Moolenaare9a41262005-01-15 22:18:47 +000023121call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023122 ufunc_T *fp; /* pointer to function */
23123 int argcount; /* nr of args */
Bram Moolenaar33570922005-01-25 22:26:29 +000023124 typval_T *argvars; /* arguments */
23125 typval_T *rettv; /* return value */
Bram Moolenaar071d4272004-06-13 20:20:40 +000023126 linenr_T firstline; /* first line of range */
23127 linenr_T lastline; /* last line of range */
Bram Moolenaar33570922005-01-25 22:26:29 +000023128 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000023129{
Bram Moolenaar33570922005-01-25 22:26:29 +000023130 char_u *save_sourcing_name;
23131 linenr_T save_sourcing_lnum;
23132 scid_T save_current_SID;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023133 funccall_T *fc;
Bram Moolenaar33570922005-01-25 22:26:29 +000023134 int save_did_emsg;
23135 static int depth = 0;
23136 dictitem_T *v;
23137 int fixvar_idx = 0; /* index in fixvar[] */
23138 int i;
23139 int ai;
23140 char_u numbuf[NUMBUFLEN];
23141 char_u *name;
Bram Moolenaar05159a02005-02-26 23:04:13 +000023142#ifdef FEAT_PROFILE
23143 proftime_T wait_start;
Bram Moolenaare9da72e2006-11-01 17:34:40 +000023144 proftime_T call_start;
Bram Moolenaar05159a02005-02-26 23:04:13 +000023145#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000023146
23147 /* If depth of calling is getting too high, don't execute the function */
23148 if (depth >= p_mfd)
23149 {
23150 EMSG(_("E132: Function call depth is higher than 'maxfuncdepth'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023151 rettv->v_type = VAR_NUMBER;
23152 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023153 return;
23154 }
23155 ++depth;
23156
23157 line_breakcheck(); /* check for CTRL-C hit */
23158
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023159 fc = (funccall_T *)alloc(sizeof(funccall_T));
23160 fc->caller = current_funccal;
23161 current_funccal = fc;
23162 fc->func = fp;
23163 fc->rettv = rettv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023164 rettv->vval.v_number = 0;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023165 fc->linenr = 0;
23166 fc->returned = FALSE;
23167 fc->level = ex_nesting_level;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023168 /* Check if this function has a breakpoint. */
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023169 fc->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0);
23170 fc->dbg_tick = debug_tick;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023171
Bram Moolenaar33570922005-01-25 22:26:29 +000023172 /*
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023173 * Note about using fc->fixvar[]: This is an array of FIXVAR_CNT variables
Bram Moolenaar33570922005-01-25 22:26:29 +000023174 * with names up to VAR_SHORT_LEN long. This avoids having to alloc/free
23175 * each argument variable and saves a lot of time.
23176 */
23177 /*
23178 * Init l: variables.
23179 */
Bram Moolenaarbdb62052012-07-16 17:31:53 +020023180 init_var_dict(&fc->l_vars, &fc->l_vars_var, VAR_DEF_SCOPE);
Bram Moolenaara7043832005-01-21 11:56:39 +000023181 if (selfdict != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000023182 {
Bram Moolenaar76b92b22006-03-24 22:46:53 +000023183 /* Set l:self to "selfdict". Use "name" to avoid a warning from
23184 * some compiler that checks the destination size. */
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023185 v = &fc->fixvar[fixvar_idx++].var;
Bram Moolenaar76b92b22006-03-24 22:46:53 +000023186 name = v->di_key;
23187 STRCPY(name, "self");
Bram Moolenaar33570922005-01-25 22:26:29 +000023188 v->di_flags = DI_FLAGS_RO + DI_FLAGS_FIX;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023189 hash_add(&fc->l_vars.dv_hashtab, DI2HIKEY(v));
Bram Moolenaar33570922005-01-25 22:26:29 +000023190 v->di_tv.v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000023191 v->di_tv.v_lock = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000023192 v->di_tv.vval.v_dict = selfdict;
23193 ++selfdict->dv_refcount;
23194 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000023195
Bram Moolenaar33570922005-01-25 22:26:29 +000023196 /*
23197 * Init a: variables.
23198 * Set a:0 to "argcount".
23199 * Set a:000 to a list with room for the "..." arguments.
23200 */
Bram Moolenaarbdb62052012-07-16 17:31:53 +020023201 init_var_dict(&fc->l_avars, &fc->l_avars_var, VAR_SCOPE);
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023202 add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "0",
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023203 (varnumber_T)(argcount - fp->uf_args.ga_len));
Bram Moolenaar0cd49302008-11-20 09:37:01 +000023204 /* Use "name" to avoid a warning from some compiler that checks the
23205 * destination size. */
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023206 v = &fc->fixvar[fixvar_idx++].var;
Bram Moolenaar0cd49302008-11-20 09:37:01 +000023207 name = v->di_key;
23208 STRCPY(name, "000");
Bram Moolenaar33570922005-01-25 22:26:29 +000023209 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023210 hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v));
Bram Moolenaar33570922005-01-25 22:26:29 +000023211 v->di_tv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000023212 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023213 v->di_tv.vval.v_list = &fc->l_varlist;
23214 vim_memset(&fc->l_varlist, 0, sizeof(list_T));
23215 fc->l_varlist.lv_refcount = DO_NOT_FREE_CNT;
23216 fc->l_varlist.lv_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000023217
23218 /*
23219 * Set a:firstline to "firstline" and a:lastline to "lastline".
23220 * Set a:name to named arguments.
23221 * Set a:N to the "..." arguments.
23222 */
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023223 add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "firstline",
Bram Moolenaar33570922005-01-25 22:26:29 +000023224 (varnumber_T)firstline);
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023225 add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "lastline",
Bram Moolenaar33570922005-01-25 22:26:29 +000023226 (varnumber_T)lastline);
23227 for (i = 0; i < argcount; ++i)
23228 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023229 ai = i - fp->uf_args.ga_len;
Bram Moolenaar33570922005-01-25 22:26:29 +000023230 if (ai < 0)
23231 /* named argument a:name */
23232 name = FUNCARG(fp, i);
23233 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000023234 {
Bram Moolenaar33570922005-01-25 22:26:29 +000023235 /* "..." argument a:1, a:2, etc. */
23236 sprintf((char *)numbuf, "%d", ai + 1);
23237 name = numbuf;
23238 }
23239 if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN)
23240 {
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023241 v = &fc->fixvar[fixvar_idx++].var;
Bram Moolenaar33570922005-01-25 22:26:29 +000023242 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
23243 }
23244 else
23245 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000023246 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
23247 + STRLEN(name)));
Bram Moolenaar33570922005-01-25 22:26:29 +000023248 if (v == NULL)
23249 break;
23250 v->di_flags = DI_FLAGS_RO;
23251 }
23252 STRCPY(v->di_key, name);
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023253 hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v));
Bram Moolenaar33570922005-01-25 22:26:29 +000023254
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000023255 /* Note: the values are copied directly to avoid alloc/free.
23256 * "argvars" must have VAR_FIXED for v_lock. */
Bram Moolenaar33570922005-01-25 22:26:29 +000023257 v->di_tv = argvars[i];
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000023258 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000023259
23260 if (ai >= 0 && ai < MAX_FUNC_ARGS)
23261 {
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023262 list_append(&fc->l_varlist, &fc->l_listitems[ai]);
23263 fc->l_listitems[ai].li_tv = argvars[i];
23264 fc->l_listitems[ai].li_tv.v_lock = VAR_FIXED;
Bram Moolenaare9a41262005-01-15 22:18:47 +000023265 }
23266 }
23267
Bram Moolenaar071d4272004-06-13 20:20:40 +000023268 /* Don't redraw while executing the function. */
23269 ++RedrawingDisabled;
23270 save_sourcing_name = sourcing_name;
23271 save_sourcing_lnum = sourcing_lnum;
23272 sourcing_lnum = 1;
23273 sourcing_name = alloc((unsigned)((save_sourcing_name == NULL ? 0
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023274 : STRLEN(save_sourcing_name)) + STRLEN(fp->uf_name) + 13));
Bram Moolenaar071d4272004-06-13 20:20:40 +000023275 if (sourcing_name != NULL)
23276 {
23277 if (save_sourcing_name != NULL
23278 && STRNCMP(save_sourcing_name, "function ", 9) == 0)
23279 sprintf((char *)sourcing_name, "%s..", save_sourcing_name);
23280 else
23281 STRCPY(sourcing_name, "function ");
23282 cat_func_name(sourcing_name + STRLEN(sourcing_name), fp);
23283
23284 if (p_verbose >= 12)
23285 {
23286 ++no_wait_return;
Bram Moolenaar54ee7752005-05-31 22:22:17 +000023287 verbose_enter_scroll();
23288
Bram Moolenaar555b2802005-05-19 21:08:39 +000023289 smsg((char_u *)_("calling %s"), sourcing_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023290 if (p_verbose >= 14)
23291 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000023292 char_u buf[MSG_BUF_LEN];
Bram Moolenaar89d40322006-08-29 15:30:07 +000023293 char_u numbuf2[NUMBUFLEN];
Bram Moolenaar758711c2005-02-02 23:11:38 +000023294 char_u *tofree;
Bram Moolenaar92c5aba2007-08-14 20:29:31 +000023295 char_u *s;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023296
23297 msg_puts((char_u *)"(");
23298 for (i = 0; i < argcount; ++i)
23299 {
23300 if (i > 0)
23301 msg_puts((char_u *)", ");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000023302 if (argvars[i].v_type == VAR_NUMBER)
23303 msg_outnum((long)argvars[i].vval.v_number);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023304 else
23305 {
Bram Moolenaar92c5aba2007-08-14 20:29:31 +000023306 s = tv2string(&argvars[i], &tofree, numbuf2, 0);
23307 if (s != NULL)
23308 {
Bram Moolenaarf31b7642012-01-20 20:44:43 +010023309 if (vim_strsize(s) > MSG_BUF_CLEN)
23310 {
23311 trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN);
23312 s = buf;
23313 }
23314 msg_puts(s);
Bram Moolenaar92c5aba2007-08-14 20:29:31 +000023315 vim_free(tofree);
23316 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000023317 }
23318 }
23319 msg_puts((char_u *)")");
23320 }
23321 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaar54ee7752005-05-31 22:22:17 +000023322
23323 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000023324 --no_wait_return;
23325 }
23326 }
Bram Moolenaar05159a02005-02-26 23:04:13 +000023327#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +000023328 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +000023329 {
23330 if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL))
23331 func_do_profile(fp);
23332 if (fp->uf_profiling
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023333 || (fc->caller != NULL && fc->caller->func->uf_profiling))
Bram Moolenaar05159a02005-02-26 23:04:13 +000023334 {
23335 ++fp->uf_tm_count;
Bram Moolenaare9da72e2006-11-01 17:34:40 +000023336 profile_start(&call_start);
Bram Moolenaar05159a02005-02-26 23:04:13 +000023337 profile_zero(&fp->uf_tm_children);
23338 }
23339 script_prof_save(&wait_start);
23340 }
23341#endif
23342
Bram Moolenaar071d4272004-06-13 20:20:40 +000023343 save_current_SID = current_SID;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023344 current_SID = fp->uf_script_ID;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023345 save_did_emsg = did_emsg;
23346 did_emsg = FALSE;
23347
23348 /* call do_cmdline() to execute the lines */
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023349 do_cmdline(NULL, get_func_line, (void *)fc,
Bram Moolenaar071d4272004-06-13 20:20:40 +000023350 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
23351
23352 --RedrawingDisabled;
23353
23354 /* when the function was aborted because of an error, return -1 */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023355 if ((did_emsg && (fp->uf_flags & FC_ABORT)) || rettv->v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023356 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023357 clear_tv(rettv);
23358 rettv->v_type = VAR_NUMBER;
23359 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023360 }
23361
Bram Moolenaar05159a02005-02-26 23:04:13 +000023362#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +000023363 if (do_profiling == PROF_YES && (fp->uf_profiling
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023364 || (fc->caller != NULL && fc->caller->func->uf_profiling)))
Bram Moolenaar05159a02005-02-26 23:04:13 +000023365 {
Bram Moolenaare9da72e2006-11-01 17:34:40 +000023366 profile_end(&call_start);
23367 profile_sub_wait(&wait_start, &call_start);
23368 profile_add(&fp->uf_tm_total, &call_start);
23369 profile_self(&fp->uf_tm_self, &call_start, &fp->uf_tm_children);
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023370 if (fc->caller != NULL && fc->caller->func->uf_profiling)
Bram Moolenaar05159a02005-02-26 23:04:13 +000023371 {
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023372 profile_add(&fc->caller->func->uf_tm_children, &call_start);
23373 profile_add(&fc->caller->func->uf_tml_children, &call_start);
Bram Moolenaar05159a02005-02-26 23:04:13 +000023374 }
23375 }
23376#endif
23377
Bram Moolenaar071d4272004-06-13 20:20:40 +000023378 /* when being verbose, mention the return value */
23379 if (p_verbose >= 12)
23380 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000023381 ++no_wait_return;
Bram Moolenaar54ee7752005-05-31 22:22:17 +000023382 verbose_enter_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000023383
Bram Moolenaar071d4272004-06-13 20:20:40 +000023384 if (aborting())
Bram Moolenaar555b2802005-05-19 21:08:39 +000023385 smsg((char_u *)_("%s aborted"), sourcing_name);
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023386 else if (fc->rettv->v_type == VAR_NUMBER)
Bram Moolenaar555b2802005-05-19 21:08:39 +000023387 smsg((char_u *)_("%s returning #%ld"), sourcing_name,
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023388 (long)fc->rettv->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +000023389 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000023390 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000023391 char_u buf[MSG_BUF_LEN];
Bram Moolenaar89d40322006-08-29 15:30:07 +000023392 char_u numbuf2[NUMBUFLEN];
Bram Moolenaar758711c2005-02-02 23:11:38 +000023393 char_u *tofree;
Bram Moolenaar92c5aba2007-08-14 20:29:31 +000023394 char_u *s;
Bram Moolenaar758711c2005-02-02 23:11:38 +000023395
Bram Moolenaar555b2802005-05-19 21:08:39 +000023396 /* The value may be very long. Skip the middle part, so that we
23397 * have some idea how it starts and ends. smsg() would always
23398 * truncate it at the end. */
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023399 s = tv2string(fc->rettv, &tofree, numbuf2, 0);
Bram Moolenaar92c5aba2007-08-14 20:29:31 +000023400 if (s != NULL)
23401 {
Bram Moolenaarf31b7642012-01-20 20:44:43 +010023402 if (vim_strsize(s) > MSG_BUF_CLEN)
23403 {
23404 trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN);
23405 s = buf;
23406 }
23407 smsg((char_u *)_("%s returning %s"), sourcing_name, s);
Bram Moolenaar92c5aba2007-08-14 20:29:31 +000023408 vim_free(tofree);
23409 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000023410 }
23411 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaar54ee7752005-05-31 22:22:17 +000023412
23413 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000023414 --no_wait_return;
23415 }
23416
23417 vim_free(sourcing_name);
23418 sourcing_name = save_sourcing_name;
23419 sourcing_lnum = save_sourcing_lnum;
23420 current_SID = save_current_SID;
Bram Moolenaar05159a02005-02-26 23:04:13 +000023421#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +000023422 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +000023423 script_prof_restore(&wait_start);
23424#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000023425
23426 if (p_verbose >= 12 && sourcing_name != NULL)
23427 {
23428 ++no_wait_return;
Bram Moolenaar54ee7752005-05-31 22:22:17 +000023429 verbose_enter_scroll();
23430
Bram Moolenaar555b2802005-05-19 21:08:39 +000023431 smsg((char_u *)_("continuing in %s"), sourcing_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023432 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaar54ee7752005-05-31 22:22:17 +000023433
23434 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000023435 --no_wait_return;
23436 }
23437
23438 did_emsg |= save_did_emsg;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023439 current_funccal = fc->caller;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023440 --depth;
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023441
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +000023442 /* If the a:000 list and the l: and a: dicts are not referenced we can
23443 * free the funccall_T and what's in it. */
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023444 if (fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT
23445 && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT
23446 && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT)
23447 {
23448 free_funccal(fc, FALSE);
23449 }
23450 else
23451 {
23452 hashitem_T *hi;
23453 listitem_T *li;
23454 int todo;
23455
23456 /* "fc" is still in use. This can happen when returning "a:000" or
23457 * assigning "l:" to a global variable.
23458 * Link "fc" in the list for garbage collection later. */
23459 fc->caller = previous_funccal;
23460 previous_funccal = fc;
23461
23462 /* Make a copy of the a: variables, since we didn't do that above. */
23463 todo = (int)fc->l_avars.dv_hashtab.ht_used;
23464 for (hi = fc->l_avars.dv_hashtab.ht_array; todo > 0; ++hi)
23465 {
23466 if (!HASHITEM_EMPTY(hi))
23467 {
23468 --todo;
23469 v = HI2DI(hi);
23470 copy_tv(&v->di_tv, &v->di_tv);
23471 }
23472 }
23473
23474 /* Make a copy of the a:000 items, since we didn't do that above. */
23475 for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next)
23476 copy_tv(&li->li_tv, &li->li_tv);
23477 }
23478}
23479
23480/*
23481 * Return TRUE if items in "fc" do not have "copyID". That means they are not
Bram Moolenaarc0a6fac2009-05-24 11:40:58 +000023482 * referenced from anywhere that is in use.
Bram Moolenaar8ba1bd22008-12-23 22:52:58 +000023483 */
23484 static int
23485can_free_funccal(fc, copyID)
23486 funccall_T *fc;
23487 int copyID;
23488{
23489 return (fc->l_varlist.lv_copyID != copyID
23490 && fc->l_vars.dv_copyID != copyID
23491 && fc->l_avars.dv_copyID != copyID);
23492}
23493
23494/*
23495 * Free "fc" and what it contains.
23496 */
23497 static void
23498free_funccal(fc, free_val)
23499 funccall_T *fc;
23500 int free_val; /* a: vars were allocated */
23501{
23502 listitem_T *li;
23503
23504 /* The a: variables typevals may not have been allocated, only free the
23505 * allocated variables. */
23506 vars_clear_ext(&fc->l_avars.dv_hashtab, free_val);
23507
23508 /* free all l: variables */
23509 vars_clear(&fc->l_vars.dv_hashtab);
23510
23511 /* Free the a:000 variables if they were allocated. */
23512 if (free_val)
23513 for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next)
23514 clear_tv(&li->li_tv);
23515
23516 vim_free(fc);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023517}
23518
23519/*
Bram Moolenaar33570922005-01-25 22:26:29 +000023520 * Add a number variable "name" to dict "dp" with value "nr".
23521 */
23522 static void
23523add_nr_var(dp, v, name, nr)
23524 dict_T *dp;
23525 dictitem_T *v;
23526 char *name;
23527 varnumber_T nr;
23528{
23529 STRCPY(v->di_key, name);
23530 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
23531 hash_add(&dp->dv_hashtab, DI2HIKEY(v));
23532 v->di_tv.v_type = VAR_NUMBER;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000023533 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000023534 v->di_tv.vval.v_number = nr;
23535}
23536
23537/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000023538 * ":return [expr]"
23539 */
23540 void
23541ex_return(eap)
23542 exarg_T *eap;
23543{
23544 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000023545 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023546 int returning = FALSE;
23547
23548 if (current_funccal == NULL)
23549 {
23550 EMSG(_("E133: :return not inside a function"));
23551 return;
23552 }
23553
23554 if (eap->skip)
23555 ++emsg_skip;
23556
23557 eap->nextcmd = NULL;
23558 if ((*arg != NUL && *arg != '|' && *arg != '\n')
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023559 && eval0(arg, &rettv, &eap->nextcmd, !eap->skip) != FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023560 {
23561 if (!eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023562 returning = do_return(eap, FALSE, TRUE, &rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023563 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023564 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023565 }
23566 /* It's safer to return also on error. */
23567 else if (!eap->skip)
23568 {
23569 /*
23570 * Return unless the expression evaluation has been cancelled due to an
23571 * aborting error, an interrupt, or an exception.
23572 */
23573 if (!aborting())
23574 returning = do_return(eap, FALSE, TRUE, NULL);
23575 }
23576
23577 /* When skipping or the return gets pending, advance to the next command
23578 * in this line (!returning). Otherwise, ignore the rest of the line.
23579 * Following lines will be ignored by get_func_line(). */
23580 if (returning)
23581 eap->nextcmd = NULL;
23582 else if (eap->nextcmd == NULL) /* no argument */
23583 eap->nextcmd = check_nextcmd(arg);
23584
23585 if (eap->skip)
23586 --emsg_skip;
23587}
23588
23589/*
23590 * Return from a function. Possibly makes the return pending. Also called
23591 * for a pending return at the ":endtry" or after returning from an extra
23592 * do_cmdline(). "reanimate" is used in the latter case. "is_cmd" is set
Bram Moolenaar33570922005-01-25 22:26:29 +000023593 * when called due to a ":return" command. "rettv" may point to a typval_T
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023594 * with the return rettv. Returns TRUE when the return can be carried out,
Bram Moolenaar071d4272004-06-13 20:20:40 +000023595 * FALSE when the return gets pending.
23596 */
23597 int
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023598do_return(eap, reanimate, is_cmd, rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023599 exarg_T *eap;
23600 int reanimate;
23601 int is_cmd;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023602 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023603{
23604 int idx;
23605 struct condstack *cstack = eap->cstack;
23606
23607 if (reanimate)
23608 /* Undo the return. */
23609 current_funccal->returned = FALSE;
23610
23611 /*
23612 * Cleanup (and inactivate) conditionals, but stop when a try conditional
23613 * not in its finally clause (which then is to be executed next) is found.
23614 * In this case, make the ":return" pending for execution at the ":endtry".
23615 * Otherwise, return normally.
23616 */
23617 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
23618 if (idx >= 0)
23619 {
23620 cstack->cs_pending[idx] = CSTP_RETURN;
23621
23622 if (!is_cmd && !reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023623 /* A pending return again gets pending. "rettv" points to an
23624 * allocated variable with the rettv of the original ":return"'s
Bram Moolenaar071d4272004-06-13 20:20:40 +000023625 * argument if present or is NULL else. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023626 cstack->cs_rettv[idx] = rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023627 else
23628 {
23629 /* When undoing a return in order to make it pending, get the stored
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023630 * return rettv. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000023631 if (reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023632 rettv = current_funccal->rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023633
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023634 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023635 {
23636 /* Store the value of the pending return. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023637 if ((cstack->cs_rettv[idx] = alloc_tv()) != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000023638 *(typval_T *)cstack->cs_rettv[idx] = *(typval_T *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023639 else
23640 EMSG(_(e_outofmem));
23641 }
23642 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023643 cstack->cs_rettv[idx] = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023644
23645 if (reanimate)
23646 {
23647 /* The pending return value could be overwritten by a ":return"
23648 * without argument in a finally clause; reset the default
23649 * return value. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023650 current_funccal->rettv->v_type = VAR_NUMBER;
23651 current_funccal->rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023652 }
23653 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023654 report_make_pending(CSTP_RETURN, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023655 }
23656 else
23657 {
23658 current_funccal->returned = TRUE;
23659
23660 /* If the return is carried out now, store the return value. For
23661 * a return immediately after reanimation, the value is already
23662 * there. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023663 if (!reanimate && rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023664 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023665 clear_tv(current_funccal->rettv);
Bram Moolenaar33570922005-01-25 22:26:29 +000023666 *current_funccal->rettv = *(typval_T *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023667 if (!is_cmd)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023668 vim_free(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023669 }
23670 }
23671
23672 return idx < 0;
23673}
23674
23675/*
23676 * Free the variable with a pending return value.
23677 */
23678 void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023679discard_pending_return(rettv)
23680 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023681{
Bram Moolenaar33570922005-01-25 22:26:29 +000023682 free_tv((typval_T *)rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023683}
23684
23685/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023686 * Generate a return command for producing the value of "rettv". The result
Bram Moolenaar071d4272004-06-13 20:20:40 +000023687 * is an allocated string. Used by report_pending() for verbose messages.
23688 */
23689 char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023690get_return_cmd(rettv)
23691 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023692{
Bram Moolenaar81bf7082005-02-12 14:31:42 +000023693 char_u *s = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023694 char_u *tofree = NULL;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000023695 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000023696
Bram Moolenaar81bf7082005-02-12 14:31:42 +000023697 if (rettv != NULL)
Bram Moolenaarb71eaae2006-01-20 23:10:18 +000023698 s = echo_string((typval_T *)rettv, &tofree, numbuf, 0);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000023699 if (s == NULL)
23700 s = (char_u *)"";
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023701
23702 STRCPY(IObuff, ":return ");
23703 STRNCPY(IObuff + 8, s, IOSIZE - 8);
23704 if (STRLEN(s) + 8 >= IOSIZE)
23705 STRCPY(IObuff + IOSIZE - 4, "...");
23706 vim_free(tofree);
23707 return vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023708}
23709
23710/*
23711 * Get next function line.
23712 * Called by do_cmdline() to get the next line.
23713 * Returns allocated string, or NULL for end of function.
23714 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000023715 char_u *
23716get_func_line(c, cookie, indent)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000023717 int c UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023718 void *cookie;
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000023719 int indent UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023720{
Bram Moolenaar33570922005-01-25 22:26:29 +000023721 funccall_T *fcp = (funccall_T *)cookie;
Bram Moolenaar05159a02005-02-26 23:04:13 +000023722 ufunc_T *fp = fcp->func;
23723 char_u *retval;
23724 garray_T *gap; /* growarray with function lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +000023725
23726 /* If breakpoints have been added/deleted need to check for it. */
23727 if (fcp->dbg_tick != debug_tick)
23728 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000023729 fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
Bram Moolenaar071d4272004-06-13 20:20:40 +000023730 sourcing_lnum);
23731 fcp->dbg_tick = debug_tick;
23732 }
Bram Moolenaar05159a02005-02-26 23:04:13 +000023733#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +000023734 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +000023735 func_line_end(cookie);
23736#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000023737
Bram Moolenaar05159a02005-02-26 23:04:13 +000023738 gap = &fp->uf_lines;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000023739 if (((fp->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
23740 || fcp->returned)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023741 retval = NULL;
23742 else
23743 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000023744 /* Skip NULL lines (continuation lines). */
23745 while (fcp->linenr < gap->ga_len
23746 && ((char_u **)(gap->ga_data))[fcp->linenr] == NULL)
23747 ++fcp->linenr;
23748 if (fcp->linenr >= gap->ga_len)
23749 retval = NULL;
23750 else
23751 {
23752 retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]);
23753 sourcing_lnum = fcp->linenr;
Bram Moolenaar05159a02005-02-26 23:04:13 +000023754#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +000023755 if (do_profiling == PROF_YES)
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000023756 func_line_start(cookie);
Bram Moolenaar05159a02005-02-26 23:04:13 +000023757#endif
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000023758 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000023759 }
23760
23761 /* Did we encounter a breakpoint? */
23762 if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum)
23763 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000023764 dbg_breakpoint(fp->uf_name, sourcing_lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023765 /* Find next breakpoint. */
Bram Moolenaar05159a02005-02-26 23:04:13 +000023766 fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
Bram Moolenaar071d4272004-06-13 20:20:40 +000023767 sourcing_lnum);
23768 fcp->dbg_tick = debug_tick;
23769 }
23770
23771 return retval;
23772}
23773
Bram Moolenaar05159a02005-02-26 23:04:13 +000023774#if defined(FEAT_PROFILE) || defined(PROTO)
23775/*
23776 * Called when starting to read a function line.
23777 * "sourcing_lnum" must be correct!
23778 * When skipping lines it may not actually be executed, but we won't find out
23779 * until later and we need to store the time now.
23780 */
23781 void
23782func_line_start(cookie)
23783 void *cookie;
23784{
23785 funccall_T *fcp = (funccall_T *)cookie;
23786 ufunc_T *fp = fcp->func;
23787
23788 if (fp->uf_profiling && sourcing_lnum >= 1
23789 && sourcing_lnum <= fp->uf_lines.ga_len)
23790 {
23791 fp->uf_tml_idx = sourcing_lnum - 1;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000023792 /* Skip continuation lines. */
23793 while (fp->uf_tml_idx > 0 && FUNCLINE(fp, fp->uf_tml_idx) == NULL)
23794 --fp->uf_tml_idx;
Bram Moolenaar05159a02005-02-26 23:04:13 +000023795 fp->uf_tml_execed = FALSE;
23796 profile_start(&fp->uf_tml_start);
23797 profile_zero(&fp->uf_tml_children);
23798 profile_get_wait(&fp->uf_tml_wait);
23799 }
23800}
23801
23802/*
23803 * Called when actually executing a function line.
23804 */
23805 void
23806func_line_exec(cookie)
23807 void *cookie;
23808{
23809 funccall_T *fcp = (funccall_T *)cookie;
23810 ufunc_T *fp = fcp->func;
23811
23812 if (fp->uf_profiling && fp->uf_tml_idx >= 0)
23813 fp->uf_tml_execed = TRUE;
23814}
23815
23816/*
23817 * Called when done with a function line.
23818 */
23819 void
23820func_line_end(cookie)
23821 void *cookie;
23822{
23823 funccall_T *fcp = (funccall_T *)cookie;
23824 ufunc_T *fp = fcp->func;
23825
23826 if (fp->uf_profiling && fp->uf_tml_idx >= 0)
23827 {
23828 if (fp->uf_tml_execed)
23829 {
23830 ++fp->uf_tml_count[fp->uf_tml_idx];
23831 profile_end(&fp->uf_tml_start);
23832 profile_sub_wait(&fp->uf_tml_wait, &fp->uf_tml_start);
Bram Moolenaar05159a02005-02-26 23:04:13 +000023833 profile_add(&fp->uf_tml_total[fp->uf_tml_idx], &fp->uf_tml_start);
Bram Moolenaar1056d982006-03-09 22:37:52 +000023834 profile_self(&fp->uf_tml_self[fp->uf_tml_idx], &fp->uf_tml_start,
23835 &fp->uf_tml_children);
Bram Moolenaar05159a02005-02-26 23:04:13 +000023836 }
23837 fp->uf_tml_idx = -1;
23838 }
23839}
23840#endif
23841
Bram Moolenaar071d4272004-06-13 20:20:40 +000023842/*
23843 * Return TRUE if the currently active function should be ended, because a
Bram Moolenaar8c8de832008-06-24 22:58:06 +000023844 * return was encountered or an error occurred. Used inside a ":while".
Bram Moolenaar071d4272004-06-13 20:20:40 +000023845 */
23846 int
23847func_has_ended(cookie)
23848 void *cookie;
23849{
Bram Moolenaar33570922005-01-25 22:26:29 +000023850 funccall_T *fcp = (funccall_T *)cookie;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023851
23852 /* Ignore the "abort" flag if the abortion behavior has been changed due to
23853 * an error inside a try conditional. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023854 return (((fcp->func->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
Bram Moolenaar071d4272004-06-13 20:20:40 +000023855 || fcp->returned);
23856}
23857
23858/*
23859 * return TRUE if cookie indicates a function which "abort"s on errors.
23860 */
23861 int
23862func_has_abort(cookie)
23863 void *cookie;
23864{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000023865 return ((funccall_T *)cookie)->func->uf_flags & FC_ABORT;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023866}
23867
23868#if defined(FEAT_VIMINFO) || defined(FEAT_SESSION)
23869typedef enum
23870{
Bram Moolenaar8c8de832008-06-24 22:58:06 +000023871 VAR_FLAVOUR_DEFAULT, /* doesn't start with uppercase */
23872 VAR_FLAVOUR_SESSION, /* starts with uppercase, some lower */
23873 VAR_FLAVOUR_VIMINFO /* all uppercase */
Bram Moolenaar071d4272004-06-13 20:20:40 +000023874} var_flavour_T;
23875
23876static var_flavour_T var_flavour __ARGS((char_u *varname));
23877
23878 static var_flavour_T
23879var_flavour(varname)
23880 char_u *varname;
23881{
23882 char_u *p = varname;
23883
23884 if (ASCII_ISUPPER(*p))
23885 {
23886 while (*(++p))
23887 if (ASCII_ISLOWER(*p))
23888 return VAR_FLAVOUR_SESSION;
23889 return VAR_FLAVOUR_VIMINFO;
23890 }
23891 else
23892 return VAR_FLAVOUR_DEFAULT;
23893}
23894#endif
23895
23896#if defined(FEAT_VIMINFO) || defined(PROTO)
23897/*
23898 * Restore global vars that start with a capital from the viminfo file
23899 */
23900 int
23901read_viminfo_varlist(virp, writing)
23902 vir_T *virp;
23903 int writing;
23904{
23905 char_u *tab;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000023906 int type = VAR_NUMBER;
Bram Moolenaar33570922005-01-25 22:26:29 +000023907 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000023908
23909 if (!writing && (find_viminfo_parameter('!') != NULL))
23910 {
23911 tab = vim_strchr(virp->vir_line + 1, '\t');
23912 if (tab != NULL)
23913 {
23914 *tab++ = '\0'; /* isolate the variable name */
Bram Moolenaar680eeca2010-10-20 17:44:42 +020023915 switch (*tab)
23916 {
23917 case 'S': type = VAR_STRING; break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000023918#ifdef FEAT_FLOAT
Bram Moolenaar680eeca2010-10-20 17:44:42 +020023919 case 'F': type = VAR_FLOAT; break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000023920#endif
Bram Moolenaar680eeca2010-10-20 17:44:42 +020023921 case 'D': type = VAR_DICT; break;
23922 case 'L': type = VAR_LIST; break;
23923 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000023924
23925 tab = vim_strchr(tab, '\t');
23926 if (tab != NULL)
23927 {
Bram Moolenaar8c8de832008-06-24 22:58:06 +000023928 tv.v_type = type;
Bram Moolenaar680eeca2010-10-20 17:44:42 +020023929 if (type == VAR_STRING || type == VAR_DICT || type == VAR_LIST)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000023930 tv.vval.v_string = viminfo_readstring(virp,
Bram Moolenaar071d4272004-06-13 20:20:40 +000023931 (int)(tab - virp->vir_line + 1), TRUE);
Bram Moolenaar8c8de832008-06-24 22:58:06 +000023932#ifdef FEAT_FLOAT
23933 else if (type == VAR_FLOAT)
23934 (void)string2float(tab + 1, &tv.vval.v_float);
23935#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000023936 else
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000023937 tv.vval.v_number = atol((char *)tab + 1);
Bram Moolenaar680eeca2010-10-20 17:44:42 +020023938 if (type == VAR_DICT || type == VAR_LIST)
23939 {
23940 typval_T *etv = eval_expr(tv.vval.v_string, NULL);
23941
23942 if (etv == NULL)
23943 /* Failed to parse back the dict or list, use it as a
23944 * string. */
23945 tv.v_type = VAR_STRING;
23946 else
23947 {
23948 vim_free(tv.vval.v_string);
23949 tv = *etv;
Bram Moolenaar507cc8a2012-03-23 15:37:02 +010023950 vim_free(etv);
Bram Moolenaar680eeca2010-10-20 17:44:42 +020023951 }
23952 }
23953
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000023954 set_var(virp->vir_line + 1, &tv, FALSE);
Bram Moolenaar680eeca2010-10-20 17:44:42 +020023955
23956 if (tv.v_type == VAR_STRING)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000023957 vim_free(tv.vval.v_string);
Bram Moolenaar680eeca2010-10-20 17:44:42 +020023958 else if (tv.v_type == VAR_DICT || tv.v_type == VAR_LIST)
23959 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000023960 }
23961 }
23962 }
23963
23964 return viminfo_readline(virp);
23965}
23966
23967/*
23968 * Write global vars that start with a capital to the viminfo file
23969 */
23970 void
23971write_viminfo_varlist(fp)
23972 FILE *fp;
23973{
Bram Moolenaar33570922005-01-25 22:26:29 +000023974 hashitem_T *hi;
23975 dictitem_T *this_var;
Bram Moolenaara7043832005-01-21 11:56:39 +000023976 int todo;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023977 char *s;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000023978 char_u *p;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023979 char_u *tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000023980 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000023981
23982 if (find_viminfo_parameter('!') == NULL)
23983 return;
23984
Bram Moolenaar9577c3e2010-05-14 12:16:25 +020023985 fputs(_("\n# global variables:\n"), fp);
Bram Moolenaara7043832005-01-21 11:56:39 +000023986
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000023987 todo = (int)globvarht.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +000023988 for (hi = globvarht.ht_array; todo > 0; ++hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000023989 {
Bram Moolenaara7043832005-01-21 11:56:39 +000023990 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar071d4272004-06-13 20:20:40 +000023991 {
Bram Moolenaara7043832005-01-21 11:56:39 +000023992 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000023993 this_var = HI2DI(hi);
23994 if (var_flavour(this_var->di_key) == VAR_FLAVOUR_VIMINFO)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000023995 {
Bram Moolenaar33570922005-01-25 22:26:29 +000023996 switch (this_var->di_tv.v_type)
Bram Moolenaara7043832005-01-21 11:56:39 +000023997 {
23998 case VAR_STRING: s = "STR"; break;
23999 case VAR_NUMBER: s = "NUM"; break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000024000#ifdef FEAT_FLOAT
Bram Moolenaar680eeca2010-10-20 17:44:42 +020024001 case VAR_FLOAT: s = "FLO"; break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +000024002#endif
Bram Moolenaar680eeca2010-10-20 17:44:42 +020024003 case VAR_DICT: s = "DIC"; break;
24004 case VAR_LIST: s = "LIS"; break;
Bram Moolenaara7043832005-01-21 11:56:39 +000024005 default: continue;
24006 }
Bram Moolenaar33570922005-01-25 22:26:29 +000024007 fprintf(fp, "!%s\t%s\t", this_var->di_key, s);
Bram Moolenaarb71eaae2006-01-20 23:10:18 +000024008 p = echo_string(&this_var->di_tv, &tofree, numbuf, 0);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000024009 if (p != NULL)
24010 viminfo_writestring(fp, p);
Bram Moolenaara7043832005-01-21 11:56:39 +000024011 vim_free(tofree);
24012 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000024013 }
24014 }
24015}
24016#endif
24017
24018#if defined(FEAT_SESSION) || defined(PROTO)
24019 int
24020store_session_globals(fd)
24021 FILE *fd;
24022{
Bram Moolenaar33570922005-01-25 22:26:29 +000024023 hashitem_T *hi;
24024 dictitem_T *this_var;
Bram Moolenaara7043832005-01-21 11:56:39 +000024025 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024026 char_u *p, *t;
24027
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000024028 todo = (int)globvarht.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +000024029 for (hi = globvarht.ht_array; todo > 0; ++hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024030 {
Bram Moolenaara7043832005-01-21 11:56:39 +000024031 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar071d4272004-06-13 20:20:40 +000024032 {
Bram Moolenaara7043832005-01-21 11:56:39 +000024033 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000024034 this_var = HI2DI(hi);
24035 if ((this_var->di_tv.v_type == VAR_NUMBER
24036 || this_var->di_tv.v_type == VAR_STRING)
24037 && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000024038 {
Bram Moolenaara7043832005-01-21 11:56:39 +000024039 /* Escape special characters with a backslash. Turn a LF and
24040 * CR into \n and \r. */
Bram Moolenaar33570922005-01-25 22:26:29 +000024041 p = vim_strsave_escaped(get_tv_string(&this_var->di_tv),
Bram Moolenaara7043832005-01-21 11:56:39 +000024042 (char_u *)"\\\"\n\r");
24043 if (p == NULL) /* out of memory */
24044 break;
24045 for (t = p; *t != NUL; ++t)
24046 if (*t == '\n')
24047 *t = 'n';
24048 else if (*t == '\r')
24049 *t = 'r';
24050 if ((fprintf(fd, "let %s = %c%s%c",
Bram Moolenaar33570922005-01-25 22:26:29 +000024051 this_var->di_key,
24052 (this_var->di_tv.v_type == VAR_STRING) ? '"'
24053 : ' ',
24054 p,
24055 (this_var->di_tv.v_type == VAR_STRING) ? '"'
24056 : ' ') < 0)
Bram Moolenaara7043832005-01-21 11:56:39 +000024057 || put_eol(fd) == FAIL)
24058 {
24059 vim_free(p);
24060 return FAIL;
24061 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000024062 vim_free(p);
24063 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +000024064#ifdef FEAT_FLOAT
24065 else if (this_var->di_tv.v_type == VAR_FLOAT
24066 && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION)
24067 {
24068 float_T f = this_var->di_tv.vval.v_float;
24069 int sign = ' ';
24070
24071 if (f < 0)
24072 {
24073 f = -f;
24074 sign = '-';
24075 }
Bram Moolenaar2b04b192012-01-26 11:45:30 +010024076 if ((fprintf(fd, "let %s = %c%f",
Bram Moolenaar8c8de832008-06-24 22:58:06 +000024077 this_var->di_key, sign, f) < 0)
24078 || put_eol(fd) == FAIL)
24079 return FAIL;
24080 }
24081#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000024082 }
24083 }
24084 return OK;
24085}
24086#endif
24087
Bram Moolenaar661b1822005-07-28 22:36:45 +000024088/*
24089 * Display script name where an item was last set.
24090 * Should only be invoked when 'verbose' is non-zero.
24091 */
24092 void
24093last_set_msg(scriptID)
24094 scid_T scriptID;
24095{
Bram Moolenaarcafda4f2005-09-06 19:25:11 +000024096 char_u *p;
24097
Bram Moolenaar661b1822005-07-28 22:36:45 +000024098 if (scriptID != 0)
24099 {
Bram Moolenaarcafda4f2005-09-06 19:25:11 +000024100 p = home_replace_save(NULL, get_scriptname(scriptID));
24101 if (p != NULL)
24102 {
24103 verbose_enter();
24104 MSG_PUTS(_("\n\tLast set from "));
24105 MSG_PUTS(p);
24106 vim_free(p);
24107 verbose_leave();
24108 }
Bram Moolenaar661b1822005-07-28 22:36:45 +000024109 }
24110}
24111
Bram Moolenaard812df62008-11-09 12:46:09 +000024112/*
24113 * List v:oldfiles in a nice way.
24114 */
Bram Moolenaard812df62008-11-09 12:46:09 +000024115 void
24116ex_oldfiles(eap)
Bram Moolenaaraf0167f2009-05-16 15:31:32 +000024117 exarg_T *eap UNUSED;
Bram Moolenaard812df62008-11-09 12:46:09 +000024118{
24119 list_T *l = vimvars[VV_OLDFILES].vv_list;
24120 listitem_T *li;
24121 int nr = 0;
24122
24123 if (l == NULL)
24124 msg((char_u *)_("No old files"));
24125 else
24126 {
24127 msg_start();
24128 msg_scroll = TRUE;
24129 for (li = l->lv_first; li != NULL && !got_int; li = li->li_next)
24130 {
24131 msg_outnum((long)++nr);
24132 MSG_PUTS(": ");
24133 msg_outtrans(get_tv_string(&li->li_tv));
24134 msg_putchar('\n');
24135 out_flush(); /* output one line at a time */
24136 ui_breakcheck();
24137 }
24138 /* Assume "got_int" was set to truncate the listing. */
24139 got_int = FALSE;
24140
24141#ifdef FEAT_BROWSE_CMD
24142 if (cmdmod.browse)
24143 {
24144 quit_more = FALSE;
24145 nr = prompt_for_number(FALSE);
24146 msg_starthere();
24147 if (nr > 0)
24148 {
24149 char_u *p = list_find_str(get_vim_var_list(VV_OLDFILES),
24150 (long)nr);
24151
24152 if (p != NULL)
24153 {
24154 p = expand_env_save(p);
24155 eap->arg = p;
24156 eap->cmdidx = CMD_edit;
24157 cmdmod.browse = FALSE;
24158 do_exedit(eap, NULL);
24159 vim_free(p);
24160 }
24161 }
24162 }
24163#endif
24164 }
24165}
24166
Bram Moolenaar071d4272004-06-13 20:20:40 +000024167#endif /* FEAT_EVAL */
24168
Bram Moolenaar071d4272004-06-13 20:20:40 +000024169
Bram Moolenaar8c8de832008-06-24 22:58:06 +000024170#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024171
24172#ifdef WIN3264
24173/*
24174 * Functions for ":8" filename modifier: get 8.3 version of a filename.
24175 */
24176static int get_short_pathname __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
24177static int shortpath_for_invalid_fname __ARGS((char_u **fname, char_u **bufp, int *fnamelen));
24178static int shortpath_for_partial __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
24179
24180/*
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024181 * Get the short path (8.3) for the filename in "fnamep".
24182 * Only works for a valid file name.
24183 * When the path gets longer "fnamep" is changed and the allocated buffer
24184 * is put in "bufp".
24185 * *fnamelen is the length of "fnamep" and set to 0 for a nonexistent path.
24186 * Returns OK on success, FAIL on failure.
Bram Moolenaar071d4272004-06-13 20:20:40 +000024187 */
24188 static int
24189get_short_pathname(fnamep, bufp, fnamelen)
24190 char_u **fnamep;
24191 char_u **bufp;
24192 int *fnamelen;
24193{
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024194 int l, len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024195 char_u *newbuf;
24196
24197 len = *fnamelen;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024198 l = GetShortPathName(*fnamep, *fnamep, len);
24199 if (l > len - 1)
24200 {
24201 /* If that doesn't work (not enough space), then save the string
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024202 * and try again with a new buffer big enough. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000024203 newbuf = vim_strnsave(*fnamep, l);
24204 if (newbuf == NULL)
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024205 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024206
24207 vim_free(*bufp);
24208 *fnamep = *bufp = newbuf;
24209
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024210 /* Really should always succeed, as the buffer is big enough. */
24211 l = GetShortPathName(*fnamep, *fnamep, l+1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024212 }
24213
24214 *fnamelen = l;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024215 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024216}
24217
24218/*
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024219 * Get the short path (8.3) for the filename in "fname". The converted
24220 * path is returned in "bufp".
24221 *
24222 * Some of the directories specified in "fname" may not exist. This function
24223 * will shorten the existing directories at the beginning of the path and then
24224 * append the remaining non-existing path.
24225 *
24226 * fname - Pointer to the filename to shorten. On return, contains the
Bram Moolenaar2c704a72010-06-03 21:17:25 +020024227 * pointer to the shortened pathname
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024228 * bufp - Pointer to an allocated buffer for the filename.
24229 * fnamelen - Length of the filename pointed to by fname
24230 *
24231 * Returns OK on success (or nothing done) and FAIL on failure (out of memory).
Bram Moolenaar071d4272004-06-13 20:20:40 +000024232 */
24233 static int
24234shortpath_for_invalid_fname(fname, bufp, fnamelen)
24235 char_u **fname;
24236 char_u **bufp;
24237 int *fnamelen;
24238{
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024239 char_u *short_fname, *save_fname, *pbuf_unused;
24240 char_u *endp, *save_endp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024241 char_u ch;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024242 int old_len, len;
24243 int new_len, sfx_len;
24244 int retval = OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024245
24246 /* Make a copy */
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024247 old_len = *fnamelen;
24248 save_fname = vim_strnsave(*fname, old_len);
24249 pbuf_unused = NULL;
24250 short_fname = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024251
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024252 endp = save_fname + old_len - 1; /* Find the end of the copy */
24253 save_endp = endp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024254
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024255 /*
24256 * Try shortening the supplied path till it succeeds by removing one
24257 * directory at a time from the tail of the path.
24258 */
24259 len = 0;
24260 for (;;)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024261 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024262 /* go back one path-separator */
24263 while (endp > save_fname && !after_pathsep(save_fname, endp + 1))
24264 --endp;
24265 if (endp <= save_fname)
24266 break; /* processed the complete path */
24267
24268 /*
24269 * Replace the path separator with a NUL and try to shorten the
24270 * resulting path.
24271 */
24272 ch = *endp;
24273 *endp = 0;
24274 short_fname = save_fname;
Bram Moolenaarc236c162008-07-13 17:41:49 +000024275 len = (int)STRLEN(short_fname) + 1;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024276 if (get_short_pathname(&short_fname, &pbuf_unused, &len) == FAIL)
24277 {
24278 retval = FAIL;
24279 goto theend;
24280 }
24281 *endp = ch; /* preserve the string */
24282
24283 if (len > 0)
24284 break; /* successfully shortened the path */
24285
24286 /* failed to shorten the path. Skip the path separator */
24287 --endp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024288 }
24289
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024290 if (len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024291 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024292 /*
24293 * Succeeded in shortening the path. Now concatenate the shortened
24294 * path with the remaining path at the tail.
24295 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000024296
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024297 /* Compute the length of the new path. */
24298 sfx_len = (int)(save_endp - endp) + 1;
24299 new_len = len + sfx_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024300
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024301 *fnamelen = new_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024302 vim_free(*bufp);
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024303 if (new_len > old_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024304 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024305 /* There is not enough space in the currently allocated string,
24306 * copy it to a buffer big enough. */
24307 *fname = *bufp = vim_strnsave(short_fname, new_len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024308 if (*fname == NULL)
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024309 {
24310 retval = FAIL;
24311 goto theend;
24312 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000024313 }
24314 else
24315 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024316 /* Transfer short_fname to the main buffer (it's big enough),
24317 * unless get_short_pathname() did its work in-place. */
24318 *fname = *bufp = save_fname;
24319 if (short_fname != save_fname)
24320 vim_strncpy(save_fname, short_fname, len);
24321 save_fname = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024322 }
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024323
24324 /* concat the not-shortened part of the path */
24325 vim_strncpy(*fname + len, endp, sfx_len);
24326 (*fname)[new_len] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024327 }
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024328
24329theend:
24330 vim_free(pbuf_unused);
24331 vim_free(save_fname);
24332
24333 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024334}
24335
24336/*
24337 * Get a pathname for a partial path.
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024338 * Returns OK for success, FAIL for failure.
Bram Moolenaar071d4272004-06-13 20:20:40 +000024339 */
24340 static int
24341shortpath_for_partial(fnamep, bufp, fnamelen)
24342 char_u **fnamep;
24343 char_u **bufp;
24344 int *fnamelen;
24345{
24346 int sepcount, len, tflen;
24347 char_u *p;
24348 char_u *pbuf, *tfname;
24349 int hasTilde;
24350
Bram Moolenaar8c8de832008-06-24 22:58:06 +000024351 /* Count up the path separators from the RHS.. so we know which part
24352 * of the path to return. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000024353 sepcount = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000024354 for (p = *fnamep; p < *fnamep + *fnamelen; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000024355 if (vim_ispathsep(*p))
24356 ++sepcount;
24357
24358 /* Need full path first (use expand_env() to remove a "~/") */
24359 hasTilde = (**fnamep == '~');
24360 if (hasTilde)
24361 pbuf = tfname = expand_env_save(*fnamep);
24362 else
24363 pbuf = tfname = FullName_save(*fnamep, FALSE);
24364
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000024365 len = tflen = (int)STRLEN(tfname);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024366
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024367 if (get_short_pathname(&tfname, &pbuf, &len) == FAIL)
24368 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024369
24370 if (len == 0)
24371 {
24372 /* Don't have a valid filename, so shorten the rest of the
24373 * path if we can. This CAN give us invalid 8.3 filenames, but
24374 * there's not a lot of point in guessing what it might be.
24375 */
24376 len = tflen;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024377 if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == FAIL)
24378 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024379 }
24380
24381 /* Count the paths backward to find the beginning of the desired string. */
24382 for (p = tfname + len - 1; p >= tfname; --p)
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000024383 {
24384#ifdef FEAT_MBYTE
24385 if (has_mbyte)
24386 p -= mb_head_off(tfname, p);
24387#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000024388 if (vim_ispathsep(*p))
24389 {
24390 if (sepcount == 0 || (hasTilde && sepcount == 1))
24391 break;
24392 else
24393 sepcount --;
24394 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000024395 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000024396 if (hasTilde)
24397 {
24398 --p;
24399 if (p >= tfname)
24400 *p = '~';
24401 else
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024402 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024403 }
24404 else
24405 ++p;
24406
24407 /* Copy in the string - p indexes into tfname - allocated at pbuf */
24408 vim_free(*bufp);
24409 *fnamelen = (int)STRLEN(p);
24410 *bufp = pbuf;
24411 *fnamep = p;
24412
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024413 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024414}
24415#endif /* WIN3264 */
24416
24417/*
24418 * Adjust a filename, according to a string of modifiers.
24419 * *fnamep must be NUL terminated when called. When returning, the length is
24420 * determined by *fnamelen.
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024421 * Returns VALID_ flags or -1 for failure.
Bram Moolenaar071d4272004-06-13 20:20:40 +000024422 * When there is an error, *fnamep is set to NULL.
24423 */
24424 int
24425modify_fname(src, usedlen, fnamep, bufp, fnamelen)
24426 char_u *src; /* string with modifiers */
24427 int *usedlen; /* characters after src that are used */
24428 char_u **fnamep; /* file name so far */
24429 char_u **bufp; /* buffer for allocated file name or NULL */
24430 int *fnamelen; /* length of fnamep */
24431{
24432 int valid = 0;
24433 char_u *tail;
24434 char_u *s, *p, *pbuf;
24435 char_u dirname[MAXPATHL];
24436 int c;
24437 int has_fullname = 0;
24438#ifdef WIN3264
Bram Moolenaardc935552011-08-17 15:23:23 +020024439 char_u *fname_start = *fnamep;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024440 int has_shortname = 0;
24441#endif
24442
24443repeat:
24444 /* ":p" - full path/file_name */
24445 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p')
24446 {
24447 has_fullname = 1;
24448
24449 valid |= VALID_PATH;
24450 *usedlen += 2;
24451
24452 /* Expand "~/path" for all systems and "~user/path" for Unix and VMS */
24453 if ((*fnamep)[0] == '~'
24454#if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME))
24455 && ((*fnamep)[1] == '/'
24456# ifdef BACKSLASH_IN_FILENAME
24457 || (*fnamep)[1] == '\\'
24458# endif
24459 || (*fnamep)[1] == NUL)
24460
24461#endif
24462 )
24463 {
24464 *fnamep = expand_env_save(*fnamep);
24465 vim_free(*bufp); /* free any allocated file name */
24466 *bufp = *fnamep;
24467 if (*fnamep == NULL)
24468 return -1;
24469 }
24470
24471 /* When "/." or "/.." is used: force expansion to get rid of it. */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000024472 for (p = *fnamep; *p != NUL; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000024473 {
24474 if (vim_ispathsep(*p)
24475 && p[1] == '.'
24476 && (p[2] == NUL
24477 || vim_ispathsep(p[2])
24478 || (p[2] == '.'
24479 && (p[3] == NUL || vim_ispathsep(p[3])))))
24480 break;
24481 }
24482
24483 /* FullName_save() is slow, don't use it when not needed. */
24484 if (*p != NUL || !vim_isAbsName(*fnamep))
24485 {
24486 *fnamep = FullName_save(*fnamep, *p != NUL);
24487 vim_free(*bufp); /* free any allocated file name */
24488 *bufp = *fnamep;
24489 if (*fnamep == NULL)
24490 return -1;
24491 }
24492
Bram Moolenaar9158f9e2012-06-20 14:02:27 +020024493#ifdef WIN3264
24494# if _WIN32_WINNT >= 0x0500
24495 if (vim_strchr(*fnamep, '~') != NULL)
24496 {
24497 /* Expand 8.3 filename to full path. Needed to make sure the same
24498 * file does not have two different names.
24499 * Note: problem does not occur if _WIN32_WINNT < 0x0500. */
24500 p = alloc(_MAX_PATH + 1);
24501 if (p != NULL)
24502 {
24503 if (GetLongPathName(*fnamep, p, MAXPATHL))
24504 {
24505 vim_free(*bufp);
24506 *bufp = *fnamep = p;
24507 }
24508 else
24509 vim_free(p);
24510 }
24511 }
24512# endif
24513#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000024514 /* Append a path separator to a directory. */
24515 if (mch_isdir(*fnamep))
24516 {
24517 /* Make room for one or two extra characters. */
24518 *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2);
24519 vim_free(*bufp); /* free any allocated file name */
24520 *bufp = *fnamep;
24521 if (*fnamep == NULL)
24522 return -1;
24523 add_pathsep(*fnamep);
24524 }
24525 }
24526
24527 /* ":." - path relative to the current directory */
24528 /* ":~" - path relative to the home directory */
24529 /* ":8" - shortname path - postponed till after */
24530 while (src[*usedlen] == ':'
24531 && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8'))
24532 {
24533 *usedlen += 2;
24534 if (c == '8')
24535 {
24536#ifdef WIN3264
24537 has_shortname = 1; /* Postpone this. */
24538#endif
24539 continue;
24540 }
24541 pbuf = NULL;
24542 /* Need full path first (use expand_env() to remove a "~/") */
24543 if (!has_fullname)
24544 {
24545 if (c == '.' && **fnamep == '~')
24546 p = pbuf = expand_env_save(*fnamep);
24547 else
24548 p = pbuf = FullName_save(*fnamep, FALSE);
24549 }
24550 else
24551 p = *fnamep;
24552
24553 has_fullname = 0;
24554
24555 if (p != NULL)
24556 {
24557 if (c == '.')
24558 {
24559 mch_dirname(dirname, MAXPATHL);
24560 s = shorten_fname(p, dirname);
24561 if (s != NULL)
24562 {
24563 *fnamep = s;
24564 if (pbuf != NULL)
24565 {
24566 vim_free(*bufp); /* free any allocated file name */
24567 *bufp = pbuf;
24568 pbuf = NULL;
24569 }
24570 }
24571 }
24572 else
24573 {
24574 home_replace(NULL, p, dirname, MAXPATHL, TRUE);
24575 /* Only replace it when it starts with '~' */
24576 if (*dirname == '~')
24577 {
24578 s = vim_strsave(dirname);
24579 if (s != NULL)
24580 {
24581 *fnamep = s;
24582 vim_free(*bufp);
24583 *bufp = s;
24584 }
24585 }
24586 }
24587 vim_free(pbuf);
24588 }
24589 }
24590
24591 tail = gettail(*fnamep);
24592 *fnamelen = (int)STRLEN(*fnamep);
24593
24594 /* ":h" - head, remove "/file_name", can be repeated */
24595 /* Don't remove the first "/" or "c:\" */
24596 while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h')
24597 {
24598 valid |= VALID_HEAD;
24599 *usedlen += 2;
24600 s = get_past_head(*fnamep);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000024601 while (tail > s && after_pathsep(s, tail))
Bram Moolenaar5461cfe2007-09-25 18:40:14 +000024602 mb_ptr_back(*fnamep, tail);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024603 *fnamelen = (int)(tail - *fnamep);
24604#ifdef VMS
24605 if (*fnamelen > 0)
24606 *fnamelen += 1; /* the path separator is part of the path */
24607#endif
Bram Moolenaar5461cfe2007-09-25 18:40:14 +000024608 if (*fnamelen == 0)
24609 {
24610 /* Result is empty. Turn it into "." to make ":cd %:h" work. */
24611 p = vim_strsave((char_u *)".");
24612 if (p == NULL)
24613 return -1;
24614 vim_free(*bufp);
24615 *bufp = *fnamep = tail = p;
24616 *fnamelen = 1;
24617 }
24618 else
24619 {
24620 while (tail > s && !after_pathsep(s, tail))
24621 mb_ptr_back(*fnamep, tail);
24622 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000024623 }
24624
24625 /* ":8" - shortname */
24626 if (src[*usedlen] == ':' && src[*usedlen + 1] == '8')
24627 {
24628 *usedlen += 2;
24629#ifdef WIN3264
24630 has_shortname = 1;
24631#endif
24632 }
24633
24634#ifdef WIN3264
Bram Moolenaardc935552011-08-17 15:23:23 +020024635 /*
24636 * Handle ":8" after we have done 'heads' and before we do 'tails'.
Bram Moolenaar071d4272004-06-13 20:20:40 +000024637 */
24638 if (has_shortname)
24639 {
Bram Moolenaardc935552011-08-17 15:23:23 +020024640 /* Copy the string if it is shortened by :h and when it wasn't copied
24641 * yet, because we are going to change it in place. Avoids changing
24642 * the buffer name for "%:8". */
24643 if (*fnamelen < (int)STRLEN(*fnamep) || *fnamep == fname_start)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024644 {
24645 p = vim_strnsave(*fnamep, *fnamelen);
Bram Moolenaardc935552011-08-17 15:23:23 +020024646 if (p == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024647 return -1;
24648 vim_free(*bufp);
24649 *bufp = *fnamep = p;
24650 }
24651
24652 /* Split into two implementations - makes it easier. First is where
Bram Moolenaardc935552011-08-17 15:23:23 +020024653 * there isn't a full name already, second is where there is. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000024654 if (!has_fullname && !vim_isAbsName(*fnamep))
24655 {
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024656 if (shortpath_for_partial(fnamep, bufp, fnamelen) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024657 return -1;
24658 }
24659 else
24660 {
Bram Moolenaardc935552011-08-17 15:23:23 +020024661 int l = *fnamelen;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024662
Bram Moolenaardc935552011-08-17 15:23:23 +020024663 /* Simple case, already have the full-name.
Bram Moolenaar071d4272004-06-13 20:20:40 +000024664 * Nearly always shorter, so try first time. */
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024665 if (get_short_pathname(fnamep, bufp, &l) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024666 return -1;
24667
24668 if (l == 0)
24669 {
Bram Moolenaardc935552011-08-17 15:23:23 +020024670 /* Couldn't find the filename, search the paths. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000024671 l = *fnamelen;
Bram Moolenaarbcebfb62008-05-29 19:47:13 +000024672 if (shortpath_for_invalid_fname(fnamep, bufp, &l) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000024673 return -1;
24674 }
24675 *fnamelen = l;
24676 }
24677 }
24678#endif /* WIN3264 */
24679
24680 /* ":t" - tail, just the basename */
24681 if (src[*usedlen] == ':' && src[*usedlen + 1] == 't')
24682 {
24683 *usedlen += 2;
24684 *fnamelen -= (int)(tail - *fnamep);
24685 *fnamep = tail;
24686 }
24687
24688 /* ":e" - extension, can be repeated */
24689 /* ":r" - root, without extension, can be repeated */
24690 while (src[*usedlen] == ':'
24691 && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r'))
24692 {
24693 /* find a '.' in the tail:
24694 * - for second :e: before the current fname
24695 * - otherwise: The last '.'
24696 */
24697 if (src[*usedlen + 1] == 'e' && *fnamep > tail)
24698 s = *fnamep - 2;
24699 else
24700 s = *fnamep + *fnamelen - 1;
24701 for ( ; s > tail; --s)
24702 if (s[0] == '.')
24703 break;
24704 if (src[*usedlen + 1] == 'e') /* :e */
24705 {
24706 if (s > tail)
24707 {
24708 *fnamelen += (int)(*fnamep - (s + 1));
24709 *fnamep = s + 1;
24710#ifdef VMS
24711 /* cut version from the extension */
24712 s = *fnamep + *fnamelen - 1;
24713 for ( ; s > *fnamep; --s)
24714 if (s[0] == ';')
24715 break;
24716 if (s > *fnamep)
24717 *fnamelen = s - *fnamep;
24718#endif
24719 }
24720 else if (*fnamep <= tail)
24721 *fnamelen = 0;
24722 }
24723 else /* :r */
24724 {
24725 if (s > tail) /* remove one extension */
24726 *fnamelen = (int)(s - *fnamep);
24727 }
24728 *usedlen += 2;
24729 }
24730
24731 /* ":s?pat?foo?" - substitute */
24732 /* ":gs?pat?foo?" - global substitute */
24733 if (src[*usedlen] == ':'
24734 && (src[*usedlen + 1] == 's'
24735 || (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's')))
24736 {
24737 char_u *str;
24738 char_u *pat;
24739 char_u *sub;
24740 int sep;
24741 char_u *flags;
24742 int didit = FALSE;
24743
24744 flags = (char_u *)"";
24745 s = src + *usedlen + 2;
24746 if (src[*usedlen + 1] == 'g')
24747 {
24748 flags = (char_u *)"g";
24749 ++s;
24750 }
24751
24752 sep = *s++;
24753 if (sep)
24754 {
24755 /* find end of pattern */
24756 p = vim_strchr(s, sep);
24757 if (p != NULL)
24758 {
24759 pat = vim_strnsave(s, (int)(p - s));
24760 if (pat != NULL)
24761 {
24762 s = p + 1;
24763 /* find end of substitution */
24764 p = vim_strchr(s, sep);
24765 if (p != NULL)
24766 {
24767 sub = vim_strnsave(s, (int)(p - s));
24768 str = vim_strnsave(*fnamep, *fnamelen);
24769 if (sub != NULL && str != NULL)
24770 {
24771 *usedlen = (int)(p + 1 - src);
24772 s = do_string_sub(str, pat, sub, flags);
24773 if (s != NULL)
24774 {
24775 *fnamep = s;
24776 *fnamelen = (int)STRLEN(s);
24777 vim_free(*bufp);
24778 *bufp = s;
24779 didit = TRUE;
24780 }
24781 }
24782 vim_free(sub);
24783 vim_free(str);
24784 }
24785 vim_free(pat);
24786 }
24787 }
24788 /* after using ":s", repeat all the modifiers */
24789 if (didit)
24790 goto repeat;
24791 }
24792 }
24793
Bram Moolenaar26df0922014-02-23 23:39:13 +010024794 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'S')
24795 {
24796 p = vim_strsave_shellescape(*fnamep, FALSE, FALSE);
24797 if (p == NULL)
24798 return -1;
24799 vim_free(*bufp);
24800 *bufp = *fnamep = p;
24801 *fnamelen = (int)STRLEN(p);
24802 *usedlen += 2;
24803 }
24804
Bram Moolenaar071d4272004-06-13 20:20:40 +000024805 return valid;
24806}
24807
24808/*
24809 * Perform a substitution on "str" with pattern "pat" and substitute "sub".
24810 * "flags" can be "g" to do a global substitute.
24811 * Returns an allocated string, NULL for error.
24812 */
24813 char_u *
24814do_string_sub(str, pat, sub, flags)
24815 char_u *str;
24816 char_u *pat;
24817 char_u *sub;
24818 char_u *flags;
24819{
24820 int sublen;
24821 regmatch_T regmatch;
24822 int i;
24823 int do_all;
24824 char_u *tail;
24825 garray_T ga;
24826 char_u *ret;
24827 char_u *save_cpo;
Bram Moolenaar8af26912014-01-23 20:09:34 +010024828 char_u *zero_width = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024829
24830 /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */
24831 save_cpo = p_cpo;
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +000024832 p_cpo = empty_option;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024833
24834 ga_init2(&ga, 1, 200);
24835
24836 do_all = (flags[0] == 'g');
24837
24838 regmatch.rm_ic = p_ic;
24839 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
24840 if (regmatch.regprog != NULL)
24841 {
24842 tail = str;
24843 while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
24844 {
Bram Moolenaar8af26912014-01-23 20:09:34 +010024845 /* Skip empty match except for first match. */
24846 if (regmatch.startp[0] == regmatch.endp[0])
24847 {
24848 if (zero_width == regmatch.startp[0])
24849 {
24850 /* avoid getting stuck on a match with an empty string */
24851 *((char_u *)ga.ga_data + ga.ga_len) = *tail++;
24852 ++ga.ga_len;
24853 continue;
24854 }
24855 zero_width = regmatch.startp[0];
24856 }
24857
Bram Moolenaar071d4272004-06-13 20:20:40 +000024858 /*
24859 * Get some space for a temporary buffer to do the substitution
24860 * into. It will contain:
24861 * - The text up to where the match is.
24862 * - The substituted text.
24863 * - The text after the match.
24864 */
24865 sublen = vim_regsub(&regmatch, sub, tail, FALSE, TRUE, FALSE);
24866 if (ga_grow(&ga, (int)(STRLEN(tail) + sublen -
24867 (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
24868 {
24869 ga_clear(&ga);
24870 break;
24871 }
24872
24873 /* copy the text up to where the match is */
24874 i = (int)(regmatch.startp[0] - tail);
24875 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
24876 /* add the substituted text */
24877 (void)vim_regsub(&regmatch, sub, (char_u *)ga.ga_data
24878 + ga.ga_len + i, TRUE, TRUE, FALSE);
24879 ga.ga_len += i + sublen - 1;
Bram Moolenaarceb84af2013-09-29 21:11:05 +020024880 tail = regmatch.endp[0];
24881 if (*tail == NUL)
24882 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000024883 if (!do_all)
24884 break;
24885 }
24886
24887 if (ga.ga_data != NULL)
24888 STRCPY((char *)ga.ga_data + ga.ga_len, tail);
24889
Bram Moolenaar473de612013-06-08 18:19:48 +020024890 vim_regfree(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024891 }
24892
24893 ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data);
24894 ga_clear(&ga);
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +000024895 if (p_cpo == empty_option)
24896 p_cpo = save_cpo;
24897 else
24898 /* Darn, evaluating {sub} expression changed the value. */
24899 free_string_option(save_cpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +000024900
24901 return ret;
24902}
24903
24904#endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */