blob: 5b5bfbc75b29e24ca32d113b3bf26976246918b2 [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 */
13#if defined(MSDOS) || defined(MSWIN)
Bram Moolenaar362e1a32006-03-06 23:29:24 +000014# include "vimio.h" /* for mch_open(), must be before vim.h */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015#endif
16
17#include "vim.h"
18
19#ifdef AMIGA
20# include <time.h> /* for strftime() */
21#endif
22
23#ifdef MACOS
24# include <time.h> /* for time_t */
25#endif
26
27#ifdef HAVE_FCNTL_H
28# include <fcntl.h>
29#endif
30
31#if defined(FEAT_EVAL) || defined(PROTO)
32
Bram Moolenaar33570922005-01-25 22:26:29 +000033#define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */
Bram Moolenaar071d4272004-06-13 20:20:40 +000034
35/*
Bram Moolenaar33570922005-01-25 22:26:29 +000036 * In a hashtab item "hi_key" points to "di_key" in a dictitem.
37 * This avoids adding a pointer to the hashtab item.
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000038 * DI2HIKEY() converts a dictitem pointer to a hashitem key pointer.
39 * HIKEY2DI() converts a hashitem key pointer to a dictitem pointer.
40 * HI2DI() converts a hashitem pointer to a dictitem pointer.
41 */
Bram Moolenaar33570922005-01-25 22:26:29 +000042static dictitem_T dumdi;
Bram Moolenaara7043832005-01-21 11:56:39 +000043#define DI2HIKEY(di) ((di)->di_key)
Bram Moolenaar33570922005-01-25 22:26:29 +000044#define HIKEY2DI(p) ((dictitem_T *)(p - (dumdi.di_key - (char_u *)&dumdi)))
Bram Moolenaara7043832005-01-21 11:56:39 +000045#define HI2DI(hi) HIKEY2DI((hi)->hi_key)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000046
47/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000048 * Structure returned by get_lval() and used by set_var_lval().
49 * For a plain name:
50 * "name" points to the variable name.
51 * "exp_name" is NULL.
52 * "tv" is NULL
53 * For a magic braces name:
54 * "name" points to the expanded variable name.
55 * "exp_name" is non-NULL, to be freed later.
56 * "tv" is NULL
57 * For an index in a list:
58 * "name" points to the (expanded) variable name.
59 * "exp_name" NULL or non-NULL, to be freed later.
60 * "tv" points to the (first) list item value
61 * "li" points to the (first) list item
62 * "range", "n1", "n2" and "empty2" indicate what items are used.
63 * For an existing Dict item:
64 * "name" points to the (expanded) variable name.
65 * "exp_name" NULL or non-NULL, to be freed later.
66 * "tv" points to the dict item value
67 * "newkey" is NULL
68 * For a non-existing Dict item:
69 * "name" points to the (expanded) variable name.
70 * "exp_name" NULL or non-NULL, to be freed later.
Bram Moolenaar33570922005-01-25 22:26:29 +000071 * "tv" points to the Dictionary typval_T
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000072 * "newkey" is the key for the new item.
73 */
74typedef struct lval_S
75{
76 char_u *ll_name; /* start of variable name (can be NULL) */
77 char_u *ll_exp_name; /* NULL or expanded name in allocated memory. */
Bram Moolenaar33570922005-01-25 22:26:29 +000078 typval_T *ll_tv; /* Typeval of item being used. If "newkey"
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000079 isn't NULL it's the Dict to which to add
80 the item. */
Bram Moolenaar33570922005-01-25 22:26:29 +000081 listitem_T *ll_li; /* The list item or NULL. */
82 list_T *ll_list; /* The list or NULL. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000083 int ll_range; /* TRUE when a [i:j] range was used */
84 long ll_n1; /* First index for list */
85 long ll_n2; /* Second index for list range */
86 int ll_empty2; /* Second index is empty: [i:] */
Bram Moolenaar33570922005-01-25 22:26:29 +000087 dict_T *ll_dict; /* The Dictionary or NULL */
88 dictitem_T *ll_di; /* The dictitem or NULL */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000089 char_u *ll_newkey; /* New key for Dict in alloc. mem or NULL. */
Bram Moolenaar33570922005-01-25 22:26:29 +000090} lval_T;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000091
Bram Moolenaar8c711452005-01-14 21:53:12 +000092
Bram Moolenaarc70646c2005-01-04 21:52:38 +000093static char *e_letunexp = N_("E18: Unexpected characters in :let");
Bram Moolenaare49b69a2005-01-08 16:11:57 +000094static char *e_listidx = N_("E684: list index out of range: %ld");
Bram Moolenaarc70646c2005-01-04 21:52:38 +000095static char *e_undefvar = N_("E121: Undefined variable: %s");
96static char *e_missbrac = N_("E111: Missing ']'");
Bram Moolenaar8c711452005-01-14 21:53:12 +000097static char *e_listarg = N_("E686: Argument of %s must be a List");
Bram Moolenaar13fcaaf2005-04-15 21:13:42 +000098static char *e_listdictarg = N_("E712: Argument of %s must be a List or Dictionary");
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000099static char *e_emptykey = N_("E713: Cannot use empty key for Dictionary");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000100static char *e_listreq = N_("E714: List required");
101static char *e_dictreq = N_("E715: Dictionary required");
Bram Moolenaar8c711452005-01-14 21:53:12 +0000102static char *e_toomanyarg = N_("E118: Too many arguments for function: %s");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000103static char *e_dictkey = N_("E716: Key not present in Dictionary: %s");
104static char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it");
105static char *e_funcdict = N_("E717: Dictionary entry already exists");
106static char *e_funcref = N_("E718: Funcref required");
107static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary");
108static char *e_letwrong = N_("E734: Wrong variable type for %s=");
Bram Moolenaar05159a02005-02-26 23:04:13 +0000109static char *e_nofunc = N_("E130: Unknown function: %s");
Bram Moolenaar92124a32005-06-17 22:03:40 +0000110static char *e_illvar = N_("E461: Illegal variable name: %s");
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000111/*
Bram Moolenaar33570922005-01-25 22:26:29 +0000112 * All user-defined global variables are stored in dictionary "globvardict".
113 * "globvars_var" is the variable that is used for "g:".
Bram Moolenaar071d4272004-06-13 20:20:40 +0000114 */
Bram Moolenaar33570922005-01-25 22:26:29 +0000115static dict_T globvardict;
116static dictitem_T globvars_var;
117#define globvarht globvardict.dv_hashtab
Bram Moolenaar071d4272004-06-13 20:20:40 +0000118
119/*
Bram Moolenaar532c7802005-01-27 14:44:31 +0000120 * Old Vim variables such as "v:version" are also available without the "v:".
121 * Also in functions. We need a special hashtable for them.
122 */
Bram Moolenaar4debb442005-06-01 21:57:40 +0000123static hashtab_T compat_hashtab;
Bram Moolenaar532c7802005-01-27 14:44:31 +0000124
125/*
Bram Moolenaard9fba312005-06-26 22:34:35 +0000126 * When recursively copying lists and dicts we need to remember which ones we
127 * have done to avoid endless recursiveness. This unique ID is used for that.
128 */
129static int current_copyID = 0;
130
131/*
Bram Moolenaar33570922005-01-25 22:26:29 +0000132 * Array to hold the hashtab with variables local to each sourced script.
133 * Each item holds a variable (nameless) that points to the dict_T.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000134 */
Bram Moolenaar33570922005-01-25 22:26:29 +0000135typedef struct
136{
137 dictitem_T sv_var;
138 dict_T sv_dict;
139} scriptvar_T;
140
141static garray_T ga_scripts = {0, 0, sizeof(scriptvar_T), 4, NULL};
142#define SCRIPT_SV(id) (((scriptvar_T *)ga_scripts.ga_data)[(id) - 1])
143#define SCRIPT_VARS(id) (SCRIPT_SV(id).sv_dict.dv_hashtab)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000144
145static int echo_attr = 0; /* attributes used for ":echo" */
146
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000147/* Values for trans_function_name() argument: */
148#define TFN_INT 1 /* internal function name OK */
149#define TFN_QUIET 2 /* no error messages */
150
Bram Moolenaar071d4272004-06-13 20:20:40 +0000151/*
152 * Structure to hold info for a user function.
153 */
154typedef struct ufunc ufunc_T;
155
156struct ufunc
157{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000158 int uf_varargs; /* variable nr of arguments */
159 int uf_flags;
160 int uf_calls; /* nr of active calls */
161 garray_T uf_args; /* arguments */
162 garray_T uf_lines; /* function lines */
Bram Moolenaar05159a02005-02-26 23:04:13 +0000163#ifdef FEAT_PROFILE
164 int uf_profiling; /* TRUE when func is being profiled */
165 /* profiling the function as a whole */
166 int uf_tm_count; /* nr of calls */
167 proftime_T uf_tm_total; /* time spend in function + children */
168 proftime_T uf_tm_self; /* time spend in function itself */
169 proftime_T uf_tm_start; /* time at function call */
170 proftime_T uf_tm_children; /* time spent in children this call */
171 /* profiling the function per line */
172 int *uf_tml_count; /* nr of times line was executed */
173 proftime_T *uf_tml_total; /* time spend in a line + children */
174 proftime_T *uf_tml_self; /* time spend in a line itself */
175 proftime_T uf_tml_start; /* start time for current line */
176 proftime_T uf_tml_children; /* time spent in children for this line */
177 proftime_T uf_tml_wait; /* start wait time for current line */
178 int uf_tml_idx; /* index of line being timed; -1 if none */
179 int uf_tml_execed; /* line being timed was executed */
180#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000181 scid_T uf_script_ID; /* ID of script where function was defined,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000182 used for s: variables */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000183 int uf_refcount; /* for numbered function: reference count */
184 char_u uf_name[1]; /* name of function (actually longer); can
185 start with <SNR>123_ (<SNR> is K_SPECIAL
186 KS_EXTRA KE_SNR) */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000187};
188
189/* function flags */
190#define FC_ABORT 1 /* abort function on error */
191#define FC_RANGE 2 /* function accepts range */
Bram Moolenaare9a41262005-01-15 22:18:47 +0000192#define FC_DICT 4 /* Dict function, uses "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000193
Bram Moolenaard9fba312005-06-26 22:34:35 +0000194#define DEL_REFCOUNT 999999 /* list/dict is being deleted */
195
Bram Moolenaar071d4272004-06-13 20:20:40 +0000196/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000197 * All user-defined functions are found in this hashtable.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000198 */
Bram Moolenaar4debb442005-06-01 21:57:40 +0000199static hashtab_T func_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000200
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000201/* The names of packages that once were loaded are remembered. */
Bram Moolenaaraa35dd12006-04-29 22:03:41 +0000202static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL};
203
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000204/* list heads for garbage collection */
205static dict_T *first_dict = NULL; /* list of all dicts */
206static list_T *first_list = NULL; /* list of all lists */
207
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000208/* From user function to hashitem and back. */
209static ufunc_T dumuf;
210#define UF2HIKEY(fp) ((fp)->uf_name)
211#define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf)))
212#define HI2UF(hi) HIKEY2UF((hi)->hi_key)
213
214#define FUNCARG(fp, j) ((char_u **)(fp->uf_args.ga_data))[j]
215#define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j]
Bram Moolenaar071d4272004-06-13 20:20:40 +0000216
Bram Moolenaar33570922005-01-25 22:26:29 +0000217#define MAX_FUNC_ARGS 20 /* maximum number of function arguments */
218#define VAR_SHORT_LEN 20 /* short variable name length */
219#define FIXVAR_CNT 12 /* number of fixed variables */
220
Bram Moolenaar071d4272004-06-13 20:20:40 +0000221/* structure to hold info for a function that is currently being executed. */
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000222typedef struct funccall_S funccall_T;
223
224struct funccall_S
Bram Moolenaar071d4272004-06-13 20:20:40 +0000225{
226 ufunc_T *func; /* function being called */
227 int linenr; /* next line to be executed */
228 int returned; /* ":return" used */
Bram Moolenaar33570922005-01-25 22:26:29 +0000229 struct /* fixed variables for arguments */
230 {
231 dictitem_T var; /* variable (without room for name) */
232 char_u room[VAR_SHORT_LEN]; /* room for the name */
233 } fixvar[FIXVAR_CNT];
234 dict_T l_vars; /* l: local function variables */
235 dictitem_T l_vars_var; /* variable for l: scope */
236 dict_T l_avars; /* a: argument variables */
237 dictitem_T l_avars_var; /* variable for a: scope */
238 list_T l_varlist; /* list for a:000 */
239 listitem_T l_listitems[MAX_FUNC_ARGS]; /* listitems for a:000 */
240 typval_T *rettv; /* return value */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000241 linenr_T breakpoint; /* next line with breakpoint or zero */
242 int dbg_tick; /* debug_tick when breakpoint was set */
243 int level; /* top nesting level of executed function */
Bram Moolenaar05159a02005-02-26 23:04:13 +0000244#ifdef FEAT_PROFILE
245 proftime_T prof_child; /* time spent in a child */
246#endif
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000247 funccall_T *caller; /* calling function or NULL */
248};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000249
250/*
Bram Moolenaarac48dbf2006-09-03 13:34:00 +0000251 * Struct used to make a list of all arguments used in internal functions.
252 */
253typedef struct av_list_item_S av_list_item_T;
254struct av_list_item_S {
255 av_list_item_T *avl_next;
256 typval_T *avl_argvars;
257};
258
259av_list_item_T *argvars_list = NULL;
260
261/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000262 * Info used by a ":for" loop.
263 */
Bram Moolenaar33570922005-01-25 22:26:29 +0000264typedef struct
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000265{
266 int fi_semicolon; /* TRUE if ending in '; var]' */
267 int fi_varcount; /* nr of variables in the list */
Bram Moolenaar33570922005-01-25 22:26:29 +0000268 listwatch_T fi_lw; /* keep an eye on the item used. */
269 list_T *fi_list; /* list being used */
270} forinfo_T;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000271
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000272/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000273 * Struct used by trans_function_name()
274 */
275typedef struct
276{
Bram Moolenaar33570922005-01-25 22:26:29 +0000277 dict_T *fd_dict; /* Dictionary used */
Bram Moolenaar532c7802005-01-27 14:44:31 +0000278 char_u *fd_newkey; /* new key in "dict" in allocated memory */
Bram Moolenaar33570922005-01-25 22:26:29 +0000279 dictitem_T *fd_di; /* Dictionary item used */
280} funcdict_T;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000281
Bram Moolenaara7043832005-01-21 11:56:39 +0000282
283/*
Bram Moolenaar33570922005-01-25 22:26:29 +0000284 * Array to hold the value of v: variables.
285 * The value is in a dictitem, so that it can also be used in the v: scope.
286 * The reason to use this table anyway is for very quick access to the
287 * variables with the VV_ defines.
288 */
289#include "version.h"
290
291/* values for vv_flags: */
292#define VV_COMPAT 1 /* compatible, also used without "v:" */
293#define VV_RO 2 /* read-only */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000294#define VV_RO_SBX 4 /* read-only in the sandbox */
Bram Moolenaar33570922005-01-25 22:26:29 +0000295
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +0000296#define VV_NAME(s, t) s, {{t}}, {0}
Bram Moolenaar33570922005-01-25 22:26:29 +0000297
298static struct vimvar
299{
300 char *vv_name; /* name of variable, without v: */
Bram Moolenaar33570922005-01-25 22:26:29 +0000301 dictitem_T vv_di; /* value and name for key */
302 char vv_filler[16]; /* space for LONGEST name below!!! */
303 char vv_flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */
304} vimvars[VV_LEN] =
305{
306 /*
307 * The order here must match the VV_ defines in vim.h!
308 * Initializing a union does not work, leave tv.vval empty to get zero's.
309 */
310 {VV_NAME("count", VAR_NUMBER), VV_COMPAT+VV_RO},
311 {VV_NAME("count1", VAR_NUMBER), VV_RO},
312 {VV_NAME("prevcount", VAR_NUMBER), VV_RO},
313 {VV_NAME("errmsg", VAR_STRING), VV_COMPAT},
314 {VV_NAME("warningmsg", VAR_STRING), 0},
315 {VV_NAME("statusmsg", VAR_STRING), 0},
316 {VV_NAME("shell_error", VAR_NUMBER), VV_COMPAT+VV_RO},
317 {VV_NAME("this_session", VAR_STRING), VV_COMPAT},
318 {VV_NAME("version", VAR_NUMBER), VV_COMPAT+VV_RO},
319 {VV_NAME("lnum", VAR_NUMBER), VV_RO_SBX},
320 {VV_NAME("termresponse", VAR_STRING), VV_RO},
321 {VV_NAME("fname", VAR_STRING), VV_RO},
322 {VV_NAME("lang", VAR_STRING), VV_RO},
323 {VV_NAME("lc_time", VAR_STRING), VV_RO},
324 {VV_NAME("ctype", VAR_STRING), VV_RO},
325 {VV_NAME("charconvert_from", VAR_STRING), VV_RO},
326 {VV_NAME("charconvert_to", VAR_STRING), VV_RO},
327 {VV_NAME("fname_in", VAR_STRING), VV_RO},
328 {VV_NAME("fname_out", VAR_STRING), VV_RO},
329 {VV_NAME("fname_new", VAR_STRING), VV_RO},
330 {VV_NAME("fname_diff", VAR_STRING), VV_RO},
331 {VV_NAME("cmdarg", VAR_STRING), VV_RO},
332 {VV_NAME("foldstart", VAR_NUMBER), VV_RO_SBX},
333 {VV_NAME("foldend", VAR_NUMBER), VV_RO_SBX},
334 {VV_NAME("folddashes", VAR_STRING), VV_RO_SBX},
335 {VV_NAME("foldlevel", VAR_NUMBER), VV_RO_SBX},
336 {VV_NAME("progname", VAR_STRING), VV_RO},
337 {VV_NAME("servername", VAR_STRING), VV_RO},
338 {VV_NAME("dying", VAR_NUMBER), VV_RO},
339 {VV_NAME("exception", VAR_STRING), VV_RO},
340 {VV_NAME("throwpoint", VAR_STRING), VV_RO},
341 {VV_NAME("register", VAR_STRING), VV_RO},
342 {VV_NAME("cmdbang", VAR_NUMBER), VV_RO},
343 {VV_NAME("insertmode", VAR_STRING), VV_RO},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000344 {VV_NAME("val", VAR_UNKNOWN), VV_RO},
345 {VV_NAME("key", VAR_UNKNOWN), VV_RO},
Bram Moolenaar05159a02005-02-26 23:04:13 +0000346 {VV_NAME("profiling", VAR_NUMBER), VV_RO},
Bram Moolenaar19a09a12005-03-04 23:39:37 +0000347 {VV_NAME("fcs_reason", VAR_STRING), VV_RO},
348 {VV_NAME("fcs_choice", VAR_STRING), 0},
Bram Moolenaare2ac10d2005-03-07 23:26:06 +0000349 {VV_NAME("beval_bufnr", VAR_NUMBER), VV_RO},
350 {VV_NAME("beval_winnr", VAR_NUMBER), VV_RO},
351 {VV_NAME("beval_lnum", VAR_NUMBER), VV_RO},
352 {VV_NAME("beval_col", VAR_NUMBER), VV_RO},
353 {VV_NAME("beval_text", VAR_STRING), VV_RO},
Bram Moolenaar761b1132005-10-03 22:05:45 +0000354 {VV_NAME("scrollstart", VAR_STRING), 0},
Bram Moolenaard5bc83f2005-12-07 21:07:59 +0000355 {VV_NAME("swapname", VAR_STRING), VV_RO},
356 {VV_NAME("swapchoice", VAR_STRING), 0},
Bram Moolenaar63a121b2005-12-11 21:36:39 +0000357 {VV_NAME("swapcommand", VAR_STRING), VV_RO},
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000358 {VV_NAME("char", VAR_STRING), VV_RO},
Bram Moolenaar33570922005-01-25 22:26:29 +0000359};
360
361/* shorthand */
362#define vv_type vv_di.di_tv.v_type
363#define vv_nr vv_di.di_tv.vval.v_number
364#define vv_str vv_di.di_tv.vval.v_string
365#define vv_tv vv_di.di_tv
366
367/*
368 * The v: variables are stored in dictionary "vimvardict".
369 * "vimvars_var" is the variable that is used for the "l:" scope.
370 */
371static dict_T vimvardict;
372static dictitem_T vimvars_var;
373#define vimvarht vimvardict.dv_hashtab
374
Bram Moolenaara40058a2005-07-11 22:42:07 +0000375static void prepare_vimvar __ARGS((int idx, typval_T *save_tv));
376static void restore_vimvar __ARGS((int idx, typval_T *save_tv));
377#if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)
378static int call_vim_function __ARGS((char_u *func, int argc, char_u **argv, int safe, typval_T *rettv));
379#endif
380static 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));
383static void list_hashtable_vars __ARGS((hashtab_T *ht, char_u *prefix, int empty));
384static void list_glob_vars __ARGS((void));
385static void list_buf_vars __ARGS((void));
386static void list_win_vars __ARGS((void));
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000387#ifdef FEAT_WINDOWS
388static void list_tab_vars __ARGS((void));
389#endif
Bram Moolenaara40058a2005-07-11 22:42:07 +0000390static void list_vim_vars __ARGS((void));
Bram Moolenaarf0acfce2006-03-17 23:21:19 +0000391static void list_script_vars __ARGS((void));
392static void list_func_vars __ARGS((void));
Bram Moolenaara40058a2005-07-11 22:42:07 +0000393static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg));
394static 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));
396static char_u *get_lval __ARGS((char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int quiet, int fne_flags));
397static 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));
400static void list_add_watch __ARGS((list_T *l, listwatch_T *lw));
401static void list_rem_watch __ARGS((list_T *l, listwatch_T *lwrem));
402static void list_fix_watch __ARGS((list_T *l, listitem_T *item));
403static void ex_unletlock __ARGS((exarg_T *eap, char_u *argstart, int deep));
404static int do_unlet_var __ARGS((lval_T *lp, char_u *name_end, int forceit));
405static int do_lock_var __ARGS((lval_T *lp, char_u *name_end, int deep, int lock));
406static void item_lock __ARGS((typval_T *tv, int deep, int lock));
407static int tv_islocked __ARGS((typval_T *tv));
408
Bram Moolenaar33570922005-01-25 22:26:29 +0000409static int eval0 __ARGS((char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate));
410static int eval1 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
411static int eval2 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
412static int eval3 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
413static int eval4 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
414static int eval5 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
415static int eval6 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
416static int eval7 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
Bram Moolenaara40058a2005-07-11 22:42:07 +0000417
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000418static int eval_index __ARGS((char_u **arg, typval_T *rettv, int evaluate, int verbose));
Bram Moolenaar33570922005-01-25 22:26:29 +0000419static int get_option_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
420static int get_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
421static int get_lit_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
422static int get_list_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
Bram Moolenaareddf53b2006-02-27 00:11:10 +0000423static int rettv_list_alloc __ARGS((typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000424static listitem_T *listitem_alloc __ARGS((void));
425static void listitem_free __ARGS((listitem_T *item));
426static void listitem_remove __ARGS((list_T *l, listitem_T *item));
427static long list_len __ARGS((list_T *l));
428static int list_equal __ARGS((list_T *l1, list_T *l2, int ic));
429static int dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic));
430static int tv_equal __ARGS((typval_T *tv1, typval_T *tv2, int ic));
Bram Moolenaar33570922005-01-25 22:26:29 +0000431static listitem_T *list_find __ARGS((list_T *l, long n));
Bram Moolenaara5525202006-03-02 22:52:09 +0000432static long list_find_nr __ARGS((list_T *l, long idx, int *errorp));
Bram Moolenaar33570922005-01-25 22:26:29 +0000433static long list_idx_of_item __ARGS((list_T *l, listitem_T *item));
Bram Moolenaar33570922005-01-25 22:26:29 +0000434static void list_append __ARGS((list_T *l, listitem_T *item));
435static int list_append_tv __ARGS((list_T *l, typval_T *tv));
Bram Moolenaar4463f292005-09-25 22:20:24 +0000436static int list_append_string __ARGS((list_T *l, char_u *str, int len));
437static int list_append_number __ARGS((list_T *l, varnumber_T n));
Bram Moolenaar33570922005-01-25 22:26:29 +0000438static int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item));
439static int list_extend __ARGS((list_T *l1, list_T *l2, listitem_T *bef));
440static int list_concat __ARGS((list_T *l1, list_T *l2, typval_T *tv));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000441static list_T *list_copy __ARGS((list_T *orig, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000442static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000443static char_u *list2string __ARGS((typval_T *tv, int copyID));
444static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo, int copyID));
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000445static void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID));
446static void set_ref_in_list __ARGS((list_T *l, int copyID));
447static void set_ref_in_item __ARGS((typval_T *tv, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000448static void dict_unref __ARGS((dict_T *d));
449static void dict_free __ARGS((dict_T *d));
450static dictitem_T *dictitem_alloc __ARGS((char_u *key));
451static dictitem_T *dictitem_copy __ARGS((dictitem_T *org));
452static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item));
453static void dictitem_free __ARGS((dictitem_T *item));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000454static dict_T *dict_copy __ARGS((dict_T *orig, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000455static int dict_add __ARGS((dict_T *d, dictitem_T *item));
456static long dict_len __ARGS((dict_T *d));
457static dictitem_T *dict_find __ARGS((dict_T *d, char_u *key, int len));
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000458static char_u *dict2string __ARGS((typval_T *tv, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000459static int get_dict_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000460static char_u *echo_string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID));
461static char_u *tv2string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000462static char_u *string_quote __ARGS((char_u *str, int function));
463static int get_env_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
464static int find_internal_func __ARGS((char_u *name));
465static char_u *deref_func_name __ARGS((char_u *name, int *lenp));
466static 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));
467static int call_func __ARGS((char_u *name, 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 +0000468static void emsg_funcname __ARGS((char *ermsg, char_u *name));
Bram Moolenaar33570922005-01-25 22:26:29 +0000469
470static void f_add __ARGS((typval_T *argvars, typval_T *rettv));
471static void f_append __ARGS((typval_T *argvars, typval_T *rettv));
472static void f_argc __ARGS((typval_T *argvars, typval_T *rettv));
473static void f_argidx __ARGS((typval_T *argvars, typval_T *rettv));
474static void f_argv __ARGS((typval_T *argvars, typval_T *rettv));
475static void f_browse __ARGS((typval_T *argvars, typval_T *rettv));
476static void f_browsedir __ARGS((typval_T *argvars, typval_T *rettv));
477static void f_bufexists __ARGS((typval_T *argvars, typval_T *rettv));
478static void f_buflisted __ARGS((typval_T *argvars, typval_T *rettv));
479static void f_bufloaded __ARGS((typval_T *argvars, typval_T *rettv));
480static void f_bufname __ARGS((typval_T *argvars, typval_T *rettv));
481static void f_bufnr __ARGS((typval_T *argvars, typval_T *rettv));
482static void f_bufwinnr __ARGS((typval_T *argvars, typval_T *rettv));
483static void f_byte2line __ARGS((typval_T *argvars, typval_T *rettv));
484static void f_byteidx __ARGS((typval_T *argvars, typval_T *rettv));
485static void f_call __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaarf0acfce2006-03-17 23:21:19 +0000486static void f_changenr __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000487static void f_char2nr __ARGS((typval_T *argvars, typval_T *rettv));
488static void f_cindent __ARGS((typval_T *argvars, typval_T *rettv));
489static void f_col __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar572cb562005-08-05 21:35:02 +0000490#if defined(FEAT_INS_EXPAND)
Bram Moolenaarade00832006-03-10 21:46:58 +0000491static void f_complete __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar572cb562005-08-05 21:35:02 +0000492static void f_complete_add __ARGS((typval_T *argvars, typval_T *rettv));
493static void f_complete_check __ARGS((typval_T *argvars, typval_T *rettv));
494#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000495static void f_confirm __ARGS((typval_T *argvars, typval_T *rettv));
496static void f_copy __ARGS((typval_T *argvars, typval_T *rettv));
497static void f_count __ARGS((typval_T *argvars, typval_T *rettv));
498static void f_cscope_connection __ARGS((typval_T *argvars, typval_T *rettv));
499static void f_cursor __ARGS((typval_T *argsvars, typval_T *rettv));
500static void f_deepcopy __ARGS((typval_T *argvars, typval_T *rettv));
501static void f_delete __ARGS((typval_T *argvars, typval_T *rettv));
502static void f_did_filetype __ARGS((typval_T *argvars, typval_T *rettv));
503static void f_diff_filler __ARGS((typval_T *argvars, typval_T *rettv));
504static void f_diff_hlID __ARGS((typval_T *argvars, typval_T *rettv));
505static void f_empty __ARGS((typval_T *argvars, typval_T *rettv));
506static void f_escape __ARGS((typval_T *argvars, typval_T *rettv));
507static void f_eval __ARGS((typval_T *argvars, typval_T *rettv));
508static void f_eventhandler __ARGS((typval_T *argvars, typval_T *rettv));
509static void f_executable __ARGS((typval_T *argvars, typval_T *rettv));
510static void f_exists __ARGS((typval_T *argvars, typval_T *rettv));
511static void f_expand __ARGS((typval_T *argvars, typval_T *rettv));
512static void f_extend __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaarf9393ef2006-04-24 19:47:27 +0000513static void f_feedkeys __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000514static void f_filereadable __ARGS((typval_T *argvars, typval_T *rettv));
515static void f_filewritable __ARGS((typval_T *argvars, typval_T *rettv));
516static void f_filter __ARGS((typval_T *argvars, typval_T *rettv));
517static void f_finddir __ARGS((typval_T *argvars, typval_T *rettv));
518static void f_findfile __ARGS((typval_T *argvars, typval_T *rettv));
519static void f_fnamemodify __ARGS((typval_T *argvars, typval_T *rettv));
520static void f_foldclosed __ARGS((typval_T *argvars, typval_T *rettv));
521static void f_foldclosedend __ARGS((typval_T *argvars, typval_T *rettv));
522static void f_foldlevel __ARGS((typval_T *argvars, typval_T *rettv));
523static void f_foldtext __ARGS((typval_T *argvars, typval_T *rettv));
524static void f_foldtextresult __ARGS((typval_T *argvars, typval_T *rettv));
525static void f_foreground __ARGS((typval_T *argvars, typval_T *rettv));
526static void f_function __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000527static void f_garbagecollect __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000528static void f_get __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar80fc0432005-07-20 22:06:07 +0000529static void f_getbufline __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000530static void f_getbufvar __ARGS((typval_T *argvars, typval_T *rettv));
531static void f_getchar __ARGS((typval_T *argvars, typval_T *rettv));
532static void f_getcharmod __ARGS((typval_T *argvars, typval_T *rettv));
533static void f_getcmdline __ARGS((typval_T *argvars, typval_T *rettv));
534static void f_getcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000535static void f_getcmdtype __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000536static void f_getcwd __ARGS((typval_T *argvars, typval_T *rettv));
537static void f_getfontname __ARGS((typval_T *argvars, typval_T *rettv));
538static void f_getfperm __ARGS((typval_T *argvars, typval_T *rettv));
539static void f_getfsize __ARGS((typval_T *argvars, typval_T *rettv));
540static void f_getftime __ARGS((typval_T *argvars, typval_T *rettv));
541static void f_getftype __ARGS((typval_T *argvars, typval_T *rettv));
542static void f_getline __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaara5525202006-03-02 22:52:09 +0000543static void f_getpos __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2641f772005-03-25 21:58:17 +0000544static void f_getqflist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000545static void f_getreg __ARGS((typval_T *argvars, typval_T *rettv));
546static void f_getregtype __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar99ebf042006-04-15 20:28:54 +0000547static void f_gettabwinvar __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000548static void f_getwinposx __ARGS((typval_T *argvars, typval_T *rettv));
549static void f_getwinposy __ARGS((typval_T *argvars, typval_T *rettv));
550static void f_getwinvar __ARGS((typval_T *argvars, typval_T *rettv));
551static void f_glob __ARGS((typval_T *argvars, typval_T *rettv));
552static void f_globpath __ARGS((typval_T *argvars, typval_T *rettv));
553static void f_has __ARGS((typval_T *argvars, typval_T *rettv));
554static void f_has_key __ARGS((typval_T *argvars, typval_T *rettv));
555static void f_hasmapto __ARGS((typval_T *argvars, typval_T *rettv));
556static void f_histadd __ARGS((typval_T *argvars, typval_T *rettv));
557static void f_histdel __ARGS((typval_T *argvars, typval_T *rettv));
558static void f_histget __ARGS((typval_T *argvars, typval_T *rettv));
559static void f_histnr __ARGS((typval_T *argvars, typval_T *rettv));
560static void f_hlID __ARGS((typval_T *argvars, typval_T *rettv));
561static void f_hlexists __ARGS((typval_T *argvars, typval_T *rettv));
562static void f_hostname __ARGS((typval_T *argvars, typval_T *rettv));
563static void f_iconv __ARGS((typval_T *argvars, typval_T *rettv));
564static void f_indent __ARGS((typval_T *argvars, typval_T *rettv));
565static void f_index __ARGS((typval_T *argvars, typval_T *rettv));
566static void f_input __ARGS((typval_T *argvars, typval_T *rettv));
567static void f_inputdialog __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar6efa2b32005-09-10 19:26:26 +0000568static void f_inputlist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000569static void f_inputrestore __ARGS((typval_T *argvars, typval_T *rettv));
570static void f_inputsave __ARGS((typval_T *argvars, typval_T *rettv));
571static void f_inputsecret __ARGS((typval_T *argvars, typval_T *rettv));
572static void f_insert __ARGS((typval_T *argvars, typval_T *rettv));
573static void f_isdirectory __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000574static void f_islocked __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000575static void f_items __ARGS((typval_T *argvars, typval_T *rettv));
576static void f_join __ARGS((typval_T *argvars, typval_T *rettv));
577static void f_keys __ARGS((typval_T *argvars, typval_T *rettv));
578static void f_last_buffer_nr __ARGS((typval_T *argvars, typval_T *rettv));
579static void f_len __ARGS((typval_T *argvars, typval_T *rettv));
580static void f_libcall __ARGS((typval_T *argvars, typval_T *rettv));
581static void f_libcallnr __ARGS((typval_T *argvars, typval_T *rettv));
582static void f_line __ARGS((typval_T *argvars, typval_T *rettv));
583static void f_line2byte __ARGS((typval_T *argvars, typval_T *rettv));
584static void f_lispindent __ARGS((typval_T *argvars, typval_T *rettv));
585static void f_localtime __ARGS((typval_T *argvars, typval_T *rettv));
586static void f_map __ARGS((typval_T *argvars, typval_T *rettv));
587static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv));
588static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv));
589static void f_match __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000590static void f_matcharg __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000591static void f_matchend __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000592static void f_matchlist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000593static void f_matchstr __ARGS((typval_T *argvars, typval_T *rettv));
594static void f_max __ARGS((typval_T *argvars, typval_T *rettv));
595static void f_min __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000596#ifdef vim_mkdir
597static void f_mkdir __ARGS((typval_T *argvars, typval_T *rettv));
598#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000599static void f_mode __ARGS((typval_T *argvars, typval_T *rettv));
600static void f_nextnonblank __ARGS((typval_T *argvars, typval_T *rettv));
601static void f_nr2char __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000602static void f_pathshorten __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000603static void f_prevnonblank __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar4be06f92005-07-29 22:36:03 +0000604static void f_printf __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000605static void f_pumvisible __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000606static void f_range __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000607static void f_readfile __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaare580b0c2006-03-21 21:33:03 +0000608static void f_reltime __ARGS((typval_T *argvars, typval_T *rettv));
609static void f_reltimestr __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000610static void f_remote_expr __ARGS((typval_T *argvars, typval_T *rettv));
611static void f_remote_foreground __ARGS((typval_T *argvars, typval_T *rettv));
612static void f_remote_peek __ARGS((typval_T *argvars, typval_T *rettv));
613static void f_remote_read __ARGS((typval_T *argvars, typval_T *rettv));
614static void f_remote_send __ARGS((typval_T *argvars, typval_T *rettv));
615static void f_remove __ARGS((typval_T *argvars, typval_T *rettv));
616static void f_rename __ARGS((typval_T *argvars, typval_T *rettv));
617static void f_repeat __ARGS((typval_T *argvars, typval_T *rettv));
618static void f_resolve __ARGS((typval_T *argvars, typval_T *rettv));
619static void f_reverse __ARGS((typval_T *argvars, typval_T *rettv));
620static void f_search __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaardd2436f2005-09-05 22:14:46 +0000621static void f_searchdecl __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000622static void f_searchpair __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000623static void f_searchpairpos __ARGS((typval_T *argvars, typval_T *rettv));
624static void f_searchpos __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000625static void f_server2client __ARGS((typval_T *argvars, typval_T *rettv));
626static void f_serverlist __ARGS((typval_T *argvars, typval_T *rettv));
627static void f_setbufvar __ARGS((typval_T *argvars, typval_T *rettv));
628static void f_setcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
629static void f_setline __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar17c7c012006-01-26 22:25:15 +0000630static void f_setloclist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar0e34f622006-03-03 23:00:03 +0000631static void f_setpos __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2641f772005-03-25 21:58:17 +0000632static void f_setqflist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000633static void f_setreg __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar99ebf042006-04-15 20:28:54 +0000634static void f_settabwinvar __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000635static void f_setwinvar __ARGS((typval_T *argvars, typval_T *rettv));
636static void f_simplify __ARGS((typval_T *argvars, typval_T *rettv));
637static void f_sort __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +0000638static void f_soundfold __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaard857f0e2005-06-21 22:37:39 +0000639static void f_spellbadword __ARGS((typval_T *argvars, typval_T *rettv));
640static void f_spellsuggest __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000641static void f_split __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2c932302006-03-18 21:42:09 +0000642static void f_str2nr __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000643#ifdef HAVE_STRFTIME
644static void f_strftime __ARGS((typval_T *argvars, typval_T *rettv));
645#endif
646static void f_stridx __ARGS((typval_T *argvars, typval_T *rettv));
647static void f_string __ARGS((typval_T *argvars, typval_T *rettv));
648static void f_strlen __ARGS((typval_T *argvars, typval_T *rettv));
649static void f_strpart __ARGS((typval_T *argvars, typval_T *rettv));
650static void f_strridx __ARGS((typval_T *argvars, typval_T *rettv));
651static void f_strtrans __ARGS((typval_T *argvars, typval_T *rettv));
652static void f_submatch __ARGS((typval_T *argvars, typval_T *rettv));
653static void f_substitute __ARGS((typval_T *argvars, typval_T *rettv));
654static void f_synID __ARGS((typval_T *argvars, typval_T *rettv));
655static void f_synIDattr __ARGS((typval_T *argvars, typval_T *rettv));
656static void f_synIDtrans __ARGS((typval_T *argvars, typval_T *rettv));
657static void f_system __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaarfaa959a2006-02-20 21:37:40 +0000658static void f_tabpagebuflist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar7e8fd632006-02-18 22:14:51 +0000659static void f_tabpagenr __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaarfaa959a2006-02-20 21:37:40 +0000660static void f_tabpagewinnr __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar19a09a12005-03-04 23:39:37 +0000661static void f_taglist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaard43b6cf2005-09-09 19:53:42 +0000662static void f_tagfiles __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000663static void f_tempname __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaard52d9742005-08-21 22:20:28 +0000664static void f_test __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000665static void f_tolower __ARGS((typval_T *argvars, typval_T *rettv));
666static void f_toupper __ARGS((typval_T *argvars, typval_T *rettv));
667static void f_tr __ARGS((typval_T *argvars, typval_T *rettv));
668static void f_type __ARGS((typval_T *argvars, typval_T *rettv));
669static void f_values __ARGS((typval_T *argvars, typval_T *rettv));
670static void f_virtcol __ARGS((typval_T *argvars, typval_T *rettv));
671static void f_visualmode __ARGS((typval_T *argvars, typval_T *rettv));
672static void f_winbufnr __ARGS((typval_T *argvars, typval_T *rettv));
673static void f_wincol __ARGS((typval_T *argvars, typval_T *rettv));
674static void f_winheight __ARGS((typval_T *argvars, typval_T *rettv));
675static void f_winline __ARGS((typval_T *argvars, typval_T *rettv));
676static void f_winnr __ARGS((typval_T *argvars, typval_T *rettv));
677static void f_winrestcmd __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar768b8c42006-03-04 21:58:33 +0000678static void f_winrestview __ARGS((typval_T *argvars, typval_T *rettv));
679static void f_winsaveview __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000680static void f_winwidth __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000681static void f_writefile __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000682
Bram Moolenaar0e34f622006-03-03 23:00:03 +0000683static int list2fpos __ARGS((typval_T *arg, pos_T *posp, int *fnump));
684static pos_T *var2fpos __ARGS((typval_T *varp, int lnum, int *fnum));
Bram Moolenaar33570922005-01-25 22:26:29 +0000685static int get_env_len __ARGS((char_u **arg));
686static int get_id_len __ARGS((char_u **arg));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000687static int get_name_len __ARGS((char_u **arg, char_u **alias, int evaluate, int verbose));
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000688static char_u *find_name_end __ARGS((char_u *arg, char_u **expr_start, char_u **expr_end, int flags));
689#define FNE_INCL_BR 1 /* find_name_end(): include [] in name */
690#define FNE_CHECK_START 2 /* find_name_end(): check name starts with
691 valid character */
Bram Moolenaara40058a2005-07-11 22:42:07 +0000692static 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 +0000693static int eval_isnamec __ARGS((int c));
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000694static int eval_isnamec1 __ARGS((int c));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000695static int get_var_tv __ARGS((char_u *name, int len, typval_T *rettv, int verbose));
696static int handle_subscript __ARGS((char_u **arg, typval_T *rettv, int evaluate, int verbose));
Bram Moolenaar33570922005-01-25 22:26:29 +0000697static typval_T *alloc_tv __ARGS((void));
698static typval_T *alloc_string_tv __ARGS((char_u *string));
Bram Moolenaar33570922005-01-25 22:26:29 +0000699static void init_tv __ARGS((typval_T *varp));
700static long get_tv_number __ARGS((typval_T *varp));
701static linenr_T get_tv_lnum __ARGS((typval_T *argvars));
Bram Moolenaar661b1822005-07-28 22:36:45 +0000702static linenr_T get_tv_lnum_buf __ARGS((typval_T *argvars, buf_T *buf));
Bram Moolenaar33570922005-01-25 22:26:29 +0000703static char_u *get_tv_string __ARGS((typval_T *varp));
704static char_u *get_tv_string_buf __ARGS((typval_T *varp, char_u *buf));
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +0000705static char_u *get_tv_string_buf_chk __ARGS((typval_T *varp, char_u *buf));
Bram Moolenaar33570922005-01-25 22:26:29 +0000706static dictitem_T *find_var __ARGS((char_u *name, hashtab_T **htp));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000707static dictitem_T *find_var_in_ht __ARGS((hashtab_T *ht, char_u *varname, int writing));
Bram Moolenaar33570922005-01-25 22:26:29 +0000708static hashtab_T *find_var_ht __ARGS((char_u *name, char_u **varname));
709static void vars_clear_ext __ARGS((hashtab_T *ht, int free_val));
710static void delete_var __ARGS((hashtab_T *ht, hashitem_T *hi));
711static void list_one_var __ARGS((dictitem_T *v, char_u *prefix));
712static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string));
713static void set_var __ARGS((char_u *name, typval_T *varp, int copy));
714static int var_check_ro __ARGS((int flags, char_u *name));
Bram Moolenaar4e957af2006-09-02 11:41:07 +0000715static int var_check_fixed __ARGS((int flags, char_u *name));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000716static int tv_check_lock __ARGS((int lock, char_u *name));
Bram Moolenaar33570922005-01-25 22:26:29 +0000717static void copy_tv __ARGS((typval_T *from, typval_T *to));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000718static int item_copy __ARGS((typval_T *from, typval_T *to, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000719static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags));
720static char_u *trans_function_name __ARGS((char_u **pp, int skip, int flags, funcdict_T *fd));
721static int eval_fname_script __ARGS((char_u *p));
722static int eval_fname_sid __ARGS((char_u *p));
723static void list_func_head __ARGS((ufunc_T *fp, int indent));
Bram Moolenaar33570922005-01-25 22:26:29 +0000724static ufunc_T *find_func __ARGS((char_u *name));
725static int function_exists __ARGS((char_u *name));
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +0000726static int builtin_function __ARGS((char_u *name));
Bram Moolenaar05159a02005-02-26 23:04:13 +0000727#ifdef FEAT_PROFILE
728static void func_do_profile __ARGS((ufunc_T *fp));
Bram Moolenaar73830342005-02-28 22:48:19 +0000729static void prof_sort_list __ARGS((FILE *fd, ufunc_T **sorttab, int st_len, char *title, int prefer_self));
730static void prof_func_line __ARGS((FILE *fd, int count, proftime_T *total, proftime_T *self, int prefer_self));
731static int
732# ifdef __BORLANDC__
733 _RTLENTRYF
734# endif
735 prof_total_cmp __ARGS((const void *s1, const void *s2));
736static int
737# ifdef __BORLANDC__
738 _RTLENTRYF
739# endif
740 prof_self_cmp __ARGS((const void *s1, const void *s2));
Bram Moolenaar05159a02005-02-26 23:04:13 +0000741#endif
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000742static int script_autoload __ARGS((char_u *name, int reload));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000743static char_u *autoload_name __ARGS((char_u *name));
Bram Moolenaara40058a2005-07-11 22:42:07 +0000744static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp));
Bram Moolenaar33570922005-01-25 22:26:29 +0000745static void func_free __ARGS((ufunc_T *fp));
746static void func_unref __ARGS((char_u *name));
747static void func_ref __ARGS((char_u *name));
748static 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));
749static void add_nr_var __ARGS((dict_T *dp, dictitem_T *v, char *name, varnumber_T nr));
Bram Moolenaar99ebf042006-04-15 20:28:54 +0000750static win_T *find_win_by_nr __ARGS((typval_T *vp, tabpage_T *tp));
751static void getwinvar __ARGS((typval_T *argvars, typval_T *rettv, int off));
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000752static int searchpair_cmn __ARGS((typval_T *argvars, pos_T *match_pos));
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000753static int search_cmn __ARGS((typval_T *argvars, pos_T *match_pos, int *flagsp));
Bram Moolenaar99ebf042006-04-15 20:28:54 +0000754static void setwinvar __ARGS((typval_T *argvars, typval_T *rettv, int off));
Bram Moolenaar33570922005-01-25 22:26:29 +0000755
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000756/* Character used as separated in autoload function/variable names. */
757#define AUTOLOAD_CHAR '#'
758
Bram Moolenaar33570922005-01-25 22:26:29 +0000759/*
760 * Initialize the global and v: variables.
Bram Moolenaara7043832005-01-21 11:56:39 +0000761 */
762 void
763eval_init()
764{
Bram Moolenaar33570922005-01-25 22:26:29 +0000765 int i;
766 struct vimvar *p;
767
768 init_var_dict(&globvardict, &globvars_var);
769 init_var_dict(&vimvardict, &vimvars_var);
Bram Moolenaar532c7802005-01-27 14:44:31 +0000770 hash_init(&compat_hashtab);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000771 hash_init(&func_hashtab);
Bram Moolenaar33570922005-01-25 22:26:29 +0000772
773 for (i = 0; i < VV_LEN; ++i)
774 {
775 p = &vimvars[i];
776 STRCPY(p->vv_di.di_key, p->vv_name);
777 if (p->vv_flags & VV_RO)
778 p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
779 else if (p->vv_flags & VV_RO_SBX)
780 p->vv_di.di_flags = DI_FLAGS_RO_SBX | DI_FLAGS_FIX;
781 else
782 p->vv_di.di_flags = DI_FLAGS_FIX;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000783
784 /* add to v: scope dict, unless the value is not always available */
785 if (p->vv_type != VAR_UNKNOWN)
786 hash_add(&vimvarht, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000787 if (p->vv_flags & VV_COMPAT)
Bram Moolenaar532c7802005-01-27 14:44:31 +0000788 /* add to compat scope dict */
789 hash_add(&compat_hashtab, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000790 }
Bram Moolenaara7043832005-01-21 11:56:39 +0000791}
792
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000793#if defined(EXITFREE) || defined(PROTO)
794 void
795eval_clear()
796{
797 int i;
798 struct vimvar *p;
799
800 for (i = 0; i < VV_LEN; ++i)
801 {
802 p = &vimvars[i];
803 if (p->vv_di.di_tv.v_type == VAR_STRING)
Bram Moolenaard9fba312005-06-26 22:34:35 +0000804 {
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000805 vim_free(p->vv_di.di_tv.vval.v_string);
Bram Moolenaard9fba312005-06-26 22:34:35 +0000806 p->vv_di.di_tv.vval.v_string = NULL;
807 }
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000808 }
809 hash_clear(&vimvarht);
810 hash_clear(&compat_hashtab);
811
812 /* script-local variables */
813 for (i = 1; i <= ga_scripts.ga_len; ++i)
814 vars_clear(&SCRIPT_VARS(i));
815 ga_clear(&ga_scripts);
Bram Moolenaard9fba312005-06-26 22:34:35 +0000816 free_scriptnames();
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000817
818 /* global variables */
819 vars_clear(&globvarht);
Bram Moolenaard9fba312005-06-26 22:34:35 +0000820
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000821 /* functions */
Bram Moolenaard9fba312005-06-26 22:34:35 +0000822 free_all_functions();
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000823 hash_clear(&func_hashtab);
824
Bram Moolenaaraa35dd12006-04-29 22:03:41 +0000825 /* autoloaded script names */
826 ga_clear_strings(&ga_loaded);
827
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000828 /* unreferenced lists and dicts */
829 (void)garbage_collect();
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000830}
831#endif
832
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000833/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000834 * Return the name of the executed function.
835 */
836 char_u *
837func_name(cookie)
838 void *cookie;
839{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000840 return ((funccall_T *)cookie)->func->uf_name;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000841}
842
843/*
844 * Return the address holding the next breakpoint line for a funccall cookie.
845 */
846 linenr_T *
847func_breakpoint(cookie)
848 void *cookie;
849{
Bram Moolenaar33570922005-01-25 22:26:29 +0000850 return &((funccall_T *)cookie)->breakpoint;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000851}
852
853/*
854 * Return the address holding the debug tick for a funccall cookie.
855 */
856 int *
857func_dbg_tick(cookie)
858 void *cookie;
859{
Bram Moolenaar33570922005-01-25 22:26:29 +0000860 return &((funccall_T *)cookie)->dbg_tick;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000861}
862
863/*
864 * Return the nesting level for a funccall cookie.
865 */
866 int
867func_level(cookie)
868 void *cookie;
869{
Bram Moolenaar33570922005-01-25 22:26:29 +0000870 return ((funccall_T *)cookie)->level;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000871}
872
873/* pointer to funccal for currently active function */
Bram Moolenaar33570922005-01-25 22:26:29 +0000874funccall_T *current_funccal = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000875
876/*
877 * Return TRUE when a function was ended by a ":return" command.
878 */
879 int
880current_func_returned()
881{
882 return current_funccal->returned;
883}
884
885
886/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000887 * Set an internal variable to a string value. Creates the variable if it does
888 * not already exist.
889 */
890 void
891set_internal_string_var(name, value)
892 char_u *name;
893 char_u *value;
894{
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000895 char_u *val;
Bram Moolenaar33570922005-01-25 22:26:29 +0000896 typval_T *tvp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000897
898 val = vim_strsave(value);
899 if (val != NULL)
900 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000901 tvp = alloc_string_tv(val);
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000902 if (tvp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000903 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000904 set_var(name, tvp, FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000905 free_tv(tvp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000906 }
907 }
908}
909
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000910static lval_T *redir_lval = NULL;
911static char_u *redir_endp = NULL;
912static char_u *redir_varname = NULL;
913
914/*
915 * Start recording command output to a variable
916 * Returns OK if successfully completed the setup. FAIL otherwise.
917 */
918 int
919var_redir_start(name, append)
920 char_u *name;
921 int append; /* append to an existing variable */
922{
923 int save_emsg;
924 int err;
925 typval_T tv;
926
927 /* Make sure a valid variable name is specified */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000928 if (!eval_isnamec1(*name))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000929 {
930 EMSG(_(e_invarg));
931 return FAIL;
932 }
933
934 redir_varname = vim_strsave(name);
935 if (redir_varname == NULL)
936 return FAIL;
937
938 redir_lval = (lval_T *)alloc_clear((unsigned)sizeof(lval_T));
939 if (redir_lval == NULL)
940 {
941 var_redir_stop();
942 return FAIL;
943 }
944
945 /* Parse the variable name (can be a dict or list entry). */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000946 redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, FALSE,
947 FNE_CHECK_START);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000948 if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != NUL)
949 {
950 if (redir_endp != NULL && *redir_endp != NUL)
951 /* Trailing characters are present after the variable name */
952 EMSG(_(e_trailing));
953 else
954 EMSG(_(e_invarg));
955 var_redir_stop();
956 return FAIL;
957 }
958
959 /* check if we can write to the variable: set it to or append an empty
960 * string */
961 save_emsg = did_emsg;
962 did_emsg = FALSE;
963 tv.v_type = VAR_STRING;
964 tv.vval.v_string = (char_u *)"";
965 if (append)
966 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)".");
967 else
968 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)"=");
969 err = did_emsg;
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000970 did_emsg |= save_emsg;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000971 if (err)
972 {
973 var_redir_stop();
974 return FAIL;
975 }
976 if (redir_lval->ll_newkey != NULL)
977 {
978 /* Dictionary item was created, don't do it again. */
979 vim_free(redir_lval->ll_newkey);
980 redir_lval->ll_newkey = NULL;
981 }
982
983 return OK;
984}
985
986/*
987 * Append "value[len]" to the variable set by var_redir_start().
988 */
989 void
990var_redir_str(value, len)
991 char_u *value;
992 int len;
993{
994 char_u *val;
995 typval_T tv;
996 int save_emsg;
997 int err;
998
999 if (redir_lval == NULL)
1000 return;
1001
1002 if (len == -1)
1003 /* Append the entire string */
1004 val = vim_strsave(value);
1005 else
1006 /* Append only the specified number of characters */
1007 val = vim_strnsave(value, len);
1008 if (val == NULL)
1009 return;
1010
1011 tv.v_type = VAR_STRING;
1012 tv.vval.v_string = val;
1013
1014 save_emsg = did_emsg;
1015 did_emsg = FALSE;
1016 set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)".");
1017 err = did_emsg;
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00001018 did_emsg |= save_emsg;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001019 if (err)
1020 var_redir_stop();
1021
1022 vim_free(tv.vval.v_string);
1023}
1024
1025/*
1026 * Stop redirecting command output to a variable.
1027 */
1028 void
1029var_redir_stop()
1030{
1031 if (redir_lval != NULL)
1032 {
1033 clear_lval(redir_lval);
1034 vim_free(redir_lval);
1035 redir_lval = NULL;
1036 }
1037 vim_free(redir_varname);
1038 redir_varname = NULL;
1039}
1040
Bram Moolenaar071d4272004-06-13 20:20:40 +00001041# if defined(FEAT_MBYTE) || defined(PROTO)
1042 int
1043eval_charconvert(enc_from, enc_to, fname_from, fname_to)
1044 char_u *enc_from;
1045 char_u *enc_to;
1046 char_u *fname_from;
1047 char_u *fname_to;
1048{
1049 int err = FALSE;
1050
1051 set_vim_var_string(VV_CC_FROM, enc_from, -1);
1052 set_vim_var_string(VV_CC_TO, enc_to, -1);
1053 set_vim_var_string(VV_FNAME_IN, fname_from, -1);
1054 set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
1055 if (eval_to_bool(p_ccv, &err, NULL, FALSE))
1056 err = TRUE;
1057 set_vim_var_string(VV_CC_FROM, NULL, -1);
1058 set_vim_var_string(VV_CC_TO, NULL, -1);
1059 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1060 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
1061
1062 if (err)
1063 return FAIL;
1064 return OK;
1065}
1066# endif
1067
1068# if defined(FEAT_POSTSCRIPT) || defined(PROTO)
1069 int
1070eval_printexpr(fname, args)
1071 char_u *fname;
1072 char_u *args;
1073{
1074 int err = FALSE;
1075
1076 set_vim_var_string(VV_FNAME_IN, fname, -1);
1077 set_vim_var_string(VV_CMDARG, args, -1);
1078 if (eval_to_bool(p_pexpr, &err, NULL, FALSE))
1079 err = TRUE;
1080 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1081 set_vim_var_string(VV_CMDARG, NULL, -1);
1082
1083 if (err)
1084 {
1085 mch_remove(fname);
1086 return FAIL;
1087 }
1088 return OK;
1089}
1090# endif
1091
1092# if defined(FEAT_DIFF) || defined(PROTO)
1093 void
1094eval_diff(origfile, newfile, outfile)
1095 char_u *origfile;
1096 char_u *newfile;
1097 char_u *outfile;
1098{
1099 int err = FALSE;
1100
1101 set_vim_var_string(VV_FNAME_IN, origfile, -1);
1102 set_vim_var_string(VV_FNAME_NEW, newfile, -1);
1103 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
1104 (void)eval_to_bool(p_dex, &err, NULL, FALSE);
1105 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1106 set_vim_var_string(VV_FNAME_NEW, NULL, -1);
1107 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
1108}
1109
1110 void
1111eval_patch(origfile, difffile, outfile)
1112 char_u *origfile;
1113 char_u *difffile;
1114 char_u *outfile;
1115{
1116 int err;
1117
1118 set_vim_var_string(VV_FNAME_IN, origfile, -1);
1119 set_vim_var_string(VV_FNAME_DIFF, difffile, -1);
1120 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
1121 (void)eval_to_bool(p_pex, &err, NULL, FALSE);
1122 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1123 set_vim_var_string(VV_FNAME_DIFF, NULL, -1);
1124 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
1125}
1126# endif
1127
1128/*
1129 * Top level evaluation function, returning a boolean.
1130 * Sets "error" to TRUE if there was an error.
1131 * Return TRUE or FALSE.
1132 */
1133 int
1134eval_to_bool(arg, error, nextcmd, skip)
1135 char_u *arg;
1136 int *error;
1137 char_u **nextcmd;
1138 int skip; /* only parse, don't execute */
1139{
Bram Moolenaar33570922005-01-25 22:26:29 +00001140 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001141 int retval = FALSE;
1142
1143 if (skip)
1144 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001145 if (eval0(arg, &tv, nextcmd, !skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001146 *error = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001147 else
1148 {
1149 *error = FALSE;
1150 if (!skip)
1151 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001152 retval = (get_tv_number_chk(&tv, error) != 0);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001153 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001154 }
1155 }
1156 if (skip)
1157 --emsg_skip;
1158
1159 return retval;
1160}
1161
1162/*
1163 * Top level evaluation function, returning a string. If "skip" is TRUE,
1164 * only parsing to "nextcmd" is done, without reporting errors. Return
1165 * pointer to allocated memory, or NULL for failure or when "skip" is TRUE.
1166 */
1167 char_u *
1168eval_to_string_skip(arg, nextcmd, skip)
1169 char_u *arg;
1170 char_u **nextcmd;
1171 int skip; /* only parse, don't execute */
1172{
Bram Moolenaar33570922005-01-25 22:26:29 +00001173 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001174 char_u *retval;
1175
1176 if (skip)
1177 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001178 if (eval0(arg, &tv, nextcmd, !skip) == FAIL || skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001179 retval = NULL;
1180 else
1181 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001182 retval = vim_strsave(get_tv_string(&tv));
1183 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001184 }
1185 if (skip)
1186 --emsg_skip;
1187
1188 return retval;
1189}
1190
1191/*
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001192 * Skip over an expression at "*pp".
1193 * Return FAIL for an error, OK otherwise.
1194 */
1195 int
1196skip_expr(pp)
1197 char_u **pp;
1198{
Bram Moolenaar33570922005-01-25 22:26:29 +00001199 typval_T rettv;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001200
1201 *pp = skipwhite(*pp);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001202 return eval1(pp, &rettv, FALSE);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001203}
1204
1205/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00001206 * Top level evaluation function, returning a string.
1207 * Return pointer to allocated memory, or NULL for failure.
1208 */
1209 char_u *
Bram Moolenaar362e1a32006-03-06 23:29:24 +00001210eval_to_string(arg, nextcmd, dolist)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001211 char_u *arg;
1212 char_u **nextcmd;
Bram Moolenaar362e1a32006-03-06 23:29:24 +00001213 int dolist; /* turn List into sequence of lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001214{
Bram Moolenaar33570922005-01-25 22:26:29 +00001215 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001216 char_u *retval;
Bram Moolenaar362e1a32006-03-06 23:29:24 +00001217 garray_T ga;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001218
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001219 if (eval0(arg, &tv, nextcmd, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001220 retval = NULL;
1221 else
1222 {
Bram Moolenaar362e1a32006-03-06 23:29:24 +00001223 if (dolist && tv.v_type == VAR_LIST)
1224 {
1225 ga_init2(&ga, (int)sizeof(char), 80);
1226 list_join(&ga, tv.vval.v_list, (char_u *)"\n", TRUE, 0);
1227 ga_append(&ga, NUL);
1228 retval = (char_u *)ga.ga_data;
1229 }
1230 else
1231 retval = vim_strsave(get_tv_string(&tv));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001232 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001233 }
1234
1235 return retval;
1236}
1237
1238/*
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001239 * Call eval_to_string() without using current local variables and using
1240 * textlock. When "use_sandbox" is TRUE use the sandbox.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001241 */
1242 char_u *
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001243eval_to_string_safe(arg, nextcmd, use_sandbox)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001244 char_u *arg;
1245 char_u **nextcmd;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001246 int use_sandbox;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001247{
1248 char_u *retval;
1249 void *save_funccalp;
1250
1251 save_funccalp = save_funccal();
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001252 if (use_sandbox)
1253 ++sandbox;
1254 ++textlock;
Bram Moolenaar362e1a32006-03-06 23:29:24 +00001255 retval = eval_to_string(arg, nextcmd, FALSE);
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001256 if (use_sandbox)
1257 --sandbox;
1258 --textlock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001259 restore_funccal(save_funccalp);
1260 return retval;
1261}
1262
Bram Moolenaar071d4272004-06-13 20:20:40 +00001263/*
1264 * Top level evaluation function, returning a number.
1265 * Evaluates "expr" silently.
1266 * Returns -1 for an error.
1267 */
1268 int
1269eval_to_number(expr)
1270 char_u *expr;
1271{
Bram Moolenaar33570922005-01-25 22:26:29 +00001272 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001273 int retval;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00001274 char_u *p = skipwhite(expr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001275
1276 ++emsg_off;
1277
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001278 if (eval1(&p, &rettv, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001279 retval = -1;
1280 else
1281 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001282 retval = get_tv_number_chk(&rettv, NULL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001283 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001284 }
1285 --emsg_off;
1286
1287 return retval;
1288}
1289
Bram Moolenaara40058a2005-07-11 22:42:07 +00001290/*
1291 * Prepare v: variable "idx" to be used.
1292 * Save the current typeval in "save_tv".
1293 * When not used yet add the variable to the v: hashtable.
1294 */
1295 static void
1296prepare_vimvar(idx, save_tv)
1297 int idx;
1298 typval_T *save_tv;
1299{
1300 *save_tv = vimvars[idx].vv_tv;
1301 if (vimvars[idx].vv_type == VAR_UNKNOWN)
1302 hash_add(&vimvarht, vimvars[idx].vv_di.di_key);
1303}
1304
1305/*
1306 * Restore v: variable "idx" to typeval "save_tv".
1307 * When no longer defined, remove the variable from the v: hashtable.
1308 */
1309 static void
1310restore_vimvar(idx, save_tv)
1311 int idx;
1312 typval_T *save_tv;
1313{
1314 hashitem_T *hi;
1315
1316 clear_tv(&vimvars[idx].vv_tv);
1317 vimvars[idx].vv_tv = *save_tv;
1318 if (vimvars[idx].vv_type == VAR_UNKNOWN)
1319 {
1320 hi = hash_find(&vimvarht, vimvars[idx].vv_di.di_key);
1321 if (HASHITEM_EMPTY(hi))
1322 EMSG2(_(e_intern2), "restore_vimvar()");
1323 else
1324 hash_remove(&vimvarht, hi);
1325 }
1326}
1327
Bram Moolenaar3c56a962006-03-12 22:19:04 +00001328#if defined(FEAT_SPELL) || defined(PROTO)
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001329/*
1330 * Evaluate an expression to a list with suggestions.
1331 * For the "expr:" part of 'spellsuggest'.
1332 */
1333 list_T *
1334eval_spell_expr(badword, expr)
1335 char_u *badword;
1336 char_u *expr;
1337{
1338 typval_T save_val;
1339 typval_T rettv;
1340 list_T *list = NULL;
1341 char_u *p = skipwhite(expr);
1342
1343 /* Set "v:val" to the bad word. */
1344 prepare_vimvar(VV_VAL, &save_val);
1345 vimvars[VV_VAL].vv_type = VAR_STRING;
1346 vimvars[VV_VAL].vv_str = badword;
1347 if (p_verbose == 0)
1348 ++emsg_off;
1349
1350 if (eval1(&p, &rettv, TRUE) == OK)
1351 {
1352 if (rettv.v_type != VAR_LIST)
1353 clear_tv(&rettv);
1354 else
1355 list = rettv.vval.v_list;
1356 }
1357
1358 if (p_verbose == 0)
1359 --emsg_off;
1360 vimvars[VV_VAL].vv_str = NULL;
1361 restore_vimvar(VV_VAL, &save_val);
1362
1363 return list;
1364}
1365
1366/*
1367 * "list" is supposed to contain two items: a word and a number. Return the
1368 * word in "pp" and the number as the return value.
1369 * Return -1 if anything isn't right.
1370 * Used to get the good word and score from the eval_spell_expr() result.
1371 */
1372 int
1373get_spellword(list, pp)
1374 list_T *list;
1375 char_u **pp;
1376{
1377 listitem_T *li;
1378
1379 li = list->lv_first;
1380 if (li == NULL)
1381 return -1;
1382 *pp = get_tv_string(&li->li_tv);
1383
1384 li = li->li_next;
1385 if (li == NULL)
1386 return -1;
1387 return get_tv_number(&li->li_tv);
1388}
1389#endif
1390
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001391/*
Bram Moolenaar4770d092006-01-12 23:22:24 +00001392 * Top level evaluation function.
1393 * Returns an allocated typval_T with the result.
1394 * Returns NULL when there is an error.
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001395 */
1396 typval_T *
1397eval_expr(arg, nextcmd)
1398 char_u *arg;
1399 char_u **nextcmd;
1400{
1401 typval_T *tv;
1402
1403 tv = (typval_T *)alloc(sizeof(typval_T));
Bram Moolenaar4770d092006-01-12 23:22:24 +00001404 if (tv != NULL && eval0(arg, tv, nextcmd, TRUE) == FAIL)
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001405 {
1406 vim_free(tv);
Bram Moolenaar4770d092006-01-12 23:22:24 +00001407 tv = NULL;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001408 }
1409
1410 return tv;
1411}
1412
1413
Bram Moolenaar071d4272004-06-13 20:20:40 +00001414#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO)
1415/*
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001416 * Call some vimL function and return the result in "*rettv".
Bram Moolenaar071d4272004-06-13 20:20:40 +00001417 * Uses argv[argc] for the function arguments.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001418 * Returns OK or FAIL.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001419 */
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001420 static int
1421call_vim_function(func, argc, argv, safe, rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001422 char_u *func;
1423 int argc;
1424 char_u **argv;
1425 int safe; /* use the sandbox */
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001426 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001427{
Bram Moolenaar33570922005-01-25 22:26:29 +00001428 typval_T *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001429 long n;
1430 int len;
1431 int i;
1432 int doesrange;
1433 void *save_funccalp = NULL;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001434 int ret;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001435
Bram Moolenaareb3593b2006-04-22 22:33:57 +00001436 argvars = (typval_T *)alloc((unsigned)((argc + 1) * sizeof(typval_T)));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001437 if (argvars == NULL)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001438 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001439
1440 for (i = 0; i < argc; i++)
1441 {
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00001442 /* Pass a NULL or empty argument as an empty string */
1443 if (argv[i] == NULL || *argv[i] == NUL)
1444 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001445 argvars[i].v_type = VAR_STRING;
1446 argvars[i].vval.v_string = (char_u *)"";
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00001447 continue;
1448 }
1449
Bram Moolenaar071d4272004-06-13 20:20:40 +00001450 /* Recognize a number argument, the others must be strings. */
1451 vim_str2nr(argv[i], NULL, &len, TRUE, TRUE, &n, NULL);
1452 if (len != 0 && len == (int)STRLEN(argv[i]))
1453 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001454 argvars[i].v_type = VAR_NUMBER;
1455 argvars[i].vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001456 }
1457 else
1458 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001459 argvars[i].v_type = VAR_STRING;
1460 argvars[i].vval.v_string = argv[i];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001461 }
1462 }
1463
1464 if (safe)
1465 {
1466 save_funccalp = save_funccal();
1467 ++sandbox;
1468 }
1469
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001470 rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */
1471 ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001472 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001473 &doesrange, TRUE, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001474 if (safe)
1475 {
1476 --sandbox;
1477 restore_funccal(save_funccalp);
1478 }
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001479 vim_free(argvars);
1480
1481 if (ret == FAIL)
1482 clear_tv(rettv);
1483
1484 return ret;
1485}
1486
1487/*
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001488 * Call vimL function "func" and return the result as a string.
1489 * Returns NULL when calling the function fails.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001490 * Uses argv[argc] for the function arguments.
1491 */
1492 void *
1493call_func_retstr(func, argc, argv, safe)
1494 char_u *func;
1495 int argc;
1496 char_u **argv;
1497 int safe; /* use the sandbox */
1498{
1499 typval_T rettv;
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001500 char_u *retval;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001501
1502 if (call_vim_function(func, argc, argv, safe, &rettv) == FAIL)
1503 return NULL;
1504
1505 retval = vim_strsave(get_tv_string(&rettv));
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001506 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001507 return retval;
1508}
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001509
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001510#if defined(FEAT_COMPL_FUNC) || defined(PROTO)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001511/*
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001512 * Call vimL function "func" and return the result as a number.
1513 * Returns -1 when calling the function fails.
1514 * Uses argv[argc] for the function arguments.
1515 */
1516 long
1517call_func_retnr(func, argc, argv, safe)
1518 char_u *func;
1519 int argc;
1520 char_u **argv;
1521 int safe; /* use the sandbox */
1522{
1523 typval_T rettv;
1524 long retval;
1525
1526 if (call_vim_function(func, argc, argv, safe, &rettv) == FAIL)
1527 return -1;
1528
1529 retval = get_tv_number_chk(&rettv, NULL);
1530 clear_tv(&rettv);
1531 return retval;
1532}
1533#endif
1534
1535/*
1536 * Call vimL function "func" and return the result as a list
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001537 * Uses argv[argc] for the function arguments.
1538 */
1539 void *
1540call_func_retlist(func, argc, argv, safe)
1541 char_u *func;
1542 int argc;
1543 char_u **argv;
1544 int safe; /* use the sandbox */
1545{
1546 typval_T rettv;
1547
1548 if (call_vim_function(func, argc, argv, safe, &rettv) == FAIL)
1549 return NULL;
1550
1551 if (rettv.v_type != VAR_LIST)
1552 {
1553 clear_tv(&rettv);
1554 return NULL;
1555 }
1556
1557 return rettv.vval.v_list;
1558}
1559
Bram Moolenaar071d4272004-06-13 20:20:40 +00001560#endif
1561
1562/*
1563 * Save the current function call pointer, and set it to NULL.
1564 * Used when executing autocommands and for ":source".
1565 */
1566 void *
1567save_funccal()
1568{
Bram Moolenaar05159a02005-02-26 23:04:13 +00001569 funccall_T *fc = current_funccal;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001570
Bram Moolenaar071d4272004-06-13 20:20:40 +00001571 current_funccal = NULL;
1572 return (void *)fc;
1573}
1574
1575 void
Bram Moolenaar05159a02005-02-26 23:04:13 +00001576restore_funccal(vfc)
1577 void *vfc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001578{
Bram Moolenaar05159a02005-02-26 23:04:13 +00001579 funccall_T *fc = (funccall_T *)vfc;
1580
1581 current_funccal = fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001582}
1583
Bram Moolenaar05159a02005-02-26 23:04:13 +00001584#if defined(FEAT_PROFILE) || defined(PROTO)
1585/*
1586 * Prepare profiling for entering a child or something else that is not
1587 * counted for the script/function itself.
1588 * Should always be called in pair with prof_child_exit().
1589 */
1590 void
1591prof_child_enter(tm)
1592 proftime_T *tm; /* place to store waittime */
1593{
1594 funccall_T *fc = current_funccal;
1595
1596 if (fc != NULL && fc->func->uf_profiling)
1597 profile_start(&fc->prof_child);
1598 script_prof_save(tm);
1599}
1600
1601/*
1602 * Take care of time spent in a child.
1603 * Should always be called after prof_child_enter().
1604 */
1605 void
1606prof_child_exit(tm)
1607 proftime_T *tm; /* where waittime was stored */
1608{
1609 funccall_T *fc = current_funccal;
1610
1611 if (fc != NULL && fc->func->uf_profiling)
1612 {
1613 profile_end(&fc->prof_child);
1614 profile_sub_wait(tm, &fc->prof_child); /* don't count waiting time */
1615 profile_add(&fc->func->uf_tm_children, &fc->prof_child);
1616 profile_add(&fc->func->uf_tml_children, &fc->prof_child);
1617 }
1618 script_prof_restore(tm);
1619}
1620#endif
1621
1622
Bram Moolenaar071d4272004-06-13 20:20:40 +00001623#ifdef FEAT_FOLDING
1624/*
1625 * Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding
1626 * it in "*cp". Doesn't give error messages.
1627 */
1628 int
1629eval_foldexpr(arg, cp)
1630 char_u *arg;
1631 int *cp;
1632{
Bram Moolenaar33570922005-01-25 22:26:29 +00001633 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001634 int retval;
1635 char_u *s;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00001636 int use_sandbox = was_set_insecurely((char_u *)"foldexpr",
1637 OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001638
1639 ++emsg_off;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001640 if (use_sandbox)
1641 ++sandbox;
1642 ++textlock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001643 *cp = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001644 if (eval0(arg, &tv, NULL, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001645 retval = 0;
1646 else
1647 {
1648 /* If the result is a number, just return the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001649 if (tv.v_type == VAR_NUMBER)
1650 retval = tv.vval.v_number;
Bram Moolenaar758711c2005-02-02 23:11:38 +00001651 else if (tv.v_type != VAR_STRING || tv.vval.v_string == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001652 retval = 0;
1653 else
1654 {
1655 /* If the result is a string, check if there is a non-digit before
1656 * the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001657 s = tv.vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001658 if (!VIM_ISDIGIT(*s) && *s != '-')
1659 *cp = *s++;
1660 retval = atol((char *)s);
1661 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001662 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001663 }
1664 --emsg_off;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001665 if (use_sandbox)
1666 --sandbox;
1667 --textlock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001668
1669 return retval;
1670}
1671#endif
1672
Bram Moolenaar071d4272004-06-13 20:20:40 +00001673/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001674 * ":let" list all variable values
1675 * ":let var1 var2" list variable values
1676 * ":let var = expr" assignment command.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001677 * ":let var += expr" assignment command.
1678 * ":let var -= expr" assignment command.
1679 * ":let var .= expr" assignment command.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001680 * ":let [var1, var2] = expr" unpack list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001681 */
1682 void
1683ex_let(eap)
1684 exarg_T *eap;
1685{
1686 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001687 char_u *expr = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00001688 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001689 int i;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001690 int var_count = 0;
1691 int semicolon = 0;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001692 char_u op[2];
Bram Moolenaardb552d602006-03-23 22:59:57 +00001693 char_u *argend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001694
Bram Moolenaardb552d602006-03-23 22:59:57 +00001695 argend = skip_var_list(arg, &var_count, &semicolon);
1696 if (argend == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001697 return;
Bram Moolenaar76b92b22006-03-24 22:46:53 +00001698 if (argend > arg && argend[-1] == '.') /* for var.='str' */
1699 --argend;
Bram Moolenaardb552d602006-03-23 22:59:57 +00001700 expr = vim_strchr(argend, '=');
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001701 if (expr == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001702 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001703 /*
1704 * ":let" without "=": list variables
1705 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001706 if (*arg == '[')
1707 EMSG(_(e_invarg));
1708 else if (!ends_excmd(*arg))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001709 /* ":let var1 var2" */
1710 arg = list_arg_vars(eap, arg);
1711 else if (!eap->skip)
Bram Moolenaara7043832005-01-21 11:56:39 +00001712 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001713 /* ":let" */
Bram Moolenaara7043832005-01-21 11:56:39 +00001714 list_glob_vars();
1715 list_buf_vars();
1716 list_win_vars();
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001717#ifdef FEAT_WINDOWS
1718 list_tab_vars();
1719#endif
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00001720 list_script_vars();
1721 list_func_vars();
Bram Moolenaara7043832005-01-21 11:56:39 +00001722 list_vim_vars();
1723 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001724 eap->nextcmd = check_nextcmd(arg);
1725 }
1726 else
1727 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001728 op[0] = '=';
1729 op[1] = NUL;
Bram Moolenaardb552d602006-03-23 22:59:57 +00001730 if (expr > argend)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001731 {
1732 if (vim_strchr((char_u *)"+-.", expr[-1]) != NULL)
1733 op[0] = expr[-1]; /* +=, -= or .= */
1734 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001735 expr = skipwhite(expr + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001736
Bram Moolenaar071d4272004-06-13 20:20:40 +00001737 if (eap->skip)
1738 ++emsg_skip;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001739 i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001740 if (eap->skip)
1741 {
1742 if (i != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001743 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001744 --emsg_skip;
1745 }
1746 else if (i != FAIL)
1747 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001748 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001749 op);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001750 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001751 }
1752 }
1753}
1754
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001755/*
1756 * Assign the typevalue "tv" to the variable or variables at "arg_start".
1757 * Handles both "var" with any type and "[var, var; var]" with a list type.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001758 * When "nextchars" is not NULL it points to a string with characters that
1759 * must appear after the variable(s). Use "+", "-" or "." for add, subtract
1760 * or concatenate.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001761 * Returns OK or FAIL;
1762 */
1763 static int
1764ex_let_vars(arg_start, tv, copy, semicolon, var_count, nextchars)
1765 char_u *arg_start;
Bram Moolenaar33570922005-01-25 22:26:29 +00001766 typval_T *tv;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001767 int copy; /* copy values from "tv", don't move */
1768 int semicolon; /* from skip_var_list() */
1769 int var_count; /* from skip_var_list() */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001770 char_u *nextchars;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001771{
1772 char_u *arg = arg_start;
Bram Moolenaar33570922005-01-25 22:26:29 +00001773 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001774 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00001775 listitem_T *item;
1776 typval_T ltv;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001777
1778 if (*arg != '[')
1779 {
1780 /*
1781 * ":let var = expr" or ":for var in list"
1782 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001783 if (ex_let_one(arg, tv, copy, nextchars, nextchars) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001784 return FAIL;
1785 return OK;
1786 }
1787
1788 /*
1789 * ":let [v1, v2] = list" or ":for [v1, v2] in listlist"
1790 */
Bram Moolenaar758711c2005-02-02 23:11:38 +00001791 if (tv->v_type != VAR_LIST || (l = tv->vval.v_list) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001792 {
1793 EMSG(_(e_listreq));
1794 return FAIL;
1795 }
1796
1797 i = list_len(l);
1798 if (semicolon == 0 && var_count < i)
1799 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00001800 EMSG(_("E687: Less targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001801 return FAIL;
1802 }
1803 if (var_count - semicolon > i)
1804 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00001805 EMSG(_("E688: More targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001806 return FAIL;
1807 }
1808
1809 item = l->lv_first;
1810 while (*arg != ']')
1811 {
1812 arg = skipwhite(arg + 1);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001813 arg = ex_let_one(arg, &item->li_tv, TRUE, (char_u *)",;]", nextchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001814 item = item->li_next;
1815 if (arg == NULL)
1816 return FAIL;
1817
1818 arg = skipwhite(arg);
1819 if (*arg == ';')
1820 {
1821 /* Put the rest of the list (may be empty) in the var after ';'.
1822 * Create a new list for this. */
1823 l = list_alloc();
1824 if (l == NULL)
1825 return FAIL;
1826 while (item != NULL)
1827 {
1828 list_append_tv(l, &item->li_tv);
1829 item = item->li_next;
1830 }
1831
1832 ltv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001833 ltv.v_lock = 0;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001834 ltv.vval.v_list = l;
1835 l->lv_refcount = 1;
1836
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001837 arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE,
1838 (char_u *)"]", nextchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001839 clear_tv(&ltv);
1840 if (arg == NULL)
1841 return FAIL;
1842 break;
1843 }
1844 else if (*arg != ',' && *arg != ']')
1845 {
1846 EMSG2(_(e_intern2), "ex_let_vars()");
1847 return FAIL;
1848 }
1849 }
1850
1851 return OK;
1852}
1853
1854/*
1855 * Skip over assignable variable "var" or list of variables "[var, var]".
1856 * Used for ":let varvar = expr" and ":for varvar in expr".
1857 * For "[var, var]" increment "*var_count" for each variable.
1858 * for "[var, var; var]" set "semicolon".
1859 * Return NULL for an error.
1860 */
1861 static char_u *
1862skip_var_list(arg, var_count, semicolon)
1863 char_u *arg;
1864 int *var_count;
1865 int *semicolon;
1866{
1867 char_u *p, *s;
1868
1869 if (*arg == '[')
1870 {
1871 /* "[var, var]": find the matching ']'. */
1872 p = arg;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001873 for (;;)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001874 {
1875 p = skipwhite(p + 1); /* skip whites after '[', ';' or ',' */
1876 s = skip_var_one(p);
1877 if (s == p)
1878 {
1879 EMSG2(_(e_invarg2), p);
1880 return NULL;
1881 }
1882 ++*var_count;
1883
1884 p = skipwhite(s);
1885 if (*p == ']')
1886 break;
1887 else if (*p == ';')
1888 {
1889 if (*semicolon == 1)
1890 {
1891 EMSG(_("Double ; in list of variables"));
1892 return NULL;
1893 }
1894 *semicolon = 1;
1895 }
1896 else if (*p != ',')
1897 {
1898 EMSG2(_(e_invarg2), p);
1899 return NULL;
1900 }
1901 }
1902 return p + 1;
1903 }
1904 else
1905 return skip_var_one(arg);
1906}
1907
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001908/*
Bram Moolenaar92124a32005-06-17 22:03:40 +00001909 * Skip one (assignable) variable name, includig @r, $VAR, &option, d.key,
1910 * l[idx].
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001911 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001912 static char_u *
1913skip_var_one(arg)
1914 char_u *arg;
1915{
Bram Moolenaar92124a32005-06-17 22:03:40 +00001916 if (*arg == '@' && arg[1] != NUL)
1917 return arg + 2;
1918 return find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg,
1919 NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001920}
1921
Bram Moolenaara7043832005-01-21 11:56:39 +00001922/*
Bram Moolenaar33570922005-01-25 22:26:29 +00001923 * List variables for hashtab "ht" with prefix "prefix".
1924 * If "empty" is TRUE also list NULL strings as empty strings.
Bram Moolenaara7043832005-01-21 11:56:39 +00001925 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001926 static void
Bram Moolenaar33570922005-01-25 22:26:29 +00001927list_hashtable_vars(ht, prefix, empty)
1928 hashtab_T *ht;
Bram Moolenaara7043832005-01-21 11:56:39 +00001929 char_u *prefix;
Bram Moolenaar33570922005-01-25 22:26:29 +00001930 int empty;
Bram Moolenaara7043832005-01-21 11:56:39 +00001931{
Bram Moolenaar33570922005-01-25 22:26:29 +00001932 hashitem_T *hi;
1933 dictitem_T *di;
Bram Moolenaara7043832005-01-21 11:56:39 +00001934 int todo;
1935
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00001936 todo = (int)ht->ht_used;
Bram Moolenaara7043832005-01-21 11:56:39 +00001937 for (hi = ht->ht_array; todo > 0 && !got_int; ++hi)
1938 {
1939 if (!HASHITEM_EMPTY(hi))
1940 {
1941 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00001942 di = HI2DI(hi);
1943 if (empty || di->di_tv.v_type != VAR_STRING
1944 || di->di_tv.vval.v_string != NULL)
1945 list_one_var(di, prefix);
Bram Moolenaara7043832005-01-21 11:56:39 +00001946 }
1947 }
1948}
1949
1950/*
1951 * List global variables.
1952 */
1953 static void
1954list_glob_vars()
1955{
Bram Moolenaar33570922005-01-25 22:26:29 +00001956 list_hashtable_vars(&globvarht, (char_u *)"", TRUE);
Bram Moolenaara7043832005-01-21 11:56:39 +00001957}
1958
1959/*
1960 * List buffer variables.
1961 */
1962 static void
1963list_buf_vars()
1964{
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001965 char_u numbuf[NUMBUFLEN];
1966
Bram Moolenaar33570922005-01-25 22:26:29 +00001967 list_hashtable_vars(&curbuf->b_vars.dv_hashtab, (char_u *)"b:", TRUE);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001968
1969 sprintf((char *)numbuf, "%ld", (long)curbuf->b_changedtick);
1970 list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER, numbuf);
Bram Moolenaara7043832005-01-21 11:56:39 +00001971}
1972
1973/*
1974 * List window variables.
1975 */
1976 static void
1977list_win_vars()
1978{
Bram Moolenaar33570922005-01-25 22:26:29 +00001979 list_hashtable_vars(&curwin->w_vars.dv_hashtab, (char_u *)"w:", TRUE);
Bram Moolenaara7043832005-01-21 11:56:39 +00001980}
1981
Bram Moolenaar910f66f2006-04-05 20:41:53 +00001982#ifdef FEAT_WINDOWS
1983/*
1984 * List tab page variables.
1985 */
1986 static void
1987list_tab_vars()
1988{
1989 list_hashtable_vars(&curtab->tp_vars.dv_hashtab, (char_u *)"t:", TRUE);
1990}
1991#endif
1992
Bram Moolenaara7043832005-01-21 11:56:39 +00001993/*
1994 * List Vim variables.
1995 */
1996 static void
1997list_vim_vars()
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001998{
Bram Moolenaar33570922005-01-25 22:26:29 +00001999 list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002000}
2001
2002/*
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00002003 * List script-local variables, if there is a script.
2004 */
2005 static void
2006list_script_vars()
2007{
2008 if (current_SID > 0 && current_SID <= ga_scripts.ga_len)
2009 list_hashtable_vars(&SCRIPT_VARS(current_SID), (char_u *)"s:", FALSE);
2010}
2011
2012/*
2013 * List function variables, if there is a function.
2014 */
2015 static void
2016list_func_vars()
2017{
2018 if (current_funccal != NULL)
2019 list_hashtable_vars(&current_funccal->l_vars.dv_hashtab,
2020 (char_u *)"l:", FALSE);
2021}
2022
2023/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002024 * List variables in "arg".
2025 */
2026 static char_u *
2027list_arg_vars(eap, arg)
2028 exarg_T *eap;
2029 char_u *arg;
2030{
2031 int error = FALSE;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002032 int len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002033 char_u *name;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002034 char_u *name_start;
2035 char_u *arg_subsc;
2036 char_u *tofree;
2037 typval_T tv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002038
2039 while (!ends_excmd(*arg) && !got_int)
2040 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002041 if (error || eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002042 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002043 arg = find_name_end(arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002044 if (!vim_iswhite(*arg) && !ends_excmd(*arg))
2045 {
2046 emsg_severe = TRUE;
2047 EMSG(_(e_trailing));
2048 break;
2049 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002050 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002051 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002052 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002053 /* get_name_len() takes care of expanding curly braces */
2054 name_start = name = arg;
2055 len = get_name_len(&arg, &tofree, TRUE, TRUE);
2056 if (len <= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002057 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002058 /* This is mainly to keep test 49 working: when expanding
2059 * curly braces fails overrule the exception error message. */
2060 if (len < 0 && !aborting())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002061 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002062 emsg_severe = TRUE;
2063 EMSG2(_(e_invarg2), arg);
2064 break;
2065 }
2066 error = TRUE;
2067 }
2068 else
2069 {
2070 if (tofree != NULL)
2071 name = tofree;
2072 if (get_var_tv(name, len, &tv, TRUE) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002073 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002074 else
2075 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002076 /* handle d.key, l[idx], f(expr) */
2077 arg_subsc = arg;
2078 if (handle_subscript(&arg, &tv, TRUE, TRUE) == FAIL)
Bram Moolenaara7043832005-01-21 11:56:39 +00002079 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002080 else
Bram Moolenaara7043832005-01-21 11:56:39 +00002081 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002082 if (arg == arg_subsc && len == 2 && name[1] == ':')
Bram Moolenaara7043832005-01-21 11:56:39 +00002083 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002084 switch (*name)
Bram Moolenaara7043832005-01-21 11:56:39 +00002085 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002086 case 'g': list_glob_vars(); break;
2087 case 'b': list_buf_vars(); break;
2088 case 'w': list_win_vars(); break;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002089#ifdef FEAT_WINDOWS
2090 case 't': list_tab_vars(); break;
2091#endif
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002092 case 'v': list_vim_vars(); break;
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00002093 case 's': list_script_vars(); break;
2094 case 'l': list_func_vars(); break;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002095 default:
2096 EMSG2(_("E738: Can't list variables for %s"), name);
Bram Moolenaara7043832005-01-21 11:56:39 +00002097 }
Bram Moolenaara7043832005-01-21 11:56:39 +00002098 }
2099 else
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002100 {
2101 char_u numbuf[NUMBUFLEN];
2102 char_u *tf;
2103 int c;
2104 char_u *s;
2105
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002106 s = echo_string(&tv, &tf, numbuf, 0);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002107 c = *arg;
2108 *arg = NUL;
2109 list_one_var_a((char_u *)"",
2110 arg == arg_subsc ? name : name_start,
2111 tv.v_type, s == NULL ? (char_u *)"" : s);
2112 *arg = c;
2113 vim_free(tf);
2114 }
2115 clear_tv(&tv);
Bram Moolenaara7043832005-01-21 11:56:39 +00002116 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002117 }
2118 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002119
2120 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002121 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002122
2123 arg = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002124 }
2125
2126 return arg;
2127}
2128
2129/*
2130 * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value.
2131 * Returns a pointer to the char just after the var name.
2132 * Returns NULL if there is an error.
2133 */
2134 static char_u *
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002135ex_let_one(arg, tv, copy, endchars, op)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002136 char_u *arg; /* points to variable name */
Bram Moolenaar33570922005-01-25 22:26:29 +00002137 typval_T *tv; /* value to assign to variable */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002138 int copy; /* copy value from "tv" */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002139 char_u *endchars; /* valid chars after variable name or NULL */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002140 char_u *op; /* "+", "-", "." or NULL*/
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002141{
2142 int c1;
2143 char_u *name;
2144 char_u *p;
2145 char_u *arg_end = NULL;
2146 int len;
2147 int opt_flags;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002148 char_u *tofree = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002149
2150 /*
2151 * ":let $VAR = expr": Set environment variable.
2152 */
2153 if (*arg == '$')
2154 {
2155 /* Find the end of the name. */
2156 ++arg;
2157 name = arg;
2158 len = get_env_len(&arg);
2159 if (len == 0)
2160 EMSG2(_(e_invarg2), name - 1);
2161 else
2162 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002163 if (op != NULL && (*op == '+' || *op == '-'))
2164 EMSG2(_(e_letwrong), op);
2165 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002166 && vim_strchr(endchars, *skipwhite(arg)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002167 EMSG(_(e_letunexp));
2168 else
2169 {
2170 c1 = name[len];
2171 name[len] = NUL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002172 p = get_tv_string_chk(tv);
2173 if (p != NULL && op != NULL && *op == '.')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002174 {
2175 int mustfree = FALSE;
2176 char_u *s = vim_getenv(name, &mustfree);
2177
2178 if (s != NULL)
2179 {
2180 p = tofree = concat_str(s, p);
2181 if (mustfree)
2182 vim_free(s);
2183 }
2184 }
2185 if (p != NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002186 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002187 vim_setenv(name, p);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002188 if (STRICMP(name, "HOME") == 0)
2189 init_homedir();
2190 else if (didset_vim && STRICMP(name, "VIM") == 0)
2191 didset_vim = FALSE;
2192 else if (didset_vimruntime
2193 && STRICMP(name, "VIMRUNTIME") == 0)
2194 didset_vimruntime = FALSE;
2195 arg_end = arg;
2196 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002197 name[len] = c1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002198 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002199 }
2200 }
2201 }
2202
2203 /*
2204 * ":let &option = expr": Set option value.
2205 * ":let &l:option = expr": Set local option value.
2206 * ":let &g:option = expr": Set global option value.
2207 */
2208 else if (*arg == '&')
2209 {
2210 /* Find the end of the name. */
2211 p = find_option_end(&arg, &opt_flags);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002212 if (p == NULL || (endchars != NULL
2213 && vim_strchr(endchars, *skipwhite(p)) == NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002214 EMSG(_(e_letunexp));
2215 else
2216 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002217 long n;
2218 int opt_type;
2219 long numval;
2220 char_u *stringval = NULL;
2221 char_u *s;
2222
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002223 c1 = *p;
2224 *p = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002225
2226 n = get_tv_number(tv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002227 s = get_tv_string_chk(tv); /* != NULL if number or string */
2228 if (s != NULL && op != NULL && *op != '=')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002229 {
2230 opt_type = get_option_value(arg, &numval,
2231 &stringval, opt_flags);
2232 if ((opt_type == 1 && *op == '.')
2233 || (opt_type == 0 && *op != '.'))
2234 EMSG2(_(e_letwrong), op);
2235 else
2236 {
2237 if (opt_type == 1) /* number */
2238 {
2239 if (*op == '+')
2240 n = numval + n;
2241 else
2242 n = numval - n;
2243 }
2244 else if (opt_type == 0 && stringval != NULL) /* string */
2245 {
2246 s = concat_str(stringval, s);
2247 vim_free(stringval);
2248 stringval = s;
2249 }
2250 }
2251 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002252 if (s != NULL)
2253 {
2254 set_option_value(arg, n, s, opt_flags);
2255 arg_end = p;
2256 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002257 *p = c1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002258 vim_free(stringval);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002259 }
2260 }
2261
2262 /*
2263 * ":let @r = expr": Set register contents.
2264 */
2265 else if (*arg == '@')
2266 {
2267 ++arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002268 if (op != NULL && (*op == '+' || *op == '-'))
2269 EMSG2(_(e_letwrong), op);
2270 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002271 && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002272 EMSG(_(e_letunexp));
2273 else
2274 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00002275 char_u *ptofree = NULL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002276 char_u *s;
2277
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002278 p = get_tv_string_chk(tv);
2279 if (p != NULL && op != NULL && *op == '.')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002280 {
Bram Moolenaar92124a32005-06-17 22:03:40 +00002281 s = get_reg_contents(*arg == '@' ? '"' : *arg, TRUE, TRUE);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002282 if (s != NULL)
2283 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00002284 p = ptofree = concat_str(s, p);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002285 vim_free(s);
2286 }
2287 }
2288 if (p != NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002289 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002290 write_reg_contents(*arg == '@' ? '"' : *arg, p, -1, FALSE);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002291 arg_end = arg + 1;
2292 }
Bram Moolenaar89d40322006-08-29 15:30:07 +00002293 vim_free(ptofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002294 }
2295 }
2296
2297 /*
2298 * ":let var = expr": Set internal variable.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002299 * ":let {expr} = expr": Idem, name made with curly braces
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002300 */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002301 else if (eval_isnamec1(*arg) || *arg == '{')
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002302 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002303 lval_T lv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002304
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002305 p = get_lval(arg, tv, &lv, FALSE, FALSE, FALSE, FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002306 if (p != NULL && lv.ll_name != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002307 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002308 if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL)
2309 EMSG(_(e_letunexp));
2310 else
2311 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002312 set_var_lval(&lv, p, tv, copy, op);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002313 arg_end = p;
2314 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002315 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002316 clear_lval(&lv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002317 }
2318
2319 else
2320 EMSG2(_(e_invarg2), arg);
2321
2322 return arg_end;
2323}
2324
2325/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00002326 * If "arg" is equal to "b:changedtick" give an error and return TRUE.
2327 */
2328 static int
2329check_changedtick(arg)
2330 char_u *arg;
2331{
2332 if (STRNCMP(arg, "b:changedtick", 13) == 0 && !eval_isnamec(arg[13]))
2333 {
2334 EMSG2(_(e_readonlyvar), arg);
2335 return TRUE;
2336 }
2337 return FALSE;
2338}
2339
2340/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002341 * Get an lval: variable, Dict item or List item that can be assigned a value
2342 * to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]",
2343 * "name.key", "name.key[expr]" etc.
2344 * Indexing only works if "name" is an existing List or Dictionary.
2345 * "name" points to the start of the name.
2346 * If "rettv" is not NULL it points to the value to be assigned.
2347 * "unlet" is TRUE for ":unlet": slightly different behavior when something is
2348 * wrong; must end in space or cmd separator.
2349 *
2350 * Returns a pointer to just after the name, including indexes.
Bram Moolenaara7043832005-01-21 11:56:39 +00002351 * When an evaluation error occurs "lp->ll_name" is NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002352 * Returns NULL for a parsing error. Still need to free items in "lp"!
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002353 */
2354 static char_u *
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002355get_lval(name, rettv, lp, unlet, skip, quiet, fne_flags)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002356 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +00002357 typval_T *rettv;
2358 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002359 int unlet;
2360 int skip;
2361 int quiet; /* don't give error messages */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002362 int fne_flags; /* flags for find_name_end() */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002363{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002364 char_u *p;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002365 char_u *expr_start, *expr_end;
2366 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00002367 dictitem_T *v;
2368 typval_T var1;
2369 typval_T var2;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002370 int empty1 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00002371 listitem_T *ni;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002372 char_u *key = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002373 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +00002374 hashtab_T *ht;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002375
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002376 /* Clear everything in "lp". */
Bram Moolenaar33570922005-01-25 22:26:29 +00002377 vim_memset(lp, 0, sizeof(lval_T));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002378
2379 if (skip)
2380 {
2381 /* When skipping just find the end of the name. */
2382 lp->ll_name = name;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002383 return find_name_end(name, NULL, NULL, FNE_INCL_BR | fne_flags);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002384 }
2385
2386 /* Find the end of the name. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002387 p = find_name_end(name, &expr_start, &expr_end, fne_flags);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002388 if (expr_start != NULL)
2389 {
2390 /* Don't expand the name when we already know there is an error. */
2391 if (unlet && !vim_iswhite(*p) && !ends_excmd(*p)
2392 && *p != '[' && *p != '.')
2393 {
2394 EMSG(_(e_trailing));
2395 return NULL;
2396 }
2397
2398 lp->ll_exp_name = make_expanded_name(name, expr_start, expr_end, p);
2399 if (lp->ll_exp_name == NULL)
2400 {
2401 /* Report an invalid expression in braces, unless the
2402 * expression evaluation has been cancelled due to an
2403 * aborting error, an interrupt, or an exception. */
2404 if (!aborting() && !quiet)
2405 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002406 emsg_severe = TRUE;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002407 EMSG2(_(e_invarg2), name);
2408 return NULL;
2409 }
2410 }
2411 lp->ll_name = lp->ll_exp_name;
2412 }
2413 else
2414 lp->ll_name = name;
2415
2416 /* Without [idx] or .key we are done. */
2417 if ((*p != '[' && *p != '.') || lp->ll_name == NULL)
2418 return p;
2419
2420 cc = *p;
2421 *p = NUL;
Bram Moolenaara7043832005-01-21 11:56:39 +00002422 v = find_var(lp->ll_name, &ht);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002423 if (v == NULL && !quiet)
2424 EMSG2(_(e_undefvar), lp->ll_name);
2425 *p = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002426 if (v == NULL)
2427 return NULL;
2428
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002429 /*
2430 * Loop until no more [idx] or .key is following.
2431 */
Bram Moolenaar33570922005-01-25 22:26:29 +00002432 lp->ll_tv = &v->di_tv;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002433 while (*p == '[' || (*p == '.' && lp->ll_tv->v_type == VAR_DICT))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002434 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002435 if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL)
2436 && !(lp->ll_tv->v_type == VAR_DICT
2437 && lp->ll_tv->vval.v_dict != NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002438 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002439 if (!quiet)
2440 EMSG(_("E689: Can only index a List or Dictionary"));
2441 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002442 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002443 if (lp->ll_range)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002444 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002445 if (!quiet)
2446 EMSG(_("E708: [:] must come last"));
2447 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002448 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002449
Bram Moolenaar8c711452005-01-14 21:53:12 +00002450 len = -1;
2451 if (*p == '.')
2452 {
2453 key = p + 1;
2454 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
2455 ;
2456 if (len == 0)
2457 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002458 if (!quiet)
2459 EMSG(_(e_emptykey));
2460 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002461 }
2462 p = key + len;
2463 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002464 else
2465 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002466 /* Get the index [expr] or the first index [expr: ]. */
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002467 p = skipwhite(p + 1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002468 if (*p == ':')
2469 empty1 = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002470 else
2471 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002472 empty1 = FALSE;
2473 if (eval1(&p, &var1, TRUE) == FAIL) /* recursive! */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002474 return NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002475 if (get_tv_string_chk(&var1) == NULL)
2476 {
2477 /* not a number or string */
2478 clear_tv(&var1);
2479 return NULL;
2480 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002481 }
2482
2483 /* Optionally get the second index [ :expr]. */
2484 if (*p == ':')
2485 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002486 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002487 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002488 if (!quiet)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002489 EMSG(_(e_dictrange));
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002490 if (!empty1)
2491 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002492 return NULL;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002493 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002494 if (rettv != NULL && (rettv->v_type != VAR_LIST
2495 || rettv->vval.v_list == NULL))
Bram Moolenaar8c711452005-01-14 21:53:12 +00002496 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002497 if (!quiet)
2498 EMSG(_("E709: [:] requires a List value"));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002499 if (!empty1)
2500 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002501 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002502 }
2503 p = skipwhite(p + 1);
2504 if (*p == ']')
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002505 lp->ll_empty2 = TRUE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002506 else
2507 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002508 lp->ll_empty2 = FALSE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002509 if (eval1(&p, &var2, TRUE) == FAIL) /* recursive! */
2510 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002511 if (!empty1)
2512 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002513 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002514 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002515 if (get_tv_string_chk(&var2) == NULL)
2516 {
2517 /* not a number or string */
2518 if (!empty1)
2519 clear_tv(&var1);
2520 clear_tv(&var2);
2521 return NULL;
2522 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002523 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002524 lp->ll_range = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002525 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002526 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002527 lp->ll_range = FALSE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002528
Bram Moolenaar8c711452005-01-14 21:53:12 +00002529 if (*p != ']')
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002530 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002531 if (!quiet)
2532 EMSG(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002533 if (!empty1)
2534 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002535 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002536 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002537 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002538 }
2539
2540 /* Skip to past ']'. */
2541 ++p;
2542 }
2543
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002544 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002545 {
2546 if (len == -1)
2547 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002548 /* "[key]": get key from "var1" */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002549 key = get_tv_string(&var1); /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002550 if (*key == NUL)
2551 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002552 if (!quiet)
2553 EMSG(_(e_emptykey));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002554 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002555 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002556 }
2557 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002558 lp->ll_list = NULL;
2559 lp->ll_dict = lp->ll_tv->vval.v_dict;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002560 lp->ll_di = dict_find(lp->ll_dict, key, len);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002561 if (lp->ll_di == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002562 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002563 /* Key does not exist in dict: may need to add it. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002564 if (*p == '[' || *p == '.' || unlet)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002565 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002566 if (!quiet)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002567 EMSG2(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002568 if (len == -1)
2569 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002570 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002571 }
2572 if (len == -1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002573 lp->ll_newkey = vim_strsave(key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002574 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002575 lp->ll_newkey = vim_strnsave(key, len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002576 if (len == -1)
2577 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002578 if (lp->ll_newkey == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002579 p = NULL;
2580 break;
2581 }
2582 if (len == -1)
2583 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002584 lp->ll_tv = &lp->ll_di->di_tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002585 }
2586 else
2587 {
2588 /*
2589 * Get the number and item for the only or first index of the List.
2590 */
2591 if (empty1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002592 lp->ll_n1 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002593 else
2594 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002595 lp->ll_n1 = get_tv_number(&var1); /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002596 clear_tv(&var1);
2597 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002598 lp->ll_dict = NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002599 lp->ll_list = lp->ll_tv->vval.v_list;
2600 lp->ll_li = list_find(lp->ll_list, lp->ll_n1);
2601 if (lp->ll_li == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002602 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00002603 if (lp->ll_n1 < 0)
2604 {
2605 lp->ll_n1 = 0;
2606 lp->ll_li = list_find(lp->ll_list, lp->ll_n1);
2607 }
2608 }
2609 if (lp->ll_li == NULL)
2610 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002611 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002612 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002613 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002614 }
2615
2616 /*
2617 * May need to find the item or absolute index for the second
2618 * index of a range.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002619 * When no index given: "lp->ll_empty2" is TRUE.
2620 * Otherwise "lp->ll_n2" is set to the second index.
Bram Moolenaar8c711452005-01-14 21:53:12 +00002621 */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002622 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002623 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002624 lp->ll_n2 = get_tv_number(&var2); /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002625 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002626 if (lp->ll_n2 < 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002627 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002628 ni = list_find(lp->ll_list, lp->ll_n2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002629 if (ni == NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002630 return NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002631 lp->ll_n2 = list_idx_of_item(lp->ll_list, ni);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002632 }
2633
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002634 /* Check that lp->ll_n2 isn't before lp->ll_n1. */
2635 if (lp->ll_n1 < 0)
2636 lp->ll_n1 = list_idx_of_item(lp->ll_list, lp->ll_li);
2637 if (lp->ll_n2 < lp->ll_n1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002638 return NULL;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002639 }
2640
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002641 lp->ll_tv = &lp->ll_li->li_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002642 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002643 }
2644
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002645 return p;
2646}
2647
2648/*
Bram Moolenaar33570922005-01-25 22:26:29 +00002649 * Clear lval "lp" that was filled by get_lval().
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002650 */
2651 static void
2652clear_lval(lp)
Bram Moolenaar33570922005-01-25 22:26:29 +00002653 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002654{
2655 vim_free(lp->ll_exp_name);
2656 vim_free(lp->ll_newkey);
2657}
2658
2659/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002660 * Set a variable that was parsed by get_lval() to "rettv".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002661 * "endp" points to just after the parsed name.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002662 * "op" is NULL, "+" for "+=", "-" for "-=", "." for ".=" or "=" for "=".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002663 */
2664 static void
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002665set_var_lval(lp, endp, rettv, copy, op)
Bram Moolenaar33570922005-01-25 22:26:29 +00002666 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002667 char_u *endp;
Bram Moolenaar33570922005-01-25 22:26:29 +00002668 typval_T *rettv;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002669 int copy;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002670 char_u *op;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002671{
2672 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00002673 listitem_T *ri;
2674 dictitem_T *di;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002675
2676 if (lp->ll_tv == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002677 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002678 if (!check_changedtick(lp->ll_name))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002679 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002680 cc = *endp;
2681 *endp = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002682 if (op != NULL && *op != '=')
2683 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002684 typval_T tv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002685
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002686 /* handle +=, -= and .= */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00002687 if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002688 &tv, TRUE) == OK)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002689 {
2690 if (tv_op(&tv, rettv, op) == OK)
2691 set_var(lp->ll_name, &tv, FALSE);
2692 clear_tv(&tv);
2693 }
2694 }
2695 else
2696 set_var(lp->ll_name, rettv, copy);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002697 *endp = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002698 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002699 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002700 else if (tv_check_lock(lp->ll_newkey == NULL
2701 ? lp->ll_tv->v_lock
2702 : lp->ll_tv->vval.v_dict->dv_lock, lp->ll_name))
2703 ;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002704 else if (lp->ll_range)
2705 {
2706 /*
2707 * Assign the List values to the list items.
2708 */
2709 for (ri = rettv->vval.v_list->lv_first; ri != NULL; )
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002710 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002711 if (op != NULL && *op != '=')
2712 tv_op(&lp->ll_li->li_tv, &ri->li_tv, op);
2713 else
2714 {
2715 clear_tv(&lp->ll_li->li_tv);
2716 copy_tv(&ri->li_tv, &lp->ll_li->li_tv);
2717 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002718 ri = ri->li_next;
2719 if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == lp->ll_n1))
2720 break;
2721 if (lp->ll_li->li_next == NULL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002722 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002723 /* Need to add an empty item. */
Bram Moolenaar4463f292005-09-25 22:20:24 +00002724 if (list_append_number(lp->ll_list, 0) == FAIL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002725 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002726 ri = NULL;
2727 break;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002728 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002729 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002730 lp->ll_li = lp->ll_li->li_next;
2731 ++lp->ll_n1;
2732 }
2733 if (ri != NULL)
2734 EMSG(_("E710: List value has more items than target"));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002735 else if (lp->ll_empty2
2736 ? (lp->ll_li != NULL && lp->ll_li->li_next != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002737 : lp->ll_n1 != lp->ll_n2)
2738 EMSG(_("E711: List value has not enough items"));
2739 }
2740 else
2741 {
2742 /*
2743 * Assign to a List or Dictionary item.
2744 */
2745 if (lp->ll_newkey != NULL)
2746 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002747 if (op != NULL && *op != '=')
2748 {
2749 EMSG2(_(e_letwrong), op);
2750 return;
2751 }
2752
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002753 /* Need to add an item to the Dictionary. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002754 di = dictitem_alloc(lp->ll_newkey);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002755 if (di == NULL)
2756 return;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002757 if (dict_add(lp->ll_tv->vval.v_dict, di) == FAIL)
2758 {
2759 vim_free(di);
2760 return;
2761 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002762 lp->ll_tv = &di->di_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002763 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002764 else if (op != NULL && *op != '=')
2765 {
2766 tv_op(lp->ll_tv, rettv, op);
2767 return;
2768 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002769 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002770 clear_tv(lp->ll_tv);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002771
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002772 /*
2773 * Assign the value to the variable or list item.
2774 */
2775 if (copy)
2776 copy_tv(rettv, lp->ll_tv);
2777 else
2778 {
2779 *lp->ll_tv = *rettv;
Bram Moolenaar758711c2005-02-02 23:11:38 +00002780 lp->ll_tv->v_lock = 0;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002781 init_tv(rettv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002782 }
2783 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002784}
2785
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002786/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002787 * Handle "tv1 += tv2", "tv1 -= tv2" and "tv1 .= tv2"
2788 * Returns OK or FAIL.
2789 */
2790 static int
2791tv_op(tv1, tv2, op)
Bram Moolenaar33570922005-01-25 22:26:29 +00002792 typval_T *tv1;
2793 typval_T *tv2;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002794 char_u *op;
2795{
2796 long n;
2797 char_u numbuf[NUMBUFLEN];
2798 char_u *s;
2799
2800 /* Can't do anything with a Funcref or a Dict on the right. */
2801 if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT)
2802 {
2803 switch (tv1->v_type)
2804 {
2805 case VAR_DICT:
2806 case VAR_FUNC:
2807 break;
2808
2809 case VAR_LIST:
2810 if (*op != '+' || tv2->v_type != VAR_LIST)
2811 break;
2812 /* List += List */
2813 if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL)
2814 list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL);
2815 return OK;
2816
2817 case VAR_NUMBER:
2818 case VAR_STRING:
2819 if (tv2->v_type == VAR_LIST)
2820 break;
2821 if (*op == '+' || *op == '-')
2822 {
2823 /* nr += nr or nr -= nr*/
2824 n = get_tv_number(tv1);
2825 if (*op == '+')
2826 n += get_tv_number(tv2);
2827 else
2828 n -= get_tv_number(tv2);
2829 clear_tv(tv1);
2830 tv1->v_type = VAR_NUMBER;
2831 tv1->vval.v_number = n;
2832 }
2833 else
2834 {
2835 /* str .= str */
2836 s = get_tv_string(tv1);
2837 s = concat_str(s, get_tv_string_buf(tv2, numbuf));
2838 clear_tv(tv1);
2839 tv1->v_type = VAR_STRING;
2840 tv1->vval.v_string = s;
2841 }
2842 return OK;
2843 }
2844 }
2845
2846 EMSG2(_(e_letwrong), op);
2847 return FAIL;
2848}
2849
2850/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002851 * Add a watcher to a list.
2852 */
2853 static void
2854list_add_watch(l, lw)
Bram Moolenaar33570922005-01-25 22:26:29 +00002855 list_T *l;
2856 listwatch_T *lw;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002857{
2858 lw->lw_next = l->lv_watch;
2859 l->lv_watch = lw;
2860}
2861
2862/*
Bram Moolenaar758711c2005-02-02 23:11:38 +00002863 * Remove a watcher from a list.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002864 * No warning when it isn't found...
2865 */
2866 static void
2867list_rem_watch(l, lwrem)
Bram Moolenaar33570922005-01-25 22:26:29 +00002868 list_T *l;
2869 listwatch_T *lwrem;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002870{
Bram Moolenaar33570922005-01-25 22:26:29 +00002871 listwatch_T *lw, **lwp;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002872
2873 lwp = &l->lv_watch;
2874 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
2875 {
2876 if (lw == lwrem)
2877 {
2878 *lwp = lw->lw_next;
2879 break;
2880 }
2881 lwp = &lw->lw_next;
2882 }
2883}
2884
2885/*
2886 * Just before removing an item from a list: advance watchers to the next
2887 * item.
2888 */
2889 static void
2890list_fix_watch(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00002891 list_T *l;
2892 listitem_T *item;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002893{
Bram Moolenaar33570922005-01-25 22:26:29 +00002894 listwatch_T *lw;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002895
2896 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
2897 if (lw->lw_item == item)
2898 lw->lw_item = item->li_next;
2899}
2900
2901/*
2902 * Evaluate the expression used in a ":for var in expr" command.
2903 * "arg" points to "var".
2904 * Set "*errp" to TRUE for an error, FALSE otherwise;
2905 * Return a pointer that holds the info. Null when there is an error.
2906 */
2907 void *
2908eval_for_line(arg, errp, nextcmdp, skip)
2909 char_u *arg;
2910 int *errp;
2911 char_u **nextcmdp;
2912 int skip;
2913{
Bram Moolenaar33570922005-01-25 22:26:29 +00002914 forinfo_T *fi;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002915 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +00002916 typval_T tv;
2917 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002918
2919 *errp = TRUE; /* default: there is an error */
2920
Bram Moolenaar33570922005-01-25 22:26:29 +00002921 fi = (forinfo_T *)alloc_clear(sizeof(forinfo_T));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002922 if (fi == NULL)
2923 return NULL;
2924
2925 expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
2926 if (expr == NULL)
2927 return fi;
2928
2929 expr = skipwhite(expr);
2930 if (expr[0] != 'i' || expr[1] != 'n' || !vim_iswhite(expr[2]))
2931 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00002932 EMSG(_("E690: Missing \"in\" after :for"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002933 return fi;
2934 }
2935
2936 if (skip)
2937 ++emsg_skip;
2938 if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK)
2939 {
2940 *errp = FALSE;
2941 if (!skip)
2942 {
2943 l = tv.vval.v_list;
2944 if (tv.v_type != VAR_LIST || l == NULL)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002945 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002946 EMSG(_(e_listreq));
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002947 clear_tv(&tv);
2948 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002949 else
2950 {
Bram Moolenaar7bb4c6e2005-09-07 21:22:27 +00002951 /* No need to increment the refcount, it's already set for the
2952 * list being used in "tv". */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002953 fi->fi_list = l;
2954 list_add_watch(l, &fi->fi_lw);
2955 fi->fi_lw.lw_item = l->lv_first;
2956 }
2957 }
2958 }
2959 if (skip)
2960 --emsg_skip;
2961
2962 return fi;
2963}
2964
2965/*
2966 * Use the first item in a ":for" list. Advance to the next.
2967 * Assign the values to the variable (list). "arg" points to the first one.
2968 * Return TRUE when a valid item was found, FALSE when at end of list or
2969 * something wrong.
2970 */
2971 int
2972next_for_item(fi_void, arg)
2973 void *fi_void;
2974 char_u *arg;
2975{
Bram Moolenaar33570922005-01-25 22:26:29 +00002976 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002977 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00002978 listitem_T *item;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002979
2980 item = fi->fi_lw.lw_item;
2981 if (item == NULL)
2982 result = FALSE;
2983 else
2984 {
2985 fi->fi_lw.lw_item = item->li_next;
2986 result = (ex_let_vars(arg, &item->li_tv, TRUE,
2987 fi->fi_semicolon, fi->fi_varcount, NULL) == OK);
2988 }
2989 return result;
2990}
2991
2992/*
2993 * Free the structure used to store info used by ":for".
2994 */
2995 void
2996free_for_info(fi_void)
2997 void *fi_void;
2998{
Bram Moolenaar33570922005-01-25 22:26:29 +00002999 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003000
Bram Moolenaarab7013c2005-01-09 21:23:56 +00003001 if (fi != NULL && fi->fi_list != NULL)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00003002 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003003 list_rem_watch(fi->fi_list, &fi->fi_lw);
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00003004 list_unref(fi->fi_list);
3005 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003006 vim_free(fi);
3007}
3008
Bram Moolenaar071d4272004-06-13 20:20:40 +00003009#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
3010
3011 void
3012set_context_for_expression(xp, arg, cmdidx)
3013 expand_T *xp;
3014 char_u *arg;
3015 cmdidx_T cmdidx;
3016{
3017 int got_eq = FALSE;
3018 int c;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003019 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003020
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003021 if (cmdidx == CMD_let)
3022 {
3023 xp->xp_context = EXPAND_USER_VARS;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00003024 if (vim_strpbrk(arg, (char_u *)"\"'+-*/%.=!?~|&$([<>,#") == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003025 {
3026 /* ":let var1 var2 ...": find last space. */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00003027 for (p = arg + STRLEN(arg); p >= arg; )
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003028 {
3029 xp->xp_pattern = p;
Bram Moolenaar33570922005-01-25 22:26:29 +00003030 mb_ptr_back(arg, p);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003031 if (vim_iswhite(*p))
3032 break;
3033 }
3034 return;
3035 }
3036 }
3037 else
3038 xp->xp_context = cmdidx == CMD_call ? EXPAND_FUNCTIONS
3039 : EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003040 while ((xp->xp_pattern = vim_strpbrk(arg,
3041 (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL)
3042 {
3043 c = *xp->xp_pattern;
3044 if (c == '&')
3045 {
3046 c = xp->xp_pattern[1];
3047 if (c == '&')
3048 {
3049 ++xp->xp_pattern;
3050 xp->xp_context = cmdidx != CMD_let || got_eq
3051 ? EXPAND_EXPRESSION : EXPAND_NOTHING;
3052 }
3053 else if (c != ' ')
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00003054 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00003055 xp->xp_context = EXPAND_SETTINGS;
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00003056 if ((c == 'l' || c == 'g') && xp->xp_pattern[2] == ':')
3057 xp->xp_pattern += 2;
3058
3059 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003060 }
3061 else if (c == '$')
3062 {
3063 /* environment variable */
3064 xp->xp_context = EXPAND_ENV_VARS;
3065 }
3066 else if (c == '=')
3067 {
3068 got_eq = TRUE;
3069 xp->xp_context = EXPAND_EXPRESSION;
3070 }
3071 else if (c == '<'
3072 && xp->xp_context == EXPAND_FUNCTIONS
3073 && vim_strchr(xp->xp_pattern, '(') == NULL)
3074 {
3075 /* Function name can start with "<SNR>" */
3076 break;
3077 }
3078 else if (cmdidx != CMD_let || got_eq)
3079 {
3080 if (c == '"') /* string */
3081 {
3082 while ((c = *++xp->xp_pattern) != NUL && c != '"')
3083 if (c == '\\' && xp->xp_pattern[1] != NUL)
3084 ++xp->xp_pattern;
3085 xp->xp_context = EXPAND_NOTHING;
3086 }
3087 else if (c == '\'') /* literal string */
3088 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00003089 /* Trick: '' is like stopping and starting a literal string. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003090 while ((c = *++xp->xp_pattern) != NUL && c != '\'')
3091 /* skip */ ;
3092 xp->xp_context = EXPAND_NOTHING;
3093 }
3094 else if (c == '|')
3095 {
3096 if (xp->xp_pattern[1] == '|')
3097 {
3098 ++xp->xp_pattern;
3099 xp->xp_context = EXPAND_EXPRESSION;
3100 }
3101 else
3102 xp->xp_context = EXPAND_COMMANDS;
3103 }
3104 else
3105 xp->xp_context = EXPAND_EXPRESSION;
3106 }
3107 else
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003108 /* Doesn't look like something valid, expand as an expression
3109 * anyway. */
3110 xp->xp_context = EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003111 arg = xp->xp_pattern;
3112 if (*arg != NUL)
3113 while ((c = *++arg) != NUL && (c == ' ' || c == '\t'))
3114 /* skip */ ;
3115 }
3116 xp->xp_pattern = arg;
3117}
3118
3119#endif /* FEAT_CMDL_COMPL */
3120
3121/*
3122 * ":1,25call func(arg1, arg2)" function call.
3123 */
3124 void
3125ex_call(eap)
3126 exarg_T *eap;
3127{
3128 char_u *arg = eap->arg;
3129 char_u *startarg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003130 char_u *name;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003131 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003132 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +00003133 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003134 linenr_T lnum;
3135 int doesrange;
3136 int failed = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00003137 funcdict_T fudi;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003138
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003139 tofree = trans_function_name(&arg, eap->skip, TFN_INT, &fudi);
3140 vim_free(fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003141 if (tofree == NULL)
3142 return;
3143
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003144 /* Increase refcount on dictionary, it could get deleted when evaluating
3145 * the arguments. */
3146 if (fudi.fd_dict != NULL)
3147 ++fudi.fd_dict->dv_refcount;
3148
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003149 /* If it is the name of a variable of type VAR_FUNC use its contents. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003150 len = (int)STRLEN(tofree);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003151 name = deref_func_name(tofree, &len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003152
Bram Moolenaar532c7802005-01-27 14:44:31 +00003153 /* Skip white space to allow ":call func ()". Not good, but required for
3154 * backward compatibility. */
3155 startarg = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003156 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003157
3158 if (*startarg != '(')
3159 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00003160 EMSG2(_("E107: Missing braces: %s"), eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003161 goto end;
3162 }
3163
3164 /*
3165 * When skipping, evaluate the function once, to find the end of the
3166 * arguments.
3167 * When the function takes a range, this is discovered after the first
3168 * call, and the loop is broken.
3169 */
3170 if (eap->skip)
3171 {
3172 ++emsg_skip;
3173 lnum = eap->line2; /* do it once, also with an invalid range */
3174 }
3175 else
3176 lnum = eap->line1;
3177 for ( ; lnum <= eap->line2; ++lnum)
3178 {
3179 if (!eap->skip && eap->addr_count > 0)
3180 {
3181 curwin->w_cursor.lnum = lnum;
3182 curwin->w_cursor.col = 0;
3183 }
3184 arg = startarg;
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003185 if (get_func_tv(name, (int)STRLEN(name), &rettv, &arg,
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003186 eap->line1, eap->line2, &doesrange,
3187 !eap->skip, fudi.fd_dict) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003188 {
3189 failed = TRUE;
3190 break;
3191 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003192 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003193 if (doesrange || eap->skip)
3194 break;
3195 /* Stop when immediately aborting on error, or when an interrupt
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003196 * occurred or an exception was thrown but not caught.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003197 * get_func_tv() returned OK, so that the check for trailing
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003198 * characters below is executed. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003199 if (aborting())
3200 break;
3201 }
3202 if (eap->skip)
3203 --emsg_skip;
3204
3205 if (!failed)
3206 {
3207 /* Check for trailing illegal characters and a following command. */
3208 if (!ends_excmd(*arg))
3209 {
3210 emsg_severe = TRUE;
3211 EMSG(_(e_trailing));
3212 }
3213 else
3214 eap->nextcmd = check_nextcmd(arg);
3215 }
3216
3217end:
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003218 dict_unref(fudi.fd_dict);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003219 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003220}
3221
3222/*
3223 * ":unlet[!] var1 ... " command.
3224 */
3225 void
3226ex_unlet(eap)
3227 exarg_T *eap;
3228{
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003229 ex_unletlock(eap, eap->arg, 0);
3230}
3231
3232/*
3233 * ":lockvar" and ":unlockvar" commands
3234 */
3235 void
3236ex_lockvar(eap)
3237 exarg_T *eap;
3238{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003239 char_u *arg = eap->arg;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003240 int deep = 2;
3241
3242 if (eap->forceit)
3243 deep = -1;
3244 else if (vim_isdigit(*arg))
3245 {
3246 deep = getdigits(&arg);
3247 arg = skipwhite(arg);
3248 }
3249
3250 ex_unletlock(eap, arg, deep);
3251}
3252
3253/*
3254 * ":unlet", ":lockvar" and ":unlockvar" are quite similar.
3255 */
3256 static void
3257ex_unletlock(eap, argstart, deep)
3258 exarg_T *eap;
3259 char_u *argstart;
3260 int deep;
3261{
3262 char_u *arg = argstart;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003263 char_u *name_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003264 int error = FALSE;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003265 lval_T lv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003266
3267 do
3268 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003269 /* Parse the name and find the end. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00003270 name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error, FALSE,
3271 FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003272 if (lv.ll_name == NULL)
3273 error = TRUE; /* error but continue parsing */
3274 if (name_end == NULL || (!vim_iswhite(*name_end)
3275 && !ends_excmd(*name_end)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003276 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003277 if (name_end != NULL)
3278 {
3279 emsg_severe = TRUE;
3280 EMSG(_(e_trailing));
3281 }
3282 if (!(eap->skip || error))
3283 clear_lval(&lv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003284 break;
3285 }
3286
3287 if (!error && !eap->skip)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003288 {
3289 if (eap->cmdidx == CMD_unlet)
3290 {
3291 if (do_unlet_var(&lv, name_end, eap->forceit) == FAIL)
3292 error = TRUE;
3293 }
3294 else
3295 {
3296 if (do_lock_var(&lv, name_end, deep,
3297 eap->cmdidx == CMD_lockvar) == FAIL)
3298 error = TRUE;
3299 }
3300 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003301
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003302 if (!eap->skip)
3303 clear_lval(&lv);
3304
Bram Moolenaar071d4272004-06-13 20:20:40 +00003305 arg = skipwhite(name_end);
3306 } while (!ends_excmd(*arg));
3307
3308 eap->nextcmd = check_nextcmd(arg);
3309}
3310
Bram Moolenaar8c711452005-01-14 21:53:12 +00003311 static int
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003312do_unlet_var(lp, name_end, forceit)
Bram Moolenaar33570922005-01-25 22:26:29 +00003313 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003314 char_u *name_end;
Bram Moolenaar8c711452005-01-14 21:53:12 +00003315 int forceit;
3316{
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003317 int ret = OK;
3318 int cc;
3319
3320 if (lp->ll_tv == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00003321 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003322 cc = *name_end;
3323 *name_end = NUL;
3324
3325 /* Normal name or expanded name. */
3326 if (check_changedtick(lp->ll_name))
3327 ret = FAIL;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003328 else if (do_unlet(lp->ll_name, forceit) == FAIL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003329 ret = FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003330 *name_end = cc;
Bram Moolenaar8c711452005-01-14 21:53:12 +00003331 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003332 else if (tv_check_lock(lp->ll_tv->v_lock, lp->ll_name))
3333 return FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003334 else if (lp->ll_range)
3335 {
Bram Moolenaar33570922005-01-25 22:26:29 +00003336 listitem_T *li;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003337
3338 /* Delete a range of List items. */
3339 while (lp->ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
3340 {
3341 li = lp->ll_li->li_next;
3342 listitem_remove(lp->ll_list, lp->ll_li);
3343 lp->ll_li = li;
3344 ++lp->ll_n1;
3345 }
3346 }
3347 else
3348 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003349 if (lp->ll_list != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003350 /* unlet a List item. */
3351 listitem_remove(lp->ll_list, lp->ll_li);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003352 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003353 /* unlet a Dictionary item. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003354 dictitem_remove(lp->ll_dict, lp->ll_di);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003355 }
3356
3357 return ret;
Bram Moolenaar8c711452005-01-14 21:53:12 +00003358}
3359
Bram Moolenaar071d4272004-06-13 20:20:40 +00003360/*
3361 * "unlet" a variable. Return OK if it existed, FAIL if not.
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003362 * When "forceit" is TRUE don't complain if the variable doesn't exist.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003363 */
3364 int
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003365do_unlet(name, forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003366 char_u *name;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003367 int forceit;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003368{
Bram Moolenaar33570922005-01-25 22:26:29 +00003369 hashtab_T *ht;
3370 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003371 char_u *varname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003372
Bram Moolenaar33570922005-01-25 22:26:29 +00003373 ht = find_var_ht(name, &varname);
3374 if (ht != NULL && *varname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003375 {
Bram Moolenaar33570922005-01-25 22:26:29 +00003376 hi = hash_find(ht, varname);
3377 if (!HASHITEM_EMPTY(hi))
Bram Moolenaara7043832005-01-21 11:56:39 +00003378 {
Bram Moolenaar4e957af2006-09-02 11:41:07 +00003379 if (var_check_fixed(HI2DI(hi)->di_flags, name))
3380 return FAIL;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003381 if (var_check_ro(HI2DI(hi)->di_flags, name))
3382 return FAIL;
3383 delete_var(ht, hi);
3384 return OK;
Bram Moolenaara7043832005-01-21 11:56:39 +00003385 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003386 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003387 if (forceit)
3388 return OK;
3389 EMSG2(_("E108: No such variable: \"%s\""), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003390 return FAIL;
3391}
3392
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003393/*
3394 * Lock or unlock variable indicated by "lp".
3395 * "deep" is the levels to go (-1 for unlimited);
3396 * "lock" is TRUE for ":lockvar", FALSE for ":unlockvar".
3397 */
3398 static int
3399do_lock_var(lp, name_end, deep, lock)
3400 lval_T *lp;
3401 char_u *name_end;
3402 int deep;
3403 int lock;
3404{
3405 int ret = OK;
3406 int cc;
3407 dictitem_T *di;
3408
3409 if (deep == 0) /* nothing to do */
3410 return OK;
3411
3412 if (lp->ll_tv == NULL)
3413 {
3414 cc = *name_end;
3415 *name_end = NUL;
3416
3417 /* Normal name or expanded name. */
3418 if (check_changedtick(lp->ll_name))
3419 ret = FAIL;
3420 else
3421 {
3422 di = find_var(lp->ll_name, NULL);
3423 if (di == NULL)
3424 ret = FAIL;
3425 else
3426 {
3427 if (lock)
3428 di->di_flags |= DI_FLAGS_LOCK;
3429 else
3430 di->di_flags &= ~DI_FLAGS_LOCK;
3431 item_lock(&di->di_tv, deep, lock);
3432 }
3433 }
3434 *name_end = cc;
3435 }
3436 else if (lp->ll_range)
3437 {
3438 listitem_T *li = lp->ll_li;
3439
3440 /* (un)lock a range of List items. */
3441 while (li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
3442 {
3443 item_lock(&li->li_tv, deep, lock);
3444 li = li->li_next;
3445 ++lp->ll_n1;
3446 }
3447 }
3448 else if (lp->ll_list != NULL)
3449 /* (un)lock a List item. */
3450 item_lock(&lp->ll_li->li_tv, deep, lock);
3451 else
3452 /* un(lock) a Dictionary item. */
3453 item_lock(&lp->ll_di->di_tv, deep, lock);
3454
3455 return ret;
3456}
3457
3458/*
3459 * Lock or unlock an item. "deep" is nr of levels to go.
3460 */
3461 static void
3462item_lock(tv, deep, lock)
3463 typval_T *tv;
3464 int deep;
3465 int lock;
3466{
3467 static int recurse = 0;
3468 list_T *l;
3469 listitem_T *li;
3470 dict_T *d;
3471 hashitem_T *hi;
3472 int todo;
3473
3474 if (recurse >= DICT_MAXNEST)
3475 {
3476 EMSG(_("E743: variable nested too deep for (un)lock"));
3477 return;
3478 }
3479 if (deep == 0)
3480 return;
3481 ++recurse;
3482
3483 /* lock/unlock the item itself */
3484 if (lock)
3485 tv->v_lock |= VAR_LOCKED;
3486 else
3487 tv->v_lock &= ~VAR_LOCKED;
3488
3489 switch (tv->v_type)
3490 {
3491 case VAR_LIST:
3492 if ((l = tv->vval.v_list) != NULL)
3493 {
3494 if (lock)
3495 l->lv_lock |= VAR_LOCKED;
3496 else
3497 l->lv_lock &= ~VAR_LOCKED;
3498 if (deep < 0 || deep > 1)
3499 /* recursive: lock/unlock the items the List contains */
3500 for (li = l->lv_first; li != NULL; li = li->li_next)
3501 item_lock(&li->li_tv, deep - 1, lock);
3502 }
3503 break;
3504 case VAR_DICT:
3505 if ((d = tv->vval.v_dict) != NULL)
3506 {
3507 if (lock)
3508 d->dv_lock |= VAR_LOCKED;
3509 else
3510 d->dv_lock &= ~VAR_LOCKED;
3511 if (deep < 0 || deep > 1)
3512 {
3513 /* recursive: lock/unlock the items the List contains */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003514 todo = (int)d->dv_hashtab.ht_used;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003515 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
3516 {
3517 if (!HASHITEM_EMPTY(hi))
3518 {
3519 --todo;
3520 item_lock(&HI2DI(hi)->di_tv, deep - 1, lock);
3521 }
3522 }
3523 }
3524 }
3525 }
3526 --recurse;
3527}
3528
Bram Moolenaara40058a2005-07-11 22:42:07 +00003529/*
3530 * Return TRUE if typeval "tv" is locked: Either tha value is locked itself or
3531 * it refers to a List or Dictionary that is locked.
3532 */
3533 static int
3534tv_islocked(tv)
3535 typval_T *tv;
3536{
3537 return (tv->v_lock & VAR_LOCKED)
3538 || (tv->v_type == VAR_LIST
3539 && tv->vval.v_list != NULL
3540 && (tv->vval.v_list->lv_lock & VAR_LOCKED))
3541 || (tv->v_type == VAR_DICT
3542 && tv->vval.v_dict != NULL
3543 && (tv->vval.v_dict->dv_lock & VAR_LOCKED));
3544}
3545
Bram Moolenaar071d4272004-06-13 20:20:40 +00003546#if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO)
3547/*
3548 * Delete all "menutrans_" variables.
3549 */
3550 void
3551del_menutrans_vars()
3552{
Bram Moolenaar33570922005-01-25 22:26:29 +00003553 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003554 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003555
Bram Moolenaar33570922005-01-25 22:26:29 +00003556 hash_lock(&globvarht);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003557 todo = (int)globvarht.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00003558 for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaara7043832005-01-21 11:56:39 +00003559 {
3560 if (!HASHITEM_EMPTY(hi))
3561 {
3562 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00003563 if (STRNCMP(HI2DI(hi)->di_key, "menutrans_", 10) == 0)
3564 delete_var(&globvarht, hi);
Bram Moolenaara7043832005-01-21 11:56:39 +00003565 }
3566 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003567 hash_unlock(&globvarht);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003568}
3569#endif
3570
3571#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
3572
3573/*
3574 * Local string buffer for the next two functions to store a variable name
3575 * with its prefix. Allocated in cat_prefix_varname(), freed later in
3576 * get_user_var_name().
3577 */
3578
3579static char_u *cat_prefix_varname __ARGS((int prefix, char_u *name));
3580
3581static char_u *varnamebuf = NULL;
3582static int varnamebuflen = 0;
3583
3584/*
3585 * Function to concatenate a prefix and a variable name.
3586 */
3587 static char_u *
3588cat_prefix_varname(prefix, name)
3589 int prefix;
3590 char_u *name;
3591{
3592 int len;
3593
3594 len = (int)STRLEN(name) + 3;
3595 if (len > varnamebuflen)
3596 {
3597 vim_free(varnamebuf);
3598 len += 10; /* some additional space */
3599 varnamebuf = alloc(len);
3600 if (varnamebuf == NULL)
3601 {
3602 varnamebuflen = 0;
3603 return NULL;
3604 }
3605 varnamebuflen = len;
3606 }
3607 *varnamebuf = prefix;
3608 varnamebuf[1] = ':';
3609 STRCPY(varnamebuf + 2, name);
3610 return varnamebuf;
3611}
3612
3613/*
3614 * Function given to ExpandGeneric() to obtain the list of user defined
3615 * (global/buffer/window/built-in) variable names.
3616 */
3617/*ARGSUSED*/
3618 char_u *
3619get_user_var_name(xp, idx)
3620 expand_T *xp;
3621 int idx;
3622{
Bram Moolenaar532c7802005-01-27 14:44:31 +00003623 static long_u gdone;
3624 static long_u bdone;
3625 static long_u wdone;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003626#ifdef FEAT_WINDOWS
3627 static long_u tdone;
3628#endif
Bram Moolenaar532c7802005-01-27 14:44:31 +00003629 static int vidx;
3630 static hashitem_T *hi;
3631 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003632
3633 if (idx == 0)
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003634 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003635 gdone = bdone = wdone = vidx = 0;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003636#ifdef FEAT_WINDOWS
3637 tdone = 0;
3638#endif
3639 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003640
3641 /* Global variables */
3642 if (gdone < globvarht.ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003643 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003644 if (gdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003645 hi = globvarht.ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003646 else
3647 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003648 while (HASHITEM_EMPTY(hi))
3649 ++hi;
3650 if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
3651 return cat_prefix_varname('g', hi->hi_key);
3652 return hi->hi_key;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003653 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003654
3655 /* b: variables */
3656 ht = &curbuf->b_vars.dv_hashtab;
3657 if (bdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003658 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003659 if (bdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003660 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003661 else
3662 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003663 while (HASHITEM_EMPTY(hi))
3664 ++hi;
3665 return cat_prefix_varname('b', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003666 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003667 if (bdone == ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003668 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003669 ++bdone;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003670 return (char_u *)"b:changedtick";
3671 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003672
3673 /* w: variables */
3674 ht = &curwin->w_vars.dv_hashtab;
3675 if (wdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003676 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00003677 if (wdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003678 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003679 else
3680 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003681 while (HASHITEM_EMPTY(hi))
3682 ++hi;
3683 return cat_prefix_varname('w', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003684 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003685
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003686#ifdef FEAT_WINDOWS
3687 /* t: variables */
3688 ht = &curtab->tp_vars.dv_hashtab;
3689 if (tdone < ht->ht_used)
3690 {
3691 if (tdone++ == 0)
3692 hi = ht->ht_array;
3693 else
3694 ++hi;
3695 while (HASHITEM_EMPTY(hi))
3696 ++hi;
3697 return cat_prefix_varname('t', hi->hi_key);
3698 }
3699#endif
3700
Bram Moolenaar33570922005-01-25 22:26:29 +00003701 /* v: variables */
3702 if (vidx < VV_LEN)
3703 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].vv_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003704
3705 vim_free(varnamebuf);
3706 varnamebuf = NULL;
3707 varnamebuflen = 0;
3708 return NULL;
3709}
3710
3711#endif /* FEAT_CMDL_COMPL */
3712
3713/*
3714 * types for expressions.
3715 */
3716typedef enum
3717{
3718 TYPE_UNKNOWN = 0
3719 , TYPE_EQUAL /* == */
3720 , TYPE_NEQUAL /* != */
3721 , TYPE_GREATER /* > */
3722 , TYPE_GEQUAL /* >= */
3723 , TYPE_SMALLER /* < */
3724 , TYPE_SEQUAL /* <= */
3725 , TYPE_MATCH /* =~ */
3726 , TYPE_NOMATCH /* !~ */
3727} exptype_T;
3728
3729/*
3730 * The "evaluate" argument: When FALSE, the argument is only parsed but not
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003731 * executed. The function may return OK, but the rettv will be of type
Bram Moolenaar071d4272004-06-13 20:20:40 +00003732 * VAR_UNKNOWN. The function still returns FAIL for a syntax error.
3733 */
3734
3735/*
3736 * Handle zero level expression.
3737 * This calls eval1() and handles error message and nextcmd.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003738 * Put the result in "rettv" when returning OK and "evaluate" is TRUE.
Bram Moolenaar4463f292005-09-25 22:20:24 +00003739 * Note: "rettv.v_lock" is not set.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003740 * Return OK or FAIL.
3741 */
3742 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003743eval0(arg, rettv, nextcmd, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003744 char_u *arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003745 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003746 char_u **nextcmd;
3747 int evaluate;
3748{
3749 int ret;
3750 char_u *p;
3751
3752 p = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003753 ret = eval1(&p, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003754 if (ret == FAIL || !ends_excmd(*p))
3755 {
3756 if (ret != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003757 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003758 /*
3759 * Report the invalid expression unless the expression evaluation has
3760 * been cancelled due to an aborting error, an interrupt, or an
3761 * exception.
3762 */
3763 if (!aborting())
3764 EMSG2(_(e_invexpr2), arg);
3765 ret = FAIL;
3766 }
3767 if (nextcmd != NULL)
3768 *nextcmd = check_nextcmd(p);
3769
3770 return ret;
3771}
3772
3773/*
3774 * Handle top level expression:
3775 * expr1 ? expr0 : expr0
3776 *
3777 * "arg" must point to the first non-white of the expression.
3778 * "arg" is advanced to the next non-white after the recognized expression.
3779 *
Bram Moolenaar4463f292005-09-25 22:20:24 +00003780 * Note: "rettv.v_lock" is not set.
3781 *
Bram Moolenaar071d4272004-06-13 20:20:40 +00003782 * Return OK or FAIL.
3783 */
3784 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003785eval1(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003786 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003787 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003788 int evaluate;
3789{
3790 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00003791 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003792
3793 /*
3794 * Get the first variable.
3795 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003796 if (eval2(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003797 return FAIL;
3798
3799 if ((*arg)[0] == '?')
3800 {
3801 result = FALSE;
3802 if (evaluate)
3803 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003804 int error = FALSE;
3805
3806 if (get_tv_number_chk(rettv, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003807 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003808 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003809 if (error)
3810 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003811 }
3812
3813 /*
3814 * Get the second variable.
3815 */
3816 *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003817 if (eval1(arg, rettv, evaluate && result) == FAIL) /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003818 return FAIL;
3819
3820 /*
3821 * Check for the ":".
3822 */
3823 if ((*arg)[0] != ':')
3824 {
3825 EMSG(_("E109: Missing ':' after '?'"));
3826 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003827 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003828 return FAIL;
3829 }
3830
3831 /*
3832 * Get the third variable.
3833 */
3834 *arg = skipwhite(*arg + 1);
3835 if (eval1(arg, &var2, evaluate && !result) == FAIL) /* recursive! */
3836 {
3837 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003838 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003839 return FAIL;
3840 }
3841 if (evaluate && !result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003842 *rettv = var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003843 }
3844
3845 return OK;
3846}
3847
3848/*
3849 * Handle first level expression:
3850 * expr2 || expr2 || expr2 logical OR
3851 *
3852 * "arg" must point to the first non-white of the expression.
3853 * "arg" is advanced to the next non-white after the recognized expression.
3854 *
3855 * Return OK or FAIL.
3856 */
3857 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003858eval2(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003859 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003860 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003861 int evaluate;
3862{
Bram Moolenaar33570922005-01-25 22:26:29 +00003863 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003864 long result;
3865 int first;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003866 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003867
3868 /*
3869 * Get the first variable.
3870 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003871 if (eval3(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003872 return FAIL;
3873
3874 /*
3875 * Repeat until there is no following "||".
3876 */
3877 first = TRUE;
3878 result = FALSE;
3879 while ((*arg)[0] == '|' && (*arg)[1] == '|')
3880 {
3881 if (evaluate && first)
3882 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003883 if (get_tv_number_chk(rettv, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003884 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003885 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003886 if (error)
3887 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003888 first = FALSE;
3889 }
3890
3891 /*
3892 * Get the second variable.
3893 */
3894 *arg = skipwhite(*arg + 2);
3895 if (eval3(arg, &var2, evaluate && !result) == FAIL)
3896 return FAIL;
3897
3898 /*
3899 * Compute the result.
3900 */
3901 if (evaluate && !result)
3902 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003903 if (get_tv_number_chk(&var2, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003904 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003905 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003906 if (error)
3907 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003908 }
3909 if (evaluate)
3910 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003911 rettv->v_type = VAR_NUMBER;
3912 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003913 }
3914 }
3915
3916 return OK;
3917}
3918
3919/*
3920 * Handle second level expression:
3921 * expr3 && expr3 && expr3 logical AND
3922 *
3923 * "arg" must point to the first non-white of the expression.
3924 * "arg" is advanced to the next non-white after the recognized expression.
3925 *
3926 * Return OK or FAIL.
3927 */
3928 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003929eval3(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003930 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003931 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003932 int evaluate;
3933{
Bram Moolenaar33570922005-01-25 22:26:29 +00003934 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003935 long result;
3936 int first;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003937 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003938
3939 /*
3940 * Get the first variable.
3941 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003942 if (eval4(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003943 return FAIL;
3944
3945 /*
3946 * Repeat until there is no following "&&".
3947 */
3948 first = TRUE;
3949 result = TRUE;
3950 while ((*arg)[0] == '&' && (*arg)[1] == '&')
3951 {
3952 if (evaluate && first)
3953 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003954 if (get_tv_number_chk(rettv, &error) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003955 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003956 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003957 if (error)
3958 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003959 first = FALSE;
3960 }
3961
3962 /*
3963 * Get the second variable.
3964 */
3965 *arg = skipwhite(*arg + 2);
3966 if (eval4(arg, &var2, evaluate && result) == FAIL)
3967 return FAIL;
3968
3969 /*
3970 * Compute the result.
3971 */
3972 if (evaluate && result)
3973 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003974 if (get_tv_number_chk(&var2, &error) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003975 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003976 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003977 if (error)
3978 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003979 }
3980 if (evaluate)
3981 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003982 rettv->v_type = VAR_NUMBER;
3983 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003984 }
3985 }
3986
3987 return OK;
3988}
3989
3990/*
3991 * Handle third level expression:
3992 * var1 == var2
3993 * var1 =~ var2
3994 * var1 != var2
3995 * var1 !~ var2
3996 * var1 > var2
3997 * var1 >= var2
3998 * var1 < var2
3999 * var1 <= var2
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004000 * var1 is var2
4001 * var1 isnot var2
Bram Moolenaar071d4272004-06-13 20:20:40 +00004002 *
4003 * "arg" must point to the first non-white of the expression.
4004 * "arg" is advanced to the next non-white after the recognized expression.
4005 *
4006 * Return OK or FAIL.
4007 */
4008 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004009eval4(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004010 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004011 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004012 int evaluate;
4013{
Bram Moolenaar33570922005-01-25 22:26:29 +00004014 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004015 char_u *p;
4016 int i;
4017 exptype_T type = TYPE_UNKNOWN;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004018 int type_is = FALSE; /* TRUE for "is" and "isnot" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004019 int len = 2;
4020 long n1, n2;
4021 char_u *s1, *s2;
4022 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4023 regmatch_T regmatch;
4024 int ic;
4025 char_u *save_cpo;
4026
4027 /*
4028 * Get the first variable.
4029 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004030 if (eval5(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004031 return FAIL;
4032
4033 p = *arg;
4034 switch (p[0])
4035 {
4036 case '=': if (p[1] == '=')
4037 type = TYPE_EQUAL;
4038 else if (p[1] == '~')
4039 type = TYPE_MATCH;
4040 break;
4041 case '!': if (p[1] == '=')
4042 type = TYPE_NEQUAL;
4043 else if (p[1] == '~')
4044 type = TYPE_NOMATCH;
4045 break;
4046 case '>': if (p[1] != '=')
4047 {
4048 type = TYPE_GREATER;
4049 len = 1;
4050 }
4051 else
4052 type = TYPE_GEQUAL;
4053 break;
4054 case '<': if (p[1] != '=')
4055 {
4056 type = TYPE_SMALLER;
4057 len = 1;
4058 }
4059 else
4060 type = TYPE_SEQUAL;
4061 break;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004062 case 'i': if (p[1] == 's')
4063 {
4064 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
4065 len = 5;
4066 if (!vim_isIDc(p[len]))
4067 {
4068 type = len == 2 ? TYPE_EQUAL : TYPE_NEQUAL;
4069 type_is = TRUE;
4070 }
4071 }
4072 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004073 }
4074
4075 /*
4076 * If there is a comparitive operator, use it.
4077 */
4078 if (type != TYPE_UNKNOWN)
4079 {
4080 /* extra question mark appended: ignore case */
4081 if (p[len] == '?')
4082 {
4083 ic = TRUE;
4084 ++len;
4085 }
4086 /* extra '#' appended: match case */
4087 else if (p[len] == '#')
4088 {
4089 ic = FALSE;
4090 ++len;
4091 }
4092 /* nothing appened: use 'ignorecase' */
4093 else
4094 ic = p_ic;
4095
4096 /*
4097 * Get the second variable.
4098 */
4099 *arg = skipwhite(p + len);
4100 if (eval5(arg, &var2, evaluate) == FAIL)
4101 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004102 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004103 return FAIL;
4104 }
4105
4106 if (evaluate)
4107 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004108 if (type_is && rettv->v_type != var2.v_type)
4109 {
4110 /* For "is" a different type always means FALSE, for "notis"
4111 * it means TRUE. */
4112 n1 = (type == TYPE_NEQUAL);
4113 }
4114 else if (rettv->v_type == VAR_LIST || var2.v_type == VAR_LIST)
4115 {
4116 if (type_is)
4117 {
4118 n1 = (rettv->v_type == var2.v_type
4119 && rettv->vval.v_list == var2.vval.v_list);
4120 if (type == TYPE_NEQUAL)
4121 n1 = !n1;
4122 }
4123 else if (rettv->v_type != var2.v_type
4124 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
4125 {
4126 if (rettv->v_type != var2.v_type)
Bram Moolenaare49b69a2005-01-08 16:11:57 +00004127 EMSG(_("E691: Can only compare List with List"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004128 else
Bram Moolenaare49b69a2005-01-08 16:11:57 +00004129 EMSG(_("E692: Invalid operation for Lists"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004130 clear_tv(rettv);
4131 clear_tv(&var2);
4132 return FAIL;
4133 }
4134 else
4135 {
4136 /* Compare two Lists for being equal or unequal. */
4137 n1 = list_equal(rettv->vval.v_list, var2.vval.v_list, ic);
4138 if (type == TYPE_NEQUAL)
4139 n1 = !n1;
4140 }
4141 }
4142
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004143 else if (rettv->v_type == VAR_DICT || var2.v_type == VAR_DICT)
4144 {
4145 if (type_is)
4146 {
4147 n1 = (rettv->v_type == var2.v_type
4148 && rettv->vval.v_dict == var2.vval.v_dict);
4149 if (type == TYPE_NEQUAL)
4150 n1 = !n1;
4151 }
4152 else if (rettv->v_type != var2.v_type
4153 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
4154 {
4155 if (rettv->v_type != var2.v_type)
4156 EMSG(_("E735: Can only compare Dictionary with Dictionary"));
4157 else
4158 EMSG(_("E736: Invalid operation for Dictionary"));
4159 clear_tv(rettv);
4160 clear_tv(&var2);
4161 return FAIL;
4162 }
4163 else
4164 {
4165 /* Compare two Dictionaries for being equal or unequal. */
4166 n1 = dict_equal(rettv->vval.v_dict, var2.vval.v_dict, ic);
4167 if (type == TYPE_NEQUAL)
4168 n1 = !n1;
4169 }
4170 }
4171
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004172 else if (rettv->v_type == VAR_FUNC || var2.v_type == VAR_FUNC)
4173 {
4174 if (rettv->v_type != var2.v_type
4175 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
4176 {
4177 if (rettv->v_type != var2.v_type)
Bram Moolenaare49b69a2005-01-08 16:11:57 +00004178 EMSG(_("E693: Can only compare Funcref with Funcref"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004179 else
Bram Moolenaare49b69a2005-01-08 16:11:57 +00004180 EMSG(_("E694: Invalid operation for Funcrefs"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004181 clear_tv(rettv);
4182 clear_tv(&var2);
4183 return FAIL;
4184 }
4185 else
4186 {
4187 /* Compare two Funcrefs for being equal or unequal. */
4188 if (rettv->vval.v_string == NULL
4189 || var2.vval.v_string == NULL)
4190 n1 = FALSE;
4191 else
4192 n1 = STRCMP(rettv->vval.v_string,
4193 var2.vval.v_string) == 0;
4194 if (type == TYPE_NEQUAL)
4195 n1 = !n1;
4196 }
4197 }
4198
Bram Moolenaar071d4272004-06-13 20:20:40 +00004199 /*
4200 * If one of the two variables is a number, compare as a number.
4201 * When using "=~" or "!~", always compare as string.
4202 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004203 else if ((rettv->v_type == VAR_NUMBER || var2.v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004204 && type != TYPE_MATCH && type != TYPE_NOMATCH)
4205 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004206 n1 = get_tv_number(rettv);
4207 n2 = get_tv_number(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004208 switch (type)
4209 {
4210 case TYPE_EQUAL: n1 = (n1 == n2); break;
4211 case TYPE_NEQUAL: n1 = (n1 != n2); break;
4212 case TYPE_GREATER: n1 = (n1 > n2); break;
4213 case TYPE_GEQUAL: n1 = (n1 >= n2); break;
4214 case TYPE_SMALLER: n1 = (n1 < n2); break;
4215 case TYPE_SEQUAL: n1 = (n1 <= n2); break;
4216 case TYPE_UNKNOWN:
4217 case TYPE_MATCH:
4218 case TYPE_NOMATCH: break; /* avoid gcc warning */
4219 }
4220 }
4221 else
4222 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004223 s1 = get_tv_string_buf(rettv, buf1);
4224 s2 = get_tv_string_buf(&var2, buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004225 if (type != TYPE_MATCH && type != TYPE_NOMATCH)
4226 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2);
4227 else
4228 i = 0;
4229 n1 = FALSE;
4230 switch (type)
4231 {
4232 case TYPE_EQUAL: n1 = (i == 0); break;
4233 case TYPE_NEQUAL: n1 = (i != 0); break;
4234 case TYPE_GREATER: n1 = (i > 0); break;
4235 case TYPE_GEQUAL: n1 = (i >= 0); break;
4236 case TYPE_SMALLER: n1 = (i < 0); break;
4237 case TYPE_SEQUAL: n1 = (i <= 0); break;
4238
4239 case TYPE_MATCH:
4240 case TYPE_NOMATCH:
4241 /* avoid 'l' flag in 'cpoptions' */
4242 save_cpo = p_cpo;
4243 p_cpo = (char_u *)"";
4244 regmatch.regprog = vim_regcomp(s2,
4245 RE_MAGIC + RE_STRING);
4246 regmatch.rm_ic = ic;
4247 if (regmatch.regprog != NULL)
4248 {
4249 n1 = vim_regexec_nl(&regmatch, s1, (colnr_T)0);
4250 vim_free(regmatch.regprog);
4251 if (type == TYPE_NOMATCH)
4252 n1 = !n1;
4253 }
4254 p_cpo = save_cpo;
4255 break;
4256
4257 case TYPE_UNKNOWN: break; /* avoid gcc warning */
4258 }
4259 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004260 clear_tv(rettv);
4261 clear_tv(&var2);
4262 rettv->v_type = VAR_NUMBER;
4263 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004264 }
4265 }
4266
4267 return OK;
4268}
4269
4270/*
4271 * Handle fourth level expression:
4272 * + number addition
4273 * - number subtraction
4274 * . string concatenation
4275 *
4276 * "arg" must point to the first non-white of the expression.
4277 * "arg" is advanced to the next non-white after the recognized expression.
4278 *
4279 * Return OK or FAIL.
4280 */
4281 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004282eval5(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004283 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004284 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004285 int evaluate;
4286{
Bram Moolenaar33570922005-01-25 22:26:29 +00004287 typval_T var2;
4288 typval_T var3;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004289 int op;
4290 long n1, n2;
4291 char_u *s1, *s2;
4292 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4293 char_u *p;
4294
4295 /*
4296 * Get the first variable.
4297 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004298 if (eval6(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004299 return FAIL;
4300
4301 /*
4302 * Repeat computing, until no '+', '-' or '.' is following.
4303 */
4304 for (;;)
4305 {
4306 op = **arg;
4307 if (op != '+' && op != '-' && op != '.')
4308 break;
4309
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004310 if (op != '+' || rettv->v_type != VAR_LIST)
4311 {
4312 /* For "list + ...", an illegal use of the first operand as
4313 * a number cannot be determined before evaluating the 2nd
4314 * operand: if this is also a list, all is ok.
4315 * For "something . ...", "something - ..." or "non-list + ...",
4316 * we know that the first operand needs to be a string or number
4317 * without evaluating the 2nd operand. So check before to avoid
4318 * side effects after an error. */
4319 if (evaluate && get_tv_string_chk(rettv) == NULL)
4320 {
4321 clear_tv(rettv);
4322 return FAIL;
4323 }
4324 }
4325
Bram Moolenaar071d4272004-06-13 20:20:40 +00004326 /*
4327 * Get the second variable.
4328 */
4329 *arg = skipwhite(*arg + 1);
4330 if (eval6(arg, &var2, evaluate) == FAIL)
4331 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004332 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004333 return FAIL;
4334 }
4335
4336 if (evaluate)
4337 {
4338 /*
4339 * Compute the result.
4340 */
4341 if (op == '.')
4342 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004343 s1 = get_tv_string_buf(rettv, buf1); /* already checked */
4344 s2 = get_tv_string_buf_chk(&var2, buf2);
4345 if (s2 == NULL) /* type error ? */
4346 {
4347 clear_tv(rettv);
4348 clear_tv(&var2);
4349 return FAIL;
4350 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004351 p = concat_str(s1, s2);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004352 clear_tv(rettv);
4353 rettv->v_type = VAR_STRING;
4354 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004355 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00004356 else if (op == '+' && rettv->v_type == VAR_LIST
4357 && var2.v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004358 {
4359 /* concatenate Lists */
4360 if (list_concat(rettv->vval.v_list, var2.vval.v_list,
4361 &var3) == FAIL)
4362 {
4363 clear_tv(rettv);
4364 clear_tv(&var2);
4365 return FAIL;
4366 }
4367 clear_tv(rettv);
4368 *rettv = var3;
4369 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004370 else
4371 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004372 int error = FALSE;
4373
4374 n1 = get_tv_number_chk(rettv, &error);
4375 if (error)
4376 {
4377 /* This can only happen for "list + non-list".
4378 * For "non-list + ..." or "something - ...", we returned
4379 * before evaluating the 2nd operand. */
4380 clear_tv(rettv);
4381 return FAIL;
4382 }
4383 n2 = get_tv_number_chk(&var2, &error);
4384 if (error)
4385 {
4386 clear_tv(rettv);
4387 clear_tv(&var2);
4388 return FAIL;
4389 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004390 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004391 if (op == '+')
4392 n1 = n1 + n2;
4393 else
4394 n1 = n1 - n2;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004395 rettv->v_type = VAR_NUMBER;
4396 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004397 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004398 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004399 }
4400 }
4401 return OK;
4402}
4403
4404/*
4405 * Handle fifth level expression:
4406 * * number multiplication
4407 * / number division
4408 * % number modulo
4409 *
4410 * "arg" must point to the first non-white of the expression.
4411 * "arg" is advanced to the next non-white after the recognized expression.
4412 *
4413 * Return OK or FAIL.
4414 */
4415 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004416eval6(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004417 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004418 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004419 int evaluate;
4420{
Bram Moolenaar33570922005-01-25 22:26:29 +00004421 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004422 int op;
4423 long n1, n2;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004424 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004425
4426 /*
4427 * Get the first variable.
4428 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004429 if (eval7(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004430 return FAIL;
4431
4432 /*
4433 * Repeat computing, until no '*', '/' or '%' is following.
4434 */
4435 for (;;)
4436 {
4437 op = **arg;
4438 if (op != '*' && op != '/' && op != '%')
4439 break;
4440
4441 if (evaluate)
4442 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004443 n1 = get_tv_number_chk(rettv, &error);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004444 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004445 if (error)
4446 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004447 }
4448 else
4449 n1 = 0;
4450
4451 /*
4452 * Get the second variable.
4453 */
4454 *arg = skipwhite(*arg + 1);
4455 if (eval7(arg, &var2, evaluate) == FAIL)
4456 return FAIL;
4457
4458 if (evaluate)
4459 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004460 n2 = get_tv_number_chk(&var2, &error);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004461 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004462 if (error)
4463 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004464
4465 /*
4466 * Compute the result.
4467 */
4468 if (op == '*')
4469 n1 = n1 * n2;
4470 else if (op == '/')
4471 {
4472 if (n2 == 0) /* give an error message? */
4473 n1 = 0x7fffffffL;
4474 else
4475 n1 = n1 / n2;
4476 }
4477 else
4478 {
4479 if (n2 == 0) /* give an error message? */
4480 n1 = 0;
4481 else
4482 n1 = n1 % n2;
4483 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004484 rettv->v_type = VAR_NUMBER;
4485 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004486 }
4487 }
4488
4489 return OK;
4490}
4491
4492/*
4493 * Handle sixth level expression:
4494 * number number constant
4495 * "string" string contstant
4496 * 'string' literal string contstant
4497 * &option-name option value
4498 * @r register contents
4499 * identifier variable value
4500 * function() function call
4501 * $VAR environment variable
4502 * (expression) nested expression
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00004503 * [expr, expr] List
4504 * {key: val, key: val} Dictionary
Bram Moolenaar071d4272004-06-13 20:20:40 +00004505 *
4506 * Also handle:
4507 * ! in front logical NOT
4508 * - in front unary minus
4509 * + in front unary plus (ignored)
Bram Moolenaar8c711452005-01-14 21:53:12 +00004510 * trailing [] subscript in String or List
4511 * trailing .name entry in Dictionary
Bram Moolenaar071d4272004-06-13 20:20:40 +00004512 *
4513 * "arg" must point to the first non-white of the expression.
4514 * "arg" is advanced to the next non-white after the recognized expression.
4515 *
4516 * Return OK or FAIL.
4517 */
4518 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004519eval7(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004520 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004521 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004522 int evaluate;
4523{
Bram Moolenaar071d4272004-06-13 20:20:40 +00004524 long n;
4525 int len;
4526 char_u *s;
4527 int val;
4528 char_u *start_leader, *end_leader;
4529 int ret = OK;
4530 char_u *alias;
4531
4532 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004533 * Initialise variable so that clear_tv() can't mistake this for a
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004534 * string and free a string that isn't there.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004535 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004536 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004537
4538 /*
4539 * Skip '!' and '-' characters. They are handled later.
4540 */
4541 start_leader = *arg;
4542 while (**arg == '!' || **arg == '-' || **arg == '+')
4543 *arg = skipwhite(*arg + 1);
4544 end_leader = *arg;
4545
4546 switch (**arg)
4547 {
4548 /*
4549 * Number constant.
4550 */
4551 case '0':
4552 case '1':
4553 case '2':
4554 case '3':
4555 case '4':
4556 case '5':
4557 case '6':
4558 case '7':
4559 case '8':
4560 case '9':
4561 vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL);
4562 *arg += len;
4563 if (evaluate)
4564 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004565 rettv->v_type = VAR_NUMBER;
4566 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004567 }
4568 break;
4569
4570 /*
4571 * String constant: "string".
4572 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004573 case '"': ret = get_string_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004574 break;
4575
4576 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004577 * Literal string constant: 'str''ing'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004578 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004579 case '\'': ret = get_lit_string_tv(arg, rettv, evaluate);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004580 break;
4581
4582 /*
4583 * List: [expr, expr]
4584 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004585 case '[': ret = get_list_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004586 break;
4587
4588 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004589 * Dictionary: {key: val, key: val}
4590 */
4591 case '{': ret = get_dict_tv(arg, rettv, evaluate);
4592 break;
4593
4594 /*
Bram Moolenaare9a41262005-01-15 22:18:47 +00004595 * Option value: &name
Bram Moolenaar071d4272004-06-13 20:20:40 +00004596 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00004597 case '&': ret = get_option_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004598 break;
4599
4600 /*
4601 * Environment variable: $VAR.
4602 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004603 case '$': ret = get_env_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004604 break;
4605
4606 /*
4607 * Register contents: @r.
4608 */
4609 case '@': ++*arg;
4610 if (evaluate)
4611 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004612 rettv->v_type = VAR_STRING;
Bram Moolenaar92124a32005-06-17 22:03:40 +00004613 rettv->vval.v_string = get_reg_contents(**arg, TRUE, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004614 }
4615 if (**arg != NUL)
4616 ++*arg;
4617 break;
4618
4619 /*
4620 * nested expression: (expression).
4621 */
4622 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004623 ret = eval1(arg, rettv, evaluate); /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004624 if (**arg == ')')
4625 ++*arg;
4626 else if (ret == OK)
4627 {
4628 EMSG(_("E110: Missing ')'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004629 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004630 ret = FAIL;
4631 }
4632 break;
4633
Bram Moolenaar8c711452005-01-14 21:53:12 +00004634 default: ret = NOTDONE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004635 break;
4636 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004637
4638 if (ret == NOTDONE)
4639 {
4640 /*
4641 * Must be a variable or function name.
4642 * Can also be a curly-braces kind of name: {expr}.
4643 */
4644 s = *arg;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004645 len = get_name_len(arg, &alias, evaluate, TRUE);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004646 if (alias != NULL)
4647 s = alias;
4648
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004649 if (len <= 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00004650 ret = FAIL;
4651 else
4652 {
4653 if (**arg == '(') /* recursive! */
4654 {
4655 /* If "s" is the name of a variable of type VAR_FUNC
4656 * use its contents. */
4657 s = deref_func_name(s, &len);
4658
4659 /* Invoke the function. */
4660 ret = get_func_tv(s, len, rettv, arg,
4661 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
Bram Moolenaare9a41262005-01-15 22:18:47 +00004662 &len, evaluate, NULL);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004663 /* Stop the expression evaluation when immediately
4664 * aborting on error, or when an interrupt occurred or
4665 * an exception was thrown but not caught. */
4666 if (aborting())
4667 {
4668 if (ret == OK)
4669 clear_tv(rettv);
4670 ret = FAIL;
4671 }
4672 }
4673 else if (evaluate)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004674 ret = get_var_tv(s, len, rettv, TRUE);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004675 else
4676 ret = OK;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004677 }
4678
4679 if (alias != NULL)
4680 vim_free(alias);
4681 }
4682
Bram Moolenaar071d4272004-06-13 20:20:40 +00004683 *arg = skipwhite(*arg);
4684
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004685 /* Handle following '[', '(' and '.' for expr[expr], expr.name,
4686 * expr(expr). */
4687 if (ret == OK)
4688 ret = handle_subscript(arg, rettv, evaluate, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004689
4690 /*
4691 * Apply logical NOT and unary '-', from right to left, ignore '+'.
4692 */
4693 if (ret == OK && evaluate && end_leader > start_leader)
4694 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004695 int error = FALSE;
4696
4697 val = get_tv_number_chk(rettv, &error);
4698 if (error)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004699 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004700 clear_tv(rettv);
4701 ret = FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004702 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004703 else
4704 {
4705 while (end_leader > start_leader)
4706 {
4707 --end_leader;
4708 if (*end_leader == '!')
4709 val = !val;
4710 else if (*end_leader == '-')
4711 val = -val;
4712 }
4713 clear_tv(rettv);
4714 rettv->v_type = VAR_NUMBER;
4715 rettv->vval.v_number = val;
4716 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004717 }
4718
4719 return ret;
4720}
4721
4722/*
Bram Moolenaar9e54a0e2006-04-14 20:42:25 +00004723 * Evaluate an "[expr]" or "[expr:expr]" index. Also "dict.key".
4724 * "*arg" points to the '[' or '.'.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004725 * Returns FAIL or OK. "*arg" is advanced to after the ']'.
4726 */
4727 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004728eval_index(arg, rettv, evaluate, verbose)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004729 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004730 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004731 int evaluate;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004732 int verbose; /* give error messages */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004733{
4734 int empty1 = FALSE, empty2 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00004735 typval_T var1, var2;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004736 long n1, n2 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004737 long len = -1;
4738 int range = FALSE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004739 char_u *s;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004740 char_u *key = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004741
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004742 if (rettv->v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004743 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004744 if (verbose)
4745 EMSG(_("E695: Cannot index a Funcref"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004746 return FAIL;
4747 }
4748
Bram Moolenaar8c711452005-01-14 21:53:12 +00004749 if (**arg == '.')
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004750 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004751 /*
4752 * dict.name
4753 */
4754 key = *arg + 1;
4755 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
4756 ;
4757 if (len == 0)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004758 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004759 *arg = skipwhite(key + len);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004760 }
4761 else
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004762 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004763 /*
4764 * something[idx]
4765 *
4766 * Get the (first) variable from inside the [].
4767 */
4768 *arg = skipwhite(*arg + 1);
4769 if (**arg == ':')
4770 empty1 = TRUE;
4771 else if (eval1(arg, &var1, evaluate) == FAIL) /* recursive! */
4772 return FAIL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004773 else if (evaluate && get_tv_string_chk(&var1) == NULL)
4774 {
4775 /* not a number or string */
4776 clear_tv(&var1);
4777 return FAIL;
4778 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004779
4780 /*
4781 * Get the second variable from inside the [:].
4782 */
4783 if (**arg == ':')
4784 {
4785 range = TRUE;
4786 *arg = skipwhite(*arg + 1);
4787 if (**arg == ']')
4788 empty2 = TRUE;
4789 else if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */
4790 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004791 if (!empty1)
4792 clear_tv(&var1);
4793 return FAIL;
4794 }
4795 else if (evaluate && get_tv_string_chk(&var2) == NULL)
4796 {
4797 /* not a number or string */
4798 if (!empty1)
4799 clear_tv(&var1);
4800 clear_tv(&var2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004801 return FAIL;
4802 }
4803 }
4804
4805 /* Check for the ']'. */
4806 if (**arg != ']')
4807 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004808 if (verbose)
4809 EMSG(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004810 clear_tv(&var1);
4811 if (range)
4812 clear_tv(&var2);
4813 return FAIL;
4814 }
4815 *arg = skipwhite(*arg + 1); /* skip the ']' */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004816 }
4817
4818 if (evaluate)
4819 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004820 n1 = 0;
4821 if (!empty1 && rettv->v_type != VAR_DICT)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004822 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004823 n1 = get_tv_number(&var1);
4824 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004825 }
4826 if (range)
4827 {
4828 if (empty2)
4829 n2 = -1;
4830 else
4831 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004832 n2 = get_tv_number(&var2);
4833 clear_tv(&var2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004834 }
4835 }
4836
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004837 switch (rettv->v_type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004838 {
4839 case VAR_NUMBER:
4840 case VAR_STRING:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004841 s = get_tv_string(rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004842 len = (long)STRLEN(s);
4843 if (range)
4844 {
4845 /* The resulting variable is a substring. If the indexes
4846 * are out of range the result is empty. */
4847 if (n1 < 0)
4848 {
4849 n1 = len + n1;
4850 if (n1 < 0)
4851 n1 = 0;
4852 }
4853 if (n2 < 0)
4854 n2 = len + n2;
4855 else if (n2 >= len)
4856 n2 = len;
4857 if (n1 >= len || n2 < 0 || n1 > n2)
4858 s = NULL;
4859 else
4860 s = vim_strnsave(s + n1, (int)(n2 - n1 + 1));
4861 }
4862 else
4863 {
4864 /* The resulting variable is a string of a single
4865 * character. If the index is too big or negative the
4866 * result is empty. */
4867 if (n1 >= len || n1 < 0)
4868 s = NULL;
4869 else
4870 s = vim_strnsave(s + n1, 1);
4871 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004872 clear_tv(rettv);
4873 rettv->v_type = VAR_STRING;
4874 rettv->vval.v_string = s;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004875 break;
4876
4877 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004878 len = list_len(rettv->vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004879 if (n1 < 0)
4880 n1 = len + n1;
4881 if (!empty1 && (n1 < 0 || n1 >= len))
4882 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00004883 /* For a range we allow invalid values and return an empty
4884 * list. A list index out of range is an error. */
4885 if (!range)
4886 {
4887 if (verbose)
4888 EMSGN(_(e_listidx), n1);
4889 return FAIL;
4890 }
4891 n1 = len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004892 }
4893 if (range)
4894 {
Bram Moolenaar33570922005-01-25 22:26:29 +00004895 list_T *l;
4896 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004897
4898 if (n2 < 0)
4899 n2 = len + n2;
Bram Moolenaar9e54a0e2006-04-14 20:42:25 +00004900 else if (n2 >= len)
4901 n2 = len - 1;
4902 if (!empty2 && (n2 < 0 || n2 + 1 < n1))
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00004903 n2 = -1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004904 l = list_alloc();
4905 if (l == NULL)
4906 return FAIL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004907 for (item = list_find(rettv->vval.v_list, n1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004908 n1 <= n2; ++n1)
4909 {
4910 if (list_append_tv(l, &item->li_tv) == FAIL)
4911 {
4912 list_free(l);
4913 return FAIL;
4914 }
4915 item = item->li_next;
4916 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004917 clear_tv(rettv);
4918 rettv->v_type = VAR_LIST;
4919 rettv->vval.v_list = l;
Bram Moolenaar0d660222005-01-07 21:51:51 +00004920 ++l->lv_refcount;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004921 }
4922 else
4923 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00004924 copy_tv(&list_find(rettv->vval.v_list, n1)->li_tv, &var1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004925 clear_tv(rettv);
4926 *rettv = var1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004927 }
4928 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004929
4930 case VAR_DICT:
4931 if (range)
4932 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004933 if (verbose)
4934 EMSG(_(e_dictrange));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004935 if (len == -1)
4936 clear_tv(&var1);
4937 return FAIL;
4938 }
4939 {
Bram Moolenaar33570922005-01-25 22:26:29 +00004940 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004941
4942 if (len == -1)
4943 {
4944 key = get_tv_string(&var1);
4945 if (*key == NUL)
4946 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004947 if (verbose)
4948 EMSG(_(e_emptykey));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004949 clear_tv(&var1);
4950 return FAIL;
4951 }
4952 }
4953
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00004954 item = dict_find(rettv->vval.v_dict, key, (int)len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004955
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004956 if (item == NULL && verbose)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004957 EMSG2(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004958 if (len == -1)
4959 clear_tv(&var1);
4960 if (item == NULL)
4961 return FAIL;
4962
4963 copy_tv(&item->di_tv, &var1);
4964 clear_tv(rettv);
4965 *rettv = var1;
4966 }
4967 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004968 }
4969 }
4970
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004971 return OK;
4972}
4973
4974/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00004975 * Get an option value.
4976 * "arg" points to the '&' or '+' before the option name.
4977 * "arg" is advanced to character after the option name.
4978 * Return OK or FAIL.
4979 */
4980 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004981get_option_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004982 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004983 typval_T *rettv; /* when NULL, only check if option exists */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004984 int evaluate;
4985{
4986 char_u *option_end;
4987 long numval;
4988 char_u *stringval;
4989 int opt_type;
4990 int c;
4991 int working = (**arg == '+'); /* has("+option") */
4992 int ret = OK;
4993 int opt_flags;
4994
4995 /*
4996 * Isolate the option name and find its value.
4997 */
4998 option_end = find_option_end(arg, &opt_flags);
4999 if (option_end == NULL)
5000 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005001 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005002 EMSG2(_("E112: Option name missing: %s"), *arg);
5003 return FAIL;
5004 }
5005
5006 if (!evaluate)
5007 {
5008 *arg = option_end;
5009 return OK;
5010 }
5011
5012 c = *option_end;
5013 *option_end = NUL;
5014 opt_type = get_option_value(*arg, &numval,
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005015 rettv == NULL ? NULL : &stringval, opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005016
5017 if (opt_type == -3) /* invalid name */
5018 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005019 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005020 EMSG2(_("E113: Unknown option: %s"), *arg);
5021 ret = FAIL;
5022 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005023 else if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005024 {
5025 if (opt_type == -2) /* hidden string option */
5026 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005027 rettv->v_type = VAR_STRING;
5028 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005029 }
5030 else if (opt_type == -1) /* hidden number option */
5031 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005032 rettv->v_type = VAR_NUMBER;
5033 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005034 }
5035 else if (opt_type == 1) /* number option */
5036 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005037 rettv->v_type = VAR_NUMBER;
5038 rettv->vval.v_number = numval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005039 }
5040 else /* string option */
5041 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005042 rettv->v_type = VAR_STRING;
5043 rettv->vval.v_string = stringval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005044 }
5045 }
5046 else if (working && (opt_type == -2 || opt_type == -1))
5047 ret = FAIL;
5048
5049 *option_end = c; /* put back for error messages */
5050 *arg = option_end;
5051
5052 return ret;
5053}
5054
5055/*
5056 * Allocate a variable for a string constant.
5057 * Return OK or FAIL.
5058 */
5059 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005060get_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005061 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00005062 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005063 int evaluate;
5064{
5065 char_u *p;
5066 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005067 int extra = 0;
5068
5069 /*
5070 * Find the end of the string, skipping backslashed characters.
5071 */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005072 for (p = *arg + 1; *p != NUL && *p != '"'; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005073 {
5074 if (*p == '\\' && p[1] != NUL)
5075 {
5076 ++p;
5077 /* A "\<x>" form occupies at least 4 characters, and produces up
5078 * to 6 characters: reserve space for 2 extra */
5079 if (*p == '<')
5080 extra += 2;
5081 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005082 }
5083
5084 if (*p != '"')
5085 {
5086 EMSG2(_("E114: Missing quote: %s"), *arg);
5087 return FAIL;
5088 }
5089
5090 /* If only parsing, set *arg and return here */
5091 if (!evaluate)
5092 {
5093 *arg = p + 1;
5094 return OK;
5095 }
5096
5097 /*
5098 * Copy the string into allocated memory, handling backslashed
5099 * characters.
5100 */
5101 name = alloc((unsigned)(p - *arg + extra));
5102 if (name == NULL)
5103 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005104 rettv->v_type = VAR_STRING;
5105 rettv->vval.v_string = name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005106
Bram Moolenaar8c711452005-01-14 21:53:12 +00005107 for (p = *arg + 1; *p != NUL && *p != '"'; )
Bram Moolenaar071d4272004-06-13 20:20:40 +00005108 {
5109 if (*p == '\\')
5110 {
5111 switch (*++p)
5112 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005113 case 'b': *name++ = BS; ++p; break;
5114 case 'e': *name++ = ESC; ++p; break;
5115 case 'f': *name++ = FF; ++p; break;
5116 case 'n': *name++ = NL; ++p; break;
5117 case 'r': *name++ = CAR; ++p; break;
5118 case 't': *name++ = TAB; ++p; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005119
5120 case 'X': /* hex: "\x1", "\x12" */
5121 case 'x':
5122 case 'u': /* Unicode: "\u0023" */
5123 case 'U':
5124 if (vim_isxdigit(p[1]))
5125 {
5126 int n, nr;
5127 int c = toupper(*p);
5128
5129 if (c == 'X')
5130 n = 2;
5131 else
5132 n = 4;
5133 nr = 0;
5134 while (--n >= 0 && vim_isxdigit(p[1]))
5135 {
5136 ++p;
5137 nr = (nr << 4) + hex2nr(*p);
5138 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005139 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005140#ifdef FEAT_MBYTE
5141 /* For "\u" store the number according to
5142 * 'encoding'. */
5143 if (c != 'X')
Bram Moolenaar8c711452005-01-14 21:53:12 +00005144 name += (*mb_char2bytes)(nr, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005145 else
5146#endif
Bram Moolenaar8c711452005-01-14 21:53:12 +00005147 *name++ = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005148 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005149 break;
5150
5151 /* octal: "\1", "\12", "\123" */
5152 case '0':
5153 case '1':
5154 case '2':
5155 case '3':
5156 case '4':
5157 case '5':
5158 case '6':
Bram Moolenaar8c711452005-01-14 21:53:12 +00005159 case '7': *name = *p++ - '0';
5160 if (*p >= '0' && *p <= '7')
Bram Moolenaar071d4272004-06-13 20:20:40 +00005161 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005162 *name = (*name << 3) + *p++ - '0';
5163 if (*p >= '0' && *p <= '7')
5164 *name = (*name << 3) + *p++ - '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +00005165 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005166 ++name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005167 break;
5168
5169 /* Special key, e.g.: "\<C-W>" */
Bram Moolenaar8c711452005-01-14 21:53:12 +00005170 case '<': extra = trans_special(&p, name, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005171 if (extra != 0)
5172 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005173 name += extra;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005174 break;
5175 }
5176 /* FALLTHROUGH */
5177
Bram Moolenaar8c711452005-01-14 21:53:12 +00005178 default: MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005179 break;
5180 }
5181 }
5182 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00005183 MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005184
Bram Moolenaar071d4272004-06-13 20:20:40 +00005185 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005186 *name = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005187 *arg = p + 1;
5188
Bram Moolenaar071d4272004-06-13 20:20:40 +00005189 return OK;
5190}
5191
5192/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005193 * Allocate a variable for a 'str''ing' constant.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005194 * Return OK or FAIL.
5195 */
5196 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005197get_lit_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005198 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00005199 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005200 int evaluate;
5201{
5202 char_u *p;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005203 char_u *str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005204 int reduce = 0;
5205
5206 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005207 * Find the end of the string, skipping ''.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005208 */
5209 for (p = *arg + 1; *p != NUL; mb_ptr_adv(p))
5210 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005211 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005212 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005213 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005214 break;
5215 ++reduce;
5216 ++p;
5217 }
5218 }
5219
Bram Moolenaar8c711452005-01-14 21:53:12 +00005220 if (*p != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005221 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005222 EMSG2(_("E115: Missing quote: %s"), *arg);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005223 return FAIL;
5224 }
5225
Bram Moolenaar8c711452005-01-14 21:53:12 +00005226 /* If only parsing return after setting "*arg" */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005227 if (!evaluate)
5228 {
5229 *arg = p + 1;
5230 return OK;
5231 }
5232
5233 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005234 * Copy the string into allocated memory, handling '' to ' reduction.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005235 */
5236 str = alloc((unsigned)((p - *arg) - reduce));
5237 if (str == NULL)
5238 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005239 rettv->v_type = VAR_STRING;
5240 rettv->vval.v_string = str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005241
Bram Moolenaar8c711452005-01-14 21:53:12 +00005242 for (p = *arg + 1; *p != NUL; )
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005243 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005244 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005245 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005246 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005247 break;
5248 ++p;
5249 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005250 MB_COPY_CHAR(p, str);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005251 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005252 *str = NUL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005253 *arg = p + 1;
5254
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005255 return OK;
5256}
5257
5258/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005259 * Allocate a variable for a List and fill it from "*arg".
5260 * Return OK or FAIL.
5261 */
5262 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005263get_list_tv(arg, rettv, evaluate)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005264 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00005265 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005266 int evaluate;
5267{
Bram Moolenaar33570922005-01-25 22:26:29 +00005268 list_T *l = NULL;
5269 typval_T tv;
5270 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005271
5272 if (evaluate)
5273 {
5274 l = list_alloc();
5275 if (l == NULL)
5276 return FAIL;
5277 }
5278
5279 *arg = skipwhite(*arg + 1);
5280 while (**arg != ']' && **arg != NUL)
5281 {
5282 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
5283 goto failret;
5284 if (evaluate)
5285 {
5286 item = listitem_alloc();
5287 if (item != NULL)
5288 {
5289 item->li_tv = tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005290 item->li_tv.v_lock = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005291 list_append(l, item);
5292 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005293 else
5294 clear_tv(&tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005295 }
5296
5297 if (**arg == ']')
5298 break;
5299 if (**arg != ',')
5300 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005301 EMSG2(_("E696: Missing comma in List: %s"), *arg);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005302 goto failret;
5303 }
5304 *arg = skipwhite(*arg + 1);
5305 }
5306
5307 if (**arg != ']')
5308 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005309 EMSG2(_("E697: Missing end of List ']': %s"), *arg);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005310failret:
5311 if (evaluate)
5312 list_free(l);
5313 return FAIL;
5314 }
5315
5316 *arg = skipwhite(*arg + 1);
5317 if (evaluate)
5318 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005319 rettv->v_type = VAR_LIST;
5320 rettv->vval.v_list = l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005321 ++l->lv_refcount;
5322 }
5323
5324 return OK;
5325}
5326
5327/*
5328 * Allocate an empty header for a list.
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00005329 * Caller should take care of the reference count.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005330 */
Bram Moolenaar1ef15e32006-02-01 21:56:25 +00005331 list_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005332list_alloc()
5333{
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005334 list_T *l;
5335
5336 l = (list_T *)alloc_clear(sizeof(list_T));
5337 if (l != NULL)
5338 {
5339 /* Prepend the list to the list of lists for garbage collection. */
5340 if (first_list != NULL)
5341 first_list->lv_used_prev = l;
5342 l->lv_used_prev = NULL;
5343 l->lv_used_next = first_list;
5344 first_list = l;
5345 }
5346 return l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005347}
5348
5349/*
Bram Moolenaareddf53b2006-02-27 00:11:10 +00005350 * Allocate an empty list for a return value.
5351 * Returns OK or FAIL.
5352 */
5353 static int
5354rettv_list_alloc(rettv)
5355 typval_T *rettv;
5356{
5357 list_T *l = list_alloc();
5358
5359 if (l == NULL)
5360 return FAIL;
5361
5362 rettv->vval.v_list = l;
5363 rettv->v_type = VAR_LIST;
5364 ++l->lv_refcount;
5365 return OK;
5366}
5367
5368/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005369 * Unreference a list: decrement the reference count and free it when it
5370 * becomes zero.
5371 */
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00005372 void
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005373list_unref(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00005374 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005375{
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005376 if (l != NULL && l->lv_refcount != DEL_REFCOUNT && --l->lv_refcount <= 0)
5377 list_free(l);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005378}
5379
5380/*
5381 * Free a list, including all items it points to.
5382 * Ignores the reference count.
5383 */
Bram Moolenaar1ef15e32006-02-01 21:56:25 +00005384 void
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005385list_free(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00005386 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005387{
Bram Moolenaar33570922005-01-25 22:26:29 +00005388 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005389
Bram Moolenaard9fba312005-06-26 22:34:35 +00005390 /* Avoid that recursive reference to the list frees us again. */
5391 l->lv_refcount = DEL_REFCOUNT;
5392
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005393 /* Remove the list from the list of lists for garbage collection. */
5394 if (l->lv_used_prev == NULL)
5395 first_list = l->lv_used_next;
5396 else
5397 l->lv_used_prev->lv_used_next = l->lv_used_next;
5398 if (l->lv_used_next != NULL)
5399 l->lv_used_next->lv_used_prev = l->lv_used_prev;
5400
Bram Moolenaard9fba312005-06-26 22:34:35 +00005401 for (item = l->lv_first; item != NULL; item = l->lv_first)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005402 {
Bram Moolenaard9fba312005-06-26 22:34:35 +00005403 /* Remove the item before deleting it. */
5404 l->lv_first = item->li_next;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005405 listitem_free(item);
5406 }
5407 vim_free(l);
5408}
5409
5410/*
5411 * Allocate a list item.
5412 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005413 static listitem_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005414listitem_alloc()
5415{
Bram Moolenaar33570922005-01-25 22:26:29 +00005416 return (listitem_T *)alloc(sizeof(listitem_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005417}
5418
5419/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00005420 * Free a list item. Also clears the value. Does not notify watchers.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005421 */
5422 static void
5423listitem_free(item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005424 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005425{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005426 clear_tv(&item->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005427 vim_free(item);
5428}
5429
5430/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005431 * Remove a list item from a List and free it. Also clears the value.
5432 */
5433 static void
5434listitem_remove(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005435 list_T *l;
5436 listitem_T *item;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005437{
5438 list_remove(l, item, item);
5439 listitem_free(item);
5440}
5441
5442/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005443 * Get the number of items in a list.
5444 */
5445 static long
5446list_len(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00005447 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005448{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005449 if (l == NULL)
5450 return 0L;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005451 return l->lv_len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005452}
5453
5454/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005455 * Return TRUE when two lists have exactly the same values.
5456 */
5457 static int
5458list_equal(l1, l2, ic)
Bram Moolenaar33570922005-01-25 22:26:29 +00005459 list_T *l1;
5460 list_T *l2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005461 int ic; /* ignore case for strings */
5462{
Bram Moolenaar33570922005-01-25 22:26:29 +00005463 listitem_T *item1, *item2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005464
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005465 if (list_len(l1) != list_len(l2))
5466 return FALSE;
5467
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005468 for (item1 = l1->lv_first, item2 = l2->lv_first;
5469 item1 != NULL && item2 != NULL;
5470 item1 = item1->li_next, item2 = item2->li_next)
5471 if (!tv_equal(&item1->li_tv, &item2->li_tv, ic))
5472 return FALSE;
5473 return item1 == NULL && item2 == NULL;
5474}
5475
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005476#if defined(FEAT_PYTHON) || defined(PROTO)
5477/*
5478 * Return the dictitem that an entry in a hashtable points to.
5479 */
5480 dictitem_T *
5481dict_lookup(hi)
5482 hashitem_T *hi;
5483{
5484 return HI2DI(hi);
5485}
5486#endif
5487
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005488/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005489 * Return TRUE when two dictionaries have exactly the same key/values.
5490 */
5491 static int
5492dict_equal(d1, d2, ic)
Bram Moolenaar33570922005-01-25 22:26:29 +00005493 dict_T *d1;
5494 dict_T *d2;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005495 int ic; /* ignore case for strings */
5496{
Bram Moolenaar33570922005-01-25 22:26:29 +00005497 hashitem_T *hi;
5498 dictitem_T *item2;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005499 int todo;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005500
5501 if (dict_len(d1) != dict_len(d2))
5502 return FALSE;
5503
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00005504 todo = (int)d1->dv_hashtab.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00005505 for (hi = d1->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005506 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005507 if (!HASHITEM_EMPTY(hi))
5508 {
5509 item2 = dict_find(d2, hi->hi_key, -1);
5510 if (item2 == NULL)
5511 return FALSE;
5512 if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic))
5513 return FALSE;
5514 --todo;
5515 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005516 }
5517 return TRUE;
5518}
5519
5520/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005521 * Return TRUE if "tv1" and "tv2" have the same value.
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005522 * Compares the items just like "==" would compare them, but strings and
5523 * numbers are different.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005524 */
5525 static int
5526tv_equal(tv1, tv2, ic)
Bram Moolenaar33570922005-01-25 22:26:29 +00005527 typval_T *tv1;
5528 typval_T *tv2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005529 int ic; /* ignore case */
5530{
5531 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005532 char_u *s1, *s2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005533
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005534 if (tv1->v_type != tv2->v_type)
5535 return FALSE;
5536
5537 switch (tv1->v_type)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005538 {
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005539 case VAR_LIST:
5540 /* recursive! */
5541 return list_equal(tv1->vval.v_list, tv2->vval.v_list, ic);
5542
5543 case VAR_DICT:
5544 /* recursive! */
5545 return dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic);
5546
5547 case VAR_FUNC:
5548 return (tv1->vval.v_string != NULL
5549 && tv2->vval.v_string != NULL
5550 && STRCMP(tv1->vval.v_string, tv2->vval.v_string) == 0);
5551
5552 case VAR_NUMBER:
5553 return tv1->vval.v_number == tv2->vval.v_number;
5554
5555 case VAR_STRING:
5556 s1 = get_tv_string_buf(tv1, buf1);
5557 s2 = get_tv_string_buf(tv2, buf2);
5558 return ((ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2)) == 0);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005559 }
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005560
5561 EMSG2(_(e_intern2), "tv_equal()");
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005562 return TRUE;
5563}
5564
5565/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005566 * Locate item with index "n" in list "l" and return it.
5567 * A negative index is counted from the end; -1 is the last item.
5568 * Returns NULL when "n" is out of range.
5569 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005570 static listitem_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005571list_find(l, n)
Bram Moolenaar33570922005-01-25 22:26:29 +00005572 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005573 long n;
5574{
Bram Moolenaar33570922005-01-25 22:26:29 +00005575 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005576 long idx;
5577
5578 if (l == NULL)
5579 return NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005580
5581 /* Negative index is relative to the end. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005582 if (n < 0)
Bram Moolenaar758711c2005-02-02 23:11:38 +00005583 n = l->lv_len + n;
5584
5585 /* Check for index out of range. */
5586 if (n < 0 || n >= l->lv_len)
5587 return NULL;
5588
5589 /* When there is a cached index may start search from there. */
5590 if (l->lv_idx_item != NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005591 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00005592 if (n < l->lv_idx / 2)
5593 {
5594 /* closest to the start of the list */
5595 item = l->lv_first;
5596 idx = 0;
5597 }
5598 else if (n > (l->lv_idx + l->lv_len) / 2)
5599 {
5600 /* closest to the end of the list */
5601 item = l->lv_last;
5602 idx = l->lv_len - 1;
5603 }
5604 else
5605 {
5606 /* closest to the cached index */
5607 item = l->lv_idx_item;
5608 idx = l->lv_idx;
5609 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005610 }
5611 else
5612 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00005613 if (n < l->lv_len / 2)
5614 {
5615 /* closest to the start of the list */
5616 item = l->lv_first;
5617 idx = 0;
5618 }
5619 else
5620 {
5621 /* closest to the end of the list */
5622 item = l->lv_last;
5623 idx = l->lv_len - 1;
5624 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005625 }
Bram Moolenaar758711c2005-02-02 23:11:38 +00005626
5627 while (n > idx)
5628 {
5629 /* search forward */
5630 item = item->li_next;
5631 ++idx;
5632 }
5633 while (n < idx)
5634 {
5635 /* search backward */
5636 item = item->li_prev;
5637 --idx;
5638 }
5639
5640 /* cache the used index */
5641 l->lv_idx = idx;
5642 l->lv_idx_item = item;
5643
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005644 return item;
5645}
5646
5647/*
Bram Moolenaara5525202006-03-02 22:52:09 +00005648 * Get list item "l[idx]" as a number.
5649 */
5650 static long
5651list_find_nr(l, idx, errorp)
5652 list_T *l;
5653 long idx;
5654 int *errorp; /* set to TRUE when something wrong */
5655{
5656 listitem_T *li;
5657
5658 li = list_find(l, idx);
5659 if (li == NULL)
5660 {
5661 if (errorp != NULL)
5662 *errorp = TRUE;
5663 return -1L;
5664 }
5665 return get_tv_number_chk(&li->li_tv, errorp);
5666}
5667
5668/*
Bram Moolenaar6cc16192005-01-08 21:49:45 +00005669 * Locate "item" list "l" and return its index.
5670 * Returns -1 when "item" is not in the list.
5671 */
5672 static long
5673list_idx_of_item(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005674 list_T *l;
5675 listitem_T *item;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00005676{
5677 long idx = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00005678 listitem_T *li;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00005679
5680 if (l == NULL)
5681 return -1;
5682 idx = 0;
5683 for (li = l->lv_first; li != NULL && li != item; li = li->li_next)
5684 ++idx;
5685 if (li == NULL)
5686 return -1;
Bram Moolenaar75c50c42005-06-04 22:06:24 +00005687 return idx;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00005688}
5689
5690/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005691 * Append item "item" to the end of list "l".
5692 */
5693 static void
5694list_append(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005695 list_T *l;
5696 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005697{
5698 if (l->lv_last == NULL)
5699 {
5700 /* empty list */
5701 l->lv_first = item;
5702 l->lv_last = item;
5703 item->li_prev = NULL;
5704 }
5705 else
5706 {
5707 l->lv_last->li_next = item;
5708 item->li_prev = l->lv_last;
5709 l->lv_last = item;
5710 }
Bram Moolenaar758711c2005-02-02 23:11:38 +00005711 ++l->lv_len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005712 item->li_next = NULL;
5713}
5714
5715/*
Bram Moolenaar33570922005-01-25 22:26:29 +00005716 * Append typval_T "tv" to the end of list "l".
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005717 * Return FAIL when out of memory.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005718 */
5719 static int
5720list_append_tv(l, tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005721 list_T *l;
5722 typval_T *tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005723{
Bram Moolenaar05159a02005-02-26 23:04:13 +00005724 listitem_T *li = listitem_alloc();
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005725
Bram Moolenaar05159a02005-02-26 23:04:13 +00005726 if (li == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005727 return FAIL;
Bram Moolenaar05159a02005-02-26 23:04:13 +00005728 copy_tv(tv, &li->li_tv);
5729 list_append(l, li);
5730 return OK;
5731}
5732
5733/*
Bram Moolenaar2641f772005-03-25 21:58:17 +00005734 * Add a dictionary to a list. Used by getqflist().
Bram Moolenaar05159a02005-02-26 23:04:13 +00005735 * Return FAIL when out of memory.
5736 */
5737 int
5738list_append_dict(list, dict)
5739 list_T *list;
5740 dict_T *dict;
5741{
5742 listitem_T *li = listitem_alloc();
5743
5744 if (li == NULL)
5745 return FAIL;
5746 li->li_tv.v_type = VAR_DICT;
5747 li->li_tv.v_lock = 0;
5748 li->li_tv.vval.v_dict = dict;
5749 list_append(list, li);
5750 ++dict->dv_refcount;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005751 return OK;
5752}
5753
5754/*
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00005755 * Make a copy of "str" and append it as an item to list "l".
Bram Moolenaar4463f292005-09-25 22:20:24 +00005756 * When "len" >= 0 use "str[len]".
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00005757 * Returns FAIL when out of memory.
5758 */
5759 static int
Bram Moolenaar4463f292005-09-25 22:20:24 +00005760list_append_string(l, str, len)
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00005761 list_T *l;
5762 char_u *str;
Bram Moolenaar4463f292005-09-25 22:20:24 +00005763 int len;
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00005764{
5765 listitem_T *li = listitem_alloc();
5766
5767 if (li == NULL)
5768 return FAIL;
5769 list_append(l, li);
5770 li->li_tv.v_type = VAR_STRING;
5771 li->li_tv.v_lock = 0;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00005772 if (str == NULL)
5773 li->li_tv.vval.v_string = NULL;
5774 else if ((li->li_tv.vval.v_string = (len >= 0 ? vim_strnsave(str, len)
Bram Moolenaar482aaeb2005-09-29 18:26:07 +00005775 : vim_strsave(str))) == NULL)
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00005776 return FAIL;
5777 return OK;
5778}
5779
5780/*
Bram Moolenaar4463f292005-09-25 22:20:24 +00005781 * Append "n" to list "l".
5782 * Returns FAIL when out of memory.
5783 */
5784 static int
5785list_append_number(l, n)
5786 list_T *l;
5787 varnumber_T n;
5788{
5789 listitem_T *li;
5790
5791 li = listitem_alloc();
5792 if (li == NULL)
5793 return FAIL;
5794 li->li_tv.v_type = VAR_NUMBER;
5795 li->li_tv.v_lock = 0;
5796 li->li_tv.vval.v_number = n;
5797 list_append(l, li);
5798 return OK;
5799}
5800
5801/*
Bram Moolenaar33570922005-01-25 22:26:29 +00005802 * Insert typval_T "tv" in list "l" before "item".
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005803 * If "item" is NULL append at the end.
5804 * Return FAIL when out of memory.
5805 */
5806 static int
5807list_insert_tv(l, tv, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005808 list_T *l;
5809 typval_T *tv;
5810 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005811{
Bram Moolenaar33570922005-01-25 22:26:29 +00005812 listitem_T *ni = listitem_alloc();
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005813
5814 if (ni == NULL)
5815 return FAIL;
5816 copy_tv(tv, &ni->li_tv);
5817 if (item == NULL)
5818 /* Append new item at end of list. */
5819 list_append(l, ni);
5820 else
5821 {
5822 /* Insert new item before existing item. */
5823 ni->li_prev = item->li_prev;
5824 ni->li_next = item;
5825 if (item->li_prev == NULL)
Bram Moolenaar758711c2005-02-02 23:11:38 +00005826 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005827 l->lv_first = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005828 ++l->lv_idx;
5829 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005830 else
Bram Moolenaar758711c2005-02-02 23:11:38 +00005831 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005832 item->li_prev->li_next = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005833 l->lv_idx_item = NULL;
5834 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005835 item->li_prev = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005836 ++l->lv_len;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005837 }
5838 return OK;
5839}
5840
5841/*
5842 * Extend "l1" with "l2".
5843 * If "bef" is NULL append at the end, otherwise insert before this item.
5844 * Returns FAIL when out of memory.
5845 */
5846 static int
5847list_extend(l1, l2, bef)
Bram Moolenaar33570922005-01-25 22:26:29 +00005848 list_T *l1;
5849 list_T *l2;
5850 listitem_T *bef;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005851{
Bram Moolenaar33570922005-01-25 22:26:29 +00005852 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005853
5854 for (item = l2->lv_first; item != NULL; item = item->li_next)
5855 if (list_insert_tv(l1, &item->li_tv, bef) == FAIL)
5856 return FAIL;
5857 return OK;
5858}
5859
5860/*
5861 * Concatenate lists "l1" and "l2" into a new list, stored in "tv".
5862 * Return FAIL when out of memory.
5863 */
5864 static int
5865list_concat(l1, l2, tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005866 list_T *l1;
5867 list_T *l2;
5868 typval_T *tv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005869{
Bram Moolenaar33570922005-01-25 22:26:29 +00005870 list_T *l;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005871
5872 /* make a copy of the first list. */
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005873 l = list_copy(l1, FALSE, 0);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005874 if (l == NULL)
5875 return FAIL;
5876 tv->v_type = VAR_LIST;
5877 tv->vval.v_list = l;
5878
5879 /* append all items from the second list */
5880 return list_extend(l, l2, NULL);
5881}
5882
5883/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005884 * Make a copy of list "orig". Shallow if "deep" is FALSE.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005885 * The refcount of the new list is set to 1.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005886 * See item_copy() for "copyID".
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005887 * Returns NULL when out of memory.
5888 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005889 static list_T *
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005890list_copy(orig, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00005891 list_T *orig;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005892 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005893 int copyID;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005894{
Bram Moolenaar33570922005-01-25 22:26:29 +00005895 list_T *copy;
5896 listitem_T *item;
5897 listitem_T *ni;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005898
5899 if (orig == NULL)
5900 return NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005901
5902 copy = list_alloc();
5903 if (copy != NULL)
5904 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005905 if (copyID != 0)
5906 {
5907 /* Do this before adding the items, because one of the items may
5908 * refer back to this list. */
5909 orig->lv_copyID = copyID;
5910 orig->lv_copylist = copy;
5911 }
5912 for (item = orig->lv_first; item != NULL && !got_int;
5913 item = item->li_next)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005914 {
5915 ni = listitem_alloc();
5916 if (ni == NULL)
5917 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005918 if (deep)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005919 {
5920 if (item_copy(&item->li_tv, &ni->li_tv, deep, copyID) == FAIL)
5921 {
5922 vim_free(ni);
5923 break;
5924 }
5925 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005926 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005927 copy_tv(&item->li_tv, &ni->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005928 list_append(copy, ni);
5929 }
5930 ++copy->lv_refcount;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005931 if (item != NULL)
5932 {
5933 list_unref(copy);
5934 copy = NULL;
5935 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005936 }
5937
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005938 return copy;
5939}
5940
5941/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005942 * Remove items "item" to "item2" from list "l".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005943 * Does not free the listitem or the value!
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005944 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005945 static void
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005946list_remove(l, item, item2)
Bram Moolenaar33570922005-01-25 22:26:29 +00005947 list_T *l;
5948 listitem_T *item;
5949 listitem_T *item2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005950{
Bram Moolenaar33570922005-01-25 22:26:29 +00005951 listitem_T *ip;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005952
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005953 /* notify watchers */
5954 for (ip = item; ip != NULL; ip = ip->li_next)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005955 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00005956 --l->lv_len;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005957 list_fix_watch(l, ip);
5958 if (ip == item2)
5959 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005960 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005961
5962 if (item2->li_next == NULL)
5963 l->lv_last = item->li_prev;
5964 else
5965 item2->li_next->li_prev = item->li_prev;
5966 if (item->li_prev == NULL)
5967 l->lv_first = item2->li_next;
5968 else
5969 item->li_prev->li_next = item2->li_next;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005970 l->lv_idx_item = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005971}
5972
5973/*
5974 * Return an allocated string with the string representation of a list.
5975 * May return NULL.
5976 */
5977 static char_u *
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005978list2string(tv, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00005979 typval_T *tv;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005980 int copyID;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005981{
5982 garray_T ga;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005983
5984 if (tv->vval.v_list == NULL)
5985 return NULL;
5986 ga_init2(&ga, (int)sizeof(char), 80);
5987 ga_append(&ga, '[');
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005988 if (list_join(&ga, tv->vval.v_list, (char_u *)", ", FALSE, copyID) == FAIL)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005989 {
5990 vim_free(ga.ga_data);
5991 return NULL;
5992 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005993 ga_append(&ga, ']');
5994 ga_append(&ga, NUL);
5995 return (char_u *)ga.ga_data;
5996}
5997
5998/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005999 * Join list "l" into a string in "*gap", using separator "sep".
6000 * When "echo" is TRUE use String as echoed, otherwise as inside a List.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006001 * Return FAIL or OK.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006002 */
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006003 static int
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006004list_join(gap, l, sep, echo, copyID)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006005 garray_T *gap;
Bram Moolenaar33570922005-01-25 22:26:29 +00006006 list_T *l;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006007 char_u *sep;
6008 int echo;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006009 int copyID;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006010{
6011 int first = TRUE;
6012 char_u *tofree;
6013 char_u numbuf[NUMBUFLEN];
Bram Moolenaar33570922005-01-25 22:26:29 +00006014 listitem_T *item;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006015 char_u *s;
6016
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006017 for (item = l->lv_first; item != NULL && !got_int; item = item->li_next)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006018 {
6019 if (first)
6020 first = FALSE;
6021 else
6022 ga_concat(gap, sep);
6023
6024 if (echo)
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006025 s = echo_string(&item->li_tv, &tofree, numbuf, copyID);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006026 else
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006027 s = tv2string(&item->li_tv, &tofree, numbuf, copyID);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006028 if (s != NULL)
6029 ga_concat(gap, s);
6030 vim_free(tofree);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006031 if (s == NULL)
6032 return FAIL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006033 }
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006034 return OK;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006035}
6036
6037/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006038 * Garbage collection for lists and dictionaries.
6039 *
6040 * We use reference counts to be able to free most items right away when they
6041 * are no longer used. But for composite items it's possible that it becomes
6042 * unused while the reference count is > 0: When there is a recursive
6043 * reference. Example:
6044 * :let l = [1, 2, 3]
6045 * :let d = {9: l}
6046 * :let l[1] = d
6047 *
6048 * Since this is quite unusual we handle this with garbage collection: every
6049 * once in a while find out which lists and dicts are not referenced from any
6050 * variable.
6051 *
6052 * Here is a good reference text about garbage collection (refers to Python
6053 * but it applies to all reference-counting mechanisms):
6054 * http://python.ca/nas/python/gc/
Bram Moolenaard9fba312005-06-26 22:34:35 +00006055 */
Bram Moolenaard9fba312005-06-26 22:34:35 +00006056
6057/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006058 * Do garbage collection for lists and dicts.
6059 * Return TRUE if some memory was freed.
Bram Moolenaard9fba312005-06-26 22:34:35 +00006060 */
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006061 int
6062garbage_collect()
Bram Moolenaard9fba312005-06-26 22:34:35 +00006063{
6064 dict_T *dd;
6065 list_T *ll;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006066 int copyID = ++current_copyID;
6067 buf_T *buf;
6068 win_T *wp;
6069 int i;
6070 funccall_T *fc;
6071 int did_free = FALSE;
Bram Moolenaarac48dbf2006-09-03 13:34:00 +00006072 av_list_item_T *av;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00006073#ifdef FEAT_WINDOWS
6074 tabpage_T *tp;
6075#endif
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006076
Bram Moolenaar9fecb462006-09-05 10:59:47 +00006077 /* Only do this once. */
6078 want_garbage_collect = FALSE;
6079 may_garbage_collect = FALSE;
6080
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006081 /*
6082 * 1. Go through all accessible variables and mark all lists and dicts
6083 * with copyID.
6084 */
6085 /* script-local variables */
6086 for (i = 1; i <= ga_scripts.ga_len; ++i)
6087 set_ref_in_ht(&SCRIPT_VARS(i), copyID);
6088
6089 /* buffer-local variables */
6090 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
6091 set_ref_in_ht(&buf->b_vars.dv_hashtab, copyID);
6092
6093 /* window-local variables */
Bram Moolenaar910f66f2006-04-05 20:41:53 +00006094 FOR_ALL_TAB_WINDOWS(tp, wp)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006095 set_ref_in_ht(&wp->w_vars.dv_hashtab, copyID);
6096
Bram Moolenaar910f66f2006-04-05 20:41:53 +00006097#ifdef FEAT_WINDOWS
6098 /* tabpage-local variables */
6099 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
6100 set_ref_in_ht(&tp->tp_vars.dv_hashtab, copyID);
6101#endif
6102
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006103 /* global variables */
6104 set_ref_in_ht(&globvarht, copyID);
6105
6106 /* function-local variables */
6107 for (fc = current_funccal; fc != NULL; fc = fc->caller)
6108 {
6109 set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID);
6110 set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID);
6111 }
6112
Bram Moolenaarac48dbf2006-09-03 13:34:00 +00006113 /* arguments for internal functions */
6114 for (av = argvars_list; av != NULL; av = av->avl_next)
6115 for (i = 0; av->avl_argvars[i].v_type != VAR_UNKNOWN; ++i)
6116 set_ref_in_item(&av->avl_argvars[i], copyID);
6117
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006118 /*
6119 * 2. Go through the list of dicts and free items without the copyID.
6120 */
6121 for (dd = first_dict; dd != NULL; )
6122 if (dd->dv_copyID != copyID)
6123 {
6124 dict_free(dd);
6125 did_free = TRUE;
6126
6127 /* restart, next dict may also have been freed */
6128 dd = first_dict;
6129 }
6130 else
6131 dd = dd->dv_used_next;
6132
6133 /*
6134 * 3. Go through the list of lists and free items without the copyID.
Bram Moolenaar7bb4c6e2005-09-07 21:22:27 +00006135 * But don't free a list that has a watcher (used in a for loop), these
6136 * are not referenced anywhere.
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006137 */
6138 for (ll = first_list; ll != NULL; )
Bram Moolenaar7bb4c6e2005-09-07 21:22:27 +00006139 if (ll->lv_copyID != copyID && ll->lv_watch == NULL)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006140 {
6141 list_free(ll);
6142 did_free = TRUE;
6143
Bram Moolenaar7bb4c6e2005-09-07 21:22:27 +00006144 /* restart, next list may also have been freed */
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006145 ll = first_list;
6146 }
6147 else
6148 ll = ll->lv_used_next;
6149
6150 return did_free;
6151}
6152
6153/*
6154 * Mark all lists and dicts referenced through hashtab "ht" with "copyID".
6155 */
6156 static void
6157set_ref_in_ht(ht, copyID)
6158 hashtab_T *ht;
6159 int copyID;
6160{
6161 int todo;
6162 hashitem_T *hi;
6163
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00006164 todo = (int)ht->ht_used;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006165 for (hi = ht->ht_array; todo > 0; ++hi)
6166 if (!HASHITEM_EMPTY(hi))
6167 {
6168 --todo;
6169 set_ref_in_item(&HI2DI(hi)->di_tv, copyID);
6170 }
6171}
6172
6173/*
6174 * Mark all lists and dicts referenced through list "l" with "copyID".
6175 */
6176 static void
6177set_ref_in_list(l, copyID)
6178 list_T *l;
6179 int copyID;
6180{
6181 listitem_T *li;
6182
6183 for (li = l->lv_first; li != NULL; li = li->li_next)
6184 set_ref_in_item(&li->li_tv, copyID);
6185}
6186
6187/*
6188 * Mark all lists and dicts referenced through typval "tv" with "copyID".
6189 */
6190 static void
6191set_ref_in_item(tv, copyID)
6192 typval_T *tv;
6193 int copyID;
6194{
6195 dict_T *dd;
6196 list_T *ll;
Bram Moolenaard9fba312005-06-26 22:34:35 +00006197
6198 switch (tv->v_type)
6199 {
6200 case VAR_DICT:
6201 dd = tv->vval.v_dict;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006202 if (dd->dv_copyID != copyID)
Bram Moolenaard9fba312005-06-26 22:34:35 +00006203 {
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006204 /* Didn't see this dict yet. */
6205 dd->dv_copyID = copyID;
6206 set_ref_in_ht(&dd->dv_hashtab, copyID);
Bram Moolenaard9fba312005-06-26 22:34:35 +00006207 }
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006208 break;
Bram Moolenaard9fba312005-06-26 22:34:35 +00006209
6210 case VAR_LIST:
6211 ll = tv->vval.v_list;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006212 if (ll->lv_copyID != copyID)
Bram Moolenaard9fba312005-06-26 22:34:35 +00006213 {
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006214 /* Didn't see this list yet. */
6215 ll->lv_copyID = copyID;
6216 set_ref_in_list(ll, copyID);
Bram Moolenaard9fba312005-06-26 22:34:35 +00006217 }
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006218 break;
Bram Moolenaard9fba312005-06-26 22:34:35 +00006219 }
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006220 return;
Bram Moolenaard9fba312005-06-26 22:34:35 +00006221}
6222
6223/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00006224 * Allocate an empty header for a dictionary.
6225 */
Bram Moolenaar05159a02005-02-26 23:04:13 +00006226 dict_T *
Bram Moolenaar8c711452005-01-14 21:53:12 +00006227dict_alloc()
6228{
Bram Moolenaar33570922005-01-25 22:26:29 +00006229 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006230
Bram Moolenaar33570922005-01-25 22:26:29 +00006231 d = (dict_T *)alloc(sizeof(dict_T));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006232 if (d != NULL)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006233 {
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006234 /* Add the list to the hashtable for garbage collection. */
6235 if (first_dict != NULL)
6236 first_dict->dv_used_prev = d;
6237 d->dv_used_next = first_dict;
6238 d->dv_used_prev = NULL;
6239
Bram Moolenaar33570922005-01-25 22:26:29 +00006240 hash_init(&d->dv_hashtab);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006241 d->dv_lock = 0;
6242 d->dv_refcount = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006243 d->dv_copyID = 0;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006244 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006245 return d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006246}
6247
6248/*
6249 * Unreference a Dictionary: decrement the reference count and free it when it
6250 * becomes zero.
6251 */
6252 static void
6253dict_unref(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00006254 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006255{
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006256 if (d != NULL && d->dv_refcount != DEL_REFCOUNT && --d->dv_refcount <= 0)
6257 dict_free(d);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006258}
6259
6260/*
6261 * Free a Dictionary, including all items it contains.
6262 * Ignores the reference count.
6263 */
6264 static void
6265dict_free(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00006266 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006267{
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006268 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00006269 hashitem_T *hi;
Bram Moolenaard9fba312005-06-26 22:34:35 +00006270 dictitem_T *di;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006271
Bram Moolenaard9fba312005-06-26 22:34:35 +00006272 /* Avoid that recursive reference to the dict frees us again. */
6273 d->dv_refcount = DEL_REFCOUNT;
6274
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006275 /* Remove the dict from the list of dicts for garbage collection. */
6276 if (d->dv_used_prev == NULL)
6277 first_dict = d->dv_used_next;
6278 else
6279 d->dv_used_prev->dv_used_next = d->dv_used_next;
6280 if (d->dv_used_next != NULL)
6281 d->dv_used_next->dv_used_prev = d->dv_used_prev;
6282
6283 /* Lock the hashtab, we don't want it to resize while freeing items. */
Bram Moolenaard9fba312005-06-26 22:34:35 +00006284 hash_lock(&d->dv_hashtab);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00006285 todo = (int)d->dv_hashtab.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00006286 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +00006287 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006288 if (!HASHITEM_EMPTY(hi))
6289 {
Bram Moolenaard9fba312005-06-26 22:34:35 +00006290 /* Remove the item before deleting it, just in case there is
6291 * something recursive causing trouble. */
6292 di = HI2DI(hi);
6293 hash_remove(&d->dv_hashtab, hi);
6294 dictitem_free(di);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006295 --todo;
6296 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006297 }
Bram Moolenaar33570922005-01-25 22:26:29 +00006298 hash_clear(&d->dv_hashtab);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006299 vim_free(d);
6300}
6301
6302/*
6303 * Allocate a Dictionary item.
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006304 * The "key" is copied to the new item.
6305 * Note that the value of the item "di_tv" still needs to be initialized!
6306 * Returns NULL when out of memory.
Bram Moolenaar8c711452005-01-14 21:53:12 +00006307 */
Bram Moolenaar33570922005-01-25 22:26:29 +00006308 static dictitem_T *
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006309dictitem_alloc(key)
6310 char_u *key;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006311{
Bram Moolenaar33570922005-01-25 22:26:29 +00006312 dictitem_T *di;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006313
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00006314 di = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T) + STRLEN(key)));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006315 if (di != NULL)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006316 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006317 STRCPY(di->di_key, key);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006318 di->di_flags = 0;
6319 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006320 return di;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006321}
6322
6323/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00006324 * Make a copy of a Dictionary item.
6325 */
Bram Moolenaar33570922005-01-25 22:26:29 +00006326 static dictitem_T *
Bram Moolenaare9a41262005-01-15 22:18:47 +00006327dictitem_copy(org)
Bram Moolenaar33570922005-01-25 22:26:29 +00006328 dictitem_T *org;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006329{
Bram Moolenaar33570922005-01-25 22:26:29 +00006330 dictitem_T *di;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006331
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00006332 di = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
6333 + STRLEN(org->di_key)));
Bram Moolenaare9a41262005-01-15 22:18:47 +00006334 if (di != NULL)
6335 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006336 STRCPY(di->di_key, org->di_key);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006337 di->di_flags = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006338 copy_tv(&org->di_tv, &di->di_tv);
6339 }
6340 return di;
6341}
6342
6343/*
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006344 * Remove item "item" from Dictionary "dict" and free it.
6345 */
6346 static void
6347dictitem_remove(dict, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00006348 dict_T *dict;
6349 dictitem_T *item;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006350{
Bram Moolenaar33570922005-01-25 22:26:29 +00006351 hashitem_T *hi;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006352
Bram Moolenaar33570922005-01-25 22:26:29 +00006353 hi = hash_find(&dict->dv_hashtab, item->di_key);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006354 if (HASHITEM_EMPTY(hi))
6355 EMSG2(_(e_intern2), "dictitem_remove()");
6356 else
Bram Moolenaar33570922005-01-25 22:26:29 +00006357 hash_remove(&dict->dv_hashtab, hi);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006358 dictitem_free(item);
6359}
6360
6361/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00006362 * Free a dict item. Also clears the value.
6363 */
6364 static void
6365dictitem_free(item)
Bram Moolenaar33570922005-01-25 22:26:29 +00006366 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006367{
Bram Moolenaar8c711452005-01-14 21:53:12 +00006368 clear_tv(&item->di_tv);
6369 vim_free(item);
6370}
6371
6372/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00006373 * Make a copy of dict "d". Shallow if "deep" is FALSE.
6374 * The refcount of the new dict is set to 1.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006375 * See item_copy() for "copyID".
Bram Moolenaare9a41262005-01-15 22:18:47 +00006376 * Returns NULL when out of memory.
6377 */
Bram Moolenaar33570922005-01-25 22:26:29 +00006378 static dict_T *
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006379dict_copy(orig, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00006380 dict_T *orig;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006381 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006382 int copyID;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006383{
Bram Moolenaar33570922005-01-25 22:26:29 +00006384 dict_T *copy;
6385 dictitem_T *di;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006386 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00006387 hashitem_T *hi;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006388
6389 if (orig == NULL)
6390 return NULL;
6391
6392 copy = dict_alloc();
6393 if (copy != NULL)
6394 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006395 if (copyID != 0)
6396 {
6397 orig->dv_copyID = copyID;
6398 orig->dv_copydict = copy;
6399 }
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00006400 todo = (int)orig->dv_hashtab.ht_used;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006401 for (hi = orig->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006402 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006403 if (!HASHITEM_EMPTY(hi))
Bram Moolenaare9a41262005-01-15 22:18:47 +00006404 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006405 --todo;
6406
6407 di = dictitem_alloc(hi->hi_key);
6408 if (di == NULL)
6409 break;
6410 if (deep)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006411 {
6412 if (item_copy(&HI2DI(hi)->di_tv, &di->di_tv, deep,
6413 copyID) == FAIL)
6414 {
6415 vim_free(di);
6416 break;
6417 }
6418 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006419 else
6420 copy_tv(&HI2DI(hi)->di_tv, &di->di_tv);
6421 if (dict_add(copy, di) == FAIL)
6422 {
6423 dictitem_free(di);
6424 break;
6425 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006426 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006427 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006428
Bram Moolenaare9a41262005-01-15 22:18:47 +00006429 ++copy->dv_refcount;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006430 if (todo > 0)
6431 {
6432 dict_unref(copy);
6433 copy = NULL;
6434 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006435 }
6436
6437 return copy;
6438}
6439
6440/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00006441 * Add item "item" to Dictionary "d".
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006442 * Returns FAIL when out of memory and when key already existed.
Bram Moolenaar8c711452005-01-14 21:53:12 +00006443 */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006444 static int
Bram Moolenaar8c711452005-01-14 21:53:12 +00006445dict_add(d, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00006446 dict_T *d;
6447 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006448{
Bram Moolenaar33570922005-01-25 22:26:29 +00006449 return hash_add(&d->dv_hashtab, item->di_key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006450}
6451
Bram Moolenaar8c711452005-01-14 21:53:12 +00006452/*
Bram Moolenaar05159a02005-02-26 23:04:13 +00006453 * Add a number or string entry to dictionary "d".
6454 * When "str" is NULL use number "nr", otherwise use "str".
6455 * Returns FAIL when out of memory and when key already exists.
6456 */
6457 int
6458dict_add_nr_str(d, key, nr, str)
6459 dict_T *d;
6460 char *key;
6461 long nr;
6462 char_u *str;
6463{
6464 dictitem_T *item;
6465
6466 item = dictitem_alloc((char_u *)key);
6467 if (item == NULL)
6468 return FAIL;
6469 item->di_tv.v_lock = 0;
6470 if (str == NULL)
6471 {
6472 item->di_tv.v_type = VAR_NUMBER;
6473 item->di_tv.vval.v_number = nr;
6474 }
6475 else
6476 {
6477 item->di_tv.v_type = VAR_STRING;
6478 item->di_tv.vval.v_string = vim_strsave(str);
6479 }
6480 if (dict_add(d, item) == FAIL)
6481 {
6482 dictitem_free(item);
6483 return FAIL;
6484 }
6485 return OK;
6486}
6487
6488/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00006489 * Get the number of items in a Dictionary.
6490 */
6491 static long
6492dict_len(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00006493 dict_T *d;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006494{
Bram Moolenaare9a41262005-01-15 22:18:47 +00006495 if (d == NULL)
6496 return 0L;
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00006497 return (long)d->dv_hashtab.ht_used;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006498}
6499
6500/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00006501 * Find item "key[len]" in Dictionary "d".
6502 * If "len" is negative use strlen(key).
6503 * Returns NULL when not found.
6504 */
Bram Moolenaar33570922005-01-25 22:26:29 +00006505 static dictitem_T *
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006506dict_find(d, key, len)
Bram Moolenaar33570922005-01-25 22:26:29 +00006507 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006508 char_u *key;
6509 int len;
6510{
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006511#define AKEYLEN 200
6512 char_u buf[AKEYLEN];
6513 char_u *akey;
6514 char_u *tofree = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00006515 hashitem_T *hi;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006516
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006517 if (len < 0)
6518 akey = key;
6519 else if (len >= AKEYLEN)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00006520 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006521 tofree = akey = vim_strnsave(key, len);
6522 if (akey == NULL)
6523 return NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00006524 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006525 else
6526 {
6527 /* Avoid a malloc/free by using buf[]. */
Bram Moolenaarce0842a2005-07-18 21:58:11 +00006528 vim_strncpy(buf, key, len);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006529 akey = buf;
6530 }
6531
Bram Moolenaar33570922005-01-25 22:26:29 +00006532 hi = hash_find(&d->dv_hashtab, akey);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006533 vim_free(tofree);
6534 if (HASHITEM_EMPTY(hi))
6535 return NULL;
6536 return HI2DI(hi);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006537}
6538
6539/*
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00006540 * Get a string item from a dictionary.
6541 * When "save" is TRUE allocate memory for it.
Bram Moolenaar2641f772005-03-25 21:58:17 +00006542 * Returns NULL if the entry doesn't exist or out of memory.
6543 */
6544 char_u *
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00006545get_dict_string(d, key, save)
Bram Moolenaar2641f772005-03-25 21:58:17 +00006546 dict_T *d;
6547 char_u *key;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00006548 int save;
Bram Moolenaar2641f772005-03-25 21:58:17 +00006549{
6550 dictitem_T *di;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00006551 char_u *s;
Bram Moolenaar2641f772005-03-25 21:58:17 +00006552
6553 di = dict_find(d, key, -1);
6554 if (di == NULL)
6555 return NULL;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00006556 s = get_tv_string(&di->di_tv);
6557 if (save && s != NULL)
6558 s = vim_strsave(s);
6559 return s;
Bram Moolenaar2641f772005-03-25 21:58:17 +00006560}
6561
6562/*
6563 * Get a number item from a dictionary.
6564 * Returns 0 if the entry doesn't exist or out of memory.
6565 */
6566 long
6567get_dict_number(d, key)
6568 dict_T *d;
6569 char_u *key;
6570{
6571 dictitem_T *di;
6572
6573 di = dict_find(d, key, -1);
6574 if (di == NULL)
6575 return 0;
6576 return get_tv_number(&di->di_tv);
6577}
6578
6579/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00006580 * Return an allocated string with the string representation of a Dictionary.
6581 * May return NULL.
6582 */
6583 static char_u *
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006584dict2string(tv, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00006585 typval_T *tv;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006586 int copyID;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006587{
6588 garray_T ga;
6589 int first = TRUE;
6590 char_u *tofree;
6591 char_u numbuf[NUMBUFLEN];
Bram Moolenaar33570922005-01-25 22:26:29 +00006592 hashitem_T *hi;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006593 char_u *s;
Bram Moolenaar33570922005-01-25 22:26:29 +00006594 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006595 int todo;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006596
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006597 if ((d = tv->vval.v_dict) == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00006598 return NULL;
6599 ga_init2(&ga, (int)sizeof(char), 80);
6600 ga_append(&ga, '{');
6601
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00006602 todo = (int)d->dv_hashtab.ht_used;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006603 for (hi = d->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +00006604 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006605 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar8c711452005-01-14 21:53:12 +00006606 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006607 --todo;
6608
6609 if (first)
6610 first = FALSE;
6611 else
6612 ga_concat(&ga, (char_u *)", ");
6613
6614 tofree = string_quote(hi->hi_key, FALSE);
6615 if (tofree != NULL)
6616 {
6617 ga_concat(&ga, tofree);
6618 vim_free(tofree);
6619 }
6620 ga_concat(&ga, (char_u *)": ");
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006621 s = tv2string(&HI2DI(hi)->di_tv, &tofree, numbuf, copyID);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006622 if (s != NULL)
6623 ga_concat(&ga, s);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006624 vim_free(tofree);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006625 if (s == NULL)
6626 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006627 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006628 }
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006629 if (todo > 0)
6630 {
6631 vim_free(ga.ga_data);
6632 return NULL;
6633 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006634
6635 ga_append(&ga, '}');
6636 ga_append(&ga, NUL);
6637 return (char_u *)ga.ga_data;
6638}
6639
6640/*
6641 * Allocate a variable for a Dictionary and fill it from "*arg".
6642 * Return OK or FAIL. Returns NOTDONE for {expr}.
6643 */
6644 static int
6645get_dict_tv(arg, rettv, evaluate)
6646 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00006647 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006648 int evaluate;
6649{
Bram Moolenaar33570922005-01-25 22:26:29 +00006650 dict_T *d = NULL;
6651 typval_T tvkey;
6652 typval_T tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006653 char_u *key;
Bram Moolenaar33570922005-01-25 22:26:29 +00006654 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006655 char_u *start = skipwhite(*arg + 1);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006656 char_u buf[NUMBUFLEN];
Bram Moolenaar8c711452005-01-14 21:53:12 +00006657
6658 /*
6659 * First check if it's not a curly-braces thing: {expr}.
6660 * Must do this without evaluating, otherwise a function may be called
6661 * twice. Unfortunately this means we need to call eval1() twice for the
6662 * first item.
Bram Moolenaare9a41262005-01-15 22:18:47 +00006663 * But {} is an empty Dictionary.
Bram Moolenaar8c711452005-01-14 21:53:12 +00006664 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00006665 if (*start != '}')
6666 {
6667 if (eval1(&start, &tv, FALSE) == FAIL) /* recursive! */
6668 return FAIL;
6669 if (*start == '}')
6670 return NOTDONE;
6671 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006672
6673 if (evaluate)
6674 {
6675 d = dict_alloc();
6676 if (d == NULL)
6677 return FAIL;
6678 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006679 tvkey.v_type = VAR_UNKNOWN;
6680 tv.v_type = VAR_UNKNOWN;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006681
6682 *arg = skipwhite(*arg + 1);
6683 while (**arg != '}' && **arg != NUL)
6684 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006685 if (eval1(arg, &tvkey, evaluate) == FAIL) /* recursive! */
Bram Moolenaar8c711452005-01-14 21:53:12 +00006686 goto failret;
6687 if (**arg != ':')
6688 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006689 EMSG2(_("E720: Missing colon in Dictionary: %s"), *arg);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006690 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006691 goto failret;
6692 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006693 key = get_tv_string_buf_chk(&tvkey, buf);
6694 if (key == NULL || *key == NUL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00006695 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006696 /* "key" is NULL when get_tv_string_buf_chk() gave an errmsg */
6697 if (key != NULL)
6698 EMSG(_(e_emptykey));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006699 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006700 goto failret;
6701 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006702
6703 *arg = skipwhite(*arg + 1);
6704 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
6705 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006706 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006707 goto failret;
6708 }
6709 if (evaluate)
6710 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006711 item = dict_find(d, key, -1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006712 if (item != NULL)
6713 {
Bram Moolenaarb982ca52005-03-28 21:02:15 +00006714 EMSG2(_("E721: Duplicate key in Dictionary: \"%s\""), key);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006715 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006716 clear_tv(&tv);
6717 goto failret;
6718 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006719 item = dictitem_alloc(key);
6720 clear_tv(&tvkey);
6721 if (item != NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00006722 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00006723 item->di_tv = tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006724 item->di_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006725 if (dict_add(d, item) == FAIL)
6726 dictitem_free(item);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006727 }
6728 }
6729
6730 if (**arg == '}')
6731 break;
6732 if (**arg != ',')
6733 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006734 EMSG2(_("E722: Missing comma in Dictionary: %s"), *arg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006735 goto failret;
6736 }
6737 *arg = skipwhite(*arg + 1);
6738 }
6739
6740 if (**arg != '}')
6741 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006742 EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006743failret:
6744 if (evaluate)
6745 dict_free(d);
6746 return FAIL;
6747 }
6748
6749 *arg = skipwhite(*arg + 1);
6750 if (evaluate)
6751 {
6752 rettv->v_type = VAR_DICT;
6753 rettv->vval.v_dict = d;
6754 ++d->dv_refcount;
6755 }
6756
6757 return OK;
6758}
6759
Bram Moolenaar8c711452005-01-14 21:53:12 +00006760/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006761 * Return a string with the string representation of a variable.
6762 * If the memory is allocated "tofree" is set to it, otherwise NULL.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006763 * "numbuf" is used for a number.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006764 * Does not put quotes around strings, as ":echo" displays values.
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006765 * When "copyID" is not NULL replace recursive lists and dicts with "...".
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006766 * May return NULL;
6767 */
6768 static char_u *
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006769echo_string(tv, tofree, numbuf, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00006770 typval_T *tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006771 char_u **tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006772 char_u *numbuf;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006773 int copyID;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006774{
Bram Moolenaare9a41262005-01-15 22:18:47 +00006775 static int recurse = 0;
6776 char_u *r = NULL;
6777
Bram Moolenaar33570922005-01-25 22:26:29 +00006778 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006779 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006780 EMSG(_("E724: variable nested too deep for displaying"));
Bram Moolenaare9a41262005-01-15 22:18:47 +00006781 *tofree = NULL;
6782 return NULL;
6783 }
6784 ++recurse;
6785
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006786 switch (tv->v_type)
6787 {
6788 case VAR_FUNC:
6789 *tofree = NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006790 r = tv->vval.v_string;
6791 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006792
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006793 case VAR_LIST:
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006794 if (tv->vval.v_list == NULL)
6795 {
6796 *tofree = NULL;
6797 r = NULL;
6798 }
6799 else if (copyID != 0 && tv->vval.v_list->lv_copyID == copyID)
6800 {
6801 *tofree = NULL;
6802 r = (char_u *)"[...]";
6803 }
6804 else
6805 {
6806 tv->vval.v_list->lv_copyID = copyID;
6807 *tofree = list2string(tv, copyID);
6808 r = *tofree;
6809 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006810 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006811
Bram Moolenaar8c711452005-01-14 21:53:12 +00006812 case VAR_DICT:
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006813 if (tv->vval.v_dict == NULL)
6814 {
6815 *tofree = NULL;
6816 r = NULL;
6817 }
6818 else if (copyID != 0 && tv->vval.v_dict->dv_copyID == copyID)
6819 {
6820 *tofree = NULL;
6821 r = (char_u *)"{...}";
6822 }
6823 else
6824 {
6825 tv->vval.v_dict->dv_copyID = copyID;
6826 *tofree = dict2string(tv, copyID);
6827 r = *tofree;
6828 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006829 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006830
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006831 case VAR_STRING:
6832 case VAR_NUMBER:
Bram Moolenaare9a41262005-01-15 22:18:47 +00006833 *tofree = NULL;
6834 r = get_tv_string_buf(tv, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006835 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006836
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006837 default:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006838 EMSG2(_(e_intern2), "echo_string()");
Bram Moolenaare9a41262005-01-15 22:18:47 +00006839 *tofree = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006840 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006841
6842 --recurse;
6843 return r;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006844}
6845
6846/*
6847 * Return a string with the string representation of a variable.
6848 * If the memory is allocated "tofree" is set to it, otherwise NULL.
6849 * "numbuf" is used for a number.
6850 * Puts quotes around strings, so that they can be parsed back by eval().
6851 * May return NULL;
6852 */
6853 static char_u *
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006854tv2string(tv, tofree, numbuf, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00006855 typval_T *tv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006856 char_u **tofree;
6857 char_u *numbuf;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006858 int copyID;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006859{
6860 switch (tv->v_type)
6861 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006862 case VAR_FUNC:
6863 *tofree = string_quote(tv->vval.v_string, TRUE);
6864 return *tofree;
6865 case VAR_STRING:
6866 *tofree = string_quote(tv->vval.v_string, FALSE);
6867 return *tofree;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006868 case VAR_NUMBER:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006869 case VAR_LIST:
Bram Moolenaar8c711452005-01-14 21:53:12 +00006870 case VAR_DICT:
Bram Moolenaare9a41262005-01-15 22:18:47 +00006871 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006872 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006873 EMSG2(_(e_intern2), "tv2string()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006874 }
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006875 return echo_string(tv, tofree, numbuf, copyID);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006876}
6877
6878/*
Bram Moolenaar33570922005-01-25 22:26:29 +00006879 * Return string "str" in ' quotes, doubling ' characters.
6880 * If "str" is NULL an empty string is assumed.
Bram Moolenaar8c711452005-01-14 21:53:12 +00006881 * If "function" is TRUE make it function('string').
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006882 */
6883 static char_u *
6884string_quote(str, function)
6885 char_u *str;
6886 int function;
6887{
Bram Moolenaar33570922005-01-25 22:26:29 +00006888 unsigned len;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006889 char_u *p, *r, *s;
6890
Bram Moolenaar33570922005-01-25 22:26:29 +00006891 len = (function ? 13 : 3);
6892 if (str != NULL)
6893 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00006894 len += (unsigned)STRLEN(str);
Bram Moolenaar33570922005-01-25 22:26:29 +00006895 for (p = str; *p != NUL; mb_ptr_adv(p))
6896 if (*p == '\'')
6897 ++len;
6898 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006899 s = r = alloc(len);
6900 if (r != NULL)
6901 {
6902 if (function)
6903 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00006904 STRCPY(r, "function('");
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006905 r += 10;
6906 }
6907 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00006908 *r++ = '\'';
Bram Moolenaar33570922005-01-25 22:26:29 +00006909 if (str != NULL)
6910 for (p = str; *p != NUL; )
6911 {
6912 if (*p == '\'')
6913 *r++ = '\'';
6914 MB_COPY_CHAR(p, r);
6915 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006916 *r++ = '\'';
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006917 if (function)
6918 *r++ = ')';
6919 *r++ = NUL;
6920 }
6921 return s;
6922}
6923
6924/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006925 * Get the value of an environment variable.
6926 * "arg" is pointing to the '$'. It is advanced to after the name.
6927 * If the environment variable was not set, silently assume it is empty.
6928 * Always return OK.
6929 */
6930 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006931get_env_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006932 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00006933 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006934 int evaluate;
6935{
6936 char_u *string = NULL;
6937 int len;
6938 int cc;
6939 char_u *name;
Bram Moolenaar05159a02005-02-26 23:04:13 +00006940 int mustfree = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006941
6942 ++*arg;
6943 name = *arg;
6944 len = get_env_len(arg);
6945 if (evaluate)
6946 {
6947 if (len != 0)
6948 {
6949 cc = name[len];
6950 name[len] = NUL;
Bram Moolenaar05159a02005-02-26 23:04:13 +00006951 /* first try vim_getenv(), fast for normal environment vars */
6952 string = vim_getenv(name, &mustfree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006953 if (string != NULL && *string != NUL)
Bram Moolenaar05159a02005-02-26 23:04:13 +00006954 {
6955 if (!mustfree)
6956 string = vim_strsave(string);
6957 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006958 else
6959 {
Bram Moolenaar05159a02005-02-26 23:04:13 +00006960 if (mustfree)
6961 vim_free(string);
6962
Bram Moolenaar071d4272004-06-13 20:20:40 +00006963 /* next try expanding things like $VIM and ${HOME} */
6964 string = expand_env_save(name - 1);
6965 if (string != NULL && *string == '$')
6966 {
6967 vim_free(string);
6968 string = NULL;
6969 }
6970 }
6971 name[len] = cc;
6972 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006973 rettv->v_type = VAR_STRING;
6974 rettv->vval.v_string = string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006975 }
6976
6977 return OK;
6978}
6979
6980/*
6981 * Array with names and number of arguments of all internal functions
6982 * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH!
6983 */
6984static struct fst
6985{
6986 char *f_name; /* function name */
6987 char f_min_argc; /* minimal number of arguments */
6988 char f_max_argc; /* maximal number of arguments */
Bram Moolenaar33570922005-01-25 22:26:29 +00006989 void (*f_func) __ARGS((typval_T *args, typval_T *rvar));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006990 /* implemenation of function */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006991} functions[] =
6992{
Bram Moolenaar0d660222005-01-07 21:51:51 +00006993 {"add", 2, 2, f_add},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006994 {"append", 2, 2, f_append},
6995 {"argc", 0, 0, f_argc},
6996 {"argidx", 0, 0, f_argidx},
Bram Moolenaare2f98b92006-03-29 21:18:24 +00006997 {"argv", 0, 1, f_argv},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006998 {"browse", 4, 4, f_browse},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006999 {"browsedir", 2, 2, f_browsedir},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007000 {"bufexists", 1, 1, f_bufexists},
7001 {"buffer_exists", 1, 1, f_bufexists}, /* obsolete */
7002 {"buffer_name", 1, 1, f_bufname}, /* obsolete */
7003 {"buffer_number", 1, 1, f_bufnr}, /* obsolete */
7004 {"buflisted", 1, 1, f_buflisted},
7005 {"bufloaded", 1, 1, f_bufloaded},
7006 {"bufname", 1, 1, f_bufname},
Bram Moolenaar0e34f622006-03-03 23:00:03 +00007007 {"bufnr", 1, 2, f_bufnr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007008 {"bufwinnr", 1, 1, f_bufwinnr},
7009 {"byte2line", 1, 1, f_byte2line},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007010 {"byteidx", 2, 2, f_byteidx},
Bram Moolenaare9a41262005-01-15 22:18:47 +00007011 {"call", 2, 3, f_call},
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00007012 {"changenr", 0, 0, f_changenr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007013 {"char2nr", 1, 1, f_char2nr},
7014 {"cindent", 1, 1, f_cindent},
7015 {"col", 1, 1, f_col},
Bram Moolenaar572cb562005-08-05 21:35:02 +00007016#if defined(FEAT_INS_EXPAND)
Bram Moolenaarade00832006-03-10 21:46:58 +00007017 {"complete", 2, 2, f_complete},
Bram Moolenaar572cb562005-08-05 21:35:02 +00007018 {"complete_add", 1, 1, f_complete_add},
7019 {"complete_check", 0, 0, f_complete_check},
7020#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007021 {"confirm", 1, 4, f_confirm},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007022 {"copy", 1, 1, f_copy},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007023 {"count", 2, 4, f_count},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007024 {"cscope_connection",0,3, f_cscope_connection},
Bram Moolenaara5525202006-03-02 22:52:09 +00007025 {"cursor", 1, 3, f_cursor},
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007026 {"deepcopy", 1, 2, f_deepcopy},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007027 {"delete", 1, 1, f_delete},
7028 {"did_filetype", 0, 0, f_did_filetype},
Bram Moolenaar47136d72004-10-12 20:02:24 +00007029 {"diff_filler", 1, 1, f_diff_filler},
7030 {"diff_hlID", 2, 2, f_diff_hlID},
Bram Moolenaare49b69a2005-01-08 16:11:57 +00007031 {"empty", 1, 1, f_empty},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007032 {"escape", 2, 2, f_escape},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007033 {"eval", 1, 1, f_eval},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007034 {"eventhandler", 0, 0, f_eventhandler},
7035 {"executable", 1, 1, f_executable},
7036 {"exists", 1, 1, f_exists},
7037 {"expand", 1, 2, f_expand},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007038 {"extend", 2, 3, f_extend},
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00007039 {"feedkeys", 1, 2, f_feedkeys},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007040 {"file_readable", 1, 1, f_filereadable}, /* obsolete */
7041 {"filereadable", 1, 1, f_filereadable},
7042 {"filewritable", 1, 1, f_filewritable},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007043 {"filter", 2, 2, f_filter},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007044 {"finddir", 1, 3, f_finddir},
7045 {"findfile", 1, 3, f_findfile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007046 {"fnamemodify", 2, 2, f_fnamemodify},
7047 {"foldclosed", 1, 1, f_foldclosed},
7048 {"foldclosedend", 1, 1, f_foldclosedend},
7049 {"foldlevel", 1, 1, f_foldlevel},
7050 {"foldtext", 0, 0, f_foldtext},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007051 {"foldtextresult", 1, 1, f_foldtextresult},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007052 {"foreground", 0, 0, f_foreground},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007053 {"function", 1, 1, f_function},
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00007054 {"garbagecollect", 0, 0, f_garbagecollect},
Bram Moolenaar0d660222005-01-07 21:51:51 +00007055 {"get", 2, 3, f_get},
Bram Moolenaar80fc0432005-07-20 22:06:07 +00007056 {"getbufline", 2, 3, f_getbufline},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007057 {"getbufvar", 2, 2, f_getbufvar},
7058 {"getchar", 0, 1, f_getchar},
7059 {"getcharmod", 0, 0, f_getcharmod},
7060 {"getcmdline", 0, 0, f_getcmdline},
7061 {"getcmdpos", 0, 0, f_getcmdpos},
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +00007062 {"getcmdtype", 0, 0, f_getcmdtype},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007063 {"getcwd", 0, 0, f_getcwd},
Bram Moolenaar46c9c732004-12-12 11:37:09 +00007064 {"getfontname", 0, 1, f_getfontname},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007065 {"getfperm", 1, 1, f_getfperm},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007066 {"getfsize", 1, 1, f_getfsize},
7067 {"getftime", 1, 1, f_getftime},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007068 {"getftype", 1, 1, f_getftype},
Bram Moolenaar0d660222005-01-07 21:51:51 +00007069 {"getline", 1, 2, f_getline},
Bram Moolenaar280f1262006-01-30 00:14:18 +00007070 {"getloclist", 1, 1, f_getqflist},
Bram Moolenaara5525202006-03-02 22:52:09 +00007071 {"getpos", 1, 1, f_getpos},
Bram Moolenaar2641f772005-03-25 21:58:17 +00007072 {"getqflist", 0, 0, f_getqflist},
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00007073 {"getreg", 0, 2, f_getreg},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007074 {"getregtype", 0, 1, f_getregtype},
Bram Moolenaar99ebf042006-04-15 20:28:54 +00007075 {"gettabwinvar", 3, 3, f_gettabwinvar},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007076 {"getwinposx", 0, 0, f_getwinposx},
7077 {"getwinposy", 0, 0, f_getwinposy},
7078 {"getwinvar", 2, 2, f_getwinvar},
7079 {"glob", 1, 1, f_glob},
7080 {"globpath", 2, 2, f_globpath},
7081 {"has", 1, 1, f_has},
Bram Moolenaare9a41262005-01-15 22:18:47 +00007082 {"has_key", 2, 2, f_has_key},
Bram Moolenaar2c932302006-03-18 21:42:09 +00007083 {"hasmapto", 1, 3, f_hasmapto},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007084 {"highlightID", 1, 1, f_hlID}, /* obsolete */
7085 {"highlight_exists",1, 1, f_hlexists}, /* obsolete */
7086 {"histadd", 2, 2, f_histadd},
7087 {"histdel", 1, 2, f_histdel},
7088 {"histget", 1, 2, f_histget},
7089 {"histnr", 1, 1, f_histnr},
7090 {"hlID", 1, 1, f_hlID},
7091 {"hlexists", 1, 1, f_hlexists},
7092 {"hostname", 0, 0, f_hostname},
7093 {"iconv", 3, 3, f_iconv},
7094 {"indent", 1, 1, f_indent},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007095 {"index", 2, 4, f_index},
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +00007096 {"input", 1, 3, f_input},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007097 {"inputdialog", 1, 3, f_inputdialog},
Bram Moolenaar6efa2b32005-09-10 19:26:26 +00007098 {"inputlist", 1, 1, f_inputlist},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007099 {"inputrestore", 0, 0, f_inputrestore},
7100 {"inputsave", 0, 0, f_inputsave},
7101 {"inputsecret", 1, 2, f_inputsecret},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007102 {"insert", 2, 3, f_insert},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007103 {"isdirectory", 1, 1, f_isdirectory},
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007104 {"islocked", 1, 1, f_islocked},
Bram Moolenaar8c711452005-01-14 21:53:12 +00007105 {"items", 1, 1, f_items},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007106 {"join", 1, 2, f_join},
Bram Moolenaar8c711452005-01-14 21:53:12 +00007107 {"keys", 1, 1, f_keys},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007108 {"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007109 {"len", 1, 1, f_len},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007110 {"libcall", 3, 3, f_libcall},
7111 {"libcallnr", 3, 3, f_libcallnr},
7112 {"line", 1, 1, f_line},
7113 {"line2byte", 1, 1, f_line2byte},
7114 {"lispindent", 1, 1, f_lispindent},
7115 {"localtime", 0, 0, f_localtime},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007116 {"map", 2, 2, f_map},
Bram Moolenaar2c932302006-03-18 21:42:09 +00007117 {"maparg", 1, 3, f_maparg},
7118 {"mapcheck", 1, 3, f_mapcheck},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007119 {"match", 2, 4, f_match},
Bram Moolenaar910f66f2006-04-05 20:41:53 +00007120 {"matcharg", 1, 1, f_matcharg},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007121 {"matchend", 2, 4, f_matchend},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007122 {"matchlist", 2, 4, f_matchlist},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007123 {"matchstr", 2, 4, f_matchstr},
Bram Moolenaar6cc16192005-01-08 21:49:45 +00007124 {"max", 1, 1, f_max},
7125 {"min", 1, 1, f_min},
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00007126#ifdef vim_mkdir
7127 {"mkdir", 1, 3, f_mkdir},
7128#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007129 {"mode", 0, 0, f_mode},
7130 {"nextnonblank", 1, 1, f_nextnonblank},
7131 {"nr2char", 1, 1, f_nr2char},
Bram Moolenaar910f66f2006-04-05 20:41:53 +00007132 {"pathshorten", 1, 1, f_pathshorten},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007133 {"prevnonblank", 1, 1, f_prevnonblank},
Bram Moolenaar4be06f92005-07-29 22:36:03 +00007134 {"printf", 2, 19, f_printf},
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00007135 {"pumvisible", 0, 0, f_pumvisible},
Bram Moolenaar8c711452005-01-14 21:53:12 +00007136 {"range", 1, 3, f_range},
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00007137 {"readfile", 1, 3, f_readfile},
Bram Moolenaare580b0c2006-03-21 21:33:03 +00007138 {"reltime", 0, 2, f_reltime},
7139 {"reltimestr", 1, 1, f_reltimestr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007140 {"remote_expr", 2, 3, f_remote_expr},
7141 {"remote_foreground", 1, 1, f_remote_foreground},
7142 {"remote_peek", 1, 2, f_remote_peek},
7143 {"remote_read", 1, 1, f_remote_read},
7144 {"remote_send", 2, 3, f_remote_send},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007145 {"remove", 2, 3, f_remove},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007146 {"rename", 2, 2, f_rename},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007147 {"repeat", 2, 2, f_repeat},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007148 {"resolve", 1, 1, f_resolve},
Bram Moolenaar0d660222005-01-07 21:51:51 +00007149 {"reverse", 1, 1, f_reverse},
Bram Moolenaareddf53b2006-02-27 00:11:10 +00007150 {"search", 1, 3, f_search},
Bram Moolenaare6facf92005-09-13 21:22:27 +00007151 {"searchdecl", 1, 3, f_searchdecl},
Bram Moolenaareddf53b2006-02-27 00:11:10 +00007152 {"searchpair", 3, 6, f_searchpair},
7153 {"searchpairpos", 3, 6, f_searchpairpos},
7154 {"searchpos", 1, 3, f_searchpos},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007155 {"server2client", 2, 2, f_server2client},
7156 {"serverlist", 0, 0, f_serverlist},
7157 {"setbufvar", 3, 3, f_setbufvar},
7158 {"setcmdpos", 1, 1, f_setcmdpos},
7159 {"setline", 2, 2, f_setline},
Bram Moolenaar17c7c012006-01-26 22:25:15 +00007160 {"setloclist", 2, 3, f_setloclist},
Bram Moolenaar0e34f622006-03-03 23:00:03 +00007161 {"setpos", 2, 2, f_setpos},
Bram Moolenaarf4630b62005-05-20 21:31:17 +00007162 {"setqflist", 1, 2, f_setqflist},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007163 {"setreg", 2, 3, f_setreg},
Bram Moolenaar99ebf042006-04-15 20:28:54 +00007164 {"settabwinvar", 4, 4, f_settabwinvar},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007165 {"setwinvar", 3, 3, f_setwinvar},
7166 {"simplify", 1, 1, f_simplify},
Bram Moolenaar0d660222005-01-07 21:51:51 +00007167 {"sort", 1, 2, f_sort},
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00007168 {"soundfold", 1, 1, f_soundfold},
Bram Moolenaar4463f292005-09-25 22:20:24 +00007169 {"spellbadword", 0, 1, f_spellbadword},
Bram Moolenaar69e0ff92005-09-30 21:23:56 +00007170 {"spellsuggest", 1, 3, f_spellsuggest},
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00007171 {"split", 1, 3, f_split},
Bram Moolenaar2c932302006-03-18 21:42:09 +00007172 {"str2nr", 1, 2, f_str2nr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007173#ifdef HAVE_STRFTIME
7174 {"strftime", 1, 2, f_strftime},
7175#endif
Bram Moolenaar33570922005-01-25 22:26:29 +00007176 {"stridx", 2, 3, f_stridx},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007177 {"string", 1, 1, f_string},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007178 {"strlen", 1, 1, f_strlen},
7179 {"strpart", 2, 3, f_strpart},
Bram Moolenaar532c7802005-01-27 14:44:31 +00007180 {"strridx", 2, 3, f_strridx},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007181 {"strtrans", 1, 1, f_strtrans},
7182 {"submatch", 1, 1, f_submatch},
7183 {"substitute", 4, 4, f_substitute},
7184 {"synID", 3, 3, f_synID},
7185 {"synIDattr", 2, 3, f_synIDattr},
7186 {"synIDtrans", 1, 1, f_synIDtrans},
Bram Moolenaarc0197e22004-09-13 20:26:32 +00007187 {"system", 1, 2, f_system},
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00007188 {"tabpagebuflist", 0, 1, f_tabpagebuflist},
Bram Moolenaar7e8fd632006-02-18 22:14:51 +00007189 {"tabpagenr", 0, 1, f_tabpagenr},
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00007190 {"tabpagewinnr", 1, 2, f_tabpagewinnr},
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00007191 {"tagfiles", 0, 0, f_tagfiles},
Bram Moolenaar19a09a12005-03-04 23:39:37 +00007192 {"taglist", 1, 1, f_taglist},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007193 {"tempname", 0, 0, f_tempname},
Bram Moolenaard52d9742005-08-21 22:20:28 +00007194 {"test", 1, 1, f_test},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007195 {"tolower", 1, 1, f_tolower},
7196 {"toupper", 1, 1, f_toupper},
Bram Moolenaar8299df92004-07-10 09:47:34 +00007197 {"tr", 3, 3, f_tr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007198 {"type", 1, 1, f_type},
Bram Moolenaar8c711452005-01-14 21:53:12 +00007199 {"values", 1, 1, f_values},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007200 {"virtcol", 1, 1, f_virtcol},
7201 {"visualmode", 0, 1, f_visualmode},
7202 {"winbufnr", 1, 1, f_winbufnr},
7203 {"wincol", 0, 0, f_wincol},
7204 {"winheight", 1, 1, f_winheight},
7205 {"winline", 0, 0, f_winline},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007206 {"winnr", 0, 1, f_winnr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007207 {"winrestcmd", 0, 0, f_winrestcmd},
Bram Moolenaar768b8c42006-03-04 21:58:33 +00007208 {"winrestview", 1, 1, f_winrestview},
7209 {"winsaveview", 0, 0, f_winsaveview},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007210 {"winwidth", 1, 1, f_winwidth},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007211 {"writefile", 2, 3, f_writefile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00007212};
7213
7214#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
7215
7216/*
7217 * Function given to ExpandGeneric() to obtain the list of internal
7218 * or user defined function names.
7219 */
7220 char_u *
7221get_function_name(xp, idx)
7222 expand_T *xp;
7223 int idx;
7224{
7225 static int intidx = -1;
7226 char_u *name;
7227
7228 if (idx == 0)
7229 intidx = -1;
7230 if (intidx < 0)
7231 {
7232 name = get_user_func_name(xp, idx);
7233 if (name != NULL)
7234 return name;
7235 }
7236 if (++intidx < (int)(sizeof(functions) / sizeof(struct fst)))
7237 {
7238 STRCPY(IObuff, functions[intidx].f_name);
7239 STRCAT(IObuff, "(");
7240 if (functions[intidx].f_max_argc == 0)
7241 STRCAT(IObuff, ")");
7242 return IObuff;
7243 }
7244
7245 return NULL;
7246}
7247
7248/*
7249 * Function given to ExpandGeneric() to obtain the list of internal or
7250 * user defined variable or function names.
7251 */
7252/*ARGSUSED*/
7253 char_u *
7254get_expr_name(xp, idx)
7255 expand_T *xp;
7256 int idx;
7257{
7258 static int intidx = -1;
7259 char_u *name;
7260
7261 if (idx == 0)
7262 intidx = -1;
7263 if (intidx < 0)
7264 {
7265 name = get_function_name(xp, idx);
7266 if (name != NULL)
7267 return name;
7268 }
7269 return get_user_var_name(xp, ++intidx);
7270}
7271
7272#endif /* FEAT_CMDL_COMPL */
7273
7274/*
7275 * Find internal function in table above.
7276 * Return index, or -1 if not found
7277 */
7278 static int
7279find_internal_func(name)
7280 char_u *name; /* name of the function */
7281{
7282 int first = 0;
7283 int last = (int)(sizeof(functions) / sizeof(struct fst)) - 1;
7284 int cmp;
7285 int x;
7286
7287 /*
7288 * Find the function name in the table. Binary search.
7289 */
7290 while (first <= last)
7291 {
7292 x = first + ((unsigned)(last - first) >> 1);
7293 cmp = STRCMP(name, functions[x].f_name);
7294 if (cmp < 0)
7295 last = x - 1;
7296 else if (cmp > 0)
7297 first = x + 1;
7298 else
7299 return x;
7300 }
7301 return -1;
7302}
7303
7304/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007305 * Check if "name" is a variable of type VAR_FUNC. If so, return the function
7306 * name it contains, otherwise return "name".
7307 */
7308 static char_u *
7309deref_func_name(name, lenp)
7310 char_u *name;
7311 int *lenp;
7312{
Bram Moolenaar33570922005-01-25 22:26:29 +00007313 dictitem_T *v;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007314 int cc;
7315
7316 cc = name[*lenp];
7317 name[*lenp] = NUL;
Bram Moolenaara7043832005-01-21 11:56:39 +00007318 v = find_var(name, NULL);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007319 name[*lenp] = cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00007320 if (v != NULL && v->di_tv.v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007321 {
Bram Moolenaar33570922005-01-25 22:26:29 +00007322 if (v->di_tv.vval.v_string == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007323 {
7324 *lenp = 0;
7325 return (char_u *)""; /* just in case */
7326 }
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007327 *lenp = (int)STRLEN(v->di_tv.vval.v_string);
Bram Moolenaar33570922005-01-25 22:26:29 +00007328 return v->di_tv.vval.v_string;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007329 }
7330
7331 return name;
7332}
7333
7334/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007335 * Allocate a variable for the result of a function.
7336 * Return OK or FAIL.
7337 */
7338 static int
Bram Moolenaare9a41262005-01-15 22:18:47 +00007339get_func_tv(name, len, rettv, arg, firstline, lastline, doesrange,
7340 evaluate, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007341 char_u *name; /* name of the function */
7342 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +00007343 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007344 char_u **arg; /* argument, pointing to the '(' */
7345 linenr_T firstline; /* first line of range */
7346 linenr_T lastline; /* last line of range */
7347 int *doesrange; /* return: function handled range */
7348 int evaluate;
Bram Moolenaar33570922005-01-25 22:26:29 +00007349 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007350{
7351 char_u *argp;
7352 int ret = OK;
Bram Moolenaareb3593b2006-04-22 22:33:57 +00007353 typval_T argvars[MAX_FUNC_ARGS + 1]; /* vars for arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007354 int argcount = 0; /* number of arguments found */
7355
7356 /*
7357 * Get the arguments.
7358 */
7359 argp = *arg;
7360 while (argcount < MAX_FUNC_ARGS)
7361 {
7362 argp = skipwhite(argp + 1); /* skip the '(' or ',' */
7363 if (*argp == ')' || *argp == ',' || *argp == NUL)
7364 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007365 if (eval1(&argp, &argvars[argcount], evaluate) == FAIL)
7366 {
7367 ret = FAIL;
7368 break;
7369 }
7370 ++argcount;
7371 if (*argp != ',')
7372 break;
7373 }
7374 if (*argp == ')')
7375 ++argp;
7376 else
7377 ret = FAIL;
7378
7379 if (ret == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007380 ret = call_func(name, len, rettv, argcount, argvars,
Bram Moolenaare9a41262005-01-15 22:18:47 +00007381 firstline, lastline, doesrange, evaluate, selfdict);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007382 else if (!aborting())
Bram Moolenaar33570922005-01-25 22:26:29 +00007383 {
7384 if (argcount == MAX_FUNC_ARGS)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007385 emsg_funcname("E740: Too many arguments for function %s", name);
Bram Moolenaar33570922005-01-25 22:26:29 +00007386 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007387 emsg_funcname("E116: Invalid arguments for function %s", name);
Bram Moolenaar33570922005-01-25 22:26:29 +00007388 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007389
7390 while (--argcount >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007391 clear_tv(&argvars[argcount]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007392
7393 *arg = skipwhite(argp);
7394 return ret;
7395}
7396
7397
7398/*
7399 * Call a function with its resolved parameters
Bram Moolenaar280f1262006-01-30 00:14:18 +00007400 * Return OK when the function can't be called, FAIL otherwise.
7401 * Also returns OK when an error was encountered while executing the function.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007402 */
7403 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007404call_func(name, len, rettv, argcount, argvars, firstline, lastline,
Bram Moolenaare9a41262005-01-15 22:18:47 +00007405 doesrange, evaluate, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007406 char_u *name; /* name of the function */
7407 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +00007408 typval_T *rettv; /* return value goes here */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007409 int argcount; /* number of "argvars" */
Bram Moolenaareb3593b2006-04-22 22:33:57 +00007410 typval_T *argvars; /* vars for arguments, must have "argcount"
7411 PLUS ONE elements! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007412 linenr_T firstline; /* first line of range */
7413 linenr_T lastline; /* last line of range */
7414 int *doesrange; /* return: function handled range */
7415 int evaluate;
Bram Moolenaar33570922005-01-25 22:26:29 +00007416 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007417{
7418 int ret = FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007419#define ERROR_UNKNOWN 0
7420#define ERROR_TOOMANY 1
7421#define ERROR_TOOFEW 2
7422#define ERROR_SCRIPT 3
Bram Moolenaare9a41262005-01-15 22:18:47 +00007423#define ERROR_DICT 4
7424#define ERROR_NONE 5
7425#define ERROR_OTHER 6
Bram Moolenaar071d4272004-06-13 20:20:40 +00007426 int error = ERROR_NONE;
7427 int i;
7428 int llen;
7429 ufunc_T *fp;
7430 int cc;
7431#define FLEN_FIXED 40
7432 char_u fname_buf[FLEN_FIXED + 1];
7433 char_u *fname;
7434
7435 /*
7436 * In a script change <SID>name() and s:name() to K_SNR 123_name().
7437 * Change <SNR>123_name() to K_SNR 123_name().
7438 * Use fname_buf[] when it fits, otherwise allocate memory (slow).
7439 */
7440 cc = name[len];
7441 name[len] = NUL;
7442 llen = eval_fname_script(name);
7443 if (llen > 0)
7444 {
7445 fname_buf[0] = K_SPECIAL;
7446 fname_buf[1] = KS_EXTRA;
7447 fname_buf[2] = (int)KE_SNR;
7448 i = 3;
7449 if (eval_fname_sid(name)) /* "<SID>" or "s:" */
7450 {
7451 if (current_SID <= 0)
7452 error = ERROR_SCRIPT;
7453 else
7454 {
7455 sprintf((char *)fname_buf + 3, "%ld_", (long)current_SID);
7456 i = (int)STRLEN(fname_buf);
7457 }
7458 }
7459 if (i + STRLEN(name + llen) < FLEN_FIXED)
7460 {
7461 STRCPY(fname_buf + i, name + llen);
7462 fname = fname_buf;
7463 }
7464 else
7465 {
7466 fname = alloc((unsigned)(i + STRLEN(name + llen) + 1));
7467 if (fname == NULL)
7468 error = ERROR_OTHER;
7469 else
7470 {
7471 mch_memmove(fname, fname_buf, (size_t)i);
7472 STRCPY(fname + i, name + llen);
7473 }
7474 }
7475 }
7476 else
7477 fname = name;
7478
7479 *doesrange = FALSE;
7480
7481
7482 /* execute the function if no errors detected and executing */
7483 if (evaluate && error == ERROR_NONE)
7484 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007485 rettv->v_type = VAR_NUMBER; /* default is number rettv */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007486 error = ERROR_UNKNOWN;
7487
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00007488 if (!builtin_function(fname))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007489 {
7490 /*
7491 * User defined function.
7492 */
7493 fp = find_func(fname);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00007494
Bram Moolenaar071d4272004-06-13 20:20:40 +00007495#ifdef FEAT_AUTOCMD
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00007496 /* Trigger FuncUndefined event, may load the function. */
7497 if (fp == NULL
7498 && apply_autocmds(EVENT_FUNCUNDEFINED,
7499 fname, fname, TRUE, NULL)
7500 && !aborting())
Bram Moolenaar071d4272004-06-13 20:20:40 +00007501 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00007502 /* executed an autocommand, search for the function again */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007503 fp = find_func(fname);
7504 }
7505#endif
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00007506 /* Try loading a package. */
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00007507 if (fp == NULL && script_autoload(fname, TRUE) && !aborting())
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00007508 {
7509 /* loaded a package, search for the function again */
7510 fp = find_func(fname);
7511 }
7512
Bram Moolenaar071d4272004-06-13 20:20:40 +00007513 if (fp != NULL)
7514 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00007515 if (fp->uf_flags & FC_RANGE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007516 *doesrange = TRUE;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00007517 if (argcount < fp->uf_args.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007518 error = ERROR_TOOFEW;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00007519 else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007520 error = ERROR_TOOMANY;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00007521 else if ((fp->uf_flags & FC_DICT) && selfdict == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007522 error = ERROR_DICT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007523 else
7524 {
7525 /*
7526 * Call the user function.
7527 * Save and restore search patterns, script variables and
7528 * redo buffer.
7529 */
7530 save_search_patterns();
7531 saveRedobuff();
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00007532 ++fp->uf_calls;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007533 call_user_func(fp, argcount, argvars, rettv,
Bram Moolenaare9a41262005-01-15 22:18:47 +00007534 firstline, lastline,
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00007535 (fp->uf_flags & FC_DICT) ? selfdict : NULL);
7536 if (--fp->uf_calls <= 0 && isdigit(*fp->uf_name)
7537 && fp->uf_refcount <= 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007538 /* Function was unreferenced while being used, free it
7539 * now. */
7540 func_free(fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007541 restoreRedobuff();
7542 restore_search_patterns();
7543 error = ERROR_NONE;
7544 }
7545 }
7546 }
7547 else
7548 {
7549 /*
7550 * Find the function name in the table, call its implementation.
7551 */
7552 i = find_internal_func(fname);
7553 if (i >= 0)
7554 {
7555 if (argcount < functions[i].f_min_argc)
7556 error = ERROR_TOOFEW;
7557 else if (argcount > functions[i].f_max_argc)
7558 error = ERROR_TOOMANY;
7559 else
7560 {
Bram Moolenaarac48dbf2006-09-03 13:34:00 +00007561 av_list_item_T av_list_item;
7562
7563 /* Add the arguments to the "argvars_list" to avoid the
7564 * garbage collector not seeing them. This isn't needed
7565 * for user functions, because the arguments are available
7566 * in the a: hashtab. */
7567 av_list_item.avl_argvars = argvars;
7568 av_list_item.avl_next = argvars_list;
7569 argvars_list = &av_list_item;
7570
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007571 argvars[argcount].v_type = VAR_UNKNOWN;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007572 functions[i].f_func(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007573 error = ERROR_NONE;
Bram Moolenaarac48dbf2006-09-03 13:34:00 +00007574
7575 argvars_list = av_list_item.avl_next;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007576 }
7577 }
7578 }
7579 /*
7580 * The function call (or "FuncUndefined" autocommand sequence) might
7581 * have been aborted by an error, an interrupt, or an explicitly thrown
7582 * exception that has not been caught so far. This situation can be
7583 * tested for by calling aborting(). For an error in an internal
7584 * function or for the "E132" error in call_user_func(), however, the
7585 * throw point at which the "force_abort" flag (temporarily reset by
7586 * emsg()) is normally updated has not been reached yet. We need to
7587 * update that flag first to make aborting() reliable.
7588 */
7589 update_force_abort();
7590 }
7591 if (error == ERROR_NONE)
7592 ret = OK;
7593
7594 /*
7595 * Report an error unless the argument evaluation or function call has been
7596 * cancelled due to an aborting error, an interrupt, or an exception.
7597 */
Bram Moolenaar8c711452005-01-14 21:53:12 +00007598 if (!aborting())
7599 {
7600 switch (error)
7601 {
7602 case ERROR_UNKNOWN:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007603 emsg_funcname(N_("E117: Unknown function: %s"), name);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007604 break;
7605 case ERROR_TOOMANY:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007606 emsg_funcname(e_toomanyarg, name);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007607 break;
7608 case ERROR_TOOFEW:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007609 emsg_funcname(N_("E119: Not enough arguments for function: %s"),
Bram Moolenaar8c711452005-01-14 21:53:12 +00007610 name);
7611 break;
7612 case ERROR_SCRIPT:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007613 emsg_funcname(N_("E120: Using <SID> not in a script context: %s"),
Bram Moolenaar8c711452005-01-14 21:53:12 +00007614 name);
7615 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007616 case ERROR_DICT:
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00007617 emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"),
Bram Moolenaare9a41262005-01-15 22:18:47 +00007618 name);
7619 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007620 }
7621 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007622
7623 name[len] = cc;
7624 if (fname != name && fname != fname_buf)
7625 vim_free(fname);
7626
7627 return ret;
7628}
7629
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007630/*
7631 * Give an error message with a function name. Handle <SNR> things.
7632 */
7633 static void
Bram Moolenaar89d40322006-08-29 15:30:07 +00007634emsg_funcname(ermsg, name)
7635 char *ermsg;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007636 char_u *name;
7637{
7638 char_u *p;
7639
7640 if (*name == K_SPECIAL)
7641 p = concat_str((char_u *)"<SNR>", name + 3);
7642 else
7643 p = name;
Bram Moolenaar89d40322006-08-29 15:30:07 +00007644 EMSG2(_(ermsg), p);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007645 if (p != name)
7646 vim_free(p);
7647}
7648
Bram Moolenaar071d4272004-06-13 20:20:40 +00007649/*********************************************
7650 * Implementation of the built-in functions
7651 */
7652
7653/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00007654 * "add(list, item)" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00007655 */
7656 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +00007657f_add(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007658 typval_T *argvars;
7659 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007660{
Bram Moolenaar33570922005-01-25 22:26:29 +00007661 list_T *l;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007662
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007663 rettv->vval.v_number = 1; /* Default: Failed */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007664 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007665 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007666 if ((l = argvars[0].vval.v_list) != NULL
7667 && !tv_check_lock(l->lv_lock, (char_u *)"add()")
7668 && list_append_tv(l, &argvars[1]) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007669 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007670 }
7671 else
Bram Moolenaar0d660222005-01-07 21:51:51 +00007672 EMSG(_(e_listreq));
7673}
7674
7675/*
7676 * "append(lnum, string/list)" function
7677 */
7678 static void
7679f_append(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007680 typval_T *argvars;
7681 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00007682{
7683 long lnum;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007684 char_u *line;
Bram Moolenaar33570922005-01-25 22:26:29 +00007685 list_T *l = NULL;
7686 listitem_T *li = NULL;
7687 typval_T *tv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00007688 long added = 0;
7689
Bram Moolenaar0d660222005-01-07 21:51:51 +00007690 lnum = get_tv_lnum(argvars);
7691 if (lnum >= 0
7692 && lnum <= curbuf->b_ml.ml_line_count
7693 && u_save(lnum, lnum + 1) == OK)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007694 {
Bram Moolenaar0d660222005-01-07 21:51:51 +00007695 if (argvars[1].v_type == VAR_LIST)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007696 {
Bram Moolenaar0d660222005-01-07 21:51:51 +00007697 l = argvars[1].vval.v_list;
7698 if (l == NULL)
7699 return;
7700 li = l->lv_first;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007701 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007702 rettv->vval.v_number = 0; /* Default: Success */
Bram Moolenaar0d660222005-01-07 21:51:51 +00007703 for (;;)
7704 {
7705 if (l == NULL)
7706 tv = &argvars[1]; /* append a string */
7707 else if (li == NULL)
7708 break; /* end of list */
7709 else
7710 tv = &li->li_tv; /* append item from list */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007711 line = get_tv_string_chk(tv);
7712 if (line == NULL) /* type error */
7713 {
7714 rettv->vval.v_number = 1; /* Failed */
7715 break;
7716 }
7717 ml_append(lnum + added, line, (colnr_T)0, FALSE);
Bram Moolenaar0d660222005-01-07 21:51:51 +00007718 ++added;
7719 if (l == NULL)
7720 break;
7721 li = li->li_next;
7722 }
7723
7724 appended_lines_mark(lnum, added);
7725 if (curwin->w_cursor.lnum > lnum)
7726 curwin->w_cursor.lnum += added;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007727 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007728 else
7729 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007730}
7731
7732/*
7733 * "argc()" function
7734 */
7735/* ARGSUSED */
7736 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007737f_argc(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007738 typval_T *argvars;
7739 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007740{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007741 rettv->vval.v_number = ARGCOUNT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007742}
7743
7744/*
7745 * "argidx()" function
7746 */
7747/* ARGSUSED */
7748 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007749f_argidx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007750 typval_T *argvars;
7751 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007752{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007753 rettv->vval.v_number = curwin->w_arg_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007754}
7755
7756/*
7757 * "argv(nr)" function
7758 */
7759 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007760f_argv(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007761 typval_T *argvars;
7762 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007763{
7764 int idx;
7765
Bram Moolenaare2f98b92006-03-29 21:18:24 +00007766 if (argvars[0].v_type != VAR_UNKNOWN)
7767 {
7768 idx = get_tv_number_chk(&argvars[0], NULL);
7769 if (idx >= 0 && idx < ARGCOUNT)
7770 rettv->vval.v_string = vim_strsave(alist_name(&ARGLIST[idx]));
7771 else
7772 rettv->vval.v_string = NULL;
7773 rettv->v_type = VAR_STRING;
7774 }
7775 else if (rettv_list_alloc(rettv) == OK)
7776 for (idx = 0; idx < ARGCOUNT; ++idx)
7777 list_append_string(rettv->vval.v_list,
7778 alist_name(&ARGLIST[idx]), -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007779}
7780
7781/*
7782 * "browse(save, title, initdir, default)" function
7783 */
7784/* ARGSUSED */
7785 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007786f_browse(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007787 typval_T *argvars;
7788 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007789{
7790#ifdef FEAT_BROWSE
7791 int save;
7792 char_u *title;
7793 char_u *initdir;
7794 char_u *defname;
7795 char_u buf[NUMBUFLEN];
7796 char_u buf2[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007797 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007798
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007799 save = get_tv_number_chk(&argvars[0], &error);
7800 title = get_tv_string_chk(&argvars[1]);
7801 initdir = get_tv_string_buf_chk(&argvars[2], buf);
7802 defname = get_tv_string_buf_chk(&argvars[3], buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007803
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007804 if (error || title == NULL || initdir == NULL || defname == NULL)
7805 rettv->vval.v_string = NULL;
7806 else
7807 rettv->vval.v_string =
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007808 do_browse(save ? BROWSE_SAVE : 0,
7809 title, defname, NULL, initdir, NULL, curbuf);
7810#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007811 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007812#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007813 rettv->v_type = VAR_STRING;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007814}
7815
7816/*
7817 * "browsedir(title, initdir)" function
7818 */
7819/* ARGSUSED */
7820 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007821f_browsedir(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007822 typval_T *argvars;
7823 typval_T *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007824{
7825#ifdef FEAT_BROWSE
7826 char_u *title;
7827 char_u *initdir;
7828 char_u buf[NUMBUFLEN];
7829
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007830 title = get_tv_string_chk(&argvars[0]);
7831 initdir = get_tv_string_buf_chk(&argvars[1], buf);
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007832
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007833 if (title == NULL || initdir == NULL)
7834 rettv->vval.v_string = NULL;
7835 else
7836 rettv->vval.v_string = do_browse(BROWSE_DIR,
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007837 title, NULL, NULL, initdir, NULL, curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007838#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007839 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007840#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007841 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007842}
7843
Bram Moolenaar33570922005-01-25 22:26:29 +00007844static buf_T *find_buffer __ARGS((typval_T *avar));
Bram Moolenaar0d660222005-01-07 21:51:51 +00007845
Bram Moolenaar071d4272004-06-13 20:20:40 +00007846/*
7847 * Find a buffer by number or exact name.
7848 */
7849 static buf_T *
7850find_buffer(avar)
Bram Moolenaar33570922005-01-25 22:26:29 +00007851 typval_T *avar;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007852{
7853 buf_T *buf = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007854
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007855 if (avar->v_type == VAR_NUMBER)
7856 buf = buflist_findnr((int)avar->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +00007857 else if (avar->v_type == VAR_STRING && avar->vval.v_string != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007858 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007859 buf = buflist_findname_exp(avar->vval.v_string);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00007860 if (buf == NULL)
7861 {
7862 /* No full path name match, try a match with a URL or a "nofile"
7863 * buffer, these don't use the full path. */
7864 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
7865 if (buf->b_fname != NULL
7866 && (path_with_url(buf->b_fname)
7867#ifdef FEAT_QUICKFIX
7868 || bt_nofile(buf)
7869#endif
7870 )
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007871 && STRCMP(buf->b_fname, avar->vval.v_string) == 0)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00007872 break;
7873 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007874 }
7875 return buf;
7876}
7877
7878/*
7879 * "bufexists(expr)" function
7880 */
7881 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007882f_bufexists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007883 typval_T *argvars;
7884 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007885{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007886 rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007887}
7888
7889/*
7890 * "buflisted(expr)" function
7891 */
7892 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007893f_buflisted(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007894 typval_T *argvars;
7895 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007896{
7897 buf_T *buf;
7898
7899 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007900 rettv->vval.v_number = (buf != NULL && buf->b_p_bl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007901}
7902
7903/*
7904 * "bufloaded(expr)" function
7905 */
7906 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007907f_bufloaded(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007908 typval_T *argvars;
7909 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007910{
7911 buf_T *buf;
7912
7913 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007914 rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007915}
7916
Bram Moolenaar33570922005-01-25 22:26:29 +00007917static buf_T *get_buf_tv __ARGS((typval_T *tv));
Bram Moolenaar0d660222005-01-07 21:51:51 +00007918
Bram Moolenaar071d4272004-06-13 20:20:40 +00007919/*
7920 * Get buffer by number or pattern.
7921 */
7922 static buf_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007923get_buf_tv(tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007924 typval_T *tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007925{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007926 char_u *name = tv->vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007927 int save_magic;
7928 char_u *save_cpo;
7929 buf_T *buf;
7930
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007931 if (tv->v_type == VAR_NUMBER)
7932 return buflist_findnr((int)tv->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +00007933 if (tv->v_type != VAR_STRING)
7934 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007935 if (name == NULL || *name == NUL)
7936 return curbuf;
7937 if (name[0] == '$' && name[1] == NUL)
7938 return lastbuf;
7939
7940 /* Ignore 'magic' and 'cpoptions' here to make scripts portable */
7941 save_magic = p_magic;
7942 p_magic = TRUE;
7943 save_cpo = p_cpo;
7944 p_cpo = (char_u *)"";
7945
7946 buf = buflist_findnr(buflist_findpat(name, name + STRLEN(name),
7947 TRUE, FALSE));
7948
7949 p_magic = save_magic;
7950 p_cpo = save_cpo;
7951
7952 /* If not found, try expanding the name, like done for bufexists(). */
7953 if (buf == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007954 buf = find_buffer(tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007955
7956 return buf;
7957}
7958
7959/*
7960 * "bufname(expr)" function
7961 */
7962 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007963f_bufname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007964 typval_T *argvars;
7965 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007966{
7967 buf_T *buf;
7968
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007969 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007970 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007971 buf = get_buf_tv(&argvars[0]);
7972 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007973 if (buf != NULL && buf->b_fname != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007974 rettv->vval.v_string = vim_strsave(buf->b_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007975 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007976 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007977 --emsg_off;
7978}
7979
7980/*
7981 * "bufnr(expr)" function
7982 */
7983 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007984f_bufnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007985 typval_T *argvars;
7986 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007987{
7988 buf_T *buf;
Bram Moolenaar0e34f622006-03-03 23:00:03 +00007989 int error = FALSE;
7990 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007991
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007992 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007993 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007994 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar0e34f622006-03-03 23:00:03 +00007995 --emsg_off;
7996
7997 /* If the buffer isn't found and the second argument is not zero create a
7998 * new buffer. */
7999 if (buf == NULL
8000 && argvars[1].v_type != VAR_UNKNOWN
8001 && get_tv_number_chk(&argvars[1], &error) != 0
8002 && !error
8003 && (name = get_tv_string_chk(&argvars[0])) != NULL
8004 && !error)
8005 buf = buflist_new(name, NULL, (linenr_T)1, 0);
8006
Bram Moolenaar071d4272004-06-13 20:20:40 +00008007 if (buf != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008008 rettv->vval.v_number = buf->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008009 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008010 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008011}
8012
8013/*
8014 * "bufwinnr(nr)" function
8015 */
8016 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008017f_bufwinnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008018 typval_T *argvars;
8019 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008020{
8021#ifdef FEAT_WINDOWS
8022 win_T *wp;
8023 int winnr = 0;
8024#endif
8025 buf_T *buf;
8026
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008027 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008028 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008029 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008030#ifdef FEAT_WINDOWS
8031 for (wp = firstwin; wp; wp = wp->w_next)
8032 {
8033 ++winnr;
8034 if (wp->w_buffer == buf)
8035 break;
8036 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008037 rettv->vval.v_number = (wp != NULL ? winnr : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008038#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008039 rettv->vval.v_number = (curwin->w_buffer == buf ? 1 : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008040#endif
8041 --emsg_off;
8042}
8043
8044/*
8045 * "byte2line(byte)" function
8046 */
8047/*ARGSUSED*/
8048 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008049f_byte2line(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008050 typval_T *argvars;
8051 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008052{
8053#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008054 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008055#else
8056 long boff = 0;
8057
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008058 boff = get_tv_number(&argvars[0]) - 1; /* boff gets -1 on type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008059 if (boff < 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008060 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008061 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008062 rettv->vval.v_number = ml_find_line_or_offset(curbuf,
Bram Moolenaar071d4272004-06-13 20:20:40 +00008063 (linenr_T)0, &boff);
8064#endif
8065}
8066
8067/*
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00008068 * "byteidx()" function
8069 */
8070/*ARGSUSED*/
8071 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008072f_byteidx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008073 typval_T *argvars;
8074 typval_T *rettv;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00008075{
8076#ifdef FEAT_MBYTE
8077 char_u *t;
8078#endif
8079 char_u *str;
8080 long idx;
8081
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008082 str = get_tv_string_chk(&argvars[0]);
8083 idx = get_tv_number_chk(&argvars[1], NULL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008084 rettv->vval.v_number = -1;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008085 if (str == NULL || idx < 0)
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00008086 return;
8087
8088#ifdef FEAT_MBYTE
8089 t = str;
8090 for ( ; idx > 0; idx--)
8091 {
8092 if (*t == NUL) /* EOL reached */
8093 return;
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00008094 t += (*mb_ptr2len)(t);
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00008095 }
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008096 rettv->vval.v_number = (varnumber_T)(t - str);
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00008097#else
8098 if (idx <= STRLEN(str))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008099 rettv->vval.v_number = idx;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00008100#endif
8101}
8102
8103/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008104 * "call(func, arglist)" function
8105 */
8106 static void
8107f_call(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008108 typval_T *argvars;
8109 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008110{
8111 char_u *func;
Bram Moolenaareb3593b2006-04-22 22:33:57 +00008112 typval_T argv[MAX_FUNC_ARGS + 1];
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008113 int argc = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00008114 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008115 int dummy;
Bram Moolenaar33570922005-01-25 22:26:29 +00008116 dict_T *selfdict = NULL;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008117
8118 rettv->vval.v_number = 0;
8119 if (argvars[1].v_type != VAR_LIST)
8120 {
8121 EMSG(_(e_listreq));
8122 return;
8123 }
8124 if (argvars[1].vval.v_list == NULL)
8125 return;
8126
8127 if (argvars[0].v_type == VAR_FUNC)
8128 func = argvars[0].vval.v_string;
8129 else
8130 func = get_tv_string(&argvars[0]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008131 if (*func == NUL)
8132 return; /* type error or empty name */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008133
Bram Moolenaare9a41262005-01-15 22:18:47 +00008134 if (argvars[2].v_type != VAR_UNKNOWN)
8135 {
8136 if (argvars[2].v_type != VAR_DICT)
8137 {
8138 EMSG(_(e_dictreq));
8139 return;
8140 }
8141 selfdict = argvars[2].vval.v_dict;
8142 }
8143
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008144 for (item = argvars[1].vval.v_list->lv_first; item != NULL;
8145 item = item->li_next)
8146 {
8147 if (argc == MAX_FUNC_ARGS)
8148 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00008149 EMSG(_("E699: Too many arguments"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008150 break;
8151 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008152 /* Make a copy of each argument. This is needed to be able to set
8153 * v_lock to VAR_FIXED in the copy without changing the original list.
8154 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008155 copy_tv(&item->li_tv, &argv[argc++]);
8156 }
8157
8158 if (item == NULL)
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008159 (void)call_func(func, (int)STRLEN(func), rettv, argc, argv,
Bram Moolenaare9a41262005-01-15 22:18:47 +00008160 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
8161 &dummy, TRUE, selfdict);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008162
8163 /* Free the arguments. */
8164 while (argc > 0)
8165 clear_tv(&argv[--argc]);
8166}
8167
8168/*
Bram Moolenaarf0acfce2006-03-17 23:21:19 +00008169 * "changenr()" function
8170 */
8171/*ARGSUSED*/
8172 static void
8173f_changenr(argvars, rettv)
8174 typval_T *argvars;
8175 typval_T *rettv;
8176{
8177 rettv->vval.v_number = curbuf->b_u_seq_cur;
8178}
8179
8180/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008181 * "char2nr(string)" function
8182 */
8183 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008184f_char2nr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008185 typval_T *argvars;
8186 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008187{
8188#ifdef FEAT_MBYTE
8189 if (has_mbyte)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008190 rettv->vval.v_number = (*mb_ptr2char)(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008191 else
8192#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008193 rettv->vval.v_number = get_tv_string(&argvars[0])[0];
Bram Moolenaar071d4272004-06-13 20:20:40 +00008194}
8195
8196/*
8197 * "cindent(lnum)" function
8198 */
8199 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008200f_cindent(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008201 typval_T *argvars;
8202 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008203{
8204#ifdef FEAT_CINDENT
8205 pos_T pos;
8206 linenr_T lnum;
8207
8208 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008209 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008210 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
8211 {
8212 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008213 rettv->vval.v_number = get_c_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +00008214 curwin->w_cursor = pos;
8215 }
8216 else
8217#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008218 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008219}
8220
8221/*
8222 * "col(string)" function
8223 */
8224 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008225f_col(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008226 typval_T *argvars;
8227 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008228{
8229 colnr_T col = 0;
8230 pos_T *fp;
Bram Moolenaar0e34f622006-03-03 23:00:03 +00008231 int fnum = curbuf->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008232
Bram Moolenaar0e34f622006-03-03 23:00:03 +00008233 fp = var2fpos(&argvars[0], FALSE, &fnum);
8234 if (fp != NULL && fnum == curbuf->b_fnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008235 {
8236 if (fp->col == MAXCOL)
8237 {
8238 /* '> can be MAXCOL, get the length of the line then */
8239 if (fp->lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008240 col = (colnr_T)STRLEN(ml_get(fp->lnum)) + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008241 else
8242 col = MAXCOL;
8243 }
8244 else
8245 {
8246 col = fp->col + 1;
8247#ifdef FEAT_VIRTUALEDIT
8248 /* col(".") when the cursor is on the NUL at the end of the line
8249 * because of "coladd" can be seen as an extra column. */
8250 if (virtual_active() && fp == &curwin->w_cursor)
8251 {
8252 char_u *p = ml_get_cursor();
8253
8254 if (curwin->w_cursor.coladd >= (colnr_T)chartabsize(p,
8255 curwin->w_virtcol - curwin->w_cursor.coladd))
8256 {
8257# ifdef FEAT_MBYTE
8258 int l;
8259
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00008260 if (*p != NUL && p[(l = (*mb_ptr2len)(p))] == NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008261 col += l;
8262# else
8263 if (*p != NUL && p[1] == NUL)
8264 ++col;
8265# endif
8266 }
8267 }
8268#endif
8269 }
8270 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008271 rettv->vval.v_number = col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008272}
8273
Bram Moolenaar572cb562005-08-05 21:35:02 +00008274#if defined(FEAT_INS_EXPAND)
8275/*
Bram Moolenaarade00832006-03-10 21:46:58 +00008276 * "complete()" function
8277 */
8278/*ARGSUSED*/
8279 static void
8280f_complete(argvars, rettv)
8281 typval_T *argvars;
8282 typval_T *rettv;
8283{
8284 int startcol;
8285
8286 if ((State & INSERT) == 0)
8287 {
8288 EMSG(_("E785: complete() can only be used in Insert mode"));
8289 return;
8290 }
Bram Moolenaarce6ef252006-07-12 19:49:41 +00008291
8292 /* Check for undo allowed here, because if something was already inserted
8293 * the line was already saved for undo and this check isn't done. */
8294 if (!undo_allowed())
8295 return;
8296
Bram Moolenaarade00832006-03-10 21:46:58 +00008297 if (argvars[1].v_type != VAR_LIST || argvars[1].vval.v_list == NULL)
8298 {
8299 EMSG(_(e_invarg));
8300 return;
8301 }
8302
8303 startcol = get_tv_number_chk(&argvars[0], NULL);
8304 if (startcol <= 0)
8305 return;
8306
8307 set_completion(startcol - 1, argvars[1].vval.v_list);
8308}
8309
8310/*
Bram Moolenaar572cb562005-08-05 21:35:02 +00008311 * "complete_add()" function
8312 */
8313/*ARGSUSED*/
8314 static void
8315f_complete_add(argvars, rettv)
8316 typval_T *argvars;
8317 typval_T *rettv;
8318{
Bram Moolenaarceaf7b82006-03-19 22:18:55 +00008319 rettv->vval.v_number = ins_compl_add_tv(&argvars[0], 0);
Bram Moolenaar572cb562005-08-05 21:35:02 +00008320}
8321
8322/*
8323 * "complete_check()" function
8324 */
8325/*ARGSUSED*/
8326 static void
8327f_complete_check(argvars, rettv)
8328 typval_T *argvars;
8329 typval_T *rettv;
8330{
8331 int saved = RedrawingDisabled;
8332
8333 RedrawingDisabled = 0;
8334 ins_compl_check_keys(0);
8335 rettv->vval.v_number = compl_interrupted;
8336 RedrawingDisabled = saved;
8337}
8338#endif
8339
Bram Moolenaar071d4272004-06-13 20:20:40 +00008340/*
8341 * "confirm(message, buttons[, default [, type]])" function
8342 */
8343/*ARGSUSED*/
8344 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008345f_confirm(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008346 typval_T *argvars;
8347 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008348{
8349#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
8350 char_u *message;
8351 char_u *buttons = NULL;
8352 char_u buf[NUMBUFLEN];
8353 char_u buf2[NUMBUFLEN];
8354 int def = 1;
8355 int type = VIM_GENERIC;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008356 char_u *typestr;
8357 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008358
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008359 message = get_tv_string_chk(&argvars[0]);
8360 if (message == NULL)
8361 error = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008362 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008363 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008364 buttons = get_tv_string_buf_chk(&argvars[1], buf);
8365 if (buttons == NULL)
8366 error = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008367 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008368 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008369 def = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008370 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008371 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008372 typestr = get_tv_string_buf_chk(&argvars[3], buf2);
8373 if (typestr == NULL)
8374 error = TRUE;
8375 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00008376 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008377 switch (TOUPPER_ASC(*typestr))
8378 {
8379 case 'E': type = VIM_ERROR; break;
8380 case 'Q': type = VIM_QUESTION; break;
8381 case 'I': type = VIM_INFO; break;
8382 case 'W': type = VIM_WARNING; break;
8383 case 'G': type = VIM_GENERIC; break;
8384 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008385 }
8386 }
8387 }
8388 }
8389
8390 if (buttons == NULL || *buttons == NUL)
8391 buttons = (char_u *)_("&Ok");
8392
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008393 if (error)
8394 rettv->vval.v_number = 0;
8395 else
8396 rettv->vval.v_number = do_dialog(type, NULL, message, buttons,
Bram Moolenaar071d4272004-06-13 20:20:40 +00008397 def, NULL);
8398#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008399 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008400#endif
8401}
8402
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008403/*
8404 * "copy()" function
8405 */
8406 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008407f_copy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008408 typval_T *argvars;
8409 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008410{
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008411 item_copy(&argvars[0], rettv, FALSE, 0);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008412}
Bram Moolenaar071d4272004-06-13 20:20:40 +00008413
8414/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008415 * "count()" function
8416 */
8417 static void
8418f_count(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008419 typval_T *argvars;
8420 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008421{
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008422 long n = 0;
8423 int ic = FALSE;
8424
Bram Moolenaare9a41262005-01-15 22:18:47 +00008425 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008426 {
Bram Moolenaar33570922005-01-25 22:26:29 +00008427 listitem_T *li;
8428 list_T *l;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008429 long idx;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008430
Bram Moolenaare9a41262005-01-15 22:18:47 +00008431 if ((l = argvars[0].vval.v_list) != NULL)
8432 {
8433 li = l->lv_first;
8434 if (argvars[2].v_type != VAR_UNKNOWN)
8435 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008436 int error = FALSE;
8437
8438 ic = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008439 if (argvars[3].v_type != VAR_UNKNOWN)
8440 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008441 idx = get_tv_number_chk(&argvars[3], &error);
8442 if (!error)
8443 {
8444 li = list_find(l, idx);
8445 if (li == NULL)
8446 EMSGN(_(e_listidx), idx);
8447 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008448 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008449 if (error)
8450 li = NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008451 }
8452
8453 for ( ; li != NULL; li = li->li_next)
8454 if (tv_equal(&li->li_tv, &argvars[1], ic))
8455 ++n;
8456 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008457 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008458 else if (argvars[0].v_type == VAR_DICT)
8459 {
Bram Moolenaar33570922005-01-25 22:26:29 +00008460 int todo;
8461 dict_T *d;
8462 hashitem_T *hi;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008463
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008464 if ((d = argvars[0].vval.v_dict) != NULL)
8465 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008466 int error = FALSE;
8467
Bram Moolenaare9a41262005-01-15 22:18:47 +00008468 if (argvars[2].v_type != VAR_UNKNOWN)
8469 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008470 ic = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008471 if (argvars[3].v_type != VAR_UNKNOWN)
8472 EMSG(_(e_invarg));
8473 }
8474
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00008475 todo = error ? 0 : (int)d->dv_hashtab.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00008476 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008477 {
8478 if (!HASHITEM_EMPTY(hi))
8479 {
8480 --todo;
8481 if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic))
8482 ++n;
8483 }
8484 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008485 }
8486 }
8487 else
8488 EMSG2(_(e_listdictarg), "count()");
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008489 rettv->vval.v_number = n;
8490}
8491
8492/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008493 * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
8494 *
8495 * Checks the existence of a cscope connection.
8496 */
8497/*ARGSUSED*/
8498 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008499f_cscope_connection(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008500 typval_T *argvars;
8501 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008502{
8503#ifdef FEAT_CSCOPE
8504 int num = 0;
8505 char_u *dbpath = NULL;
8506 char_u *prepend = NULL;
8507 char_u buf[NUMBUFLEN];
8508
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008509 if (argvars[0].v_type != VAR_UNKNOWN
8510 && argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008511 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008512 num = (int)get_tv_number(&argvars[0]);
8513 dbpath = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008514 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008515 prepend = get_tv_string_buf(&argvars[2], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008516 }
8517
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008518 rettv->vval.v_number = cs_connection(num, dbpath, prepend);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008519#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008520 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008521#endif
8522}
8523
8524/*
8525 * "cursor(lnum, col)" function
8526 *
8527 * Moves the cursor to the specified line and column
8528 */
8529/*ARGSUSED*/
8530 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008531f_cursor(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008532 typval_T *argvars;
8533 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008534{
8535 long line, col;
Bram Moolenaara5525202006-03-02 22:52:09 +00008536#ifdef FEAT_VIRTUALEDIT
8537 long coladd = 0;
8538#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008539
Bram Moolenaara5525202006-03-02 22:52:09 +00008540 if (argvars[1].v_type == VAR_UNKNOWN)
8541 {
Bram Moolenaar0e34f622006-03-03 23:00:03 +00008542 pos_T pos;
Bram Moolenaara5525202006-03-02 22:52:09 +00008543
Bram Moolenaar0e34f622006-03-03 23:00:03 +00008544 if (list2fpos(argvars, &pos, NULL) == FAIL)
Bram Moolenaara5525202006-03-02 22:52:09 +00008545 return;
Bram Moolenaar0e34f622006-03-03 23:00:03 +00008546 line = pos.lnum;
8547 col = pos.col;
Bram Moolenaara5525202006-03-02 22:52:09 +00008548#ifdef FEAT_VIRTUALEDIT
Bram Moolenaar0e34f622006-03-03 23:00:03 +00008549 coladd = pos.coladd;
Bram Moolenaara5525202006-03-02 22:52:09 +00008550#endif
8551 }
8552 else
8553 {
8554 line = get_tv_lnum(argvars);
8555 col = get_tv_number_chk(&argvars[1], NULL);
8556#ifdef FEAT_VIRTUALEDIT
8557 if (argvars[2].v_type != VAR_UNKNOWN)
8558 coladd = get_tv_number_chk(&argvars[2], NULL);
8559#endif
8560 }
8561 if (line < 0 || col < 0
8562#ifdef FEAT_VIRTUALEDIT
8563 || coladd < 0
8564#endif
8565 )
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008566 return; /* type error; errmsg already given */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008567 if (line > 0)
8568 curwin->w_cursor.lnum = line;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008569 if (col > 0)
8570 curwin->w_cursor.col = col - 1;
8571#ifdef FEAT_VIRTUALEDIT
Bram Moolenaara5525202006-03-02 22:52:09 +00008572 curwin->w_cursor.coladd = coladd;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008573#endif
8574
8575 /* Make sure the cursor is in a valid position. */
8576 check_cursor();
8577#ifdef FEAT_MBYTE
8578 /* Correct cursor for multi-byte character. */
8579 if (has_mbyte)
8580 mb_adjust_cursor();
8581#endif
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00008582
8583 curwin->w_set_curswant = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008584}
8585
8586/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008587 * "deepcopy()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00008588 */
8589 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008590f_deepcopy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008591 typval_T *argvars;
8592 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008593{
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008594 int noref = 0;
8595
8596 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008597 noref = get_tv_number_chk(&argvars[1], NULL);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008598 if (noref < 0 || noref > 1)
8599 EMSG(_(e_invarg));
8600 else
Bram Moolenaard9fba312005-06-26 22:34:35 +00008601 item_copy(&argvars[0], rettv, TRUE, noref == 0 ? ++current_copyID : 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008602}
8603
8604/*
8605 * "delete()" function
8606 */
8607 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008608f_delete(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008609 typval_T *argvars;
8610 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008611{
8612 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008613 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008614 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008615 rettv->vval.v_number = mch_remove(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008616}
8617
8618/*
8619 * "did_filetype()" function
8620 */
8621/*ARGSUSED*/
8622 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008623f_did_filetype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008624 typval_T *argvars;
8625 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008626{
8627#ifdef FEAT_AUTOCMD
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008628 rettv->vval.v_number = did_filetype;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008629#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008630 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008631#endif
8632}
8633
8634/*
Bram Moolenaar47136d72004-10-12 20:02:24 +00008635 * "diff_filler()" function
8636 */
8637/*ARGSUSED*/
8638 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008639f_diff_filler(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008640 typval_T *argvars;
8641 typval_T *rettv;
Bram Moolenaar47136d72004-10-12 20:02:24 +00008642{
8643#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008644 rettv->vval.v_number = diff_check_fill(curwin, get_tv_lnum(argvars));
Bram Moolenaar47136d72004-10-12 20:02:24 +00008645#endif
8646}
8647
8648/*
8649 * "diff_hlID()" function
8650 */
8651/*ARGSUSED*/
8652 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008653f_diff_hlID(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008654 typval_T *argvars;
8655 typval_T *rettv;
Bram Moolenaar47136d72004-10-12 20:02:24 +00008656{
8657#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008658 linenr_T lnum = get_tv_lnum(argvars);
Bram Moolenaar47136d72004-10-12 20:02:24 +00008659 static linenr_T prev_lnum = 0;
8660 static int changedtick = 0;
8661 static int fnum = 0;
8662 static int change_start = 0;
8663 static int change_end = 0;
Bram Moolenaar482aaeb2005-09-29 18:26:07 +00008664 static hlf_T hlID = 0;
Bram Moolenaar47136d72004-10-12 20:02:24 +00008665 int filler_lines;
8666 int col;
8667
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008668 if (lnum < 0) /* ignore type error in {lnum} arg */
8669 lnum = 0;
Bram Moolenaar47136d72004-10-12 20:02:24 +00008670 if (lnum != prev_lnum
8671 || changedtick != curbuf->b_changedtick
8672 || fnum != curbuf->b_fnum)
8673 {
8674 /* New line, buffer, change: need to get the values. */
8675 filler_lines = diff_check(curwin, lnum);
8676 if (filler_lines < 0)
8677 {
8678 if (filler_lines == -1)
8679 {
8680 change_start = MAXCOL;
8681 change_end = -1;
8682 if (diff_find_change(curwin, lnum, &change_start, &change_end))
8683 hlID = HLF_ADD; /* added line */
8684 else
8685 hlID = HLF_CHD; /* changed line */
8686 }
8687 else
8688 hlID = HLF_ADD; /* added line */
8689 }
8690 else
Bram Moolenaar482aaeb2005-09-29 18:26:07 +00008691 hlID = (hlf_T)0;
Bram Moolenaar47136d72004-10-12 20:02:24 +00008692 prev_lnum = lnum;
8693 changedtick = curbuf->b_changedtick;
8694 fnum = curbuf->b_fnum;
8695 }
8696
8697 if (hlID == HLF_CHD || hlID == HLF_TXD)
8698 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008699 col = get_tv_number(&argvars[1]) - 1; /* ignore type error in {col} */
Bram Moolenaar47136d72004-10-12 20:02:24 +00008700 if (col >= change_start && col <= change_end)
8701 hlID = HLF_TXD; /* changed text */
8702 else
8703 hlID = HLF_CHD; /* changed line */
8704 }
Bram Moolenaar482aaeb2005-09-29 18:26:07 +00008705 rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (int)hlID;
Bram Moolenaar47136d72004-10-12 20:02:24 +00008706#endif
8707}
8708
8709/*
Bram Moolenaare49b69a2005-01-08 16:11:57 +00008710 * "empty({expr})" function
8711 */
8712 static void
8713f_empty(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008714 typval_T *argvars;
8715 typval_T *rettv;
Bram Moolenaare49b69a2005-01-08 16:11:57 +00008716{
8717 int n;
8718
8719 switch (argvars[0].v_type)
8720 {
8721 case VAR_STRING:
8722 case VAR_FUNC:
8723 n = argvars[0].vval.v_string == NULL
8724 || *argvars[0].vval.v_string == NUL;
8725 break;
8726 case VAR_NUMBER:
8727 n = argvars[0].vval.v_number == 0;
8728 break;
8729 case VAR_LIST:
8730 n = argvars[0].vval.v_list == NULL
8731 || argvars[0].vval.v_list->lv_first == NULL;
8732 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008733 case VAR_DICT:
8734 n = argvars[0].vval.v_dict == NULL
Bram Moolenaar33570922005-01-25 22:26:29 +00008735 || argvars[0].vval.v_dict->dv_hashtab.ht_used == 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008736 break;
Bram Moolenaare49b69a2005-01-08 16:11:57 +00008737 default:
8738 EMSG2(_(e_intern2), "f_empty()");
8739 n = 0;
8740 }
8741
8742 rettv->vval.v_number = n;
8743}
8744
8745/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008746 * "escape({string}, {chars})" function
8747 */
8748 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008749f_escape(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{
8753 char_u buf[NUMBUFLEN];
8754
Bram Moolenaar758711c2005-02-02 23:11:38 +00008755 rettv->vval.v_string = vim_strsave_escaped(get_tv_string(&argvars[0]),
8756 get_tv_string_buf(&argvars[1], buf));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008757 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008758}
8759
8760/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008761 * "eval()" function
8762 */
8763/*ARGSUSED*/
8764 static void
8765f_eval(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008766 typval_T *argvars;
8767 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008768{
8769 char_u *s;
8770
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008771 s = get_tv_string_chk(&argvars[0]);
8772 if (s != NULL)
8773 s = skipwhite(s);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008774
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008775 if (s == NULL || eval1(&s, rettv, TRUE) == FAIL)
8776 {
8777 rettv->v_type = VAR_NUMBER;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008778 rettv->vval.v_number = 0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008779 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008780 else if (*s != NUL)
8781 EMSG(_(e_trailing));
8782}
8783
8784/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008785 * "eventhandler()" function
8786 */
8787/*ARGSUSED*/
8788 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008789f_eventhandler(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008790 typval_T *argvars;
8791 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008792{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008793 rettv->vval.v_number = vgetc_busy;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008794}
8795
8796/*
8797 * "executable()" function
8798 */
8799 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008800f_executable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008801 typval_T *argvars;
8802 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008803{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008804 rettv->vval.v_number = mch_can_exe(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008805}
8806
8807/*
8808 * "exists()" function
8809 */
8810 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008811f_exists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008812 typval_T *argvars;
8813 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008814{
8815 char_u *p;
8816 char_u *name;
8817 int n = FALSE;
8818 int len = 0;
8819
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008820 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008821 if (*p == '$') /* environment variable */
8822 {
8823 /* first try "normal" environment variables (fast) */
8824 if (mch_getenv(p + 1) != NULL)
8825 n = TRUE;
8826 else
8827 {
8828 /* try expanding things like $VIM and ${HOME} */
8829 p = expand_env_save(p);
8830 if (p != NULL && *p != '$')
8831 n = TRUE;
8832 vim_free(p);
8833 }
8834 }
8835 else if (*p == '&' || *p == '+') /* option */
Bram Moolenaar79783442006-05-05 21:18:03 +00008836 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008837 n = (get_option_tv(&p, NULL, TRUE) == OK);
Bram Moolenaar79783442006-05-05 21:18:03 +00008838 if (*skipwhite(p) != NUL)
8839 n = FALSE; /* trailing garbage */
8840 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008841 else if (*p == '*') /* internal or user defined function */
8842 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008843 n = function_exists(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008844 }
8845 else if (*p == ':')
8846 {
8847 n = cmd_exists(p + 1);
8848 }
8849 else if (*p == '#')
8850 {
8851#ifdef FEAT_AUTOCMD
Bram Moolenaarf4cd3e82005-12-22 22:47:02 +00008852 if (p[1] == '#')
8853 n = autocmd_supported(p + 2);
8854 else
8855 n = au_exists(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008856#endif
8857 }
8858 else /* internal variable */
8859 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008860 char_u *tofree;
8861 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008862
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008863 /* get_name_len() takes care of expanding curly braces */
8864 name = p;
8865 len = get_name_len(&p, &tofree, TRUE, FALSE);
8866 if (len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008867 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008868 if (tofree != NULL)
8869 name = tofree;
8870 n = (get_var_tv(name, len, &tv, FALSE) == OK);
8871 if (n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008872 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008873 /* handle d.key, l[idx], f(expr) */
8874 n = (handle_subscript(&p, &tv, TRUE, FALSE) == OK);
8875 if (n)
8876 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008877 }
8878 }
Bram Moolenaar79783442006-05-05 21:18:03 +00008879 if (*p != NUL)
8880 n = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008881
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008882 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008883 }
8884
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008885 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008886}
8887
8888/*
8889 * "expand()" function
8890 */
8891 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008892f_expand(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008893 typval_T *argvars;
8894 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008895{
8896 char_u *s;
8897 int len;
8898 char_u *errormsg;
8899 int flags = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND;
8900 expand_T xpc;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008901 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008902
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008903 rettv->v_type = VAR_STRING;
8904 s = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008905 if (*s == '%' || *s == '#' || *s == '<')
8906 {
8907 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008908 rettv->vval.v_string = eval_vars(s, &len, NULL, &errormsg, s);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008909 --emsg_off;
8910 }
8911 else
8912 {
8913 /* When the optional second argument is non-zero, don't remove matches
8914 * for 'suffixes' and 'wildignore' */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008915 if (argvars[1].v_type != VAR_UNKNOWN
8916 && get_tv_number_chk(&argvars[1], &error))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008917 flags |= WILD_KEEP_ALL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008918 if (!error)
8919 {
8920 ExpandInit(&xpc);
8921 xpc.xp_context = EXPAND_FILES;
8922 rettv->vval.v_string = ExpandOne(&xpc, s, NULL, flags, WILD_ALL);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008923 }
8924 else
8925 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008926 }
8927}
8928
8929/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008930 * "extend(list, list [, idx])" function
Bram Moolenaare9a41262005-01-15 22:18:47 +00008931 * "extend(dict, dict [, action])" function
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008932 */
8933 static void
8934f_extend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008935 typval_T *argvars;
8936 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008937{
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008938 rettv->vval.v_number = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008939 if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008940 {
Bram Moolenaar33570922005-01-25 22:26:29 +00008941 list_T *l1, *l2;
8942 listitem_T *item;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008943 long before;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008944 int error = FALSE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008945
Bram Moolenaare9a41262005-01-15 22:18:47 +00008946 l1 = argvars[0].vval.v_list;
8947 l2 = argvars[1].vval.v_list;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008948 if (l1 != NULL && !tv_check_lock(l1->lv_lock, (char_u *)"extend()")
8949 && l2 != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008950 {
8951 if (argvars[2].v_type != VAR_UNKNOWN)
8952 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008953 before = get_tv_number_chk(&argvars[2], &error);
8954 if (error)
8955 return; /* type error; errmsg already given */
8956
Bram Moolenaar758711c2005-02-02 23:11:38 +00008957 if (before == l1->lv_len)
8958 item = NULL;
8959 else
Bram Moolenaare9a41262005-01-15 22:18:47 +00008960 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00008961 item = list_find(l1, before);
8962 if (item == NULL)
8963 {
8964 EMSGN(_(e_listidx), before);
8965 return;
8966 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008967 }
8968 }
8969 else
8970 item = NULL;
8971 list_extend(l1, l2, item);
8972
Bram Moolenaare9a41262005-01-15 22:18:47 +00008973 copy_tv(&argvars[0], rettv);
8974 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008975 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008976 else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT)
8977 {
Bram Moolenaar33570922005-01-25 22:26:29 +00008978 dict_T *d1, *d2;
8979 dictitem_T *di1;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008980 char_u *action;
8981 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00008982 hashitem_T *hi2;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008983 int todo;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008984
8985 d1 = argvars[0].vval.v_dict;
8986 d2 = argvars[1].vval.v_dict;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008987 if (d1 != NULL && !tv_check_lock(d1->dv_lock, (char_u *)"extend()")
8988 && d2 != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008989 {
8990 /* Check the third argument. */
8991 if (argvars[2].v_type != VAR_UNKNOWN)
8992 {
8993 static char *(av[]) = {"keep", "force", "error"};
8994
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008995 action = get_tv_string_chk(&argvars[2]);
8996 if (action == NULL)
8997 return; /* type error; errmsg already given */
Bram Moolenaare9a41262005-01-15 22:18:47 +00008998 for (i = 0; i < 3; ++i)
8999 if (STRCMP(action, av[i]) == 0)
9000 break;
9001 if (i == 3)
9002 {
Bram Moolenaareb3593b2006-04-22 22:33:57 +00009003 EMSG2(_(e_invarg2), action);
Bram Moolenaare9a41262005-01-15 22:18:47 +00009004 return;
9005 }
9006 }
9007 else
9008 action = (char_u *)"force";
9009
9010 /* Go over all entries in the second dict and add them to the
9011 * first dict. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00009012 todo = (int)d2->dv_hashtab.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00009013 for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2)
Bram Moolenaare9a41262005-01-15 22:18:47 +00009014 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00009015 if (!HASHITEM_EMPTY(hi2))
Bram Moolenaare9a41262005-01-15 22:18:47 +00009016 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00009017 --todo;
9018 di1 = dict_find(d1, hi2->hi_key, -1);
9019 if (di1 == NULL)
9020 {
9021 di1 = dictitem_copy(HI2DI(hi2));
9022 if (di1 != NULL && dict_add(d1, di1) == FAIL)
9023 dictitem_free(di1);
9024 }
9025 else if (*action == 'e')
9026 {
9027 EMSG2(_("E737: Key already exists: %s"), hi2->hi_key);
9028 break;
9029 }
9030 else if (*action == 'f')
9031 {
9032 clear_tv(&di1->di_tv);
9033 copy_tv(&HI2DI(hi2)->di_tv, &di1->di_tv);
9034 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00009035 }
9036 }
9037
Bram Moolenaare9a41262005-01-15 22:18:47 +00009038 copy_tv(&argvars[0], rettv);
9039 }
9040 }
9041 else
9042 EMSG2(_(e_listdictarg), "extend()");
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009043}
9044
9045/*
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00009046 * "feedkeys()" function
9047 */
9048/*ARGSUSED*/
9049 static void
9050f_feedkeys(argvars, rettv)
9051 typval_T *argvars;
9052 typval_T *rettv;
9053{
9054 int remap = TRUE;
9055 char_u *keys, *flags;
9056 char_u nbuf[NUMBUFLEN];
9057 int typed = FALSE;
Bram Moolenaarf193fff2006-04-27 00:02:13 +00009058 char_u *keys_esc;
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00009059
9060 rettv->vval.v_number = 0;
9061 keys = get_tv_string(&argvars[0]);
9062 if (*keys != NUL)
9063 {
9064 if (argvars[1].v_type != VAR_UNKNOWN)
9065 {
9066 flags = get_tv_string_buf(&argvars[1], nbuf);
9067 for ( ; *flags != NUL; ++flags)
9068 {
9069 switch (*flags)
9070 {
9071 case 'n': remap = FALSE; break;
9072 case 'm': remap = TRUE; break;
9073 case 't': typed = TRUE; break;
9074 }
9075 }
9076 }
9077
Bram Moolenaarf193fff2006-04-27 00:02:13 +00009078 /* Need to escape K_SPECIAL and CSI before putting the string in the
9079 * typeahead buffer. */
9080 keys_esc = vim_strsave_escape_csi(keys);
9081 if (keys_esc != NULL)
9082 {
9083 ins_typebuf(keys_esc, (remap ? REMAP_YES : REMAP_NONE),
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00009084 typebuf.tb_len, !typed, FALSE);
Bram Moolenaarf193fff2006-04-27 00:02:13 +00009085 vim_free(keys_esc);
Bram Moolenaar437df8f2006-04-27 21:47:44 +00009086 if (vgetc_busy)
9087 typebuf_was_filled = TRUE;
Bram Moolenaarf193fff2006-04-27 00:02:13 +00009088 }
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00009089 }
9090}
9091
9092/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009093 * "filereadable()" function
9094 */
9095 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009096f_filereadable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009097 typval_T *argvars;
9098 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009099{
9100 FILE *fd;
9101 char_u *p;
9102 int n;
9103
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009104 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009105 if (*p && !mch_isdir(p) && (fd = mch_fopen((char *)p, "r")) != NULL)
9106 {
9107 n = TRUE;
9108 fclose(fd);
9109 }
9110 else
9111 n = FALSE;
9112
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009113 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009114}
9115
9116/*
Bram Moolenaar0e4d8772005-06-07 21:12:49 +00009117 * Return 0 for not writable, 1 for writable file, 2 for a dir which we have
Bram Moolenaar071d4272004-06-13 20:20:40 +00009118 * rights to write into.
9119 */
9120 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009121f_filewritable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009122 typval_T *argvars;
9123 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009124{
Bram Moolenaar0e4d8772005-06-07 21:12:49 +00009125 rettv->vval.v_number = filewritable(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009126}
9127
Bram Moolenaar33570922005-01-25 22:26:29 +00009128static void findfilendir __ARGS((typval_T *argvars, typval_T *rettv, int dir));
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00009129
9130 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +00009131findfilendir(argvars, rettv, dir)
Bram Moolenaar33570922005-01-25 22:26:29 +00009132 typval_T *argvars;
9133 typval_T *rettv;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00009134 int dir;
9135{
9136#ifdef FEAT_SEARCHPATH
9137 char_u *fname;
9138 char_u *fresult = NULL;
9139 char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
9140 char_u *p;
9141 char_u pathbuf[NUMBUFLEN];
9142 int count = 1;
9143 int first = TRUE;
Bram Moolenaar899dddf2006-03-26 21:06:50 +00009144 int error = FALSE;
9145#endif
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00009146
Bram Moolenaar899dddf2006-03-26 21:06:50 +00009147 rettv->vval.v_string = NULL;
9148 rettv->v_type = VAR_STRING;
9149
9150#ifdef FEAT_SEARCHPATH
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009151 fname = get_tv_string(&argvars[0]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00009152
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009153 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00009154 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009155 p = get_tv_string_buf_chk(&argvars[1], pathbuf);
9156 if (p == NULL)
Bram Moolenaar899dddf2006-03-26 21:06:50 +00009157 error = TRUE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009158 else
9159 {
9160 if (*p != NUL)
9161 path = p;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00009162
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009163 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar899dddf2006-03-26 21:06:50 +00009164 count = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009165 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00009166 }
9167
Bram Moolenaar899dddf2006-03-26 21:06:50 +00009168 if (count < 0 && rettv_list_alloc(rettv) == FAIL)
9169 error = TRUE;
9170
9171 if (*fname != NUL && !error)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00009172 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009173 do
9174 {
Bram Moolenaar899dddf2006-03-26 21:06:50 +00009175 if (rettv->v_type == VAR_STRING)
9176 vim_free(fresult);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009177 fresult = find_file_in_path_option(first ? fname : NULL,
9178 first ? (int)STRLEN(fname) : 0,
Bram Moolenaare580b0c2006-03-21 21:33:03 +00009179 0, first, path, dir, NULL,
9180 dir ? (char_u *)"" : curbuf->b_p_sua);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009181 first = FALSE;
Bram Moolenaar899dddf2006-03-26 21:06:50 +00009182
9183 if (fresult != NULL && rettv->v_type == VAR_LIST)
9184 list_append_string(rettv->vval.v_list, fresult, -1);
9185
9186 } while ((rettv->v_type == VAR_LIST || --count > 0) && fresult != NULL);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009187 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00009188
Bram Moolenaar899dddf2006-03-26 21:06:50 +00009189 if (rettv->v_type == VAR_STRING)
9190 rettv->vval.v_string = fresult;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00009191#endif
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00009192}
9193
Bram Moolenaar33570922005-01-25 22:26:29 +00009194static void filter_map __ARGS((typval_T *argvars, typval_T *rettv, int map));
9195static int filter_map_one __ARGS((typval_T *tv, char_u *expr, int map, int *remp));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00009196
9197/*
9198 * Implementation of map() and filter().
9199 */
9200 static void
9201filter_map(argvars, rettv, map)
Bram Moolenaar33570922005-01-25 22:26:29 +00009202 typval_T *argvars;
9203 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00009204 int map;
9205{
9206 char_u buf[NUMBUFLEN];
Bram Moolenaare9a41262005-01-15 22:18:47 +00009207 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +00009208 listitem_T *li, *nli;
9209 list_T *l = NULL;
9210 dictitem_T *di;
9211 hashtab_T *ht;
9212 hashitem_T *hi;
9213 dict_T *d = NULL;
9214 typval_T save_val;
9215 typval_T save_key;
Bram Moolenaare9a41262005-01-15 22:18:47 +00009216 int rem;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00009217 int todo;
Bram Moolenaar89d40322006-08-29 15:30:07 +00009218 char_u *ermsg = map ? (char_u *)"map()" : (char_u *)"filter()";
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00009219 int save_did_emsg;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00009220
9221 rettv->vval.v_number = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00009222 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00009223 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00009224 if ((l = argvars[0].vval.v_list) == NULL
Bram Moolenaar89d40322006-08-29 15:30:07 +00009225 || (map && tv_check_lock(l->lv_lock, ermsg)))
Bram Moolenaare9a41262005-01-15 22:18:47 +00009226 return;
9227 }
9228 else if (argvars[0].v_type == VAR_DICT)
9229 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00009230 if ((d = argvars[0].vval.v_dict) == NULL
Bram Moolenaar89d40322006-08-29 15:30:07 +00009231 || (map && tv_check_lock(d->dv_lock, ermsg)))
Bram Moolenaare9a41262005-01-15 22:18:47 +00009232 return;
9233 }
9234 else
9235 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00009236 EMSG2(_(e_listdictarg), ermsg);
Bram Moolenaare9a41262005-01-15 22:18:47 +00009237 return;
9238 }
9239
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009240 expr = get_tv_string_buf_chk(&argvars[1], buf);
9241 /* On type errors, the preceding call has already displayed an error
9242 * message. Avoid a misleading error message for an empty string that
9243 * was not passed as argument. */
9244 if (expr != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00009245 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009246 prepare_vimvar(VV_VAL, &save_val);
9247 expr = skipwhite(expr);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00009248
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00009249 /* We reset "did_emsg" to be able to detect whether an error
9250 * occurred during evaluation of the expression. */
9251 save_did_emsg = did_emsg;
9252 did_emsg = FALSE;
Bram Moolenaar280f1262006-01-30 00:14:18 +00009253
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009254 if (argvars[0].v_type == VAR_DICT)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00009255 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009256 prepare_vimvar(VV_KEY, &save_key);
9257 vimvars[VV_KEY].vv_type = VAR_STRING;
9258
9259 ht = &d->dv_hashtab;
9260 hash_lock(ht);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00009261 todo = (int)ht->ht_used;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009262 for (hi = ht->ht_array; todo > 0; ++hi)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00009263 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009264 if (!HASHITEM_EMPTY(hi))
9265 {
9266 --todo;
9267 di = HI2DI(hi);
Bram Moolenaar89d40322006-08-29 15:30:07 +00009268 if (tv_check_lock(di->di_tv.v_lock, ermsg))
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009269 break;
9270 vimvars[VV_KEY].vv_str = vim_strsave(di->di_key);
Bram Moolenaar280f1262006-01-30 00:14:18 +00009271 if (filter_map_one(&di->di_tv, expr, map, &rem) == FAIL
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00009272 || did_emsg)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009273 break;
9274 if (!map && rem)
9275 dictitem_remove(d, di);
9276 clear_tv(&vimvars[VV_KEY].vv_tv);
9277 }
9278 }
9279 hash_unlock(ht);
9280
9281 restore_vimvar(VV_KEY, &save_key);
9282 }
9283 else
9284 {
9285 for (li = l->lv_first; li != NULL; li = nli)
9286 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00009287 if (tv_check_lock(li->li_tv.v_lock, ermsg))
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00009288 break;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009289 nli = li->li_next;
Bram Moolenaar280f1262006-01-30 00:14:18 +00009290 if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00009291 || did_emsg)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00009292 break;
9293 if (!map && rem)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009294 listitem_remove(l, li);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00009295 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00009296 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00009297
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009298 restore_vimvar(VV_VAL, &save_val);
Bram Moolenaar280f1262006-01-30 00:14:18 +00009299
Bram Moolenaar1f35bf92006-03-07 22:38:47 +00009300 did_emsg |= save_did_emsg;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00009301 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00009302
9303 copy_tv(&argvars[0], rettv);
9304}
9305
9306 static int
9307filter_map_one(tv, expr, map, remp)
Bram Moolenaar33570922005-01-25 22:26:29 +00009308 typval_T *tv;
Bram Moolenaare9a41262005-01-15 22:18:47 +00009309 char_u *expr;
9310 int map;
9311 int *remp;
9312{
Bram Moolenaar33570922005-01-25 22:26:29 +00009313 typval_T rettv;
Bram Moolenaare9a41262005-01-15 22:18:47 +00009314 char_u *s;
9315
Bram Moolenaar33570922005-01-25 22:26:29 +00009316 copy_tv(tv, &vimvars[VV_VAL].vv_tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00009317 s = expr;
9318 if (eval1(&s, &rettv, TRUE) == FAIL)
9319 return FAIL;
9320 if (*s != NUL) /* check for trailing chars after expr */
9321 {
9322 EMSG2(_(e_invexpr2), s);
9323 return FAIL;
9324 }
9325 if (map)
9326 {
9327 /* map(): replace the list item value */
9328 clear_tv(tv);
Bram Moolenaar4463f292005-09-25 22:20:24 +00009329 rettv.v_lock = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00009330 *tv = rettv;
9331 }
9332 else
9333 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009334 int error = FALSE;
9335
Bram Moolenaare9a41262005-01-15 22:18:47 +00009336 /* filter(): when expr is zero remove the item */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009337 *remp = (get_tv_number_chk(&rettv, &error) == 0);
Bram Moolenaare9a41262005-01-15 22:18:47 +00009338 clear_tv(&rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009339 /* On type error, nothing has been removed; return FAIL to stop the
9340 * loop. The error message was given by get_tv_number_chk(). */
9341 if (error)
9342 return FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00009343 }
Bram Moolenaar33570922005-01-25 22:26:29 +00009344 clear_tv(&vimvars[VV_VAL].vv_tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00009345 return OK;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00009346}
9347
9348/*
9349 * "filter()" function
9350 */
9351 static void
9352f_filter(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009353 typval_T *argvars;
9354 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00009355{
9356 filter_map(argvars, rettv, FALSE);
9357}
9358
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00009359/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00009360 * "finddir({fname}[, {path}[, {count}]])" function
9361 */
9362 static void
9363f_finddir(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009364 typval_T *argvars;
9365 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009366{
9367 findfilendir(argvars, rettv, TRUE);
9368}
9369
9370/*
9371 * "findfile({fname}[, {path}[, {count}]])" function
9372 */
9373 static void
9374f_findfile(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009375 typval_T *argvars;
9376 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009377{
9378 findfilendir(argvars, rettv, FALSE);
9379}
9380
9381/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009382 * "fnamemodify({fname}, {mods})" function
9383 */
9384 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009385f_fnamemodify(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009386 typval_T *argvars;
9387 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009388{
9389 char_u *fname;
9390 char_u *mods;
9391 int usedlen = 0;
9392 int len;
9393 char_u *fbuf = NULL;
9394 char_u buf[NUMBUFLEN];
9395
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009396 fname = get_tv_string_chk(&argvars[0]);
9397 mods = get_tv_string_buf_chk(&argvars[1], buf);
9398 if (fname == NULL || mods == NULL)
9399 fname = NULL;
9400 else
9401 {
9402 len = (int)STRLEN(fname);
9403 (void)modify_fname(mods, &usedlen, &fname, &fbuf, &len);
9404 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009405
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009406 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009407 if (fname == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009408 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009409 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009410 rettv->vval.v_string = vim_strnsave(fname, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009411 vim_free(fbuf);
9412}
9413
Bram Moolenaar33570922005-01-25 22:26:29 +00009414static void foldclosed_both __ARGS((typval_T *argvars, typval_T *rettv, int end));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009415
9416/*
9417 * "foldclosed()" function
9418 */
9419 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009420foldclosed_both(argvars, rettv, end)
Bram Moolenaar33570922005-01-25 22:26:29 +00009421 typval_T *argvars;
9422 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009423 int end;
9424{
9425#ifdef FEAT_FOLDING
9426 linenr_T lnum;
9427 linenr_T first, last;
9428
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009429 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009430 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
9431 {
9432 if (hasFoldingWin(curwin, lnum, &first, &last, FALSE, NULL))
9433 {
9434 if (end)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009435 rettv->vval.v_number = (varnumber_T)last;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009436 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009437 rettv->vval.v_number = (varnumber_T)first;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009438 return;
9439 }
9440 }
9441#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009442 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009443}
9444
9445/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00009446 * "foldclosed()" function
9447 */
9448 static void
9449f_foldclosed(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009450 typval_T *argvars;
9451 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009452{
9453 foldclosed_both(argvars, rettv, FALSE);
9454}
9455
9456/*
9457 * "foldclosedend()" function
9458 */
9459 static void
9460f_foldclosedend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009461 typval_T *argvars;
9462 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009463{
9464 foldclosed_both(argvars, rettv, TRUE);
9465}
9466
9467/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009468 * "foldlevel()" function
9469 */
9470 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009471f_foldlevel(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009472 typval_T *argvars;
9473 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009474{
9475#ifdef FEAT_FOLDING
9476 linenr_T lnum;
9477
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009478 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009479 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009480 rettv->vval.v_number = foldLevel(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009481 else
9482#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009483 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009484}
9485
9486/*
9487 * "foldtext()" function
9488 */
9489/*ARGSUSED*/
9490 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009491f_foldtext(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009492 typval_T *argvars;
9493 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009494{
9495#ifdef FEAT_FOLDING
9496 linenr_T lnum;
9497 char_u *s;
9498 char_u *r;
9499 int len;
9500 char *txt;
9501#endif
9502
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009503 rettv->v_type = VAR_STRING;
9504 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009505#ifdef FEAT_FOLDING
Bram Moolenaare9a41262005-01-15 22:18:47 +00009506 if ((linenr_T)vimvars[VV_FOLDSTART].vv_nr > 0
9507 && (linenr_T)vimvars[VV_FOLDEND].vv_nr
9508 <= curbuf->b_ml.ml_line_count
9509 && vimvars[VV_FOLDDASHES].vv_str != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009510 {
9511 /* Find first non-empty line in the fold. */
Bram Moolenaare9a41262005-01-15 22:18:47 +00009512 lnum = (linenr_T)vimvars[VV_FOLDSTART].vv_nr;
9513 while (lnum < (linenr_T)vimvars[VV_FOLDEND].vv_nr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009514 {
9515 if (!linewhite(lnum))
9516 break;
9517 ++lnum;
9518 }
9519
9520 /* Find interesting text in this line. */
9521 s = skipwhite(ml_get(lnum));
9522 /* skip C comment-start */
9523 if (s[0] == '/' && (s[1] == '*' || s[1] == '/'))
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00009524 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00009525 s = skipwhite(s + 2);
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00009526 if (*skipwhite(s) == NUL
Bram Moolenaare9a41262005-01-15 22:18:47 +00009527 && lnum + 1 < (linenr_T)vimvars[VV_FOLDEND].vv_nr)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00009528 {
9529 s = skipwhite(ml_get(lnum + 1));
9530 if (*s == '*')
9531 s = skipwhite(s + 1);
9532 }
9533 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009534 txt = _("+-%s%3ld lines: ");
9535 r = alloc((unsigned)(STRLEN(txt)
Bram Moolenaare9a41262005-01-15 22:18:47 +00009536 + STRLEN(vimvars[VV_FOLDDASHES].vv_str) /* for %s */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009537 + 20 /* for %3ld */
9538 + STRLEN(s))); /* concatenated */
9539 if (r != NULL)
9540 {
Bram Moolenaare9a41262005-01-15 22:18:47 +00009541 sprintf((char *)r, txt, vimvars[VV_FOLDDASHES].vv_str,
9542 (long)((linenr_T)vimvars[VV_FOLDEND].vv_nr
9543 - (linenr_T)vimvars[VV_FOLDSTART].vv_nr + 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009544 len = (int)STRLEN(r);
9545 STRCAT(r, s);
9546 /* remove 'foldmarker' and 'commentstring' */
9547 foldtext_cleanup(r + len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009548 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009549 }
9550 }
9551#endif
9552}
9553
9554/*
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009555 * "foldtextresult(lnum)" function
9556 */
9557/*ARGSUSED*/
9558 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009559f_foldtextresult(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009560 typval_T *argvars;
9561 typval_T *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009562{
9563#ifdef FEAT_FOLDING
9564 linenr_T lnum;
9565 char_u *text;
9566 char_u buf[51];
9567 foldinfo_T foldinfo;
9568 int fold_count;
9569#endif
9570
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009571 rettv->v_type = VAR_STRING;
9572 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009573#ifdef FEAT_FOLDING
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009574 lnum = get_tv_lnum(argvars);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009575 /* treat illegal types and illegal string values for {lnum} the same */
9576 if (lnum < 0)
9577 lnum = 0;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009578 fold_count = foldedCount(curwin, lnum, &foldinfo);
9579 if (fold_count > 0)
9580 {
9581 text = get_foldtext(curwin, lnum, lnum + fold_count - 1,
9582 &foldinfo, buf);
9583 if (text == buf)
9584 text = vim_strsave(text);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009585 rettv->vval.v_string = text;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009586 }
9587#endif
9588}
9589
9590/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009591 * "foreground()" function
9592 */
9593/*ARGSUSED*/
9594 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009595f_foreground(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009596 typval_T *argvars;
9597 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009598{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009599 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009600#ifdef FEAT_GUI
9601 if (gui.in_use)
9602 gui_mch_set_foreground();
9603#else
9604# ifdef WIN32
9605 win32_set_foreground();
9606# endif
9607#endif
9608}
9609
9610/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009611 * "function()" function
9612 */
9613/*ARGSUSED*/
9614 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009615f_function(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009616 typval_T *argvars;
9617 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009618{
9619 char_u *s;
9620
Bram Moolenaara7043832005-01-21 11:56:39 +00009621 rettv->vval.v_number = 0;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009622 s = get_tv_string(&argvars[0]);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00009623 if (s == NULL || *s == NUL || VIM_ISDIGIT(*s))
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009624 EMSG2(_(e_invarg2), s);
9625 else if (!function_exists(s))
Bram Moolenaare49b69a2005-01-08 16:11:57 +00009626 EMSG2(_("E700: Unknown function: %s"), s);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009627 else
9628 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009629 rettv->vval.v_string = vim_strsave(s);
9630 rettv->v_type = VAR_FUNC;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009631 }
9632}
9633
9634/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00009635 * "garbagecollect()" function
9636 */
9637/*ARGSUSED*/
9638 static void
9639f_garbagecollect(argvars, rettv)
9640 typval_T *argvars;
9641 typval_T *rettv;
9642{
Bram Moolenaar9fecb462006-09-05 10:59:47 +00009643 /* This is postponed until we are back at the toplevel, because we may be
9644 * using Lists and Dicts internally. E.g.: ":echo [garbagecollect()]". */
9645 want_garbage_collect = TRUE;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00009646}
9647
9648/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00009649 * "get()" function
9650 */
9651 static void
9652f_get(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009653 typval_T *argvars;
9654 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009655{
Bram Moolenaar33570922005-01-25 22:26:29 +00009656 listitem_T *li;
9657 list_T *l;
9658 dictitem_T *di;
9659 dict_T *d;
9660 typval_T *tv = NULL;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009661
Bram Moolenaare9a41262005-01-15 22:18:47 +00009662 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar0d660222005-01-07 21:51:51 +00009663 {
Bram Moolenaare9a41262005-01-15 22:18:47 +00009664 if ((l = argvars[0].vval.v_list) != NULL)
Bram Moolenaar0d660222005-01-07 21:51:51 +00009665 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009666 int error = FALSE;
9667
9668 li = list_find(l, get_tv_number_chk(&argvars[1], &error));
9669 if (!error && li != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00009670 tv = &li->li_tv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009671 }
Bram Moolenaar0d660222005-01-07 21:51:51 +00009672 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00009673 else if (argvars[0].v_type == VAR_DICT)
9674 {
9675 if ((d = argvars[0].vval.v_dict) != NULL)
9676 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00009677 di = dict_find(d, get_tv_string(&argvars[1]), -1);
Bram Moolenaare9a41262005-01-15 22:18:47 +00009678 if (di != NULL)
9679 tv = &di->di_tv;
9680 }
9681 }
9682 else
9683 EMSG2(_(e_listdictarg), "get()");
9684
9685 if (tv == NULL)
9686 {
9687 if (argvars[2].v_type == VAR_UNKNOWN)
9688 rettv->vval.v_number = 0;
9689 else
9690 copy_tv(&argvars[2], rettv);
9691 }
9692 else
9693 copy_tv(tv, rettv);
Bram Moolenaar0d660222005-01-07 21:51:51 +00009694}
9695
Bram Moolenaar342337a2005-07-21 21:11:17 +00009696static 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 +00009697
9698/*
9699 * Get line or list of lines from buffer "buf" into "rettv".
Bram Moolenaar342337a2005-07-21 21:11:17 +00009700 * Return a range (from start to end) of lines in rettv from the specified
9701 * buffer.
9702 * If 'retlist' is TRUE, then the lines are returned as a Vim List.
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009703 */
9704 static void
Bram Moolenaar342337a2005-07-21 21:11:17 +00009705get_buffer_lines(buf, start, end, retlist, rettv)
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009706 buf_T *buf;
9707 linenr_T start;
9708 linenr_T end;
Bram Moolenaar342337a2005-07-21 21:11:17 +00009709 int retlist;
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009710 typval_T *rettv;
9711{
9712 char_u *p;
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009713
Bram Moolenaar342337a2005-07-21 21:11:17 +00009714 if (retlist)
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009715 {
Bram Moolenaareddf53b2006-02-27 00:11:10 +00009716 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar342337a2005-07-21 21:11:17 +00009717 return;
Bram Moolenaar342337a2005-07-21 21:11:17 +00009718 }
9719 else
9720 rettv->vval.v_number = 0;
9721
9722 if (buf == NULL || buf->b_ml.ml_mfp == NULL || start < 0)
9723 return;
9724
9725 if (!retlist)
9726 {
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009727 if (start >= 1 && start <= buf->b_ml.ml_line_count)
9728 p = ml_get_buf(buf, start, FALSE);
9729 else
9730 p = (char_u *)"";
9731
9732 rettv->v_type = VAR_STRING;
9733 rettv->vval.v_string = vim_strsave(p);
9734 }
9735 else
9736 {
9737 if (end < start)
Bram Moolenaar342337a2005-07-21 21:11:17 +00009738 return;
9739
9740 if (start < 1)
9741 start = 1;
9742 if (end > buf->b_ml.ml_line_count)
9743 end = buf->b_ml.ml_line_count;
9744 while (start <= end)
Bram Moolenaareddf53b2006-02-27 00:11:10 +00009745 if (list_append_string(rettv->vval.v_list,
9746 ml_get_buf(buf, start++, FALSE), -1) == FAIL)
Bram Moolenaar342337a2005-07-21 21:11:17 +00009747 break;
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009748 }
9749}
9750
9751/*
9752 * "getbufline()" function
9753 */
9754 static void
9755f_getbufline(argvars, rettv)
9756 typval_T *argvars;
9757 typval_T *rettv;
9758{
9759 linenr_T lnum;
9760 linenr_T end;
9761 buf_T *buf;
9762
9763 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
9764 ++emsg_off;
9765 buf = get_buf_tv(&argvars[0]);
9766 --emsg_off;
9767
Bram Moolenaar661b1822005-07-28 22:36:45 +00009768 lnum = get_tv_lnum_buf(&argvars[1], buf);
Bram Moolenaar342337a2005-07-21 21:11:17 +00009769 if (argvars[2].v_type == VAR_UNKNOWN)
9770 end = lnum;
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009771 else
Bram Moolenaar661b1822005-07-28 22:36:45 +00009772 end = get_tv_lnum_buf(&argvars[2], buf);
9773
Bram Moolenaar342337a2005-07-21 21:11:17 +00009774 get_buffer_lines(buf, lnum, end, TRUE, rettv);
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009775}
9776
Bram Moolenaar0d660222005-01-07 21:51:51 +00009777/*
9778 * "getbufvar()" function
9779 */
9780 static void
9781f_getbufvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009782 typval_T *argvars;
9783 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009784{
9785 buf_T *buf;
9786 buf_T *save_curbuf;
9787 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +00009788 dictitem_T *v;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009789
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009790 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
9791 varname = get_tv_string_chk(&argvars[1]);
Bram Moolenaar0d660222005-01-07 21:51:51 +00009792 ++emsg_off;
9793 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar0d660222005-01-07 21:51:51 +00009794
9795 rettv->v_type = VAR_STRING;
9796 rettv->vval.v_string = NULL;
9797
9798 if (buf != NULL && varname != NULL)
9799 {
9800 if (*varname == '&') /* buffer-local-option */
9801 {
9802 /* set curbuf to be our buf, temporarily */
9803 save_curbuf = curbuf;
9804 curbuf = buf;
9805
9806 get_option_tv(&varname, rettv, TRUE);
9807
9808 /* restore previous notion of curbuf */
9809 curbuf = save_curbuf;
9810 }
9811 else
9812 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009813 if (*varname == NUL)
9814 /* let getbufvar({nr}, "") return the "b:" dictionary. The
9815 * scope prefix before the NUL byte is required by
9816 * find_var_in_ht(). */
9817 varname = (char_u *)"b:" + 2;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009818 /* look up the variable */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00009819 v = find_var_in_ht(&buf->b_vars.dv_hashtab, varname, FALSE);
Bram Moolenaar0d660222005-01-07 21:51:51 +00009820 if (v != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +00009821 copy_tv(&v->di_tv, rettv);
Bram Moolenaar0d660222005-01-07 21:51:51 +00009822 }
9823 }
9824
9825 --emsg_off;
9826}
9827
9828/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009829 * "getchar()" function
9830 */
9831 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009832f_getchar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009833 typval_T *argvars;
9834 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009835{
9836 varnumber_T n;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009837 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009838
Bram Moolenaar4015b2c2006-06-22 19:01:34 +00009839 /* Position the cursor. Needed after a message that ends in a space. */
9840 windgoto(msg_row, msg_col);
9841
Bram Moolenaar071d4272004-06-13 20:20:40 +00009842 ++no_mapping;
9843 ++allow_keys;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009844 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009845 /* getchar(): blocking wait. */
9846 n = safe_vgetc();
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009847 else if (get_tv_number_chk(&argvars[0], &error) == 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009848 /* getchar(1): only check if char avail */
9849 n = vpeekc();
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009850 else if (error || vpeekc() == NUL)
9851 /* illegal argument or getchar(0) and no char avail: return zero */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009852 n = 0;
9853 else
9854 /* getchar(0) and char avail: return char */
9855 n = safe_vgetc();
9856 --no_mapping;
9857 --allow_keys;
9858
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009859 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009860 if (IS_SPECIAL(n) || mod_mask != 0)
9861 {
9862 char_u temp[10]; /* modifier: 3, mbyte-char: 6, NUL: 1 */
9863 int i = 0;
9864
9865 /* Turn a special key into three bytes, plus modifier. */
9866 if (mod_mask != 0)
9867 {
9868 temp[i++] = K_SPECIAL;
9869 temp[i++] = KS_MODIFIER;
9870 temp[i++] = mod_mask;
9871 }
9872 if (IS_SPECIAL(n))
9873 {
9874 temp[i++] = K_SPECIAL;
9875 temp[i++] = K_SECOND(n);
9876 temp[i++] = K_THIRD(n);
9877 }
9878#ifdef FEAT_MBYTE
9879 else if (has_mbyte)
9880 i += (*mb_char2bytes)(n, temp + i);
9881#endif
9882 else
9883 temp[i++] = n;
9884 temp[i++] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009885 rettv->v_type = VAR_STRING;
9886 rettv->vval.v_string = vim_strsave(temp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009887 }
9888}
9889
9890/*
9891 * "getcharmod()" function
9892 */
9893/*ARGSUSED*/
9894 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009895f_getcharmod(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009896 typval_T *argvars;
9897 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009898{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009899 rettv->vval.v_number = mod_mask;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009900}
9901
9902/*
9903 * "getcmdline()" function
9904 */
9905/*ARGSUSED*/
9906 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009907f_getcmdline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009908 typval_T *argvars;
9909 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009910{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009911 rettv->v_type = VAR_STRING;
9912 rettv->vval.v_string = get_cmdline_str();
Bram Moolenaar071d4272004-06-13 20:20:40 +00009913}
9914
9915/*
9916 * "getcmdpos()" function
9917 */
9918/*ARGSUSED*/
9919 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009920f_getcmdpos(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009921 typval_T *argvars;
9922 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009923{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009924 rettv->vval.v_number = get_cmdline_pos() + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009925}
9926
9927/*
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +00009928 * "getcmdtype()" function
9929 */
9930/*ARGSUSED*/
9931 static void
9932f_getcmdtype(argvars, rettv)
9933 typval_T *argvars;
9934 typval_T *rettv;
9935{
9936 rettv->v_type = VAR_STRING;
9937 rettv->vval.v_string = alloc(2);
9938 if (rettv->vval.v_string != NULL)
9939 {
9940 rettv->vval.v_string[0] = get_cmdline_type();
9941 rettv->vval.v_string[1] = NUL;
9942 }
9943}
9944
9945/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009946 * "getcwd()" function
9947 */
9948/*ARGSUSED*/
9949 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009950f_getcwd(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009951 typval_T *argvars;
9952 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009953{
9954 char_u cwd[MAXPATHL];
9955
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009956 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009957 if (mch_dirname(cwd, MAXPATHL) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009958 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009959 else
9960 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009961 rettv->vval.v_string = vim_strsave(cwd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009962#ifdef BACKSLASH_IN_FILENAME
Bram Moolenaar342337a2005-07-21 21:11:17 +00009963 if (rettv->vval.v_string != NULL)
9964 slash_adjust(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009965#endif
9966 }
9967}
9968
9969/*
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009970 * "getfontname()" function
9971 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00009972/*ARGSUSED*/
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009973 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009974f_getfontname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009975 typval_T *argvars;
9976 typval_T *rettv;
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009977{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009978 rettv->v_type = VAR_STRING;
9979 rettv->vval.v_string = NULL;
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009980#ifdef FEAT_GUI
9981 if (gui.in_use)
9982 {
9983 GuiFont font;
9984 char_u *name = NULL;
9985
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009986 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009987 {
9988 /* Get the "Normal" font. Either the name saved by
9989 * hl_set_font_name() or from the font ID. */
9990 font = gui.norm_font;
9991 name = hl_get_font_name();
9992 }
9993 else
9994 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009995 name = get_tv_string(&argvars[0]);
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009996 if (STRCMP(name, "*") == 0) /* don't use font dialog */
9997 return;
9998 font = gui_mch_get_font(name, FALSE);
9999 if (font == NOFONT)
10000 return; /* Invalid font name, return empty string. */
10001 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010002 rettv->vval.v_string = gui_mch_get_fontname(font, name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010003 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +000010004 gui_mch_free_font(font);
10005 }
10006#endif
10007}
10008
10009/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000010010 * "getfperm({fname})" function
10011 */
10012 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010013f_getfperm(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010014 typval_T *argvars;
10015 typval_T *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000010016{
10017 char_u *fname;
10018 struct stat st;
10019 char_u *perm = NULL;
10020 char_u flags[] = "rwx";
10021 int i;
10022
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010023 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000010024
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010025 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000010026 if (mch_stat((char *)fname, &st) >= 0)
10027 {
10028 perm = vim_strsave((char_u *)"---------");
10029 if (perm != NULL)
10030 {
10031 for (i = 0; i < 9; i++)
10032 {
10033 if (st.st_mode & (1 << (8 - i)))
10034 perm[i] = flags[i % 3];
10035 }
10036 }
10037 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010038 rettv->vval.v_string = perm;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000010039}
10040
10041/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010042 * "getfsize({fname})" function
10043 */
10044 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010045f_getfsize(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010046 typval_T *argvars;
10047 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010048{
10049 char_u *fname;
10050 struct stat st;
10051
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010052 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010053
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010054 rettv->v_type = VAR_NUMBER;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010055
10056 if (mch_stat((char *)fname, &st) >= 0)
10057 {
10058 if (mch_isdir(fname))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010059 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010060 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010061 rettv->vval.v_number = (varnumber_T)st.st_size;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010062 }
10063 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010064 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010065}
10066
10067/*
10068 * "getftime({fname})" function
10069 */
10070 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010071f_getftime(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010072 typval_T *argvars;
10073 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010074{
10075 char_u *fname;
10076 struct stat st;
10077
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010078 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010079
10080 if (mch_stat((char *)fname, &st) >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010081 rettv->vval.v_number = (varnumber_T)st.st_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010082 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010083 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010084}
10085
10086/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000010087 * "getftype({fname})" function
10088 */
10089 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010090f_getftype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010091 typval_T *argvars;
10092 typval_T *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000010093{
10094 char_u *fname;
10095 struct stat st;
10096 char_u *type = NULL;
10097 char *t;
10098
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010099 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000010100
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010101 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000010102 if (mch_lstat((char *)fname, &st) >= 0)
10103 {
10104#ifdef S_ISREG
10105 if (S_ISREG(st.st_mode))
10106 t = "file";
10107 else if (S_ISDIR(st.st_mode))
10108 t = "dir";
10109# ifdef S_ISLNK
10110 else if (S_ISLNK(st.st_mode))
10111 t = "link";
10112# endif
10113# ifdef S_ISBLK
10114 else if (S_ISBLK(st.st_mode))
10115 t = "bdev";
10116# endif
10117# ifdef S_ISCHR
10118 else if (S_ISCHR(st.st_mode))
10119 t = "cdev";
10120# endif
10121# ifdef S_ISFIFO
10122 else if (S_ISFIFO(st.st_mode))
10123 t = "fifo";
10124# endif
10125# ifdef S_ISSOCK
10126 else if (S_ISSOCK(st.st_mode))
10127 t = "fifo";
10128# endif
10129 else
10130 t = "other";
10131#else
10132# ifdef S_IFMT
10133 switch (st.st_mode & S_IFMT)
10134 {
10135 case S_IFREG: t = "file"; break;
10136 case S_IFDIR: t = "dir"; break;
10137# ifdef S_IFLNK
10138 case S_IFLNK: t = "link"; break;
10139# endif
10140# ifdef S_IFBLK
10141 case S_IFBLK: t = "bdev"; break;
10142# endif
10143# ifdef S_IFCHR
10144 case S_IFCHR: t = "cdev"; break;
10145# endif
10146# ifdef S_IFIFO
10147 case S_IFIFO: t = "fifo"; break;
10148# endif
10149# ifdef S_IFSOCK
10150 case S_IFSOCK: t = "socket"; break;
10151# endif
10152 default: t = "other";
10153 }
10154# else
10155 if (mch_isdir(fname))
10156 t = "dir";
10157 else
10158 t = "file";
10159# endif
10160#endif
10161 type = vim_strsave((char_u *)t);
10162 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010163 rettv->vval.v_string = type;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000010164}
10165
10166/*
Bram Moolenaar80fc0432005-07-20 22:06:07 +000010167 * "getline(lnum, [end])" function
Bram Moolenaar0d660222005-01-07 21:51:51 +000010168 */
10169 static void
10170f_getline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010171 typval_T *argvars;
10172 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010173{
10174 linenr_T lnum;
10175 linenr_T end;
Bram Moolenaar342337a2005-07-21 21:11:17 +000010176 int retlist;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010177
10178 lnum = get_tv_lnum(argvars);
Bram Moolenaar80fc0432005-07-20 22:06:07 +000010179 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar342337a2005-07-21 21:11:17 +000010180 {
Bram Moolenaar80fc0432005-07-20 22:06:07 +000010181 end = 0;
Bram Moolenaar342337a2005-07-21 21:11:17 +000010182 retlist = FALSE;
10183 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000010184 else
Bram Moolenaar342337a2005-07-21 21:11:17 +000010185 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000010186 end = get_tv_lnum(&argvars[1]);
Bram Moolenaar342337a2005-07-21 21:11:17 +000010187 retlist = TRUE;
10188 }
Bram Moolenaar80fc0432005-07-20 22:06:07 +000010189
Bram Moolenaar342337a2005-07-21 21:11:17 +000010190 get_buffer_lines(curbuf, lnum, end, retlist, rettv);
Bram Moolenaar0d660222005-01-07 21:51:51 +000010191}
10192
10193/*
Bram Moolenaara5525202006-03-02 22:52:09 +000010194 * "getpos(string)" function
10195 */
10196 static void
10197f_getpos(argvars, rettv)
10198 typval_T *argvars;
10199 typval_T *rettv;
10200{
10201 pos_T *fp;
10202 list_T *l;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000010203 int fnum = -1;
Bram Moolenaara5525202006-03-02 22:52:09 +000010204
10205 if (rettv_list_alloc(rettv) == OK)
10206 {
10207 l = rettv->vval.v_list;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000010208 fp = var2fpos(&argvars[0], TRUE, &fnum);
10209 if (fnum != -1)
10210 list_append_number(l, (varnumber_T)fnum);
10211 else
10212 list_append_number(l, (varnumber_T)0);
Bram Moolenaara5525202006-03-02 22:52:09 +000010213 list_append_number(l, (fp != NULL) ? (varnumber_T)fp->lnum
10214 : (varnumber_T)0);
10215 list_append_number(l, (fp != NULL) ? (varnumber_T)fp->col + 1
10216 : (varnumber_T)0);
10217 list_append_number(l,
10218#ifdef FEAT_VIRTUALEDIT
10219 (fp != NULL) ? (varnumber_T)fp->coladd :
10220#endif
10221 (varnumber_T)0);
10222 }
10223 else
10224 rettv->vval.v_number = FALSE;
10225}
10226
10227/*
Bram Moolenaar280f1262006-01-30 00:14:18 +000010228 * "getqflist()" and "getloclist()" functions
Bram Moolenaar2641f772005-03-25 21:58:17 +000010229 */
Bram Moolenaar280f1262006-01-30 00:14:18 +000010230/*ARGSUSED*/
Bram Moolenaar2641f772005-03-25 21:58:17 +000010231 static void
Bram Moolenaar280f1262006-01-30 00:14:18 +000010232f_getqflist(argvars, rettv)
10233 typval_T *argvars;
Bram Moolenaar2641f772005-03-25 21:58:17 +000010234 typval_T *rettv;
10235{
10236#ifdef FEAT_QUICKFIX
Bram Moolenaar280f1262006-01-30 00:14:18 +000010237 win_T *wp;
Bram Moolenaar2641f772005-03-25 21:58:17 +000010238#endif
10239
10240 rettv->vval.v_number = FALSE;
10241#ifdef FEAT_QUICKFIX
Bram Moolenaareddf53b2006-02-27 00:11:10 +000010242 if (rettv_list_alloc(rettv) == OK)
Bram Moolenaar2641f772005-03-25 21:58:17 +000010243 {
Bram Moolenaar280f1262006-01-30 00:14:18 +000010244 wp = NULL;
10245 if (argvars[0].v_type != VAR_UNKNOWN) /* getloclist() */
10246 {
Bram Moolenaar99ebf042006-04-15 20:28:54 +000010247 wp = find_win_by_nr(&argvars[0], NULL);
Bram Moolenaar280f1262006-01-30 00:14:18 +000010248 if (wp == NULL)
10249 return;
10250 }
10251
Bram Moolenaareddf53b2006-02-27 00:11:10 +000010252 (void)get_errorlist(wp, rettv->vval.v_list);
Bram Moolenaar2641f772005-03-25 21:58:17 +000010253 }
10254#endif
10255}
10256
10257/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010258 * "getreg()" function
10259 */
10260 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010261f_getreg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010262 typval_T *argvars;
10263 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010264{
10265 char_u *strregname;
10266 int regname;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000010267 int arg2 = FALSE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010268 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010269
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010270 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000010271 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010272 strregname = get_tv_string_chk(&argvars[0]);
10273 error = strregname == NULL;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000010274 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010275 arg2 = get_tv_number_chk(&argvars[1], &error);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000010276 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010277 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000010278 strregname = vimvars[VV_REG].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010279 regname = (strregname == NULL ? '"' : *strregname);
10280 if (regname == 0)
10281 regname = '"';
10282
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010283 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010284 rettv->vval.v_string = error ? NULL :
10285 get_reg_contents(regname, TRUE, arg2);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010286}
10287
10288/*
10289 * "getregtype()" function
10290 */
10291 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010292f_getregtype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010293 typval_T *argvars;
10294 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010295{
10296 char_u *strregname;
10297 int regname;
10298 char_u buf[NUMBUFLEN + 2];
10299 long reglen = 0;
10300
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010301 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010302 {
10303 strregname = get_tv_string_chk(&argvars[0]);
10304 if (strregname == NULL) /* type error; errmsg already given */
10305 {
10306 rettv->v_type = VAR_STRING;
10307 rettv->vval.v_string = NULL;
10308 return;
10309 }
10310 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010311 else
10312 /* Default to v:register */
Bram Moolenaare9a41262005-01-15 22:18:47 +000010313 strregname = vimvars[VV_REG].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010314
10315 regname = (strregname == NULL ? '"' : *strregname);
10316 if (regname == 0)
10317 regname = '"';
10318
10319 buf[0] = NUL;
10320 buf[1] = NUL;
10321 switch (get_reg_type(regname, &reglen))
10322 {
10323 case MLINE: buf[0] = 'V'; break;
10324 case MCHAR: buf[0] = 'v'; break;
10325#ifdef FEAT_VISUAL
10326 case MBLOCK:
10327 buf[0] = Ctrl_V;
10328 sprintf((char *)buf + 1, "%ld", reglen + 1);
10329 break;
10330#endif
10331 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010332 rettv->v_type = VAR_STRING;
10333 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010334}
10335
10336/*
Bram Moolenaar99ebf042006-04-15 20:28:54 +000010337 * "gettabwinvar()" function
10338 */
10339 static void
10340f_gettabwinvar(argvars, rettv)
10341 typval_T *argvars;
10342 typval_T *rettv;
10343{
10344 getwinvar(argvars, rettv, 1);
10345}
10346
10347/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010348 * "getwinposx()" function
10349 */
10350/*ARGSUSED*/
10351 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010352f_getwinposx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010353 typval_T *argvars;
10354 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010355{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010356 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010357#ifdef FEAT_GUI
10358 if (gui.in_use)
10359 {
10360 int x, y;
10361
10362 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010363 rettv->vval.v_number = x;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010364 }
10365#endif
10366}
10367
10368/*
10369 * "getwinposy()" function
10370 */
10371/*ARGSUSED*/
10372 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010373f_getwinposy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010374 typval_T *argvars;
10375 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010376{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010377 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010378#ifdef FEAT_GUI
10379 if (gui.in_use)
10380 {
10381 int x, y;
10382
10383 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010384 rettv->vval.v_number = y;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010385 }
10386#endif
10387}
10388
Bram Moolenaar99ebf042006-04-15 20:28:54 +000010389/*
10390 * Find window specifed by "vp" in tabpage "tp".
10391 */
Bram Moolenaara40058a2005-07-11 22:42:07 +000010392 static win_T *
Bram Moolenaar99ebf042006-04-15 20:28:54 +000010393find_win_by_nr(vp, tp)
Bram Moolenaara40058a2005-07-11 22:42:07 +000010394 typval_T *vp;
Bram Moolenaar99ebf042006-04-15 20:28:54 +000010395 tabpage_T *tp; /* NULL for current tab page */
Bram Moolenaara40058a2005-07-11 22:42:07 +000010396{
10397#ifdef FEAT_WINDOWS
10398 win_T *wp;
10399#endif
10400 int nr;
10401
10402 nr = get_tv_number_chk(vp, NULL);
10403
10404#ifdef FEAT_WINDOWS
10405 if (nr < 0)
10406 return NULL;
10407 if (nr == 0)
10408 return curwin;
10409
Bram Moolenaar99ebf042006-04-15 20:28:54 +000010410 for (wp = (tp == NULL || tp == curtab) ? firstwin : tp->tp_firstwin;
10411 wp != NULL; wp = wp->w_next)
Bram Moolenaara40058a2005-07-11 22:42:07 +000010412 if (--nr <= 0)
10413 break;
10414 return wp;
10415#else
10416 if (nr == 0 || nr == 1)
10417 return curwin;
10418 return NULL;
10419#endif
10420}
10421
Bram Moolenaar071d4272004-06-13 20:20:40 +000010422/*
10423 * "getwinvar()" function
10424 */
10425 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010426f_getwinvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010427 typval_T *argvars;
10428 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010429{
Bram Moolenaar99ebf042006-04-15 20:28:54 +000010430 getwinvar(argvars, rettv, 0);
10431}
10432
10433/*
10434 * getwinvar() and gettabwinvar()
10435 */
10436 static void
10437getwinvar(argvars, rettv, off)
10438 typval_T *argvars;
10439 typval_T *rettv;
10440 int off; /* 1 for gettabwinvar() */
10441{
Bram Moolenaar071d4272004-06-13 20:20:40 +000010442 win_T *win, *oldcurwin;
10443 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000010444 dictitem_T *v;
Bram Moolenaar99ebf042006-04-15 20:28:54 +000010445 tabpage_T *tp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010446
Bram Moolenaar99ebf042006-04-15 20:28:54 +000010447#ifdef FEAT_WINDOWS
10448 if (off == 1)
10449 tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL));
10450 else
10451 tp = curtab;
10452#endif
10453 win = find_win_by_nr(&argvars[off], tp);
10454 varname = get_tv_string_chk(&argvars[off + 1]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010455 ++emsg_off;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010456
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010457 rettv->v_type = VAR_STRING;
10458 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010459
10460 if (win != NULL && varname != NULL)
10461 {
10462 if (*varname == '&') /* window-local-option */
10463 {
Bram Moolenaarc0761132005-03-18 20:30:32 +000010464 /* Set curwin to be our win, temporarily. Also set curbuf, so
10465 * that we can get buffer-local options. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010466 oldcurwin = curwin;
10467 curwin = win;
Bram Moolenaarc0761132005-03-18 20:30:32 +000010468 curbuf = win->w_buffer;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010469
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010470 get_option_tv(&varname, rettv, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010471
10472 /* restore previous notion of curwin */
10473 curwin = oldcurwin;
Bram Moolenaarc0761132005-03-18 20:30:32 +000010474 curbuf = curwin->w_buffer;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010475 }
10476 else
10477 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010478 if (*varname == NUL)
10479 /* let getwinvar({nr}, "") return the "w:" dictionary. The
10480 * scope prefix before the NUL byte is required by
10481 * find_var_in_ht(). */
10482 varname = (char_u *)"w:" + 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010483 /* look up the variable */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000010484 v = find_var_in_ht(&win->w_vars.dv_hashtab, varname, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010485 if (v != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000010486 copy_tv(&v->di_tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010487 }
10488 }
10489
10490 --emsg_off;
10491}
10492
10493/*
10494 * "glob()" function
10495 */
10496 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010497f_glob(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{
10501 expand_T xpc;
10502
10503 ExpandInit(&xpc);
10504 xpc.xp_context = EXPAND_FILES;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010505 rettv->v_type = VAR_STRING;
10506 rettv->vval.v_string = ExpandOne(&xpc, get_tv_string(&argvars[0]),
Bram Moolenaar071d4272004-06-13 20:20:40 +000010507 NULL, WILD_USE_NL|WILD_SILENT, WILD_ALL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010508}
10509
10510/*
10511 * "globpath()" function
10512 */
10513 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010514f_globpath(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010515 typval_T *argvars;
10516 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010517{
10518 char_u buf1[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010519 char_u *file = get_tv_string_buf_chk(&argvars[1], buf1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010520
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010521 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010522 if (file == NULL)
10523 rettv->vval.v_string = NULL;
10524 else
10525 rettv->vval.v_string = globpath(get_tv_string(&argvars[0]), file);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010526}
10527
10528/*
10529 * "has()" function
10530 */
10531 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010532f_has(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010533 typval_T *argvars;
10534 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010535{
10536 int i;
10537 char_u *name;
10538 int n = FALSE;
10539 static char *(has_list[]) =
10540 {
10541#ifdef AMIGA
10542 "amiga",
10543# ifdef FEAT_ARP
10544 "arp",
10545# endif
10546#endif
10547#ifdef __BEOS__
10548 "beos",
10549#endif
10550#ifdef MSDOS
10551# ifdef DJGPP
10552 "dos32",
10553# else
10554 "dos16",
10555# endif
10556#endif
Bram Moolenaar241a8aa2005-12-06 20:04:44 +000010557#ifdef MACOS
Bram Moolenaar071d4272004-06-13 20:20:40 +000010558 "mac",
10559#endif
10560#if defined(MACOS_X_UNIX)
10561 "macunix",
10562#endif
10563#ifdef OS2
10564 "os2",
10565#endif
10566#ifdef __QNX__
10567 "qnx",
10568#endif
10569#ifdef RISCOS
10570 "riscos",
10571#endif
10572#ifdef UNIX
10573 "unix",
10574#endif
10575#ifdef VMS
10576 "vms",
10577#endif
10578#ifdef WIN16
10579 "win16",
10580#endif
10581#ifdef WIN32
10582 "win32",
10583#endif
10584#if defined(UNIX) && (defined(__CYGWIN32__) || defined(__CYGWIN__))
10585 "win32unix",
10586#endif
10587#ifdef WIN64
10588 "win64",
10589#endif
10590#ifdef EBCDIC
10591 "ebcdic",
10592#endif
10593#ifndef CASE_INSENSITIVE_FILENAME
10594 "fname_case",
10595#endif
10596#ifdef FEAT_ARABIC
10597 "arabic",
10598#endif
10599#ifdef FEAT_AUTOCMD
10600 "autocmd",
10601#endif
10602#ifdef FEAT_BEVAL
10603 "balloon_eval",
Bram Moolenaar342337a2005-07-21 21:11:17 +000010604# ifndef FEAT_GUI_W32 /* other GUIs always have multiline balloons */
10605 "balloon_multiline",
10606# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010607#endif
10608#if defined(SOME_BUILTIN_TCAPS) || defined(ALL_BUILTIN_TCAPS)
10609 "builtin_terms",
10610# ifdef ALL_BUILTIN_TCAPS
10611 "all_builtin_terms",
10612# endif
10613#endif
10614#ifdef FEAT_BYTEOFF
10615 "byte_offset",
10616#endif
10617#ifdef FEAT_CINDENT
10618 "cindent",
10619#endif
10620#ifdef FEAT_CLIENTSERVER
10621 "clientserver",
10622#endif
10623#ifdef FEAT_CLIPBOARD
10624 "clipboard",
10625#endif
10626#ifdef FEAT_CMDL_COMPL
10627 "cmdline_compl",
10628#endif
10629#ifdef FEAT_CMDHIST
10630 "cmdline_hist",
10631#endif
10632#ifdef FEAT_COMMENTS
10633 "comments",
10634#endif
10635#ifdef FEAT_CRYPT
10636 "cryptv",
10637#endif
10638#ifdef FEAT_CSCOPE
10639 "cscope",
10640#endif
Bram Moolenaarac6e65f2005-08-29 22:25:38 +000010641#ifdef CURSOR_SHAPE
10642 "cursorshape",
10643#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010644#ifdef DEBUG
10645 "debug",
10646#endif
10647#ifdef FEAT_CON_DIALOG
10648 "dialog_con",
10649#endif
10650#ifdef FEAT_GUI_DIALOG
10651 "dialog_gui",
10652#endif
10653#ifdef FEAT_DIFF
10654 "diff",
10655#endif
10656#ifdef FEAT_DIGRAPHS
10657 "digraphs",
10658#endif
10659#ifdef FEAT_DND
10660 "dnd",
10661#endif
10662#ifdef FEAT_EMACS_TAGS
10663 "emacs_tags",
10664#endif
10665 "eval", /* always present, of course! */
10666#ifdef FEAT_EX_EXTRA
10667 "ex_extra",
10668#endif
10669#ifdef FEAT_SEARCH_EXTRA
10670 "extra_search",
10671#endif
10672#ifdef FEAT_FKMAP
10673 "farsi",
10674#endif
10675#ifdef FEAT_SEARCHPATH
10676 "file_in_path",
10677#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000010678#if defined(UNIX) && !defined(USE_SYSTEM)
10679 "filterpipe",
10680#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010681#ifdef FEAT_FIND_ID
10682 "find_in_path",
10683#endif
10684#ifdef FEAT_FOLDING
10685 "folding",
10686#endif
10687#ifdef FEAT_FOOTER
10688 "footer",
10689#endif
10690#if !defined(USE_SYSTEM) && defined(UNIX)
10691 "fork",
10692#endif
10693#ifdef FEAT_GETTEXT
10694 "gettext",
10695#endif
10696#ifdef FEAT_GUI
10697 "gui",
10698#endif
10699#ifdef FEAT_GUI_ATHENA
10700# ifdef FEAT_GUI_NEXTAW
10701 "gui_neXtaw",
10702# else
10703 "gui_athena",
10704# endif
10705#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010706#ifdef FEAT_GUI_GTK
10707 "gui_gtk",
10708# ifdef HAVE_GTK2
10709 "gui_gtk2",
10710# endif
10711#endif
10712#ifdef FEAT_GUI_MAC
10713 "gui_mac",
10714#endif
10715#ifdef FEAT_GUI_MOTIF
10716 "gui_motif",
10717#endif
10718#ifdef FEAT_GUI_PHOTON
10719 "gui_photon",
10720#endif
10721#ifdef FEAT_GUI_W16
10722 "gui_win16",
10723#endif
10724#ifdef FEAT_GUI_W32
10725 "gui_win32",
10726#endif
10727#ifdef FEAT_HANGULIN
10728 "hangul_input",
10729#endif
10730#if defined(HAVE_ICONV_H) && defined(USE_ICONV)
10731 "iconv",
10732#endif
10733#ifdef FEAT_INS_EXPAND
10734 "insert_expand",
10735#endif
10736#ifdef FEAT_JUMPLIST
10737 "jumplist",
10738#endif
10739#ifdef FEAT_KEYMAP
10740 "keymap",
10741#endif
10742#ifdef FEAT_LANGMAP
10743 "langmap",
10744#endif
10745#ifdef FEAT_LIBCALL
10746 "libcall",
10747#endif
10748#ifdef FEAT_LINEBREAK
10749 "linebreak",
10750#endif
10751#ifdef FEAT_LISP
10752 "lispindent",
10753#endif
10754#ifdef FEAT_LISTCMDS
10755 "listcmds",
10756#endif
10757#ifdef FEAT_LOCALMAP
10758 "localmap",
10759#endif
10760#ifdef FEAT_MENU
10761 "menu",
10762#endif
10763#ifdef FEAT_SESSION
10764 "mksession",
10765#endif
10766#ifdef FEAT_MODIFY_FNAME
10767 "modify_fname",
10768#endif
10769#ifdef FEAT_MOUSE
10770 "mouse",
10771#endif
10772#ifdef FEAT_MOUSESHAPE
10773 "mouseshape",
10774#endif
10775#if defined(UNIX) || defined(VMS)
10776# ifdef FEAT_MOUSE_DEC
10777 "mouse_dec",
10778# endif
10779# ifdef FEAT_MOUSE_GPM
10780 "mouse_gpm",
10781# endif
10782# ifdef FEAT_MOUSE_JSB
10783 "mouse_jsbterm",
10784# endif
10785# ifdef FEAT_MOUSE_NET
10786 "mouse_netterm",
10787# endif
10788# ifdef FEAT_MOUSE_PTERM
10789 "mouse_pterm",
10790# endif
10791# ifdef FEAT_MOUSE_XTERM
10792 "mouse_xterm",
10793# endif
10794#endif
10795#ifdef FEAT_MBYTE
10796 "multi_byte",
10797#endif
10798#ifdef FEAT_MBYTE_IME
10799 "multi_byte_ime",
10800#endif
10801#ifdef FEAT_MULTI_LANG
10802 "multi_lang",
10803#endif
Bram Moolenaar325b7a22004-07-05 15:58:32 +000010804#ifdef FEAT_MZSCHEME
Bram Moolenaar33570922005-01-25 22:26:29 +000010805#ifndef DYNAMIC_MZSCHEME
Bram Moolenaar325b7a22004-07-05 15:58:32 +000010806 "mzscheme",
10807#endif
Bram Moolenaar33570922005-01-25 22:26:29 +000010808#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010809#ifdef FEAT_OLE
10810 "ole",
10811#endif
10812#ifdef FEAT_OSFILETYPE
10813 "osfiletype",
10814#endif
10815#ifdef FEAT_PATH_EXTRA
10816 "path_extra",
10817#endif
10818#ifdef FEAT_PERL
10819#ifndef DYNAMIC_PERL
10820 "perl",
10821#endif
10822#endif
10823#ifdef FEAT_PYTHON
10824#ifndef DYNAMIC_PYTHON
10825 "python",
10826#endif
10827#endif
10828#ifdef FEAT_POSTSCRIPT
10829 "postscript",
10830#endif
10831#ifdef FEAT_PRINTER
10832 "printer",
10833#endif
Bram Moolenaar05159a02005-02-26 23:04:13 +000010834#ifdef FEAT_PROFILE
10835 "profile",
10836#endif
Bram Moolenaare580b0c2006-03-21 21:33:03 +000010837#ifdef FEAT_RELTIME
10838 "reltime",
10839#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010840#ifdef FEAT_QUICKFIX
10841 "quickfix",
10842#endif
10843#ifdef FEAT_RIGHTLEFT
10844 "rightleft",
10845#endif
10846#if defined(FEAT_RUBY) && !defined(DYNAMIC_RUBY)
10847 "ruby",
10848#endif
10849#ifdef FEAT_SCROLLBIND
10850 "scrollbind",
10851#endif
10852#ifdef FEAT_CMDL_INFO
10853 "showcmd",
10854 "cmdline_info",
10855#endif
10856#ifdef FEAT_SIGNS
10857 "signs",
10858#endif
10859#ifdef FEAT_SMARTINDENT
10860 "smartindent",
10861#endif
10862#ifdef FEAT_SNIFF
10863 "sniff",
10864#endif
10865#ifdef FEAT_STL_OPT
10866 "statusline",
10867#endif
10868#ifdef FEAT_SUN_WORKSHOP
10869 "sun_workshop",
10870#endif
10871#ifdef FEAT_NETBEANS_INTG
10872 "netbeans_intg",
10873#endif
Bram Moolenaar3c56a962006-03-12 22:19:04 +000010874#ifdef FEAT_SPELL
Bram Moolenaar0e4d8772005-06-07 21:12:49 +000010875 "spell",
10876#endif
10877#ifdef FEAT_SYN_HL
Bram Moolenaar071d4272004-06-13 20:20:40 +000010878 "syntax",
10879#endif
10880#if defined(USE_SYSTEM) || !defined(UNIX)
10881 "system",
10882#endif
10883#ifdef FEAT_TAG_BINS
10884 "tag_binary",
10885#endif
10886#ifdef FEAT_TAG_OLDSTATIC
10887 "tag_old_static",
10888#endif
10889#ifdef FEAT_TAG_ANYWHITE
10890 "tag_any_white",
10891#endif
10892#ifdef FEAT_TCL
10893# ifndef DYNAMIC_TCL
10894 "tcl",
10895# endif
10896#endif
10897#ifdef TERMINFO
10898 "terminfo",
10899#endif
10900#ifdef FEAT_TERMRESPONSE
10901 "termresponse",
10902#endif
10903#ifdef FEAT_TEXTOBJ
10904 "textobjects",
10905#endif
10906#ifdef HAVE_TGETENT
10907 "tgetent",
10908#endif
10909#ifdef FEAT_TITLE
10910 "title",
10911#endif
10912#ifdef FEAT_TOOLBAR
10913 "toolbar",
10914#endif
10915#ifdef FEAT_USR_CMDS
10916 "user-commands", /* was accidentally included in 5.4 */
10917 "user_commands",
10918#endif
10919#ifdef FEAT_VIMINFO
10920 "viminfo",
10921#endif
10922#ifdef FEAT_VERTSPLIT
10923 "vertsplit",
10924#endif
10925#ifdef FEAT_VIRTUALEDIT
10926 "virtualedit",
10927#endif
10928#ifdef FEAT_VISUAL
10929 "visual",
10930#endif
10931#ifdef FEAT_VISUALEXTRA
10932 "visualextra",
10933#endif
10934#ifdef FEAT_VREPLACE
10935 "vreplace",
10936#endif
10937#ifdef FEAT_WILDIGN
10938 "wildignore",
10939#endif
10940#ifdef FEAT_WILDMENU
10941 "wildmenu",
10942#endif
10943#ifdef FEAT_WINDOWS
10944 "windows",
10945#endif
10946#ifdef FEAT_WAK
10947 "winaltkeys",
10948#endif
10949#ifdef FEAT_WRITEBACKUP
10950 "writebackup",
10951#endif
10952#ifdef FEAT_XIM
10953 "xim",
10954#endif
10955#ifdef FEAT_XFONTSET
10956 "xfontset",
10957#endif
10958#ifdef USE_XSMP
10959 "xsmp",
10960#endif
10961#ifdef USE_XSMP_INTERACT
10962 "xsmp_interact",
10963#endif
10964#ifdef FEAT_XCLIPBOARD
10965 "xterm_clipboard",
10966#endif
10967#ifdef FEAT_XTERM_SAVE
10968 "xterm_save",
10969#endif
10970#if defined(UNIX) && defined(FEAT_X11)
10971 "X11",
10972#endif
10973 NULL
10974 };
10975
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010976 name = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010977 for (i = 0; has_list[i] != NULL; ++i)
10978 if (STRICMP(name, has_list[i]) == 0)
10979 {
10980 n = TRUE;
10981 break;
10982 }
10983
10984 if (n == FALSE)
10985 {
10986 if (STRNICMP(name, "patch", 5) == 0)
10987 n = has_patch(atoi((char *)name + 5));
10988 else if (STRICMP(name, "vim_starting") == 0)
10989 n = (starting != 0);
Bram Moolenaar342337a2005-07-21 21:11:17 +000010990#if defined(FEAT_BEVAL) && defined(FEAT_GUI_W32)
10991 else if (STRICMP(name, "balloon_multiline") == 0)
10992 n = multiline_balloon_available();
10993#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010994#ifdef DYNAMIC_TCL
10995 else if (STRICMP(name, "tcl") == 0)
10996 n = tcl_enabled(FALSE);
10997#endif
10998#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
10999 else if (STRICMP(name, "iconv") == 0)
11000 n = iconv_enabled(FALSE);
11001#endif
Bram Moolenaar33570922005-01-25 22:26:29 +000011002#ifdef DYNAMIC_MZSCHEME
11003 else if (STRICMP(name, "mzscheme") == 0)
11004 n = mzscheme_enabled(FALSE);
11005#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000011006#ifdef DYNAMIC_RUBY
11007 else if (STRICMP(name, "ruby") == 0)
11008 n = ruby_enabled(FALSE);
11009#endif
11010#ifdef DYNAMIC_PYTHON
11011 else if (STRICMP(name, "python") == 0)
11012 n = python_enabled(FALSE);
11013#endif
11014#ifdef DYNAMIC_PERL
11015 else if (STRICMP(name, "perl") == 0)
11016 n = perl_enabled(FALSE);
11017#endif
11018#ifdef FEAT_GUI
11019 else if (STRICMP(name, "gui_running") == 0)
11020 n = (gui.in_use || gui.starting);
11021# ifdef FEAT_GUI_W32
11022 else if (STRICMP(name, "gui_win32s") == 0)
11023 n = gui_is_win32s();
11024# endif
11025# ifdef FEAT_BROWSE
11026 else if (STRICMP(name, "browse") == 0)
11027 n = gui.in_use; /* gui_mch_browse() works when GUI is running */
11028# endif
11029#endif
11030#ifdef FEAT_SYN_HL
11031 else if (STRICMP(name, "syntax_items") == 0)
11032 n = syntax_present(curbuf);
11033#endif
11034#if defined(WIN3264)
11035 else if (STRICMP(name, "win95") == 0)
11036 n = mch_windows95();
11037#endif
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +000011038#ifdef FEAT_NETBEANS_INTG
11039 else if (STRICMP(name, "netbeans_enabled") == 0)
11040 n = usingNetbeans;
11041#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000011042 }
11043
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011044 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011045}
11046
11047/*
Bram Moolenaare9a41262005-01-15 22:18:47 +000011048 * "has_key()" function
11049 */
11050 static void
11051f_has_key(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011052 typval_T *argvars;
11053 typval_T *rettv;
Bram Moolenaare9a41262005-01-15 22:18:47 +000011054{
11055 rettv->vval.v_number = 0;
11056 if (argvars[0].v_type != VAR_DICT)
11057 {
11058 EMSG(_(e_dictreq));
11059 return;
11060 }
11061 if (argvars[0].vval.v_dict == NULL)
11062 return;
11063
11064 rettv->vval.v_number = dict_find(argvars[0].vval.v_dict,
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011065 get_tv_string(&argvars[1]), -1) != NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000011066}
11067
11068/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011069 * "hasmapto()" function
11070 */
11071 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011072f_hasmapto(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011073 typval_T *argvars;
11074 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011075{
11076 char_u *name;
11077 char_u *mode;
11078 char_u buf[NUMBUFLEN];
Bram Moolenaar2c932302006-03-18 21:42:09 +000011079 int abbr = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011080
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011081 name = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011082 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011083 mode = (char_u *)"nvo";
11084 else
Bram Moolenaar2c932302006-03-18 21:42:09 +000011085 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011086 mode = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar2c932302006-03-18 21:42:09 +000011087 if (argvars[2].v_type != VAR_UNKNOWN)
11088 abbr = get_tv_number(&argvars[2]);
11089 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011090
Bram Moolenaar2c932302006-03-18 21:42:09 +000011091 if (map_to_exists(name, mode, abbr))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011092 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011093 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011094 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011095}
11096
11097/*
11098 * "histadd()" function
11099 */
11100/*ARGSUSED*/
11101 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011102f_histadd(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011103 typval_T *argvars;
11104 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011105{
11106#ifdef FEAT_CMDHIST
11107 int histype;
11108 char_u *str;
11109 char_u buf[NUMBUFLEN];
11110#endif
11111
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011112 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011113 if (check_restricted() || check_secure())
11114 return;
11115#ifdef FEAT_CMDHIST
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011116 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
11117 histype = str != NULL ? get_histtype(str) : -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011118 if (histype >= 0)
11119 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011120 str = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011121 if (*str != NUL)
11122 {
11123 add_to_history(histype, str, FALSE, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011124 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011125 return;
11126 }
11127 }
11128#endif
11129}
11130
11131/*
11132 * "histdel()" function
11133 */
11134/*ARGSUSED*/
11135 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011136f_histdel(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011137 typval_T *argvars;
11138 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011139{
11140#ifdef FEAT_CMDHIST
11141 int n;
11142 char_u buf[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011143 char_u *str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011144
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011145 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
11146 if (str == NULL)
11147 n = 0;
11148 else if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011149 /* only one argument: clear entire history */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011150 n = clr_history(get_histtype(str));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011151 else if (argvars[1].v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011152 /* index given: remove that entry */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011153 n = del_history_idx(get_histtype(str),
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011154 (int)get_tv_number(&argvars[1]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000011155 else
11156 /* string given: remove all matching entries */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011157 n = del_history_entry(get_histtype(str),
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011158 get_tv_string_buf(&argvars[1], buf));
11159 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011160#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011161 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011162#endif
11163}
11164
11165/*
11166 * "histget()" function
11167 */
11168/*ARGSUSED*/
11169 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011170f_histget(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011171 typval_T *argvars;
11172 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011173{
11174#ifdef FEAT_CMDHIST
11175 int type;
11176 int idx;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011177 char_u *str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011178
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011179 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
11180 if (str == NULL)
11181 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011182 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011183 {
11184 type = get_histtype(str);
11185 if (argvars[1].v_type == VAR_UNKNOWN)
11186 idx = get_history_idx(type);
11187 else
11188 idx = (int)get_tv_number_chk(&argvars[1], NULL);
11189 /* -1 on type error */
11190 rettv->vval.v_string = vim_strsave(get_history_entry(type, idx));
11191 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011192#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011193 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011194#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011195 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011196}
11197
11198/*
11199 * "histnr()" function
11200 */
11201/*ARGSUSED*/
11202 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011203f_histnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011204 typval_T *argvars;
11205 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011206{
11207 int i;
11208
11209#ifdef FEAT_CMDHIST
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011210 char_u *history = get_tv_string_chk(&argvars[0]);
11211
11212 i = history == NULL ? HIST_CMD - 1 : get_histtype(history);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011213 if (i >= HIST_CMD && i < HIST_COUNT)
11214 i = get_history_idx(i);
11215 else
11216#endif
11217 i = -1;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011218 rettv->vval.v_number = i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011219}
11220
11221/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011222 * "highlightID(name)" function
11223 */
11224 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011225f_hlID(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011226 typval_T *argvars;
11227 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011228{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011229 rettv->vval.v_number = syn_name2id(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000011230}
11231
11232/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011233 * "highlight_exists()" function
11234 */
11235 static void
11236f_hlexists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011237 typval_T *argvars;
11238 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011239{
11240 rettv->vval.v_number = highlight_exists(get_tv_string(&argvars[0]));
11241}
11242
11243/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011244 * "hostname()" function
11245 */
11246/*ARGSUSED*/
11247 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011248f_hostname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011249 typval_T *argvars;
11250 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011251{
11252 char_u hostname[256];
11253
11254 mch_get_host_name(hostname, 256);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011255 rettv->v_type = VAR_STRING;
11256 rettv->vval.v_string = vim_strsave(hostname);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011257}
11258
11259/*
11260 * iconv() function
11261 */
11262/*ARGSUSED*/
11263 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011264f_iconv(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011265 typval_T *argvars;
11266 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011267{
11268#ifdef FEAT_MBYTE
11269 char_u buf1[NUMBUFLEN];
11270 char_u buf2[NUMBUFLEN];
11271 char_u *from, *to, *str;
11272 vimconv_T vimconv;
11273#endif
11274
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011275 rettv->v_type = VAR_STRING;
11276 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011277
11278#ifdef FEAT_MBYTE
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011279 str = get_tv_string(&argvars[0]);
11280 from = enc_canonize(enc_skip(get_tv_string_buf(&argvars[1], buf1)));
11281 to = enc_canonize(enc_skip(get_tv_string_buf(&argvars[2], buf2)));
Bram Moolenaar071d4272004-06-13 20:20:40 +000011282 vimconv.vc_type = CONV_NONE;
11283 convert_setup(&vimconv, from, to);
11284
11285 /* If the encodings are equal, no conversion needed. */
11286 if (vimconv.vc_type == CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011287 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011288 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011289 rettv->vval.v_string = string_convert(&vimconv, str, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011290
11291 convert_setup(&vimconv, NULL, NULL);
11292 vim_free(from);
11293 vim_free(to);
11294#endif
11295}
11296
11297/*
11298 * "indent()" function
11299 */
11300 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011301f_indent(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011302 typval_T *argvars;
11303 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011304{
11305 linenr_T lnum;
11306
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011307 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011308 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011309 rettv->vval.v_number = get_indent_lnum(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011310 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011311 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011312}
11313
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011314/*
11315 * "index()" function
11316 */
11317 static void
11318f_index(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011319 typval_T *argvars;
11320 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011321{
Bram Moolenaar33570922005-01-25 22:26:29 +000011322 list_T *l;
11323 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011324 long idx = 0;
11325 int ic = FALSE;
11326
11327 rettv->vval.v_number = -1;
11328 if (argvars[0].v_type != VAR_LIST)
11329 {
11330 EMSG(_(e_listreq));
11331 return;
11332 }
11333 l = argvars[0].vval.v_list;
11334 if (l != NULL)
11335 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000011336 item = l->lv_first;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011337 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011338 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011339 int error = FALSE;
11340
Bram Moolenaar758711c2005-02-02 23:11:38 +000011341 /* Start at specified item. Use the cached index that list_find()
11342 * sets, so that a negative number also works. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011343 item = list_find(l, get_tv_number_chk(&argvars[2], &error));
Bram Moolenaar758711c2005-02-02 23:11:38 +000011344 idx = l->lv_idx;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011345 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011346 ic = get_tv_number_chk(&argvars[3], &error);
11347 if (error)
11348 item = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011349 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011350
Bram Moolenaar758711c2005-02-02 23:11:38 +000011351 for ( ; item != NULL; item = item->li_next, ++idx)
11352 if (tv_equal(&item->li_tv, &argvars[1], ic))
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011353 {
11354 rettv->vval.v_number = idx;
11355 break;
11356 }
11357 }
11358}
11359
Bram Moolenaar071d4272004-06-13 20:20:40 +000011360static int inputsecret_flag = 0;
11361
Bram Moolenaarecbaf552006-07-13 06:31:00 +000011362static void get_user_input __ARGS((typval_T *argvars, typval_T *rettv, int inputdialog));
11363
Bram Moolenaar071d4272004-06-13 20:20:40 +000011364/*
Bram Moolenaarecbaf552006-07-13 06:31:00 +000011365 * This function is used by f_input() and f_inputdialog() functions. The third
11366 * argument to f_input() specifies the type of completion to use at the
11367 * prompt. The third argument to f_inputdialog() specifies the value to return
11368 * when the user cancels the prompt.
Bram Moolenaar071d4272004-06-13 20:20:40 +000011369 */
11370 static void
Bram Moolenaarecbaf552006-07-13 06:31:00 +000011371get_user_input(argvars, rettv, inputdialog)
Bram Moolenaar33570922005-01-25 22:26:29 +000011372 typval_T *argvars;
11373 typval_T *rettv;
Bram Moolenaarecbaf552006-07-13 06:31:00 +000011374 int inputdialog;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011375{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011376 char_u *prompt = get_tv_string_chk(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011377 char_u *p = NULL;
11378 int c;
11379 char_u buf[NUMBUFLEN];
11380 int cmd_silent_save = cmd_silent;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011381 char_u *defstr = (char_u *)"";
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000011382 int xp_type = EXPAND_NOTHING;
11383 char_u *xp_arg = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011384
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011385 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011386
11387#ifdef NO_CONSOLE_INPUT
11388 /* While starting up, there is no place to enter text. */
11389 if (no_console_input())
11390 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011391 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011392 return;
11393 }
11394#endif
11395
11396 cmd_silent = FALSE; /* Want to see the prompt. */
11397 if (prompt != NULL)
11398 {
11399 /* Only the part of the message after the last NL is considered as
11400 * prompt for the command line */
11401 p = vim_strrchr(prompt, '\n');
11402 if (p == NULL)
11403 p = prompt;
11404 else
11405 {
11406 ++p;
11407 c = *p;
11408 *p = NUL;
11409 msg_start();
11410 msg_clr_eos();
11411 msg_puts_attr(prompt, echo_attr);
11412 msg_didout = FALSE;
11413 msg_starthere();
11414 *p = c;
11415 }
11416 cmdline_row = msg_row;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011417
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011418 if (argvars[1].v_type != VAR_UNKNOWN)
11419 {
11420 defstr = get_tv_string_buf_chk(&argvars[1], buf);
11421 if (defstr != NULL)
11422 stuffReadbuffSpec(defstr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011423
Bram Moolenaarecbaf552006-07-13 06:31:00 +000011424 if (!inputdialog && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar4463f292005-09-25 22:20:24 +000011425 {
11426 char_u *xp_name;
Bram Moolenaar86c9ee22006-05-13 11:33:27 +000011427 int xp_namelen;
Bram Moolenaar4463f292005-09-25 22:20:24 +000011428 long argt;
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000011429
Bram Moolenaar4463f292005-09-25 22:20:24 +000011430 rettv->vval.v_string = NULL;
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000011431
Bram Moolenaar4463f292005-09-25 22:20:24 +000011432 xp_name = get_tv_string_buf_chk(&argvars[2], buf);
11433 if (xp_name == NULL)
11434 return;
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000011435
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000011436 xp_namelen = (int)STRLEN(xp_name);
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000011437
Bram Moolenaar4463f292005-09-25 22:20:24 +000011438 if (parse_compl_arg(xp_name, xp_namelen, &xp_type, &argt,
11439 &xp_arg) == FAIL)
11440 return;
11441 }
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000011442 }
11443
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011444 if (defstr != NULL)
11445 rettv->vval.v_string =
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000011446 getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr,
11447 xp_type, xp_arg);
11448
11449 vim_free(xp_arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011450
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011451 /* since the user typed this, no need to wait for return */
11452 need_wait_return = FALSE;
11453 msg_didout = FALSE;
11454 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011455 cmd_silent = cmd_silent_save;
11456}
11457
11458/*
Bram Moolenaarecbaf552006-07-13 06:31:00 +000011459 * "input()" function
11460 * Also handles inputsecret() when inputsecret is set.
11461 */
11462 static void
11463f_input(argvars, rettv)
11464 typval_T *argvars;
11465 typval_T *rettv;
11466{
11467 get_user_input(argvars, rettv, FALSE);
11468}
11469
11470/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011471 * "inputdialog()" function
11472 */
11473 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011474f_inputdialog(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011475 typval_T *argvars;
11476 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011477{
11478#if defined(FEAT_GUI_TEXTDIALOG)
11479 /* Use a GUI dialog if the GUI is running and 'c' is not in 'guioptions' */
11480 if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
11481 {
11482 char_u *message;
11483 char_u buf[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011484 char_u *defstr = (char_u *)"";
Bram Moolenaar071d4272004-06-13 20:20:40 +000011485
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011486 message = get_tv_string_chk(&argvars[0]);
11487 if (argvars[1].v_type != VAR_UNKNOWN
Bram Moolenaarc05f93f2006-05-02 22:09:31 +000011488 && (defstr = get_tv_string_buf_chk(&argvars[1], buf)) != NULL)
Bram Moolenaarce0842a2005-07-18 21:58:11 +000011489 vim_strncpy(IObuff, defstr, IOSIZE - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011490 else
11491 IObuff[0] = NUL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011492 if (message != NULL && defstr != NULL
11493 && do_dialog(VIM_QUESTION, NULL, message,
11494 (char_u *)_("&OK\n&Cancel"), 1, IObuff) == 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011495 rettv->vval.v_string = vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011496 else
11497 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011498 if (message != NULL && defstr != NULL
11499 && argvars[1].v_type != VAR_UNKNOWN
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011500 && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011501 rettv->vval.v_string = vim_strsave(
11502 get_tv_string_buf(&argvars[2], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +000011503 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011504 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011505 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011506 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011507 }
11508 else
11509#endif
Bram Moolenaarecbaf552006-07-13 06:31:00 +000011510 get_user_input(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011511}
11512
Bram Moolenaar6efa2b32005-09-10 19:26:26 +000011513/*
11514 * "inputlist()" function
11515 */
11516 static void
11517f_inputlist(argvars, rettv)
11518 typval_T *argvars;
11519 typval_T *rettv;
11520{
11521 listitem_T *li;
11522 int selected;
11523 int mouse_used;
11524
11525 rettv->vval.v_number = 0;
11526#ifdef NO_CONSOLE_INPUT
11527 /* While starting up, there is no place to enter text. */
11528 if (no_console_input())
11529 return;
11530#endif
11531 if (argvars[0].v_type != VAR_LIST || argvars[0].vval.v_list == NULL)
11532 {
11533 EMSG2(_(e_listarg), "inputlist()");
11534 return;
11535 }
11536
11537 msg_start();
Bram Moolenaar412f7442006-07-23 19:51:57 +000011538 msg_row = Rows - 1; /* for when 'cmdheight' > 1 */
Bram Moolenaar6efa2b32005-09-10 19:26:26 +000011539 lines_left = Rows; /* avoid more prompt */
11540 msg_scroll = TRUE;
11541 msg_clr_eos();
11542
11543 for (li = argvars[0].vval.v_list->lv_first; li != NULL; li = li->li_next)
11544 {
11545 msg_puts(get_tv_string(&li->li_tv));
11546 msg_putchar('\n');
11547 }
11548
11549 /* Ask for choice. */
11550 selected = prompt_for_number(&mouse_used);
11551 if (mouse_used)
11552 selected -= lines_left;
11553
11554 rettv->vval.v_number = selected;
11555}
11556
11557
Bram Moolenaar071d4272004-06-13 20:20:40 +000011558static garray_T ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL};
11559
11560/*
11561 * "inputrestore()" function
11562 */
11563/*ARGSUSED*/
11564 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011565f_inputrestore(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011566 typval_T *argvars;
11567 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011568{
11569 if (ga_userinput.ga_len > 0)
11570 {
11571 --ga_userinput.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011572 restore_typeahead((tasave_T *)(ga_userinput.ga_data)
11573 + ga_userinput.ga_len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011574 rettv->vval.v_number = 0; /* OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011575 }
11576 else if (p_verbose > 1)
11577 {
Bram Moolenaar54ee7752005-05-31 22:22:17 +000011578 verb_msg((char_u *)_("called inputrestore() more often than inputsave()"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011579 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011580 }
11581}
11582
11583/*
11584 * "inputsave()" function
11585 */
11586/*ARGSUSED*/
11587 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011588f_inputsave(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011589 typval_T *argvars;
11590 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011591{
11592 /* Add an entry to the stack of typehead storage. */
11593 if (ga_grow(&ga_userinput, 1) == OK)
11594 {
11595 save_typeahead((tasave_T *)(ga_userinput.ga_data)
11596 + ga_userinput.ga_len);
11597 ++ga_userinput.ga_len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011598 rettv->vval.v_number = 0; /* OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011599 }
11600 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011601 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011602}
11603
11604/*
11605 * "inputsecret()" function
11606 */
11607 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011608f_inputsecret(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011609 typval_T *argvars;
11610 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011611{
11612 ++cmdline_star;
11613 ++inputsecret_flag;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011614 f_input(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011615 --cmdline_star;
11616 --inputsecret_flag;
11617}
11618
11619/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011620 * "insert()" function
11621 */
11622 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011623f_insert(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011624 typval_T *argvars;
11625 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011626{
11627 long before = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000011628 listitem_T *item;
11629 list_T *l;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011630 int error = FALSE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011631
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011632 rettv->vval.v_number = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011633 if (argvars[0].v_type != VAR_LIST)
Bram Moolenaar0d660222005-01-07 21:51:51 +000011634 EMSG2(_(e_listarg), "insert()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011635 else if ((l = argvars[0].vval.v_list) != NULL
11636 && !tv_check_lock(l->lv_lock, (char_u *)"insert()"))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011637 {
11638 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011639 before = get_tv_number_chk(&argvars[2], &error);
11640 if (error)
11641 return; /* type error; errmsg already given */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011642
Bram Moolenaar758711c2005-02-02 23:11:38 +000011643 if (before == l->lv_len)
11644 item = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011645 else
11646 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000011647 item = list_find(l, before);
11648 if (item == NULL)
11649 {
11650 EMSGN(_(e_listidx), before);
11651 l = NULL;
11652 }
11653 }
11654 if (l != NULL)
11655 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011656 list_insert_tv(l, &argvars[1], item);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011657 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011658 }
11659 }
11660}
11661
11662/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011663 * "isdirectory()" function
11664 */
11665 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011666f_isdirectory(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011667 typval_T *argvars;
11668 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011669{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011670 rettv->vval.v_number = mch_isdir(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000011671}
11672
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011673/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011674 * "islocked()" function
11675 */
11676 static void
11677f_islocked(argvars, rettv)
11678 typval_T *argvars;
11679 typval_T *rettv;
11680{
11681 lval_T lv;
11682 char_u *end;
11683 dictitem_T *di;
11684
11685 rettv->vval.v_number = -1;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000011686 end = get_lval(get_tv_string(&argvars[0]), NULL, &lv, FALSE, FALSE, FALSE,
11687 FNE_CHECK_START);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011688 if (end != NULL && lv.ll_name != NULL)
11689 {
11690 if (*end != NUL)
11691 EMSG(_(e_trailing));
11692 else
11693 {
11694 if (lv.ll_tv == NULL)
11695 {
11696 if (check_changedtick(lv.ll_name))
11697 rettv->vval.v_number = 1; /* always locked */
11698 else
11699 {
11700 di = find_var(lv.ll_name, NULL);
11701 if (di != NULL)
11702 {
11703 /* Consider a variable locked when:
11704 * 1. the variable itself is locked
11705 * 2. the value of the variable is locked.
11706 * 3. the List or Dict value is locked.
11707 */
11708 rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK)
11709 || tv_islocked(&di->di_tv));
11710 }
11711 }
11712 }
11713 else if (lv.ll_range)
Bram Moolenaar910f66f2006-04-05 20:41:53 +000011714 EMSG(_("E786: Range not allowed"));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011715 else if (lv.ll_newkey != NULL)
11716 EMSG2(_(e_dictkey), lv.ll_newkey);
11717 else if (lv.ll_list != NULL)
11718 /* List item. */
11719 rettv->vval.v_number = tv_islocked(&lv.ll_li->li_tv);
11720 else
11721 /* Dictionary item. */
11722 rettv->vval.v_number = tv_islocked(&lv.ll_di->di_tv);
11723 }
11724 }
11725
11726 clear_lval(&lv);
11727}
11728
Bram Moolenaar33570922005-01-25 22:26:29 +000011729static void dict_list __ARGS((typval_T *argvars, typval_T *rettv, int what));
Bram Moolenaar8c711452005-01-14 21:53:12 +000011730
11731/*
11732 * Turn a dict into a list:
11733 * "what" == 0: list of keys
11734 * "what" == 1: list of values
11735 * "what" == 2: list of items
11736 */
11737 static void
11738dict_list(argvars, rettv, what)
Bram Moolenaar33570922005-01-25 22:26:29 +000011739 typval_T *argvars;
11740 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011741 int what;
11742{
Bram Moolenaar33570922005-01-25 22:26:29 +000011743 list_T *l2;
11744 dictitem_T *di;
11745 hashitem_T *hi;
11746 listitem_T *li;
11747 listitem_T *li2;
11748 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011749 int todo;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011750
11751 rettv->vval.v_number = 0;
11752 if (argvars[0].v_type != VAR_DICT)
11753 {
11754 EMSG(_(e_dictreq));
11755 return;
11756 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011757 if ((d = argvars[0].vval.v_dict) == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000011758 return;
11759
Bram Moolenaareddf53b2006-02-27 00:11:10 +000011760 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000011761 return;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011762
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000011763 todo = (int)d->dv_hashtab.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +000011764 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +000011765 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011766 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar8c711452005-01-14 21:53:12 +000011767 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011768 --todo;
11769 di = HI2DI(hi);
Bram Moolenaar8c711452005-01-14 21:53:12 +000011770
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011771 li = listitem_alloc();
11772 if (li == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000011773 break;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000011774 list_append(rettv->vval.v_list, li);
Bram Moolenaar8c711452005-01-14 21:53:12 +000011775
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011776 if (what == 0)
11777 {
11778 /* keys() */
11779 li->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011780 li->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011781 li->li_tv.vval.v_string = vim_strsave(di->di_key);
11782 }
11783 else if (what == 1)
11784 {
11785 /* values() */
11786 copy_tv(&di->di_tv, &li->li_tv);
11787 }
11788 else
11789 {
11790 /* items() */
11791 l2 = list_alloc();
11792 li->li_tv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011793 li->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011794 li->li_tv.vval.v_list = l2;
11795 if (l2 == NULL)
11796 break;
11797 ++l2->lv_refcount;
11798
11799 li2 = listitem_alloc();
11800 if (li2 == NULL)
11801 break;
11802 list_append(l2, li2);
11803 li2->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011804 li2->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011805 li2->li_tv.vval.v_string = vim_strsave(di->di_key);
11806
11807 li2 = listitem_alloc();
11808 if (li2 == NULL)
11809 break;
11810 list_append(l2, li2);
11811 copy_tv(&di->di_tv, &li2->li_tv);
11812 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000011813 }
11814 }
11815}
11816
11817/*
11818 * "items(dict)" function
11819 */
11820 static void
11821f_items(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011822 typval_T *argvars;
11823 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011824{
11825 dict_list(argvars, rettv, 2);
11826}
11827
Bram Moolenaar071d4272004-06-13 20:20:40 +000011828/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011829 * "join()" function
11830 */
11831 static void
11832f_join(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011833 typval_T *argvars;
11834 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011835{
11836 garray_T ga;
11837 char_u *sep;
11838
11839 rettv->vval.v_number = 0;
11840 if (argvars[0].v_type != VAR_LIST)
11841 {
11842 EMSG(_(e_listreq));
11843 return;
11844 }
11845 if (argvars[0].vval.v_list == NULL)
11846 return;
11847 if (argvars[1].v_type == VAR_UNKNOWN)
11848 sep = (char_u *)" ";
11849 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011850 sep = get_tv_string_chk(&argvars[1]);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011851
11852 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011853
11854 if (sep != NULL)
11855 {
11856 ga_init2(&ga, (int)sizeof(char), 80);
Bram Moolenaarb71eaae2006-01-20 23:10:18 +000011857 list_join(&ga, argvars[0].vval.v_list, sep, TRUE, 0);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011858 ga_append(&ga, NUL);
11859 rettv->vval.v_string = (char_u *)ga.ga_data;
11860 }
11861 else
11862 rettv->vval.v_string = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011863}
11864
11865/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000011866 * "keys()" function
11867 */
11868 static void
11869f_keys(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011870 typval_T *argvars;
11871 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011872{
11873 dict_list(argvars, rettv, 0);
11874}
11875
11876/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011877 * "last_buffer_nr()" function.
11878 */
11879/*ARGSUSED*/
11880 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011881f_last_buffer_nr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011882 typval_T *argvars;
11883 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011884{
11885 int n = 0;
11886 buf_T *buf;
11887
11888 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
11889 if (n < buf->b_fnum)
11890 n = buf->b_fnum;
11891
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011892 rettv->vval.v_number = n;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011893}
11894
11895/*
11896 * "len()" function
11897 */
11898 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011899f_len(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011900 typval_T *argvars;
11901 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011902{
11903 switch (argvars[0].v_type)
11904 {
11905 case VAR_STRING:
11906 case VAR_NUMBER:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011907 rettv->vval.v_number = (varnumber_T)STRLEN(
11908 get_tv_string(&argvars[0]));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011909 break;
11910 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011911 rettv->vval.v_number = list_len(argvars[0].vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011912 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +000011913 case VAR_DICT:
11914 rettv->vval.v_number = dict_len(argvars[0].vval.v_dict);
11915 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011916 default:
Bram Moolenaare49b69a2005-01-08 16:11:57 +000011917 EMSG(_("E701: Invalid type for len()"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011918 break;
11919 }
11920}
11921
Bram Moolenaar33570922005-01-25 22:26:29 +000011922static void libcall_common __ARGS((typval_T *argvars, typval_T *rettv, int type));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011923
11924 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011925libcall_common(argvars, rettv, type)
Bram Moolenaar33570922005-01-25 22:26:29 +000011926 typval_T *argvars;
11927 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011928 int type;
11929{
11930#ifdef FEAT_LIBCALL
11931 char_u *string_in;
11932 char_u **string_result;
11933 int nr_result;
11934#endif
11935
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011936 rettv->v_type = type;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011937 if (type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011938 rettv->vval.v_number = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011939 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011940 rettv->vval.v_string = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011941
11942 if (check_restricted() || check_secure())
11943 return;
11944
11945#ifdef FEAT_LIBCALL
11946 /* The first two args must be strings, otherwise its meaningless */
11947 if (argvars[0].v_type == VAR_STRING && argvars[1].v_type == VAR_STRING)
11948 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000011949 string_in = NULL;
11950 if (argvars[2].v_type == VAR_STRING)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011951 string_in = argvars[2].vval.v_string;
11952 if (type == VAR_NUMBER)
11953 string_result = NULL;
11954 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011955 string_result = &rettv->vval.v_string;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011956 if (mch_libcall(argvars[0].vval.v_string,
11957 argvars[1].vval.v_string,
11958 string_in,
11959 argvars[2].vval.v_number,
11960 string_result,
11961 &nr_result) == OK
11962 && type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011963 rettv->vval.v_number = nr_result;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011964 }
11965#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000011966}
11967
11968/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011969 * "libcall()" function
11970 */
11971 static void
11972f_libcall(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011973 typval_T *argvars;
11974 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011975{
11976 libcall_common(argvars, rettv, VAR_STRING);
11977}
11978
11979/*
11980 * "libcallnr()" function
11981 */
11982 static void
11983f_libcallnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011984 typval_T *argvars;
11985 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011986{
11987 libcall_common(argvars, rettv, VAR_NUMBER);
11988}
11989
11990/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011991 * "line(string)" function
11992 */
11993 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011994f_line(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011995 typval_T *argvars;
11996 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011997{
11998 linenr_T lnum = 0;
11999 pos_T *fp;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000012000 int fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012001
Bram Moolenaar0e34f622006-03-03 23:00:03 +000012002 fp = var2fpos(&argvars[0], TRUE, &fnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012003 if (fp != NULL)
12004 lnum = fp->lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012005 rettv->vval.v_number = lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012006}
12007
12008/*
12009 * "line2byte(lnum)" function
12010 */
12011/*ARGSUSED*/
12012 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012013f_line2byte(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012014 typval_T *argvars;
12015 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012016{
12017#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012018 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012019#else
12020 linenr_T lnum;
12021
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012022 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012023 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012024 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012025 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012026 rettv->vval.v_number = ml_find_line_or_offset(curbuf, lnum, NULL);
12027 if (rettv->vval.v_number >= 0)
12028 ++rettv->vval.v_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012029#endif
12030}
12031
12032/*
12033 * "lispindent(lnum)" function
12034 */
12035 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012036f_lispindent(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012037 typval_T *argvars;
12038 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012039{
12040#ifdef FEAT_LISP
12041 pos_T pos;
12042 linenr_T lnum;
12043
12044 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012045 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012046 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
12047 {
12048 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012049 rettv->vval.v_number = get_lisp_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +000012050 curwin->w_cursor = pos;
12051 }
12052 else
12053#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012054 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012055}
12056
12057/*
12058 * "localtime()" function
12059 */
12060/*ARGSUSED*/
12061 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012062f_localtime(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012063 typval_T *argvars;
12064 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012065{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012066 rettv->vval.v_number = (varnumber_T)time(NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012067}
12068
Bram Moolenaar33570922005-01-25 22:26:29 +000012069static void get_maparg __ARGS((typval_T *argvars, typval_T *rettv, int exact));
Bram Moolenaar071d4272004-06-13 20:20:40 +000012070
12071 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012072get_maparg(argvars, rettv, exact)
Bram Moolenaar33570922005-01-25 22:26:29 +000012073 typval_T *argvars;
12074 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012075 int exact;
12076{
12077 char_u *keys;
12078 char_u *which;
12079 char_u buf[NUMBUFLEN];
12080 char_u *keys_buf = NULL;
12081 char_u *rhs;
12082 int mode;
12083 garray_T ga;
Bram Moolenaar2c932302006-03-18 21:42:09 +000012084 int abbr = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012085
12086 /* return empty string for failure */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012087 rettv->v_type = VAR_STRING;
12088 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012089
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012090 keys = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012091 if (*keys == NUL)
12092 return;
12093
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012094 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar2c932302006-03-18 21:42:09 +000012095 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012096 which = get_tv_string_buf_chk(&argvars[1], buf);
Bram Moolenaar2c932302006-03-18 21:42:09 +000012097 if (argvars[2].v_type != VAR_UNKNOWN)
12098 abbr = get_tv_number(&argvars[2]);
12099 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012100 else
12101 which = (char_u *)"";
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012102 if (which == NULL)
12103 return;
12104
Bram Moolenaar071d4272004-06-13 20:20:40 +000012105 mode = get_map_mode(&which, 0);
12106
Bram Moolenaar3fb9eda2006-05-03 21:29:58 +000012107 keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, FALSE);
Bram Moolenaar2c932302006-03-18 21:42:09 +000012108 rhs = check_map(keys, mode, exact, FALSE, abbr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012109 vim_free(keys_buf);
12110 if (rhs != NULL)
12111 {
12112 ga_init(&ga);
12113 ga.ga_itemsize = 1;
12114 ga.ga_growsize = 40;
12115
12116 while (*rhs != NUL)
12117 ga_concat(&ga, str2special(&rhs, FALSE));
12118
12119 ga_append(&ga, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012120 rettv->vval.v_string = (char_u *)ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012121 }
12122}
12123
12124/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012125 * "map()" function
12126 */
12127 static void
12128f_map(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012129 typval_T *argvars;
12130 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012131{
12132 filter_map(argvars, rettv, TRUE);
12133}
12134
12135/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012136 * "maparg()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000012137 */
12138 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000012139f_maparg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012140 typval_T *argvars;
12141 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012142{
Bram Moolenaar0d660222005-01-07 21:51:51 +000012143 get_maparg(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012144}
12145
12146/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012147 * "mapcheck()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000012148 */
12149 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000012150f_mapcheck(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012151 typval_T *argvars;
12152 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012153{
Bram Moolenaar0d660222005-01-07 21:51:51 +000012154 get_maparg(argvars, rettv, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012155}
12156
Bram Moolenaar33570922005-01-25 22:26:29 +000012157static void find_some_match __ARGS((typval_T *argvars, typval_T *rettv, int start));
Bram Moolenaar071d4272004-06-13 20:20:40 +000012158
12159 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012160find_some_match(argvars, rettv, type)
Bram Moolenaar33570922005-01-25 22:26:29 +000012161 typval_T *argvars;
12162 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012163 int type;
12164{
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012165 char_u *str = NULL;
12166 char_u *expr = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012167 char_u *pat;
12168 regmatch_T regmatch;
12169 char_u patbuf[NUMBUFLEN];
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012170 char_u strbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000012171 char_u *save_cpo;
12172 long start = 0;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000012173 long nth = 1;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000012174 colnr_T startcol = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000012175 int match = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000012176 list_T *l = NULL;
12177 listitem_T *li = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012178 long idx = 0;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012179 char_u *tofree = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012180
12181 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
12182 save_cpo = p_cpo;
12183 p_cpo = (char_u *)"";
12184
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012185 rettv->vval.v_number = -1;
12186 if (type == 3)
12187 {
12188 /* return empty list when there are no matches */
Bram Moolenaareddf53b2006-02-27 00:11:10 +000012189 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012190 goto theend;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012191 }
12192 else if (type == 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012193 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012194 rettv->v_type = VAR_STRING;
12195 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012196 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012197
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012198 if (argvars[0].v_type == VAR_LIST)
12199 {
12200 if ((l = argvars[0].vval.v_list) == NULL)
12201 goto theend;
12202 li = l->lv_first;
12203 }
12204 else
12205 expr = str = get_tv_string(&argvars[0]);
12206
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012207 pat = get_tv_string_buf_chk(&argvars[1], patbuf);
12208 if (pat == NULL)
12209 goto theend;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012210
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012211 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012212 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012213 int error = FALSE;
12214
12215 start = get_tv_number_chk(&argvars[2], &error);
12216 if (error)
12217 goto theend;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012218 if (l != NULL)
12219 {
12220 li = list_find(l, start);
12221 if (li == NULL)
12222 goto theend;
Bram Moolenaar758711c2005-02-02 23:11:38 +000012223 idx = l->lv_idx; /* use the cached index */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012224 }
12225 else
12226 {
12227 if (start < 0)
12228 start = 0;
12229 if (start > (long)STRLEN(str))
12230 goto theend;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000012231 /* When "count" argument is there ignore matches before "start",
12232 * otherwise skip part of the string. Differs when pattern is "^"
12233 * or "\<". */
12234 if (argvars[3].v_type != VAR_UNKNOWN)
12235 startcol = start;
12236 else
12237 str += start;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012238 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000012239
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012240 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012241 nth = get_tv_number_chk(&argvars[3], &error);
12242 if (error)
12243 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012244 }
12245
12246 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
12247 if (regmatch.regprog != NULL)
12248 {
12249 regmatch.rm_ic = p_ic;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000012250
Bram Moolenaard8e9bb22005-07-09 21:14:46 +000012251 for (;;)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000012252 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012253 if (l != NULL)
12254 {
12255 if (li == NULL)
12256 {
12257 match = FALSE;
12258 break;
12259 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012260 vim_free(tofree);
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000012261 str = echo_string(&li->li_tv, &tofree, strbuf, 0);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000012262 if (str == NULL)
12263 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012264 }
12265
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000012266 match = vim_regexec_nl(&regmatch, str, (colnr_T)startcol);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012267
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012268 if (match && --nth <= 0)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000012269 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012270 if (l == NULL && !match)
12271 break;
12272
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000012273 /* Advance to just after the match. */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012274 if (l != NULL)
12275 {
12276 li = li->li_next;
12277 ++idx;
12278 }
12279 else
12280 {
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000012281#ifdef FEAT_MBYTE
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000012282 startcol = (colnr_T)(regmatch.startp[0]
12283 + (*mb_ptr2len)(regmatch.startp[0]) - str);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000012284#else
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000012285 startcol = regmatch.startp[0] + 1 - str;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000012286#endif
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012287 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000012288 }
12289
12290 if (match)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012291 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012292 if (type == 3)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012293 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012294 int i;
12295
12296 /* return list with matched string and submatches */
12297 for (i = 0; i < NSUBEXP; ++i)
12298 {
12299 if (regmatch.endp[i] == NULL)
Bram Moolenaarf9393ef2006-04-24 19:47:27 +000012300 {
12301 if (list_append_string(rettv->vval.v_list,
12302 (char_u *)"", 0) == FAIL)
12303 break;
12304 }
12305 else if (list_append_string(rettv->vval.v_list,
Bram Moolenaar4463f292005-09-25 22:20:24 +000012306 regmatch.startp[i],
12307 (int)(regmatch.endp[i] - regmatch.startp[i]))
12308 == FAIL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012309 break;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012310 }
12311 }
12312 else if (type == 2)
12313 {
12314 /* return matched string */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012315 if (l != NULL)
12316 copy_tv(&li->li_tv, rettv);
12317 else
12318 rettv->vval.v_string = vim_strnsave(regmatch.startp[0],
Bram Moolenaar071d4272004-06-13 20:20:40 +000012319 (int)(regmatch.endp[0] - regmatch.startp[0]));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012320 }
12321 else if (l != NULL)
12322 rettv->vval.v_number = idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012323 else
12324 {
12325 if (type != 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012326 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +000012327 (varnumber_T)(regmatch.startp[0] - str);
12328 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012329 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +000012330 (varnumber_T)(regmatch.endp[0] - str);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000012331 rettv->vval.v_number += (varnumber_T)(str - expr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012332 }
12333 }
12334 vim_free(regmatch.regprog);
12335 }
12336
12337theend:
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012338 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012339 p_cpo = save_cpo;
12340}
12341
12342/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012343 * "match()" function
12344 */
12345 static void
12346f_match(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012347 typval_T *argvars;
12348 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012349{
12350 find_some_match(argvars, rettv, 1);
12351}
12352
12353/*
Bram Moolenaar910f66f2006-04-05 20:41:53 +000012354 * "matcharg()" function
12355 */
12356 static void
12357f_matcharg(argvars, rettv)
12358 typval_T *argvars;
12359 typval_T *rettv;
12360{
12361 if (rettv_list_alloc(rettv) == OK)
12362 {
12363#ifdef FEAT_SEARCH_EXTRA
12364 int mi = get_tv_number(&argvars[0]);
12365
12366 if (mi >= 1 && mi <= 3)
12367 {
12368 list_append_string(rettv->vval.v_list,
12369 syn_id2name(curwin->w_match_id[mi - 1]), -1);
12370 list_append_string(rettv->vval.v_list,
12371 curwin->w_match_pat[mi - 1], -1);
12372 }
12373#endif
12374 }
12375}
12376
12377/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012378 * "matchend()" function
12379 */
12380 static void
12381f_matchend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012382 typval_T *argvars;
12383 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012384{
12385 find_some_match(argvars, rettv, 0);
12386}
12387
12388/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012389 * "matchlist()" function
12390 */
12391 static void
12392f_matchlist(argvars, rettv)
12393 typval_T *argvars;
12394 typval_T *rettv;
12395{
12396 find_some_match(argvars, rettv, 3);
12397}
12398
12399/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012400 * "matchstr()" function
12401 */
12402 static void
12403f_matchstr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012404 typval_T *argvars;
12405 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012406{
12407 find_some_match(argvars, rettv, 2);
12408}
12409
Bram Moolenaar33570922005-01-25 22:26:29 +000012410static void max_min __ARGS((typval_T *argvars, typval_T *rettv, int domax));
Bram Moolenaar6cc16192005-01-08 21:49:45 +000012411
12412 static void
12413max_min(argvars, rettv, domax)
Bram Moolenaar33570922005-01-25 22:26:29 +000012414 typval_T *argvars;
12415 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000012416 int domax;
12417{
Bram Moolenaar6cc16192005-01-08 21:49:45 +000012418 long n = 0;
12419 long i;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012420 int error = FALSE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000012421
12422 if (argvars[0].v_type == VAR_LIST)
12423 {
Bram Moolenaar33570922005-01-25 22:26:29 +000012424 list_T *l;
12425 listitem_T *li;
Bram Moolenaare9a41262005-01-15 22:18:47 +000012426
Bram Moolenaar6cc16192005-01-08 21:49:45 +000012427 l = argvars[0].vval.v_list;
12428 if (l != NULL)
12429 {
12430 li = l->lv_first;
12431 if (li != NULL)
12432 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012433 n = get_tv_number_chk(&li->li_tv, &error);
Bram Moolenaard8e9bb22005-07-09 21:14:46 +000012434 for (;;)
Bram Moolenaar6cc16192005-01-08 21:49:45 +000012435 {
12436 li = li->li_next;
12437 if (li == NULL)
12438 break;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012439 i = get_tv_number_chk(&li->li_tv, &error);
Bram Moolenaar6cc16192005-01-08 21:49:45 +000012440 if (domax ? i > n : i < n)
12441 n = i;
12442 }
12443 }
12444 }
12445 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000012446 else if (argvars[0].v_type == VAR_DICT)
12447 {
Bram Moolenaar33570922005-01-25 22:26:29 +000012448 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000012449 int first = TRUE;
Bram Moolenaar33570922005-01-25 22:26:29 +000012450 hashitem_T *hi;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000012451 int todo;
Bram Moolenaare9a41262005-01-15 22:18:47 +000012452
12453 d = argvars[0].vval.v_dict;
12454 if (d != NULL)
12455 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000012456 todo = (int)d->dv_hashtab.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +000012457 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaare9a41262005-01-15 22:18:47 +000012458 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000012459 if (!HASHITEM_EMPTY(hi))
Bram Moolenaare9a41262005-01-15 22:18:47 +000012460 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000012461 --todo;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012462 i = get_tv_number_chk(&HI2DI(hi)->di_tv, &error);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000012463 if (first)
12464 {
12465 n = i;
12466 first = FALSE;
12467 }
12468 else if (domax ? i > n : i < n)
Bram Moolenaare9a41262005-01-15 22:18:47 +000012469 n = i;
12470 }
12471 }
12472 }
12473 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +000012474 else
Bram Moolenaar758711c2005-02-02 23:11:38 +000012475 EMSG(_(e_listdictarg));
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012476 rettv->vval.v_number = error ? 0 : n;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000012477}
12478
12479/*
12480 * "max()" function
12481 */
12482 static void
12483f_max(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012484 typval_T *argvars;
12485 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000012486{
12487 max_min(argvars, rettv, TRUE);
12488}
12489
12490/*
12491 * "min()" function
12492 */
12493 static void
12494f_min(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012495 typval_T *argvars;
12496 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000012497{
12498 max_min(argvars, rettv, FALSE);
12499}
12500
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000012501static int mkdir_recurse __ARGS((char_u *dir, int prot));
12502
12503/*
12504 * Create the directory in which "dir" is located, and higher levels when
12505 * needed.
12506 */
12507 static int
12508mkdir_recurse(dir, prot)
12509 char_u *dir;
12510 int prot;
12511{
12512 char_u *p;
12513 char_u *updir;
12514 int r = FAIL;
12515
12516 /* Get end of directory name in "dir".
12517 * We're done when it's "/" or "c:/". */
12518 p = gettail_sep(dir);
12519 if (p <= get_past_head(dir))
12520 return OK;
12521
12522 /* If the directory exists we're done. Otherwise: create it.*/
12523 updir = vim_strnsave(dir, (int)(p - dir));
12524 if (updir == NULL)
12525 return FAIL;
12526 if (mch_isdir(updir))
12527 r = OK;
12528 else if (mkdir_recurse(updir, prot) == OK)
12529 r = vim_mkdir_emsg(updir, prot);
12530 vim_free(updir);
12531 return r;
12532}
12533
12534#ifdef vim_mkdir
12535/*
12536 * "mkdir()" function
12537 */
12538 static void
12539f_mkdir(argvars, rettv)
12540 typval_T *argvars;
12541 typval_T *rettv;
12542{
12543 char_u *dir;
12544 char_u buf[NUMBUFLEN];
12545 int prot = 0755;
12546
12547 rettv->vval.v_number = FAIL;
12548 if (check_restricted() || check_secure())
12549 return;
12550
12551 dir = get_tv_string_buf(&argvars[0], buf);
12552 if (argvars[1].v_type != VAR_UNKNOWN)
12553 {
12554 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012555 prot = get_tv_number_chk(&argvars[2], NULL);
12556 if (prot != -1 && STRCMP(get_tv_string(&argvars[1]), "p") == 0)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000012557 mkdir_recurse(dir, prot);
12558 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012559 rettv->vval.v_number = prot != -1 ? vim_mkdir_emsg(dir, prot) : 0;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000012560}
12561#endif
12562
Bram Moolenaar0d660222005-01-07 21:51:51 +000012563/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012564 * "mode()" function
12565 */
12566/*ARGSUSED*/
12567 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012568f_mode(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012569 typval_T *argvars;
12570 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012571{
12572 char_u buf[2];
12573
12574#ifdef FEAT_VISUAL
12575 if (VIsual_active)
12576 {
12577 if (VIsual_select)
12578 buf[0] = VIsual_mode + 's' - 'v';
12579 else
12580 buf[0] = VIsual_mode;
12581 }
12582 else
12583#endif
12584 if (State == HITRETURN || State == ASKMORE || State == SETWSIZE)
12585 buf[0] = 'r';
12586 else if (State & INSERT)
12587 {
12588 if (State & REPLACE_FLAG)
12589 buf[0] = 'R';
12590 else
12591 buf[0] = 'i';
12592 }
12593 else if (State & CMDLINE)
12594 buf[0] = 'c';
12595 else
12596 buf[0] = 'n';
12597
12598 buf[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012599 rettv->vval.v_string = vim_strsave(buf);
12600 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012601}
12602
12603/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012604 * "nextnonblank()" function
12605 */
12606 static void
12607f_nextnonblank(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012608 typval_T *argvars;
12609 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012610{
12611 linenr_T lnum;
12612
12613 for (lnum = get_tv_lnum(argvars); ; ++lnum)
12614 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012615 if (lnum < 0 || lnum > curbuf->b_ml.ml_line_count)
Bram Moolenaar0d660222005-01-07 21:51:51 +000012616 {
12617 lnum = 0;
12618 break;
12619 }
12620 if (*skipwhite(ml_get(lnum)) != NUL)
12621 break;
12622 }
12623 rettv->vval.v_number = lnum;
12624}
12625
12626/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012627 * "nr2char()" function
12628 */
12629 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012630f_nr2char(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012631 typval_T *argvars;
12632 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012633{
12634 char_u buf[NUMBUFLEN];
12635
12636#ifdef FEAT_MBYTE
12637 if (has_mbyte)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012638 buf[(*mb_char2bytes)((int)get_tv_number(&argvars[0]), buf)] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012639 else
12640#endif
12641 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012642 buf[0] = (char_u)get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012643 buf[1] = NUL;
12644 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012645 rettv->v_type = VAR_STRING;
12646 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012647}
12648
12649/*
Bram Moolenaar910f66f2006-04-05 20:41:53 +000012650 * "pathshorten()" function
12651 */
12652 static void
12653f_pathshorten(argvars, rettv)
12654 typval_T *argvars;
12655 typval_T *rettv;
12656{
12657 char_u *p;
12658
12659 rettv->v_type = VAR_STRING;
12660 p = get_tv_string_chk(&argvars[0]);
12661 if (p == NULL)
12662 rettv->vval.v_string = NULL;
12663 else
12664 {
12665 p = vim_strsave(p);
12666 rettv->vval.v_string = p;
12667 if (p != NULL)
12668 shorten_dir(p);
12669 }
12670}
12671
12672/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012673 * "prevnonblank()" function
12674 */
12675 static void
12676f_prevnonblank(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012677 typval_T *argvars;
12678 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012679{
12680 linenr_T lnum;
12681
12682 lnum = get_tv_lnum(argvars);
12683 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
12684 lnum = 0;
12685 else
12686 while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL)
12687 --lnum;
12688 rettv->vval.v_number = lnum;
12689}
12690
Bram Moolenaara6c840d2005-08-22 22:59:46 +000012691#ifdef HAVE_STDARG_H
12692/* This dummy va_list is here because:
12693 * - passing a NULL pointer doesn't work when va_list isn't a pointer
12694 * - locally in the function results in a "used before set" warning
12695 * - using va_start() to initialize it gives "function with fixed args" error */
12696static va_list ap;
12697#endif
12698
Bram Moolenaar8c711452005-01-14 21:53:12 +000012699/*
Bram Moolenaar4be06f92005-07-29 22:36:03 +000012700 * "printf()" function
12701 */
12702 static void
12703f_printf(argvars, rettv)
12704 typval_T *argvars;
12705 typval_T *rettv;
12706{
12707 rettv->v_type = VAR_STRING;
12708 rettv->vval.v_string = NULL;
Bram Moolenaard52d9742005-08-21 22:20:28 +000012709#ifdef HAVE_STDARG_H /* only very old compilers can't do this */
Bram Moolenaar4be06f92005-07-29 22:36:03 +000012710 {
12711 char_u buf[NUMBUFLEN];
12712 int len;
12713 char_u *s;
12714 int saved_did_emsg = did_emsg;
12715 char *fmt;
12716
12717 /* Get the required length, allocate the buffer and do it for real. */
12718 did_emsg = FALSE;
12719 fmt = (char *)get_tv_string_buf(&argvars[0], buf);
Bram Moolenaar5b8d8fd2005-08-16 23:01:50 +000012720 len = vim_vsnprintf(NULL, 0, fmt, ap, argvars + 1);
Bram Moolenaar4be06f92005-07-29 22:36:03 +000012721 if (!did_emsg)
12722 {
12723 s = alloc(len + 1);
12724 if (s != NULL)
12725 {
12726 rettv->vval.v_string = s;
Bram Moolenaar5b8d8fd2005-08-16 23:01:50 +000012727 (void)vim_vsnprintf((char *)s, len + 1, fmt, ap, argvars + 1);
Bram Moolenaar4be06f92005-07-29 22:36:03 +000012728 }
12729 }
12730 did_emsg |= saved_did_emsg;
12731 }
12732#endif
12733}
12734
12735/*
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000012736 * "pumvisible()" function
12737 */
12738/*ARGSUSED*/
12739 static void
12740f_pumvisible(argvars, rettv)
12741 typval_T *argvars;
12742 typval_T *rettv;
12743{
12744 rettv->vval.v_number = 0;
12745#ifdef FEAT_INS_EXPAND
12746 if (pum_visible())
12747 rettv->vval.v_number = 1;
12748#endif
12749}
12750
12751/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000012752 * "range()" function
12753 */
12754 static void
12755f_range(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012756 typval_T *argvars;
12757 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000012758{
12759 long start;
12760 long end;
12761 long stride = 1;
12762 long i;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012763 int error = FALSE;
Bram Moolenaar8c711452005-01-14 21:53:12 +000012764
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012765 start = get_tv_number_chk(&argvars[0], &error);
Bram Moolenaar8c711452005-01-14 21:53:12 +000012766 if (argvars[1].v_type == VAR_UNKNOWN)
12767 {
12768 end = start - 1;
12769 start = 0;
12770 }
12771 else
12772 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012773 end = get_tv_number_chk(&argvars[1], &error);
Bram Moolenaar8c711452005-01-14 21:53:12 +000012774 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012775 stride = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaar8c711452005-01-14 21:53:12 +000012776 }
12777
12778 rettv->vval.v_number = 0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012779 if (error)
12780 return; /* type error; errmsg already given */
Bram Moolenaar8c711452005-01-14 21:53:12 +000012781 if (stride == 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000012782 EMSG(_("E726: Stride is zero"));
Bram Moolenaar92124a32005-06-17 22:03:40 +000012783 else if (stride > 0 ? end + 1 < start : end - 1 > start)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000012784 EMSG(_("E727: Start past end"));
Bram Moolenaar8c711452005-01-14 21:53:12 +000012785 else
12786 {
Bram Moolenaareddf53b2006-02-27 00:11:10 +000012787 if (rettv_list_alloc(rettv) == OK)
Bram Moolenaar8c711452005-01-14 21:53:12 +000012788 for (i = start; stride > 0 ? i <= end : i >= end; i += stride)
Bram Moolenaareddf53b2006-02-27 00:11:10 +000012789 if (list_append_number(rettv->vval.v_list,
12790 (varnumber_T)i) == FAIL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000012791 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000012792 }
12793}
12794
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012795/*
12796 * "readfile()" function
12797 */
12798 static void
12799f_readfile(argvars, rettv)
12800 typval_T *argvars;
12801 typval_T *rettv;
12802{
12803 int binary = FALSE;
12804 char_u *fname;
12805 FILE *fd;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012806 listitem_T *li;
12807#define FREAD_SIZE 200 /* optimized for text lines */
12808 char_u buf[FREAD_SIZE];
12809 int readlen; /* size of last fread() */
12810 int buflen; /* nr of valid chars in buf[] */
12811 int filtd; /* how much in buf[] was NUL -> '\n' filtered */
12812 int tolist; /* first byte in buf[] still to be put in list */
12813 int chop; /* how many CR to chop off */
12814 char_u *prev = NULL; /* previously read bytes, if any */
12815 int prevlen = 0; /* length of "prev" if not NULL */
12816 char_u *s;
12817 int len;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000012818 long maxline = MAXLNUM;
12819 long cnt = 0;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012820
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000012821 if (argvars[1].v_type != VAR_UNKNOWN)
12822 {
12823 if (STRCMP(get_tv_string(&argvars[1]), "b") == 0)
12824 binary = TRUE;
12825 if (argvars[2].v_type != VAR_UNKNOWN)
12826 maxline = get_tv_number(&argvars[2]);
12827 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012828
Bram Moolenaareddf53b2006-02-27 00:11:10 +000012829 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012830 return;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012831
12832 /* Always open the file in binary mode, library functions have a mind of
12833 * their own about CR-LF conversion. */
12834 fname = get_tv_string(&argvars[0]);
12835 if (*fname == NUL || (fd = mch_fopen((char *)fname, READBIN)) == NULL)
12836 {
12837 EMSG2(_(e_notopen), *fname == NUL ? (char_u *)_("<empty>") : fname);
12838 return;
12839 }
12840
12841 filtd = 0;
Bram Moolenaarb982ca52005-03-28 21:02:15 +000012842 while (cnt < maxline || maxline < 0)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012843 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000012844 readlen = (int)fread(buf + filtd, 1, FREAD_SIZE - filtd, fd);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012845 buflen = filtd + readlen;
12846 tolist = 0;
12847 for ( ; filtd < buflen || readlen <= 0; ++filtd)
12848 {
12849 if (buf[filtd] == '\n' || readlen <= 0)
12850 {
12851 /* Only when in binary mode add an empty list item when the
12852 * last line ends in a '\n'. */
12853 if (!binary && readlen == 0 && filtd == 0)
12854 break;
12855
12856 /* Found end-of-line or end-of-file: add a text line to the
12857 * list. */
12858 chop = 0;
12859 if (!binary)
12860 while (filtd - chop - 1 >= tolist
12861 && buf[filtd - chop - 1] == '\r')
12862 ++chop;
12863 len = filtd - tolist - chop;
12864 if (prev == NULL)
12865 s = vim_strnsave(buf + tolist, len);
12866 else
12867 {
12868 s = alloc((unsigned)(prevlen + len + 1));
12869 if (s != NULL)
12870 {
12871 mch_memmove(s, prev, prevlen);
12872 vim_free(prev);
12873 prev = NULL;
12874 mch_memmove(s + prevlen, buf + tolist, len);
12875 s[prevlen + len] = NUL;
12876 }
12877 }
12878 tolist = filtd + 1;
12879
12880 li = listitem_alloc();
12881 if (li == NULL)
12882 {
12883 vim_free(s);
12884 break;
12885 }
12886 li->li_tv.v_type = VAR_STRING;
12887 li->li_tv.v_lock = 0;
12888 li->li_tv.vval.v_string = s;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000012889 list_append(rettv->vval.v_list, li);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012890
Bram Moolenaarb982ca52005-03-28 21:02:15 +000012891 if (++cnt >= maxline && maxline >= 0)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000012892 break;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012893 if (readlen <= 0)
12894 break;
12895 }
12896 else if (buf[filtd] == NUL)
12897 buf[filtd] = '\n';
12898 }
12899 if (readlen <= 0)
12900 break;
12901
12902 if (tolist == 0)
12903 {
12904 /* "buf" is full, need to move text to an allocated buffer */
12905 if (prev == NULL)
12906 {
12907 prev = vim_strnsave(buf, buflen);
12908 prevlen = buflen;
12909 }
12910 else
12911 {
12912 s = alloc((unsigned)(prevlen + buflen));
12913 if (s != NULL)
12914 {
12915 mch_memmove(s, prev, prevlen);
12916 mch_memmove(s + prevlen, buf, buflen);
12917 vim_free(prev);
12918 prev = s;
12919 prevlen += buflen;
12920 }
12921 }
12922 filtd = 0;
12923 }
12924 else
12925 {
12926 mch_memmove(buf, buf + tolist, buflen - tolist);
12927 filtd -= tolist;
12928 }
12929 }
12930
Bram Moolenaarb982ca52005-03-28 21:02:15 +000012931 /*
12932 * For a negative line count use only the lines at the end of the file,
12933 * free the rest.
12934 */
12935 if (maxline < 0)
12936 while (cnt > -maxline)
12937 {
Bram Moolenaareddf53b2006-02-27 00:11:10 +000012938 listitem_remove(rettv->vval.v_list, rettv->vval.v_list->lv_first);
Bram Moolenaarb982ca52005-03-28 21:02:15 +000012939 --cnt;
12940 }
12941
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000012942 vim_free(prev);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012943 fclose(fd);
12944}
12945
Bram Moolenaare580b0c2006-03-21 21:33:03 +000012946#if defined(FEAT_RELTIME)
12947static int list2proftime __ARGS((typval_T *arg, proftime_T *tm));
12948
12949/*
12950 * Convert a List to proftime_T.
12951 * Return FAIL when there is something wrong.
12952 */
12953 static int
12954list2proftime(arg, tm)
12955 typval_T *arg;
12956 proftime_T *tm;
12957{
12958 long n1, n2;
12959 int error = FALSE;
12960
12961 if (arg->v_type != VAR_LIST || arg->vval.v_list == NULL
12962 || arg->vval.v_list->lv_len != 2)
12963 return FAIL;
12964 n1 = list_find_nr(arg->vval.v_list, 0L, &error);
12965 n2 = list_find_nr(arg->vval.v_list, 1L, &error);
12966# ifdef WIN3264
Bram Moolenaardb552d602006-03-23 22:59:57 +000012967 tm->HighPart = n1;
12968 tm->LowPart = n2;
Bram Moolenaare580b0c2006-03-21 21:33:03 +000012969# else
12970 tm->tv_sec = n1;
12971 tm->tv_usec = n2;
12972# endif
12973 return error ? FAIL : OK;
12974}
12975#endif /* FEAT_RELTIME */
12976
12977/*
12978 * "reltime()" function
12979 */
12980 static void
12981f_reltime(argvars, rettv)
12982 typval_T *argvars;
12983 typval_T *rettv;
12984{
12985#ifdef FEAT_RELTIME
12986 proftime_T res;
12987 proftime_T start;
12988
12989 if (argvars[0].v_type == VAR_UNKNOWN)
12990 {
12991 /* No arguments: get current time. */
12992 profile_start(&res);
12993 }
12994 else if (argvars[1].v_type == VAR_UNKNOWN)
12995 {
12996 if (list2proftime(&argvars[0], &res) == FAIL)
12997 return;
12998 profile_end(&res);
12999 }
13000 else
13001 {
13002 /* Two arguments: compute the difference. */
13003 if (list2proftime(&argvars[0], &start) == FAIL
13004 || list2proftime(&argvars[1], &res) == FAIL)
13005 return;
13006 profile_sub(&res, &start);
13007 }
13008
13009 if (rettv_list_alloc(rettv) == OK)
13010 {
13011 long n1, n2;
13012
13013# ifdef WIN3264
Bram Moolenaardb552d602006-03-23 22:59:57 +000013014 n1 = res.HighPart;
13015 n2 = res.LowPart;
Bram Moolenaare580b0c2006-03-21 21:33:03 +000013016# else
13017 n1 = res.tv_sec;
13018 n2 = res.tv_usec;
13019# endif
13020 list_append_number(rettv->vval.v_list, (varnumber_T)n1);
13021 list_append_number(rettv->vval.v_list, (varnumber_T)n2);
13022 }
13023#endif
13024}
13025
13026/*
13027 * "reltimestr()" function
13028 */
13029 static void
13030f_reltimestr(argvars, rettv)
13031 typval_T *argvars;
13032 typval_T *rettv;
13033{
13034#ifdef FEAT_RELTIME
13035 proftime_T tm;
13036#endif
13037
13038 rettv->v_type = VAR_STRING;
13039 rettv->vval.v_string = NULL;
13040#ifdef FEAT_RELTIME
13041 if (list2proftime(&argvars[0], &tm) == OK)
13042 rettv->vval.v_string = vim_strsave((char_u *)profile_msg(&tm));
13043#endif
13044}
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000013045
Bram Moolenaar0d660222005-01-07 21:51:51 +000013046#if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
13047static void make_connection __ARGS((void));
13048static int check_connection __ARGS((void));
13049
13050 static void
13051make_connection()
13052{
13053 if (X_DISPLAY == NULL
13054# ifdef FEAT_GUI
13055 && !gui.in_use
13056# endif
13057 )
13058 {
13059 x_force_connect = TRUE;
13060 setup_term_clip();
13061 x_force_connect = FALSE;
13062 }
13063}
13064
13065 static int
13066check_connection()
13067{
13068 make_connection();
13069 if (X_DISPLAY == NULL)
13070 {
13071 EMSG(_("E240: No connection to Vim server"));
13072 return FAIL;
13073 }
13074 return OK;
13075}
13076#endif
13077
13078#ifdef FEAT_CLIENTSERVER
Bram Moolenaar33570922005-01-25 22:26:29 +000013079static void remote_common __ARGS((typval_T *argvars, typval_T *rettv, int expr));
Bram Moolenaar0d660222005-01-07 21:51:51 +000013080
13081 static void
13082remote_common(argvars, rettv, expr)
Bram Moolenaar33570922005-01-25 22:26:29 +000013083 typval_T *argvars;
13084 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013085 int expr;
13086{
13087 char_u *server_name;
13088 char_u *keys;
13089 char_u *r = NULL;
13090 char_u buf[NUMBUFLEN];
13091# ifdef WIN32
13092 HWND w;
13093# else
13094 Window w;
13095# endif
13096
13097 if (check_restricted() || check_secure())
13098 return;
13099
13100# ifdef FEAT_X11
13101 if (check_connection() == FAIL)
13102 return;
13103# endif
13104
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013105 server_name = get_tv_string_chk(&argvars[0]);
13106 if (server_name == NULL)
13107 return; /* type error; errmsg already given */
Bram Moolenaar0d660222005-01-07 21:51:51 +000013108 keys = get_tv_string_buf(&argvars[1], buf);
13109# ifdef WIN32
13110 if (serverSendToVim(server_name, keys, &r, &w, expr, TRUE) < 0)
13111# else
13112 if (serverSendToVim(X_DISPLAY, server_name, keys, &r, &w, expr, 0, TRUE)
13113 < 0)
13114# endif
13115 {
13116 if (r != NULL)
13117 EMSG(r); /* sending worked but evaluation failed */
13118 else
13119 EMSG2(_("E241: Unable to send to %s"), server_name);
13120 return;
13121 }
13122
13123 rettv->vval.v_string = r;
13124
13125 if (argvars[2].v_type != VAR_UNKNOWN)
13126 {
Bram Moolenaar33570922005-01-25 22:26:29 +000013127 dictitem_T v;
Bram Moolenaar555b2802005-05-19 21:08:39 +000013128 char_u str[30];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013129 char_u *idvar;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013130
Bram Moolenaareb3593b2006-04-22 22:33:57 +000013131 sprintf((char *)str, PRINTF_HEX_LONG_U, (long_u)w);
Bram Moolenaar33570922005-01-25 22:26:29 +000013132 v.di_tv.v_type = VAR_STRING;
13133 v.di_tv.vval.v_string = vim_strsave(str);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013134 idvar = get_tv_string_chk(&argvars[2]);
13135 if (idvar != NULL)
13136 set_var(idvar, &v.di_tv, FALSE);
Bram Moolenaar33570922005-01-25 22:26:29 +000013137 vim_free(v.di_tv.vval.v_string);
Bram Moolenaar0d660222005-01-07 21:51:51 +000013138 }
13139}
13140#endif
13141
13142/*
13143 * "remote_expr()" function
13144 */
13145/*ARGSUSED*/
13146 static void
13147f_remote_expr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013148 typval_T *argvars;
13149 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013150{
13151 rettv->v_type = VAR_STRING;
13152 rettv->vval.v_string = NULL;
13153#ifdef FEAT_CLIENTSERVER
13154 remote_common(argvars, rettv, TRUE);
13155#endif
13156}
13157
13158/*
13159 * "remote_foreground()" function
13160 */
13161/*ARGSUSED*/
13162 static void
13163f_remote_foreground(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013164 typval_T *argvars;
13165 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013166{
13167 rettv->vval.v_number = 0;
13168#ifdef FEAT_CLIENTSERVER
13169# ifdef WIN32
13170 /* On Win32 it's done in this application. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013171 {
13172 char_u *server_name = get_tv_string_chk(&argvars[0]);
13173
13174 if (server_name != NULL)
13175 serverForeground(server_name);
13176 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000013177# else
13178 /* Send a foreground() expression to the server. */
13179 argvars[1].v_type = VAR_STRING;
13180 argvars[1].vval.v_string = vim_strsave((char_u *)"foreground()");
13181 argvars[2].v_type = VAR_UNKNOWN;
13182 remote_common(argvars, rettv, TRUE);
13183 vim_free(argvars[1].vval.v_string);
13184# endif
13185#endif
13186}
13187
13188/*ARGSUSED*/
13189 static void
13190f_remote_peek(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013191 typval_T *argvars;
13192 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013193{
13194#ifdef FEAT_CLIENTSERVER
Bram Moolenaar33570922005-01-25 22:26:29 +000013195 dictitem_T v;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013196 char_u *s = NULL;
13197# ifdef WIN32
Bram Moolenaareb3593b2006-04-22 22:33:57 +000013198 long_u n = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013199# endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013200 char_u *serverid;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013201
13202 if (check_restricted() || check_secure())
13203 {
13204 rettv->vval.v_number = -1;
13205 return;
13206 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013207 serverid = get_tv_string_chk(&argvars[0]);
13208 if (serverid == NULL)
13209 {
13210 rettv->vval.v_number = -1;
13211 return; /* type error; errmsg already given */
13212 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000013213# ifdef WIN32
Bram Moolenaareb3593b2006-04-22 22:33:57 +000013214 sscanf(serverid, SCANF_HEX_LONG_U, &n);
Bram Moolenaar0d660222005-01-07 21:51:51 +000013215 if (n == 0)
13216 rettv->vval.v_number = -1;
13217 else
13218 {
13219 s = serverGetReply((HWND)n, FALSE, FALSE, FALSE);
13220 rettv->vval.v_number = (s != NULL);
13221 }
13222# else
13223 rettv->vval.v_number = 0;
13224 if (check_connection() == FAIL)
13225 return;
13226
13227 rettv->vval.v_number = serverPeekReply(X_DISPLAY,
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013228 serverStrToWin(serverid), &s);
Bram Moolenaar0d660222005-01-07 21:51:51 +000013229# endif
13230
13231 if (argvars[1].v_type != VAR_UNKNOWN && rettv->vval.v_number > 0)
13232 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013233 char_u *retvar;
13234
Bram Moolenaar33570922005-01-25 22:26:29 +000013235 v.di_tv.v_type = VAR_STRING;
13236 v.di_tv.vval.v_string = vim_strsave(s);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013237 retvar = get_tv_string_chk(&argvars[1]);
13238 if (retvar != NULL)
13239 set_var(retvar, &v.di_tv, FALSE);
Bram Moolenaar33570922005-01-25 22:26:29 +000013240 vim_free(v.di_tv.vval.v_string);
Bram Moolenaar0d660222005-01-07 21:51:51 +000013241 }
13242#else
13243 rettv->vval.v_number = -1;
13244#endif
13245}
13246
13247/*ARGSUSED*/
13248 static void
13249f_remote_read(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013250 typval_T *argvars;
13251 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013252{
13253 char_u *r = NULL;
13254
13255#ifdef FEAT_CLIENTSERVER
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013256 char_u *serverid = get_tv_string_chk(&argvars[0]);
13257
13258 if (serverid != NULL && !check_restricted() && !check_secure())
Bram Moolenaar0d660222005-01-07 21:51:51 +000013259 {
13260# ifdef WIN32
13261 /* The server's HWND is encoded in the 'id' parameter */
Bram Moolenaareb3593b2006-04-22 22:33:57 +000013262 long_u n = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013263
Bram Moolenaareb3593b2006-04-22 22:33:57 +000013264 sscanf(serverid, SCANF_HEX_LONG_U, &n);
Bram Moolenaar0d660222005-01-07 21:51:51 +000013265 if (n != 0)
13266 r = serverGetReply((HWND)n, FALSE, TRUE, TRUE);
13267 if (r == NULL)
13268# else
13269 if (check_connection() == FAIL || serverReadReply(X_DISPLAY,
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013270 serverStrToWin(serverid), &r, FALSE) < 0)
Bram Moolenaar0d660222005-01-07 21:51:51 +000013271# endif
13272 EMSG(_("E277: Unable to read a server reply"));
13273 }
13274#endif
13275 rettv->v_type = VAR_STRING;
13276 rettv->vval.v_string = r;
13277}
13278
13279/*
13280 * "remote_send()" function
13281 */
13282/*ARGSUSED*/
13283 static void
13284f_remote_send(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013285 typval_T *argvars;
13286 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013287{
13288 rettv->v_type = VAR_STRING;
13289 rettv->vval.v_string = NULL;
13290#ifdef FEAT_CLIENTSERVER
13291 remote_common(argvars, rettv, FALSE);
13292#endif
13293}
13294
13295/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000013296 * "remove()" function
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013297 */
13298 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013299f_remove(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013300 typval_T *argvars;
13301 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013302{
Bram Moolenaar33570922005-01-25 22:26:29 +000013303 list_T *l;
13304 listitem_T *item, *item2;
13305 listitem_T *li;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013306 long idx;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013307 long end;
Bram Moolenaar8c711452005-01-14 21:53:12 +000013308 char_u *key;
Bram Moolenaar33570922005-01-25 22:26:29 +000013309 dict_T *d;
13310 dictitem_T *di;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013311
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013312 rettv->vval.v_number = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +000013313 if (argvars[0].v_type == VAR_DICT)
13314 {
13315 if (argvars[2].v_type != VAR_UNKNOWN)
13316 EMSG2(_(e_toomanyarg), "remove()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000013317 else if ((d = argvars[0].vval.v_dict) != NULL
Bram Moolenaar9dfb0f82006-06-22 16:03:05 +000013318 && !tv_check_lock(d->dv_lock, (char_u *)"remove() argument"))
Bram Moolenaar8c711452005-01-14 21:53:12 +000013319 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013320 key = get_tv_string_chk(&argvars[1]);
13321 if (key != NULL)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000013322 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013323 di = dict_find(d, key, -1);
13324 if (di == NULL)
13325 EMSG2(_(e_dictkey), key);
13326 else
13327 {
13328 *rettv = di->di_tv;
13329 init_tv(&di->di_tv);
13330 dictitem_remove(d, di);
13331 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000013332 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000013333 }
13334 }
13335 else if (argvars[0].v_type != VAR_LIST)
13336 EMSG2(_(e_listdictarg), "remove()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000013337 else if ((l = argvars[0].vval.v_list) != NULL
Bram Moolenaar9dfb0f82006-06-22 16:03:05 +000013338 && !tv_check_lock(l->lv_lock, (char_u *)"remove() argument"))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013339 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013340 int error = FALSE;
13341
13342 idx = get_tv_number_chk(&argvars[1], &error);
13343 if (error)
13344 ; /* type error: do nothing, errmsg already given */
13345 else if ((item = list_find(l, idx)) == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013346 EMSGN(_(e_listidx), idx);
13347 else
13348 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013349 if (argvars[2].v_type == VAR_UNKNOWN)
13350 {
13351 /* Remove one item, return its value. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000013352 list_remove(l, item, item);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013353 *rettv = item->li_tv;
13354 vim_free(item);
13355 }
13356 else
13357 {
13358 /* Remove range of items, return list with values. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013359 end = get_tv_number_chk(&argvars[2], &error);
13360 if (error)
13361 ; /* type error: do nothing */
13362 else if ((item2 = list_find(l, end)) == NULL)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013363 EMSGN(_(e_listidx), end);
13364 else
13365 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000013366 int cnt = 0;
13367
13368 for (li = item; li != NULL; li = li->li_next)
13369 {
13370 ++cnt;
13371 if (li == item2)
13372 break;
13373 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013374 if (li == NULL) /* didn't find "item2" after "item" */
13375 EMSG(_(e_invrange));
13376 else
13377 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000013378 list_remove(l, item, item2);
Bram Moolenaareddf53b2006-02-27 00:11:10 +000013379 if (rettv_list_alloc(rettv) == OK)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013380 {
Bram Moolenaareddf53b2006-02-27 00:11:10 +000013381 l = rettv->vval.v_list;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013382 l->lv_first = item;
13383 l->lv_last = item2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013384 item->li_prev = NULL;
13385 item2->li_next = NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +000013386 l->lv_len = cnt;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013387 }
13388 }
13389 }
13390 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013391 }
13392 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013393}
13394
13395/*
13396 * "rename({from}, {to})" function
13397 */
13398 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013399f_rename(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013400 typval_T *argvars;
13401 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013402{
13403 char_u buf[NUMBUFLEN];
13404
13405 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013406 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013407 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013408 rettv->vval.v_number = vim_rename(get_tv_string(&argvars[0]),
13409 get_tv_string_buf(&argvars[1], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +000013410}
13411
13412/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013413 * "repeat()" function
13414 */
13415/*ARGSUSED*/
13416 static void
13417f_repeat(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013418 typval_T *argvars;
13419 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013420{
13421 char_u *p;
13422 int n;
13423 int slen;
13424 int len;
13425 char_u *r;
13426 int i;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013427
13428 n = get_tv_number(&argvars[1]);
13429 if (argvars[0].v_type == VAR_LIST)
13430 {
Bram Moolenaareddf53b2006-02-27 00:11:10 +000013431 if (rettv_list_alloc(rettv) == OK && argvars[0].vval.v_list != NULL)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013432 while (n-- > 0)
Bram Moolenaareddf53b2006-02-27 00:11:10 +000013433 if (list_extend(rettv->vval.v_list,
13434 argvars[0].vval.v_list, NULL) == FAIL)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013435 break;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013436 }
13437 else
13438 {
13439 p = get_tv_string(&argvars[0]);
13440 rettv->v_type = VAR_STRING;
13441 rettv->vval.v_string = NULL;
13442
13443 slen = (int)STRLEN(p);
13444 len = slen * n;
13445 if (len <= 0)
13446 return;
13447
13448 r = alloc(len + 1);
13449 if (r != NULL)
13450 {
13451 for (i = 0; i < n; i++)
13452 mch_memmove(r + i * slen, p, (size_t)slen);
13453 r[len] = NUL;
13454 }
13455
13456 rettv->vval.v_string = r;
13457 }
13458}
13459
13460/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013461 * "resolve()" function
13462 */
13463 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013464f_resolve(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013465 typval_T *argvars;
13466 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013467{
13468 char_u *p;
13469
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013470 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013471#ifdef FEAT_SHORTCUT
13472 {
13473 char_u *v = NULL;
13474
13475 v = mch_resolve_shortcut(p);
13476 if (v != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013477 rettv->vval.v_string = v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013478 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013479 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013480 }
13481#else
13482# ifdef HAVE_READLINK
13483 {
13484 char_u buf[MAXPATHL + 1];
13485 char_u *cpy;
13486 int len;
13487 char_u *remain = NULL;
13488 char_u *q;
13489 int is_relative_to_current = FALSE;
13490 int has_trailing_pathsep = FALSE;
13491 int limit = 100;
13492
13493 p = vim_strsave(p);
13494
13495 if (p[0] == '.' && (vim_ispathsep(p[1])
13496 || (p[1] == '.' && (vim_ispathsep(p[2])))))
13497 is_relative_to_current = TRUE;
13498
13499 len = STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000013500 if (len > 0 && after_pathsep(p, p + len))
Bram Moolenaar071d4272004-06-13 20:20:40 +000013501 has_trailing_pathsep = TRUE;
13502
13503 q = getnextcomp(p);
13504 if (*q != NUL)
13505 {
13506 /* Separate the first path component in "p", and keep the
13507 * remainder (beginning with the path separator). */
13508 remain = vim_strsave(q - 1);
13509 q[-1] = NUL;
13510 }
13511
13512 for (;;)
13513 {
13514 for (;;)
13515 {
13516 len = readlink((char *)p, (char *)buf, MAXPATHL);
13517 if (len <= 0)
13518 break;
13519 buf[len] = NUL;
13520
13521 if (limit-- == 0)
13522 {
13523 vim_free(p);
13524 vim_free(remain);
13525 EMSG(_("E655: Too many symbolic links (cycle?)"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013526 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013527 goto fail;
13528 }
13529
13530 /* Ensure that the result will have a trailing path separator
13531 * if the argument has one. */
13532 if (remain == NULL && has_trailing_pathsep)
13533 add_pathsep(buf);
13534
13535 /* Separate the first path component in the link value and
13536 * concatenate the remainders. */
13537 q = getnextcomp(vim_ispathsep(*buf) ? buf + 1 : buf);
13538 if (*q != NUL)
13539 {
13540 if (remain == NULL)
13541 remain = vim_strsave(q - 1);
13542 else
13543 {
Bram Moolenaar900b4d72005-12-12 22:05:50 +000013544 cpy = concat_str(q - 1, remain);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013545 if (cpy != NULL)
13546 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000013547 vim_free(remain);
13548 remain = cpy;
13549 }
13550 }
13551 q[-1] = NUL;
13552 }
13553
13554 q = gettail(p);
13555 if (q > p && *q == NUL)
13556 {
13557 /* Ignore trailing path separator. */
13558 q[-1] = NUL;
13559 q = gettail(p);
13560 }
13561 if (q > p && !mch_isFullName(buf))
13562 {
13563 /* symlink is relative to directory of argument */
13564 cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1));
13565 if (cpy != NULL)
13566 {
13567 STRCPY(cpy, p);
13568 STRCPY(gettail(cpy), buf);
13569 vim_free(p);
13570 p = cpy;
13571 }
13572 }
13573 else
13574 {
13575 vim_free(p);
13576 p = vim_strsave(buf);
13577 }
13578 }
13579
13580 if (remain == NULL)
13581 break;
13582
13583 /* Append the first path component of "remain" to "p". */
13584 q = getnextcomp(remain + 1);
13585 len = q - remain - (*q != NUL);
13586 cpy = vim_strnsave(p, STRLEN(p) + len);
13587 if (cpy != NULL)
13588 {
13589 STRNCAT(cpy, remain, len);
13590 vim_free(p);
13591 p = cpy;
13592 }
13593 /* Shorten "remain". */
13594 if (*q != NUL)
13595 STRCPY(remain, q - 1);
13596 else
13597 {
13598 vim_free(remain);
13599 remain = NULL;
13600 }
13601 }
13602
13603 /* If the result is a relative path name, make it explicitly relative to
13604 * the current directory if and only if the argument had this form. */
13605 if (!vim_ispathsep(*p))
13606 {
13607 if (is_relative_to_current
13608 && *p != NUL
13609 && !(p[0] == '.'
13610 && (p[1] == NUL
13611 || vim_ispathsep(p[1])
13612 || (p[1] == '.'
13613 && (p[2] == NUL
13614 || vim_ispathsep(p[2]))))))
13615 {
13616 /* Prepend "./". */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000013617 cpy = concat_str((char_u *)"./", p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013618 if (cpy != NULL)
13619 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000013620 vim_free(p);
13621 p = cpy;
13622 }
13623 }
13624 else if (!is_relative_to_current)
13625 {
13626 /* Strip leading "./". */
13627 q = p;
13628 while (q[0] == '.' && vim_ispathsep(q[1]))
13629 q += 2;
13630 if (q > p)
13631 mch_memmove(p, p + 2, STRLEN(p + 2) + (size_t)1);
13632 }
13633 }
13634
13635 /* Ensure that the result will have no trailing path separator
13636 * if the argument had none. But keep "/" or "//". */
13637 if (!has_trailing_pathsep)
13638 {
13639 q = p + STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000013640 if (after_pathsep(p, q))
13641 *gettail_sep(p) = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013642 }
13643
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013644 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013645 }
13646# else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013647 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013648# endif
13649#endif
13650
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013651 simplify_filename(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013652
13653#ifdef HAVE_READLINK
13654fail:
13655#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013656 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013657}
13658
13659/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000013660 * "reverse({list})" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000013661 */
13662 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000013663f_reverse(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013664 typval_T *argvars;
13665 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013666{
Bram Moolenaar33570922005-01-25 22:26:29 +000013667 list_T *l;
13668 listitem_T *li, *ni;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013669
Bram Moolenaar0d660222005-01-07 21:51:51 +000013670 rettv->vval.v_number = 0;
13671 if (argvars[0].v_type != VAR_LIST)
13672 EMSG2(_(e_listarg), "reverse()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000013673 else if ((l = argvars[0].vval.v_list) != NULL
13674 && !tv_check_lock(l->lv_lock, (char_u *)"reverse()"))
Bram Moolenaar0d660222005-01-07 21:51:51 +000013675 {
13676 li = l->lv_last;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000013677 l->lv_first = l->lv_last = NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +000013678 l->lv_len = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013679 while (li != NULL)
13680 {
13681 ni = li->li_prev;
13682 list_append(l, li);
13683 li = ni;
13684 }
13685 rettv->vval.v_list = l;
13686 rettv->v_type = VAR_LIST;
13687 ++l->lv_refcount;
13688 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013689}
13690
Bram Moolenaar768b8c42006-03-04 21:58:33 +000013691#define SP_NOMOVE 0x01 /* don't move cursor */
13692#define SP_REPEAT 0x02 /* repeat to find outer pair */
13693#define SP_RETCOUNT 0x04 /* return matchcount */
13694#define SP_SETPCMARK 0x08 /* set previous context mark */
13695#define SP_START 0x10 /* accept match at start position */
13696#define SP_SUBPAT 0x20 /* return nr of matching sub-pattern */
13697#define SP_END 0x40 /* leave cursor at end of match */
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013698
Bram Moolenaar33570922005-01-25 22:26:29 +000013699static int get_search_arg __ARGS((typval_T *varp, int *flagsp));
Bram Moolenaar0d660222005-01-07 21:51:51 +000013700
13701/*
13702 * Get flags for a search function.
13703 * Possibly sets "p_ws".
13704 * Returns BACKWARD, FORWARD or zero (for an error).
13705 */
13706 static int
13707get_search_arg(varp, flagsp)
Bram Moolenaar33570922005-01-25 22:26:29 +000013708 typval_T *varp;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013709 int *flagsp;
13710{
13711 int dir = FORWARD;
13712 char_u *flags;
13713 char_u nbuf[NUMBUFLEN];
13714 int mask;
13715
13716 if (varp->v_type != VAR_UNKNOWN)
13717 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013718 flags = get_tv_string_buf_chk(varp, nbuf);
13719 if (flags == NULL)
13720 return 0; /* type error; errmsg already given */
Bram Moolenaar0d660222005-01-07 21:51:51 +000013721 while (*flags != NUL)
13722 {
13723 switch (*flags)
13724 {
13725 case 'b': dir = BACKWARD; break;
13726 case 'w': p_ws = TRUE; break;
13727 case 'W': p_ws = FALSE; break;
13728 default: mask = 0;
13729 if (flagsp != NULL)
13730 switch (*flags)
13731 {
Bram Moolenaar0e34f622006-03-03 23:00:03 +000013732 case 'c': mask = SP_START; break;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000013733 case 'e': mask = SP_END; break;
13734 case 'm': mask = SP_RETCOUNT; break;
13735 case 'n': mask = SP_NOMOVE; break;
13736 case 'p': mask = SP_SUBPAT; break;
13737 case 'r': mask = SP_REPEAT; break;
13738 case 's': mask = SP_SETPCMARK; break;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013739 }
13740 if (mask == 0)
13741 {
13742 EMSG2(_(e_invarg2), flags);
13743 dir = 0;
13744 }
13745 else
13746 *flagsp |= mask;
13747 }
13748 if (dir == 0)
13749 break;
13750 ++flags;
13751 }
13752 }
13753 return dir;
13754}
13755
Bram Moolenaar071d4272004-06-13 20:20:40 +000013756/*
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000013757 * Shared by search() and searchpos() functions
Bram Moolenaar071d4272004-06-13 20:20:40 +000013758 */
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000013759 static int
Bram Moolenaar362e1a32006-03-06 23:29:24 +000013760search_cmn(argvars, match_pos, flagsp)
Bram Moolenaar33570922005-01-25 22:26:29 +000013761 typval_T *argvars;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000013762 pos_T *match_pos;
Bram Moolenaar362e1a32006-03-06 23:29:24 +000013763 int *flagsp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013764{
Bram Moolenaar362e1a32006-03-06 23:29:24 +000013765 int flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013766 char_u *pat;
13767 pos_T pos;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013768 pos_T save_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013769 int save_p_ws = p_ws;
13770 int dir;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000013771 int retval = 0; /* default: FAIL */
Bram Moolenaareddf53b2006-02-27 00:11:10 +000013772 long lnum_stop = 0;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000013773 int options = SEARCH_KEEP;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000013774 int subpatnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013775
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013776 pat = get_tv_string(&argvars[0]);
Bram Moolenaar362e1a32006-03-06 23:29:24 +000013777 dir = get_search_arg(&argvars[1], flagsp); /* may set p_ws */
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013778 if (dir == 0)
13779 goto theend;
Bram Moolenaar362e1a32006-03-06 23:29:24 +000013780 flags = *flagsp;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000013781 if (flags & SP_START)
13782 options |= SEARCH_START;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000013783 if (flags & SP_END)
13784 options |= SEARCH_END;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000013785
13786 /* Optional extra argument: line number to stop searching. */
13787 if (argvars[1].v_type != VAR_UNKNOWN
13788 && argvars[2].v_type != VAR_UNKNOWN)
13789 {
13790 lnum_stop = get_tv_number_chk(&argvars[2], NULL);
13791 if (lnum_stop < 0)
13792 goto theend;
13793 }
13794
Bram Moolenaar231334e2005-07-25 20:46:57 +000013795 /*
Bram Moolenaar768b8c42006-03-04 21:58:33 +000013796 * This function does not accept SP_REPEAT and SP_RETCOUNT flags.
Bram Moolenaar231334e2005-07-25 20:46:57 +000013797 * Check to make sure only those flags are set.
13798 * Also, Only the SP_NOMOVE or the SP_SETPCMARK flag can be set. Both
13799 * flags cannot be set. Check for that condition also.
13800 */
Bram Moolenaar768b8c42006-03-04 21:58:33 +000013801 if (((flags & (SP_REPEAT | SP_RETCOUNT)) != 0)
Bram Moolenaar0e34f622006-03-03 23:00:03 +000013802 || ((flags & SP_NOMOVE) && (flags & SP_SETPCMARK)))
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013803 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013804 EMSG2(_(e_invarg2), get_tv_string(&argvars[1]));
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013805 goto theend;
13806 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013807
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013808 pos = save_cursor = curwin->w_cursor;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000013809 subpatnum = searchit(curwin, curbuf, &pos, dir, pat, 1L,
13810 options, RE_SEARCH, (linenr_T)lnum_stop);
13811 if (subpatnum != FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013812 {
Bram Moolenaar768b8c42006-03-04 21:58:33 +000013813 if (flags & SP_SUBPAT)
13814 retval = subpatnum;
13815 else
13816 retval = pos.lnum;
Bram Moolenaar231334e2005-07-25 20:46:57 +000013817 if (flags & SP_SETPCMARK)
13818 setpcmark();
Bram Moolenaar071d4272004-06-13 20:20:40 +000013819 curwin->w_cursor = pos;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000013820 if (match_pos != NULL)
13821 {
13822 /* Store the match cursor position */
13823 match_pos->lnum = pos.lnum;
13824 match_pos->col = pos.col + 1;
13825 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013826 /* "/$" will put the cursor after the end of the line, may need to
13827 * correct that here */
13828 check_cursor();
13829 }
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013830
13831 /* If 'n' flag is used: restore cursor position. */
13832 if (flags & SP_NOMOVE)
13833 curwin->w_cursor = save_cursor;
13834theend:
Bram Moolenaar071d4272004-06-13 20:20:40 +000013835 p_ws = save_p_ws;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000013836
13837 return retval;
13838}
13839
13840/*
13841 * "search()" function
13842 */
13843 static void
13844f_search(argvars, rettv)
13845 typval_T *argvars;
13846 typval_T *rettv;
13847{
Bram Moolenaar362e1a32006-03-06 23:29:24 +000013848 int flags = 0;
13849
13850 rettv->vval.v_number = search_cmn(argvars, NULL, &flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013851}
13852
Bram Moolenaar071d4272004-06-13 20:20:40 +000013853/*
Bram Moolenaardd2436f2005-09-05 22:14:46 +000013854 * "searchdecl()" function
13855 */
13856 static void
13857f_searchdecl(argvars, rettv)
13858 typval_T *argvars;
13859 typval_T *rettv;
13860{
13861 int locally = 1;
Bram Moolenaare6facf92005-09-13 21:22:27 +000013862 int thisblock = 0;
Bram Moolenaardd2436f2005-09-05 22:14:46 +000013863 int error = FALSE;
13864 char_u *name;
13865
13866 rettv->vval.v_number = 1; /* default: FAIL */
13867
13868 name = get_tv_string_chk(&argvars[0]);
13869 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaare6facf92005-09-13 21:22:27 +000013870 {
Bram Moolenaardd2436f2005-09-05 22:14:46 +000013871 locally = get_tv_number_chk(&argvars[1], &error) == 0;
Bram Moolenaare6facf92005-09-13 21:22:27 +000013872 if (!error && argvars[2].v_type != VAR_UNKNOWN)
13873 thisblock = get_tv_number_chk(&argvars[2], &error) != 0;
13874 }
Bram Moolenaardd2436f2005-09-05 22:14:46 +000013875 if (!error && name != NULL)
13876 rettv->vval.v_number = find_decl(name, (int)STRLEN(name),
Bram Moolenaare6facf92005-09-13 21:22:27 +000013877 locally, thisblock, SEARCH_KEEP) == FAIL;
Bram Moolenaardd2436f2005-09-05 22:14:46 +000013878}
13879
13880/*
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000013881 * Used by searchpair() and searchpairpos()
Bram Moolenaar071d4272004-06-13 20:20:40 +000013882 */
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000013883 static int
13884searchpair_cmn(argvars, match_pos)
Bram Moolenaar33570922005-01-25 22:26:29 +000013885 typval_T *argvars;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000013886 pos_T *match_pos;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013887{
13888 char_u *spat, *mpat, *epat;
13889 char_u *skip;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013890 int save_p_ws = p_ws;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013891 int dir;
13892 int flags = 0;
13893 char_u nbuf1[NUMBUFLEN];
13894 char_u nbuf2[NUMBUFLEN];
13895 char_u nbuf3[NUMBUFLEN];
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000013896 int retval = 0; /* default: FAIL */
Bram Moolenaareddf53b2006-02-27 00:11:10 +000013897 long lnum_stop = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013898
Bram Moolenaar071d4272004-06-13 20:20:40 +000013899 /* Get the three pattern arguments: start, middle, end. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013900 spat = get_tv_string_chk(&argvars[0]);
13901 mpat = get_tv_string_buf_chk(&argvars[1], nbuf1);
13902 epat = get_tv_string_buf_chk(&argvars[2], nbuf2);
13903 if (spat == NULL || mpat == NULL || epat == NULL)
13904 goto theend; /* type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013905
Bram Moolenaar071d4272004-06-13 20:20:40 +000013906 /* Handle the optional fourth argument: flags */
13907 dir = get_search_arg(&argvars[3], &flags); /* may set p_ws */
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013908 if (dir == 0)
13909 goto theend;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000013910
13911 /* Don't accept SP_END or SP_SUBPAT.
Bram Moolenaar231334e2005-07-25 20:46:57 +000013912 * Only one of the SP_NOMOVE or SP_SETPCMARK flags can be set.
13913 */
Bram Moolenaar768b8c42006-03-04 21:58:33 +000013914 if ((flags & (SP_END | SP_SUBPAT)) != 0
13915 || ((flags & SP_NOMOVE) && (flags & SP_SETPCMARK)))
Bram Moolenaar231334e2005-07-25 20:46:57 +000013916 {
Bram Moolenaar768b8c42006-03-04 21:58:33 +000013917 EMSG2(_(e_invarg2), get_tv_string(&argvars[3]));
Bram Moolenaar231334e2005-07-25 20:46:57 +000013918 goto theend;
13919 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013920
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000013921 /* Optional fifth argument: skip expression */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013922 if (argvars[3].v_type == VAR_UNKNOWN
13923 || argvars[4].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013924 skip = (char_u *)"";
13925 else
Bram Moolenaareddf53b2006-02-27 00:11:10 +000013926 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013927 skip = get_tv_string_buf_chk(&argvars[4], nbuf3);
Bram Moolenaareddf53b2006-02-27 00:11:10 +000013928 if (argvars[5].v_type != VAR_UNKNOWN)
13929 {
13930 lnum_stop = get_tv_number_chk(&argvars[5], NULL);
13931 if (lnum_stop < 0)
13932 goto theend;
13933 }
13934 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013935 if (skip == NULL)
13936 goto theend; /* type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013937
Bram Moolenaareddf53b2006-02-27 00:11:10 +000013938 retval = do_searchpair(spat, mpat, epat, dir, skip, flags,
13939 match_pos, lnum_stop);
Bram Moolenaar9fad3082005-07-19 22:22:13 +000013940
13941theend:
13942 p_ws = save_p_ws;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000013943
13944 return retval;
13945}
13946
13947/*
13948 * "searchpair()" function
13949 */
13950 static void
13951f_searchpair(argvars, rettv)
13952 typval_T *argvars;
13953 typval_T *rettv;
13954{
13955 rettv->vval.v_number = searchpair_cmn(argvars, NULL);
13956}
13957
13958/*
13959 * "searchpairpos()" function
13960 */
13961 static void
13962f_searchpairpos(argvars, rettv)
13963 typval_T *argvars;
13964 typval_T *rettv;
13965{
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000013966 pos_T match_pos;
13967 int lnum = 0;
13968 int col = 0;
13969
13970 rettv->vval.v_number = 0;
13971
Bram Moolenaareddf53b2006-02-27 00:11:10 +000013972 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000013973 return;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000013974
13975 if (searchpair_cmn(argvars, &match_pos) > 0)
13976 {
13977 lnum = match_pos.lnum;
13978 col = match_pos.col;
13979 }
13980
Bram Moolenaareddf53b2006-02-27 00:11:10 +000013981 list_append_number(rettv->vval.v_list, (varnumber_T)lnum);
13982 list_append_number(rettv->vval.v_list, (varnumber_T)col);
Bram Moolenaar9fad3082005-07-19 22:22:13 +000013983}
13984
13985/*
13986 * Search for a start/middle/end thing.
13987 * Used by searchpair(), see its documentation for the details.
13988 * Returns 0 or -1 for no match,
13989 */
13990 long
Bram Moolenaareddf53b2006-02-27 00:11:10 +000013991do_searchpair(spat, mpat, epat, dir, skip, flags, match_pos, lnum_stop)
Bram Moolenaar9fad3082005-07-19 22:22:13 +000013992 char_u *spat; /* start pattern */
13993 char_u *mpat; /* middle pattern */
13994 char_u *epat; /* end pattern */
13995 int dir; /* BACKWARD or FORWARD */
13996 char_u *skip; /* skip expression */
Bram Moolenaar768b8c42006-03-04 21:58:33 +000013997 int flags; /* SP_SETPCMARK and other SP_ values */
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000013998 pos_T *match_pos;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000013999 linenr_T lnum_stop; /* stop at this line if not zero */
Bram Moolenaar9fad3082005-07-19 22:22:13 +000014000{
14001 char_u *save_cpo;
14002 char_u *pat, *pat2 = NULL, *pat3 = NULL;
14003 long retval = 0;
14004 pos_T pos;
14005 pos_T firstpos;
14006 pos_T foundpos;
14007 pos_T save_cursor;
14008 pos_T save_pos;
14009 int n;
14010 int r;
14011 int nest = 1;
14012 int err;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000014013 int options = SEARCH_KEEP;
Bram Moolenaar9fad3082005-07-19 22:22:13 +000014014
14015 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
14016 save_cpo = p_cpo;
14017 p_cpo = (char_u *)"";
14018
14019 /* Make two search patterns: start/end (pat2, for in nested pairs) and
14020 * start/middle/end (pat3, for the top pair). */
14021 pat2 = alloc((unsigned)(STRLEN(spat) + STRLEN(epat) + 15));
14022 pat3 = alloc((unsigned)(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 23));
14023 if (pat2 == NULL || pat3 == NULL)
14024 goto theend;
14025 sprintf((char *)pat2, "\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat);
14026 if (*mpat == NUL)
14027 STRCPY(pat3, pat2);
14028 else
14029 sprintf((char *)pat3, "\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)",
14030 spat, epat, mpat);
Bram Moolenaar0e34f622006-03-03 23:00:03 +000014031 if (flags & SP_START)
14032 options |= SEARCH_START;
Bram Moolenaar9fad3082005-07-19 22:22:13 +000014033
Bram Moolenaar071d4272004-06-13 20:20:40 +000014034 save_cursor = curwin->w_cursor;
14035 pos = curwin->w_cursor;
Bram Moolenaar261bfea2006-03-01 22:12:31 +000014036 clearpos(&firstpos);
14037 clearpos(&foundpos);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014038 pat = pat3;
14039 for (;;)
14040 {
14041 n = searchit(curwin, curbuf, &pos, dir, pat, 1L,
Bram Moolenaar0e34f622006-03-03 23:00:03 +000014042 options, RE_SEARCH, lnum_stop);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014043 if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos)))
14044 /* didn't find it or found the first match again: FAIL */
14045 break;
14046
14047 if (firstpos.lnum == 0)
14048 firstpos = pos;
Bram Moolenaarc9a2d2e2005-04-24 22:09:56 +000014049 if (equalpos(pos, foundpos))
14050 {
14051 /* Found the same position again. Can happen with a pattern that
14052 * has "\zs" at the end and searching backwards. Advance one
14053 * character and try again. */
14054 if (dir == BACKWARD)
14055 decl(&pos);
14056 else
14057 incl(&pos);
14058 }
14059 foundpos = pos;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014060
14061 /* If the skip pattern matches, ignore this match. */
14062 if (*skip != NUL)
14063 {
14064 save_pos = curwin->w_cursor;
14065 curwin->w_cursor = pos;
14066 r = eval_to_bool(skip, &err, NULL, FALSE);
14067 curwin->w_cursor = save_pos;
14068 if (err)
14069 {
14070 /* Evaluating {skip} caused an error, break here. */
14071 curwin->w_cursor = save_cursor;
Bram Moolenaar9fad3082005-07-19 22:22:13 +000014072 retval = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014073 break;
14074 }
14075 if (r)
14076 continue;
14077 }
14078
14079 if ((dir == BACKWARD && n == 3) || (dir == FORWARD && n == 2))
14080 {
14081 /* Found end when searching backwards or start when searching
14082 * forward: nested pair. */
14083 ++nest;
14084 pat = pat2; /* nested, don't search for middle */
14085 }
14086 else
14087 {
14088 /* Found end when searching forward or start when searching
14089 * backward: end of (nested) pair; or found middle in outer pair. */
14090 if (--nest == 1)
14091 pat = pat3; /* outer level, search for middle */
14092 }
14093
14094 if (nest == 0)
14095 {
14096 /* Found the match: return matchcount or line number. */
14097 if (flags & SP_RETCOUNT)
Bram Moolenaar9fad3082005-07-19 22:22:13 +000014098 ++retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014099 else
Bram Moolenaar9fad3082005-07-19 22:22:13 +000014100 retval = pos.lnum;
Bram Moolenaar231334e2005-07-25 20:46:57 +000014101 if (flags & SP_SETPCMARK)
14102 setpcmark();
Bram Moolenaar071d4272004-06-13 20:20:40 +000014103 curwin->w_cursor = pos;
14104 if (!(flags & SP_REPEAT))
14105 break;
14106 nest = 1; /* search for next unmatched */
14107 }
14108 }
14109
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000014110 if (match_pos != NULL)
14111 {
14112 /* Store the match cursor position */
14113 match_pos->lnum = curwin->w_cursor.lnum;
14114 match_pos->col = curwin->w_cursor.col + 1;
14115 }
14116
Bram Moolenaar071d4272004-06-13 20:20:40 +000014117 /* If 'n' flag is used or search failed: restore cursor position. */
Bram Moolenaar9fad3082005-07-19 22:22:13 +000014118 if ((flags & SP_NOMOVE) || retval == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014119 curwin->w_cursor = save_cursor;
14120
14121theend:
14122 vim_free(pat2);
14123 vim_free(pat3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014124 p_cpo = save_cpo;
Bram Moolenaar9fad3082005-07-19 22:22:13 +000014125
14126 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014127}
14128
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000014129/*
14130 * "searchpos()" function
14131 */
14132 static void
14133f_searchpos(argvars, rettv)
14134 typval_T *argvars;
14135 typval_T *rettv;
14136{
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000014137 pos_T match_pos;
14138 int lnum = 0;
14139 int col = 0;
Bram Moolenaar362e1a32006-03-06 23:29:24 +000014140 int n;
14141 int flags = 0;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000014142
14143 rettv->vval.v_number = 0;
14144
Bram Moolenaareddf53b2006-02-27 00:11:10 +000014145 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000014146 return;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000014147
Bram Moolenaar362e1a32006-03-06 23:29:24 +000014148 n = search_cmn(argvars, &match_pos, &flags);
14149 if (n > 0)
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000014150 {
14151 lnum = match_pos.lnum;
14152 col = match_pos.col;
14153 }
14154
Bram Moolenaareddf53b2006-02-27 00:11:10 +000014155 list_append_number(rettv->vval.v_list, (varnumber_T)lnum);
14156 list_append_number(rettv->vval.v_list, (varnumber_T)col);
Bram Moolenaar362e1a32006-03-06 23:29:24 +000014157 if (flags & SP_SUBPAT)
14158 list_append_number(rettv->vval.v_list, (varnumber_T)n);
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000014159}
14160
14161
Bram Moolenaar0d660222005-01-07 21:51:51 +000014162/*ARGSUSED*/
14163 static void
14164f_server2client(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014165 typval_T *argvars;
14166 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014167{
Bram Moolenaar0d660222005-01-07 21:51:51 +000014168#ifdef FEAT_CLIENTSERVER
14169 char_u buf[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014170 char_u *server = get_tv_string_chk(&argvars[0]);
14171 char_u *reply = get_tv_string_buf_chk(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014172
Bram Moolenaar0d660222005-01-07 21:51:51 +000014173 rettv->vval.v_number = -1;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014174 if (server == NULL || reply == NULL)
14175 return;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014176 if (check_restricted() || check_secure())
14177 return;
14178# ifdef FEAT_X11
14179 if (check_connection() == FAIL)
14180 return;
14181# endif
14182
14183 if (serverSendReply(server, reply) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014184 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000014185 EMSG(_("E258: Unable to send to client"));
14186 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014187 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000014188 rettv->vval.v_number = 0;
14189#else
14190 rettv->vval.v_number = -1;
14191#endif
14192}
14193
14194/*ARGSUSED*/
14195 static void
14196f_serverlist(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014197 typval_T *argvars;
14198 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014199{
14200 char_u *r = NULL;
14201
14202#ifdef FEAT_CLIENTSERVER
14203# ifdef WIN32
14204 r = serverGetVimNames();
14205# else
14206 make_connection();
14207 if (X_DISPLAY != NULL)
14208 r = serverGetVimNames(X_DISPLAY);
14209# endif
14210#endif
14211 rettv->v_type = VAR_STRING;
14212 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014213}
14214
14215/*
14216 * "setbufvar()" function
14217 */
14218/*ARGSUSED*/
14219 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014220f_setbufvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014221 typval_T *argvars;
14222 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014223{
14224 buf_T *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014225 aco_save_T aco;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014226 char_u *varname, *bufvarname;
Bram Moolenaar33570922005-01-25 22:26:29 +000014227 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014228 char_u nbuf[NUMBUFLEN];
14229
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014230 rettv->vval.v_number = 0;
14231
Bram Moolenaar071d4272004-06-13 20:20:40 +000014232 if (check_restricted() || check_secure())
14233 return;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014234 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
14235 varname = get_tv_string_chk(&argvars[1]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014236 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014237 varp = &argvars[2];
14238
14239 if (buf != NULL && varname != NULL && varp != NULL)
14240 {
14241 /* set curbuf to be our buf, temporarily */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014242 aucmd_prepbuf(&aco, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014243
14244 if (*varname == '&')
14245 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014246 long numval;
14247 char_u *strval;
14248 int error = FALSE;
14249
Bram Moolenaar071d4272004-06-13 20:20:40 +000014250 ++varname;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014251 numval = get_tv_number_chk(varp, &error);
14252 strval = get_tv_string_buf_chk(varp, nbuf);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014253 if (!error && strval != NULL)
14254 set_option_value(varname, numval, strval, OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014255 }
14256 else
14257 {
14258 bufvarname = alloc((unsigned)STRLEN(varname) + 3);
14259 if (bufvarname != NULL)
14260 {
14261 STRCPY(bufvarname, "b:");
14262 STRCPY(bufvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000014263 set_var(bufvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014264 vim_free(bufvarname);
14265 }
14266 }
14267
14268 /* reset notion of buffer */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014269 aucmd_restbuf(&aco);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014270 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014271}
14272
14273/*
14274 * "setcmdpos()" function
14275 */
14276 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014277f_setcmdpos(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014278 typval_T *argvars;
14279 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014280{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014281 int pos = (int)get_tv_number(&argvars[0]) - 1;
14282
14283 if (pos >= 0)
14284 rettv->vval.v_number = set_cmdline_pos(pos);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014285}
14286
14287/*
14288 * "setline()" function
14289 */
14290 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014291f_setline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014292 typval_T *argvars;
14293 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014294{
14295 linenr_T lnum;
Bram Moolenaar0e6830e2005-05-27 20:23:44 +000014296 char_u *line = NULL;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014297 list_T *l = NULL;
14298 listitem_T *li = NULL;
14299 long added = 0;
14300 linenr_T lcount = curbuf->b_ml.ml_line_count;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014301
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014302 lnum = get_tv_lnum(&argvars[0]);
14303 if (argvars[1].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014304 {
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014305 l = argvars[1].vval.v_list;
14306 li = l->lv_first;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014307 }
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014308 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014309 line = get_tv_string_chk(&argvars[1]);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014310
14311 rettv->vval.v_number = 0; /* OK */
14312 for (;;)
14313 {
14314 if (l != NULL)
14315 {
14316 /* list argument, get next string */
14317 if (li == NULL)
14318 break;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014319 line = get_tv_string_chk(&li->li_tv);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014320 li = li->li_next;
14321 }
14322
14323 rettv->vval.v_number = 1; /* FAIL */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014324 if (line == NULL || lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014325 break;
14326 if (lnum <= curbuf->b_ml.ml_line_count)
14327 {
14328 /* existing line, replace it */
14329 if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK)
14330 {
14331 changed_bytes(lnum, 0);
14332 check_cursor_col();
14333 rettv->vval.v_number = 0; /* OK */
14334 }
14335 }
14336 else if (added > 0 || u_save(lnum - 1, lnum) == OK)
14337 {
14338 /* lnum is one past the last line, append the line */
14339 ++added;
14340 if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK)
14341 rettv->vval.v_number = 0; /* OK */
14342 }
14343
14344 if (l == NULL) /* only one string argument */
14345 break;
14346 ++lnum;
14347 }
14348
14349 if (added > 0)
14350 appended_lines_mark(lcount, added);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014351}
14352
14353/*
Bram Moolenaar17c7c012006-01-26 22:25:15 +000014354 * Used by "setqflist()" and "setloclist()" functions
Bram Moolenaar2641f772005-03-25 21:58:17 +000014355 */
14356/*ARGSUSED*/
14357 static void
Bram Moolenaar17c7c012006-01-26 22:25:15 +000014358set_qf_ll_list(wp, list_arg, action_arg, rettv)
14359 win_T *wp;
14360 typval_T *list_arg;
14361 typval_T *action_arg;
Bram Moolenaar2641f772005-03-25 21:58:17 +000014362 typval_T *rettv;
14363{
Bram Moolenaar0ac93792006-01-21 22:16:51 +000014364#ifdef FEAT_QUICKFIX
Bram Moolenaarf4630b62005-05-20 21:31:17 +000014365 char_u *act;
14366 int action = ' ';
Bram Moolenaar0ac93792006-01-21 22:16:51 +000014367#endif
Bram Moolenaarf4630b62005-05-20 21:31:17 +000014368
Bram Moolenaar2641f772005-03-25 21:58:17 +000014369 rettv->vval.v_number = -1;
14370
14371#ifdef FEAT_QUICKFIX
Bram Moolenaar17c7c012006-01-26 22:25:15 +000014372 if (list_arg->v_type != VAR_LIST)
Bram Moolenaar2641f772005-03-25 21:58:17 +000014373 EMSG(_(e_listreq));
14374 else
14375 {
Bram Moolenaar17c7c012006-01-26 22:25:15 +000014376 list_T *l = list_arg->vval.v_list;
Bram Moolenaar2641f772005-03-25 21:58:17 +000014377
Bram Moolenaar17c7c012006-01-26 22:25:15 +000014378 if (action_arg->v_type == VAR_STRING)
Bram Moolenaarf4630b62005-05-20 21:31:17 +000014379 {
Bram Moolenaar17c7c012006-01-26 22:25:15 +000014380 act = get_tv_string_chk(action_arg);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014381 if (act == NULL)
14382 return; /* type error; errmsg already given */
Bram Moolenaarf4630b62005-05-20 21:31:17 +000014383 if (*act == 'a' || *act == 'r')
14384 action = *act;
14385 }
14386
Bram Moolenaar17c7c012006-01-26 22:25:15 +000014387 if (l != NULL && set_errorlist(wp, l, action) == OK)
Bram Moolenaar2641f772005-03-25 21:58:17 +000014388 rettv->vval.v_number = 0;
14389 }
14390#endif
14391}
14392
14393/*
Bram Moolenaar17c7c012006-01-26 22:25:15 +000014394 * "setloclist()" function
14395 */
14396/*ARGSUSED*/
14397 static void
14398f_setloclist(argvars, rettv)
14399 typval_T *argvars;
14400 typval_T *rettv;
14401{
14402 win_T *win;
14403
14404 rettv->vval.v_number = -1;
14405
Bram Moolenaar99ebf042006-04-15 20:28:54 +000014406 win = find_win_by_nr(&argvars[0], NULL);
Bram Moolenaar17c7c012006-01-26 22:25:15 +000014407 if (win != NULL)
14408 set_qf_ll_list(win, &argvars[1], &argvars[2], rettv);
14409}
14410
14411/*
Bram Moolenaar0e34f622006-03-03 23:00:03 +000014412 * "setpos()" function
14413 */
14414/*ARGSUSED*/
14415 static void
14416f_setpos(argvars, rettv)
14417 typval_T *argvars;
14418 typval_T *rettv;
14419{
14420 pos_T pos;
14421 int fnum;
14422 char_u *name;
14423
14424 name = get_tv_string_chk(argvars);
14425 if (name != NULL)
14426 {
14427 if (list2fpos(&argvars[1], &pos, &fnum) == OK)
14428 {
14429 --pos.col;
14430 if (name[0] == '.') /* cursor */
14431 {
14432 if (fnum == curbuf->b_fnum)
14433 {
14434 curwin->w_cursor = pos;
14435 check_cursor();
14436 }
14437 else
14438 EMSG(_(e_invarg));
14439 }
14440 else if (name[0] == '\'') /* mark */
14441 (void)setmark_pos(name[1], &pos, fnum);
14442 else
14443 EMSG(_(e_invarg));
14444 }
14445 }
14446}
14447
14448/*
Bram Moolenaar17c7c012006-01-26 22:25:15 +000014449 * "setqflist()" function
14450 */
14451/*ARGSUSED*/
14452 static void
14453f_setqflist(argvars, rettv)
14454 typval_T *argvars;
14455 typval_T *rettv;
14456{
14457 set_qf_ll_list(NULL, &argvars[0], &argvars[1], rettv);
14458}
14459
14460/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014461 * "setreg()" function
14462 */
14463 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014464f_setreg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014465 typval_T *argvars;
14466 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014467{
14468 int regname;
14469 char_u *strregname;
14470 char_u *stropt;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014471 char_u *strval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014472 int append;
14473 char_u yank_type;
14474 long block_len;
14475
14476 block_len = -1;
14477 yank_type = MAUTO;
14478 append = FALSE;
14479
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014480 strregname = get_tv_string_chk(argvars);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014481 rettv->vval.v_number = 1; /* FAIL is default */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014482
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014483 if (strregname == NULL)
14484 return; /* type error; errmsg already given */
14485 regname = *strregname;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014486 if (regname == 0 || regname == '@')
14487 regname = '"';
14488 else if (regname == '=')
14489 return;
14490
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014491 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014492 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014493 stropt = get_tv_string_chk(&argvars[2]);
14494 if (stropt == NULL)
14495 return; /* type error */
14496 for (; *stropt != NUL; ++stropt)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014497 switch (*stropt)
14498 {
14499 case 'a': case 'A': /* append */
14500 append = TRUE;
14501 break;
14502 case 'v': case 'c': /* character-wise selection */
14503 yank_type = MCHAR;
14504 break;
14505 case 'V': case 'l': /* line-wise selection */
14506 yank_type = MLINE;
14507 break;
14508#ifdef FEAT_VISUAL
14509 case 'b': case Ctrl_V: /* block-wise selection */
14510 yank_type = MBLOCK;
14511 if (VIM_ISDIGIT(stropt[1]))
14512 {
14513 ++stropt;
14514 block_len = getdigits(&stropt) - 1;
14515 --stropt;
14516 }
14517 break;
14518#endif
14519 }
14520 }
14521
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014522 strval = get_tv_string_chk(&argvars[1]);
14523 if (strval != NULL)
14524 write_reg_contents_ex(regname, strval, -1,
Bram Moolenaar071d4272004-06-13 20:20:40 +000014525 append, yank_type, block_len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014526 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014527}
14528
Bram Moolenaar99ebf042006-04-15 20:28:54 +000014529/*
14530 * "settabwinvar()" function
14531 */
14532 static void
14533f_settabwinvar(argvars, rettv)
14534 typval_T *argvars;
14535 typval_T *rettv;
14536{
14537 setwinvar(argvars, rettv, 1);
14538}
Bram Moolenaar071d4272004-06-13 20:20:40 +000014539
14540/*
Bram Moolenaar99ebf042006-04-15 20:28:54 +000014541 * "setwinvar()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000014542 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014543 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014544f_setwinvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014545 typval_T *argvars;
14546 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014547{
Bram Moolenaar99ebf042006-04-15 20:28:54 +000014548 setwinvar(argvars, rettv, 0);
14549}
14550
14551/*
14552 * "setwinvar()" and "settabwinvar()" functions
14553 */
14554 static void
14555setwinvar(argvars, rettv, off)
14556 typval_T *argvars;
14557 typval_T *rettv;
14558 int off;
14559{
Bram Moolenaar071d4272004-06-13 20:20:40 +000014560 win_T *win;
14561#ifdef FEAT_WINDOWS
14562 win_T *save_curwin;
Bram Moolenaar99ebf042006-04-15 20:28:54 +000014563 tabpage_T *save_curtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014564#endif
14565 char_u *varname, *winvarname;
Bram Moolenaar33570922005-01-25 22:26:29 +000014566 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014567 char_u nbuf[NUMBUFLEN];
Bram Moolenaar99ebf042006-04-15 20:28:54 +000014568 tabpage_T *tp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014569
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014570 rettv->vval.v_number = 0;
14571
Bram Moolenaar071d4272004-06-13 20:20:40 +000014572 if (check_restricted() || check_secure())
14573 return;
Bram Moolenaar99ebf042006-04-15 20:28:54 +000014574
14575#ifdef FEAT_WINDOWS
14576 if (off == 1)
14577 tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL));
14578 else
14579 tp = curtab;
14580#endif
14581 win = find_win_by_nr(&argvars[off], tp);
14582 varname = get_tv_string_chk(&argvars[off + 1]);
14583 varp = &argvars[off + 2];
Bram Moolenaar071d4272004-06-13 20:20:40 +000014584
14585 if (win != NULL && varname != NULL && varp != NULL)
14586 {
14587#ifdef FEAT_WINDOWS
14588 /* set curwin to be our win, temporarily */
14589 save_curwin = curwin;
Bram Moolenaar99ebf042006-04-15 20:28:54 +000014590 save_curtab = curtab;
14591 goto_tabpage_tp(tp);
14592 if (!win_valid(win))
14593 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014594 curwin = win;
14595 curbuf = curwin->w_buffer;
14596#endif
14597
14598 if (*varname == '&')
14599 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014600 long numval;
14601 char_u *strval;
14602 int error = FALSE;
14603
Bram Moolenaar071d4272004-06-13 20:20:40 +000014604 ++varname;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014605 numval = get_tv_number_chk(varp, &error);
14606 strval = get_tv_string_buf_chk(varp, nbuf);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014607 if (!error && strval != NULL)
14608 set_option_value(varname, numval, strval, OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014609 }
14610 else
14611 {
14612 winvarname = alloc((unsigned)STRLEN(varname) + 3);
14613 if (winvarname != NULL)
14614 {
14615 STRCPY(winvarname, "w:");
14616 STRCPY(winvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000014617 set_var(winvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014618 vim_free(winvarname);
14619 }
14620 }
14621
14622#ifdef FEAT_WINDOWS
Bram Moolenaar99ebf042006-04-15 20:28:54 +000014623 /* Restore current tabpage and window, if still valid (autocomands can
14624 * make them invalid). */
14625 if (valid_tabpage(save_curtab))
14626 goto_tabpage_tp(save_curtab);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014627 if (win_valid(save_curwin))
14628 {
14629 curwin = save_curwin;
14630 curbuf = curwin->w_buffer;
14631 }
14632#endif
14633 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014634}
14635
14636/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000014637 * "simplify()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000014638 */
14639 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000014640f_simplify(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014641 typval_T *argvars;
14642 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014643{
Bram Moolenaar0d660222005-01-07 21:51:51 +000014644 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014645
Bram Moolenaar0d660222005-01-07 21:51:51 +000014646 p = get_tv_string(&argvars[0]);
14647 rettv->vval.v_string = vim_strsave(p);
14648 simplify_filename(rettv->vval.v_string); /* simplify in place */
14649 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014650}
14651
Bram Moolenaar0d660222005-01-07 21:51:51 +000014652static int
14653#ifdef __BORLANDC__
14654 _RTLENTRYF
14655#endif
14656 item_compare __ARGS((const void *s1, const void *s2));
14657static int
14658#ifdef __BORLANDC__
14659 _RTLENTRYF
14660#endif
14661 item_compare2 __ARGS((const void *s1, const void *s2));
14662
14663static int item_compare_ic;
14664static char_u *item_compare_func;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014665static int item_compare_func_err;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014666#define ITEM_COMPARE_FAIL 999
14667
Bram Moolenaar071d4272004-06-13 20:20:40 +000014668/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000014669 * Compare functions for f_sort() below.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014670 */
Bram Moolenaar0d660222005-01-07 21:51:51 +000014671 static int
14672#ifdef __BORLANDC__
14673_RTLENTRYF
14674#endif
14675item_compare(s1, s2)
14676 const void *s1;
14677 const void *s2;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014678{
Bram Moolenaar0d660222005-01-07 21:51:51 +000014679 char_u *p1, *p2;
14680 char_u *tofree1, *tofree2;
14681 int res;
14682 char_u numbuf1[NUMBUFLEN];
14683 char_u numbuf2[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000014684
Bram Moolenaarb71eaae2006-01-20 23:10:18 +000014685 p1 = tv2string(&(*(listitem_T **)s1)->li_tv, &tofree1, numbuf1, 0);
14686 p2 = tv2string(&(*(listitem_T **)s2)->li_tv, &tofree2, numbuf2, 0);
Bram Moolenaar0d660222005-01-07 21:51:51 +000014687 if (item_compare_ic)
14688 res = STRICMP(p1, p2);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014689 else
Bram Moolenaar0d660222005-01-07 21:51:51 +000014690 res = STRCMP(p1, p2);
14691 vim_free(tofree1);
14692 vim_free(tofree2);
14693 return res;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014694}
14695
14696 static int
Bram Moolenaar0d660222005-01-07 21:51:51 +000014697#ifdef __BORLANDC__
14698_RTLENTRYF
Bram Moolenaar071d4272004-06-13 20:20:40 +000014699#endif
Bram Moolenaar0d660222005-01-07 21:51:51 +000014700item_compare2(s1, s2)
14701 const void *s1;
14702 const void *s2;
14703{
14704 int res;
Bram Moolenaar33570922005-01-25 22:26:29 +000014705 typval_T rettv;
Bram Moolenaareb3593b2006-04-22 22:33:57 +000014706 typval_T argv[3];
Bram Moolenaar0d660222005-01-07 21:51:51 +000014707 int dummy;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014708
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014709 /* shortcut after failure in previous call; compare all items equal */
14710 if (item_compare_func_err)
14711 return 0;
14712
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014713 /* copy the values. This is needed to be able to set v_lock to VAR_FIXED
14714 * in the copy without changing the original list items. */
Bram Moolenaar33570922005-01-25 22:26:29 +000014715 copy_tv(&(*(listitem_T **)s1)->li_tv, &argv[0]);
14716 copy_tv(&(*(listitem_T **)s2)->li_tv, &argv[1]);
Bram Moolenaar0d660222005-01-07 21:51:51 +000014717
14718 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000014719 res = call_func(item_compare_func, (int)STRLEN(item_compare_func),
Bram Moolenaare9a41262005-01-15 22:18:47 +000014720 &rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL);
Bram Moolenaar0d660222005-01-07 21:51:51 +000014721 clear_tv(&argv[0]);
14722 clear_tv(&argv[1]);
14723
14724 if (res == FAIL)
14725 res = ITEM_COMPARE_FAIL;
14726 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014727 /* return value has wrong type */
14728 res = get_tv_number_chk(&rettv, &item_compare_func_err);
14729 if (item_compare_func_err)
14730 res = ITEM_COMPARE_FAIL;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014731 clear_tv(&rettv);
14732 return res;
14733}
14734
14735/*
14736 * "sort({list})" function
14737 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014738 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000014739f_sort(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014740 typval_T *argvars;
14741 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014742{
Bram Moolenaar33570922005-01-25 22:26:29 +000014743 list_T *l;
14744 listitem_T *li;
14745 listitem_T **ptrs;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014746 long len;
14747 long i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014748
Bram Moolenaar0d660222005-01-07 21:51:51 +000014749 rettv->vval.v_number = 0;
14750 if (argvars[0].v_type != VAR_LIST)
14751 EMSG2(_(e_listarg), "sort()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000014752 else
14753 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000014754 l = argvars[0].vval.v_list;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014755 if (l == NULL || tv_check_lock(l->lv_lock, (char_u *)"sort()"))
Bram Moolenaar0d660222005-01-07 21:51:51 +000014756 return;
14757 rettv->vval.v_list = l;
14758 rettv->v_type = VAR_LIST;
14759 ++l->lv_refcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014760
Bram Moolenaar0d660222005-01-07 21:51:51 +000014761 len = list_len(l);
14762 if (len <= 1)
14763 return; /* short list sorts pretty quickly */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014764
Bram Moolenaar0d660222005-01-07 21:51:51 +000014765 item_compare_ic = FALSE;
14766 item_compare_func = NULL;
14767 if (argvars[1].v_type != VAR_UNKNOWN)
14768 {
14769 if (argvars[1].v_type == VAR_FUNC)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014770 item_compare_func = argvars[1].vval.v_string;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014771 else
14772 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014773 int error = FALSE;
14774
14775 i = get_tv_number_chk(&argvars[1], &error);
14776 if (error)
14777 return; /* type error; errmsg already given */
Bram Moolenaar0d660222005-01-07 21:51:51 +000014778 if (i == 1)
14779 item_compare_ic = TRUE;
14780 else
14781 item_compare_func = get_tv_string(&argvars[1]);
14782 }
14783 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014784
Bram Moolenaar0d660222005-01-07 21:51:51 +000014785 /* Make an array with each entry pointing to an item in the List. */
Bram Moolenaar33570922005-01-25 22:26:29 +000014786 ptrs = (listitem_T **)alloc((int)(len * sizeof(listitem_T *)));
Bram Moolenaar0d660222005-01-07 21:51:51 +000014787 if (ptrs == NULL)
14788 return;
14789 i = 0;
14790 for (li = l->lv_first; li != NULL; li = li->li_next)
14791 ptrs[i++] = li;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014792
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014793 item_compare_func_err = FALSE;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014794 /* test the compare function */
14795 if (item_compare_func != NULL
14796 && item_compare2((void *)&ptrs[0], (void *)&ptrs[1])
14797 == ITEM_COMPARE_FAIL)
Bram Moolenaare49b69a2005-01-08 16:11:57 +000014798 EMSG(_("E702: Sort compare function failed"));
Bram Moolenaar071d4272004-06-13 20:20:40 +000014799 else
Bram Moolenaar0d660222005-01-07 21:51:51 +000014800 {
14801 /* Sort the array with item pointers. */
Bram Moolenaar33570922005-01-25 22:26:29 +000014802 qsort((void *)ptrs, (size_t)len, sizeof(listitem_T *),
Bram Moolenaar0d660222005-01-07 21:51:51 +000014803 item_compare_func == NULL ? item_compare : item_compare2);
14804
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014805 if (!item_compare_func_err)
14806 {
14807 /* Clear the List and append the items in the sorted order. */
14808 l->lv_first = l->lv_last = NULL;
14809 l->lv_len = 0;
14810 for (i = 0; i < len; ++i)
14811 list_append(l, ptrs[i]);
14812 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000014813 }
14814
14815 vim_free(ptrs);
14816 }
14817}
14818
Bram Moolenaard857f0e2005-06-21 22:37:39 +000014819/*
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +000014820 * "soundfold({word})" function
14821 */
14822 static void
14823f_soundfold(argvars, rettv)
14824 typval_T *argvars;
14825 typval_T *rettv;
14826{
14827 char_u *s;
14828
14829 rettv->v_type = VAR_STRING;
14830 s = get_tv_string(&argvars[0]);
Bram Moolenaar3c56a962006-03-12 22:19:04 +000014831#ifdef FEAT_SPELL
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +000014832 rettv->vval.v_string = eval_soundfold(s);
14833#else
14834 rettv->vval.v_string = vim_strsave(s);
14835#endif
14836}
14837
14838/*
Bram Moolenaard857f0e2005-06-21 22:37:39 +000014839 * "spellbadword()" function
14840 */
14841/* ARGSUSED */
14842 static void
14843f_spellbadword(argvars, rettv)
14844 typval_T *argvars;
14845 typval_T *rettv;
14846{
Bram Moolenaar4463f292005-09-25 22:20:24 +000014847 char_u *word = (char_u *)"";
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000014848 hlf_T attr = HLF_COUNT;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000014849 int len = 0;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000014850
Bram Moolenaareddf53b2006-02-27 00:11:10 +000014851 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar4463f292005-09-25 22:20:24 +000014852 return;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000014853
Bram Moolenaar3c56a962006-03-12 22:19:04 +000014854#ifdef FEAT_SPELL
Bram Moolenaar4463f292005-09-25 22:20:24 +000014855 if (argvars[0].v_type == VAR_UNKNOWN)
14856 {
14857 /* Find the start and length of the badly spelled word. */
14858 len = spell_move_to(curwin, FORWARD, TRUE, TRUE, &attr);
14859 if (len != 0)
14860 word = ml_get_cursor();
14861 }
14862 else if (curwin->w_p_spell && *curbuf->b_p_spl != NUL)
14863 {
14864 char_u *str = get_tv_string_chk(&argvars[0]);
14865 int capcol = -1;
14866
14867 if (str != NULL)
14868 {
14869 /* Check the argument for spelling. */
14870 while (*str != NUL)
14871 {
Bram Moolenaar4770d092006-01-12 23:22:24 +000014872 len = spell_check(curwin, str, &attr, &capcol, FALSE);
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000014873 if (attr != HLF_COUNT)
Bram Moolenaar4463f292005-09-25 22:20:24 +000014874 {
14875 word = str;
14876 break;
14877 }
14878 str += len;
14879 }
14880 }
14881 }
Bram Moolenaard857f0e2005-06-21 22:37:39 +000014882#endif
Bram Moolenaar4463f292005-09-25 22:20:24 +000014883
Bram Moolenaareddf53b2006-02-27 00:11:10 +000014884 list_append_string(rettv->vval.v_list, word, len);
14885 list_append_string(rettv->vval.v_list, (char_u *)(
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000014886 attr == HLF_SPB ? "bad" :
14887 attr == HLF_SPR ? "rare" :
14888 attr == HLF_SPL ? "local" :
14889 attr == HLF_SPC ? "caps" :
14890 ""), -1);
Bram Moolenaard857f0e2005-06-21 22:37:39 +000014891}
14892
14893/*
14894 * "spellsuggest()" function
14895 */
Bram Moolenaar3c56a962006-03-12 22:19:04 +000014896/*ARGSUSED*/
Bram Moolenaard857f0e2005-06-21 22:37:39 +000014897 static void
14898f_spellsuggest(argvars, rettv)
14899 typval_T *argvars;
14900 typval_T *rettv;
14901{
Bram Moolenaar3c56a962006-03-12 22:19:04 +000014902#ifdef FEAT_SPELL
Bram Moolenaard857f0e2005-06-21 22:37:39 +000014903 char_u *str;
Bram Moolenaar69e0ff92005-09-30 21:23:56 +000014904 int typeerr = FALSE;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000014905 int maxcount;
14906 garray_T ga;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000014907 int i;
Bram Moolenaar69e0ff92005-09-30 21:23:56 +000014908 listitem_T *li;
14909 int need_capital = FALSE;
14910#endif
Bram Moolenaard857f0e2005-06-21 22:37:39 +000014911
Bram Moolenaareddf53b2006-02-27 00:11:10 +000014912 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaard857f0e2005-06-21 22:37:39 +000014913 return;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000014914
Bram Moolenaar3c56a962006-03-12 22:19:04 +000014915#ifdef FEAT_SPELL
Bram Moolenaard857f0e2005-06-21 22:37:39 +000014916 if (curwin->w_p_spell && *curbuf->b_p_spl != NUL)
14917 {
14918 str = get_tv_string(&argvars[0]);
14919 if (argvars[1].v_type != VAR_UNKNOWN)
14920 {
Bram Moolenaar69e0ff92005-09-30 21:23:56 +000014921 maxcount = get_tv_number_chk(&argvars[1], &typeerr);
Bram Moolenaard857f0e2005-06-21 22:37:39 +000014922 if (maxcount <= 0)
14923 return;
Bram Moolenaar69e0ff92005-09-30 21:23:56 +000014924 if (argvars[2].v_type != VAR_UNKNOWN)
14925 {
14926 need_capital = get_tv_number_chk(&argvars[2], &typeerr);
14927 if (typeerr)
14928 return;
14929 }
Bram Moolenaard857f0e2005-06-21 22:37:39 +000014930 }
14931 else
14932 maxcount = 25;
14933
Bram Moolenaar4770d092006-01-12 23:22:24 +000014934 spell_suggest_list(&ga, str, maxcount, need_capital, FALSE);
Bram Moolenaard857f0e2005-06-21 22:37:39 +000014935
14936 for (i = 0; i < ga.ga_len; ++i)
14937 {
14938 str = ((char_u **)ga.ga_data)[i];
14939
14940 li = listitem_alloc();
14941 if (li == NULL)
14942 vim_free(str);
14943 else
14944 {
14945 li->li_tv.v_type = VAR_STRING;
14946 li->li_tv.v_lock = 0;
14947 li->li_tv.vval.v_string = str;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000014948 list_append(rettv->vval.v_list, li);
Bram Moolenaard857f0e2005-06-21 22:37:39 +000014949 }
14950 }
14951 ga_clear(&ga);
14952 }
14953#endif
14954}
14955
Bram Moolenaar0d660222005-01-07 21:51:51 +000014956 static void
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014957f_split(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014958 typval_T *argvars;
14959 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014960{
14961 char_u *str;
14962 char_u *end;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014963 char_u *pat = NULL;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014964 regmatch_T regmatch;
14965 char_u patbuf[NUMBUFLEN];
14966 char_u *save_cpo;
14967 int match;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014968 colnr_T col = 0;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014969 int keepempty = FALSE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014970 int typeerr = FALSE;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014971
14972 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
14973 save_cpo = p_cpo;
14974 p_cpo = (char_u *)"";
14975
14976 str = get_tv_string(&argvars[0]);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014977 if (argvars[1].v_type != VAR_UNKNOWN)
14978 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014979 pat = get_tv_string_buf_chk(&argvars[1], patbuf);
14980 if (pat == NULL)
14981 typeerr = TRUE;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014982 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014983 keepempty = get_tv_number_chk(&argvars[2], &typeerr);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014984 }
14985 if (pat == NULL || *pat == NUL)
14986 pat = (char_u *)"[\\x01- ]\\+";
Bram Moolenaar0d660222005-01-07 21:51:51 +000014987
Bram Moolenaareddf53b2006-02-27 00:11:10 +000014988 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014989 return;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014990 if (typeerr)
14991 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014992
Bram Moolenaar0d660222005-01-07 21:51:51 +000014993 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
14994 if (regmatch.regprog != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014995 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000014996 regmatch.rm_ic = FALSE;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014997 while (*str != NUL || keepempty)
Bram Moolenaar0d660222005-01-07 21:51:51 +000014998 {
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014999 if (*str == NUL)
15000 match = FALSE; /* empty item at the end */
15001 else
15002 match = vim_regexec_nl(&regmatch, str, col);
Bram Moolenaar0d660222005-01-07 21:51:51 +000015003 if (match)
15004 end = regmatch.startp[0];
15005 else
15006 end = str + STRLEN(str);
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015007 if (keepempty || end > str || (rettv->vval.v_list->lv_len > 0
15008 && *str != NUL && match && end < regmatch.endp[0]))
Bram Moolenaar0d660222005-01-07 21:51:51 +000015009 {
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015010 if (list_append_string(rettv->vval.v_list, str,
15011 (int)(end - str)) == FAIL)
Bram Moolenaar0d660222005-01-07 21:51:51 +000015012 break;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015013 }
15014 if (!match)
15015 break;
15016 /* Advance to just after the match. */
15017 if (regmatch.endp[0] > str)
15018 col = 0;
15019 else
15020 {
15021 /* Don't get stuck at the same match. */
15022#ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000015023 col = (*mb_ptr2len)(regmatch.endp[0]);
Bram Moolenaar0d660222005-01-07 21:51:51 +000015024#else
15025 col = 1;
15026#endif
15027 }
15028 str = regmatch.endp[0];
15029 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015030
Bram Moolenaar0d660222005-01-07 21:51:51 +000015031 vim_free(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015032 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015033
Bram Moolenaar0d660222005-01-07 21:51:51 +000015034 p_cpo = save_cpo;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015035}
15036
Bram Moolenaar2c932302006-03-18 21:42:09 +000015037/*
15038 * "str2nr()" function
15039 */
15040 static void
15041f_str2nr(argvars, rettv)
15042 typval_T *argvars;
15043 typval_T *rettv;
15044{
15045 int base = 10;
15046 char_u *p;
15047 long n;
15048
15049 if (argvars[1].v_type != VAR_UNKNOWN)
15050 {
15051 base = get_tv_number(&argvars[1]);
15052 if (base != 8 && base != 10 && base != 16)
15053 {
15054 EMSG(_(e_invarg));
15055 return;
15056 }
15057 }
15058
15059 p = skipwhite(get_tv_string(&argvars[0]));
15060 vim_str2nr(p, NULL, NULL, base == 8 ? 2 : 0, base == 16 ? 2 : 0, &n, NULL);
15061 rettv->vval.v_number = n;
15062}
15063
Bram Moolenaar071d4272004-06-13 20:20:40 +000015064#ifdef HAVE_STRFTIME
15065/*
15066 * "strftime({format}[, {time}])" function
15067 */
15068 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015069f_strftime(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015070 typval_T *argvars;
15071 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015072{
15073 char_u result_buf[256];
15074 struct tm *curtime;
15075 time_t seconds;
15076 char_u *p;
15077
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015078 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015079
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015080 p = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015081 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015082 seconds = time(NULL);
15083 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015084 seconds = (time_t)get_tv_number(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015085 curtime = localtime(&seconds);
15086 /* MSVC returns NULL for an invalid value of seconds. */
15087 if (curtime == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015088 rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
Bram Moolenaar071d4272004-06-13 20:20:40 +000015089 else
15090 {
15091# ifdef FEAT_MBYTE
15092 vimconv_T conv;
15093 char_u *enc;
15094
15095 conv.vc_type = CONV_NONE;
15096 enc = enc_locale();
15097 convert_setup(&conv, p_enc, enc);
15098 if (conv.vc_type != CONV_NONE)
15099 p = string_convert(&conv, p, NULL);
15100# endif
15101 if (p != NULL)
15102 (void)strftime((char *)result_buf, sizeof(result_buf),
15103 (char *)p, curtime);
15104 else
15105 result_buf[0] = NUL;
15106
15107# ifdef FEAT_MBYTE
15108 if (conv.vc_type != CONV_NONE)
15109 vim_free(p);
15110 convert_setup(&conv, enc, p_enc);
15111 if (conv.vc_type != CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015112 rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015113 else
15114# endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015115 rettv->vval.v_string = vim_strsave(result_buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015116
15117# ifdef FEAT_MBYTE
15118 /* Release conversion descriptors */
15119 convert_setup(&conv, NULL, NULL);
15120 vim_free(enc);
15121# endif
15122 }
15123}
15124#endif
15125
15126/*
15127 * "stridx()" function
15128 */
15129 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015130f_stridx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015131 typval_T *argvars;
15132 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015133{
15134 char_u buf[NUMBUFLEN];
15135 char_u *needle;
15136 char_u *haystack;
Bram Moolenaar33570922005-01-25 22:26:29 +000015137 char_u *save_haystack;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015138 char_u *pos;
Bram Moolenaar33570922005-01-25 22:26:29 +000015139 int start_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015140
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015141 needle = get_tv_string_chk(&argvars[1]);
15142 save_haystack = haystack = get_tv_string_buf_chk(&argvars[0], buf);
Bram Moolenaar33570922005-01-25 22:26:29 +000015143 rettv->vval.v_number = -1;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015144 if (needle == NULL || haystack == NULL)
15145 return; /* type error; errmsg already given */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015146
Bram Moolenaar33570922005-01-25 22:26:29 +000015147 if (argvars[2].v_type != VAR_UNKNOWN)
15148 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015149 int error = FALSE;
15150
15151 start_idx = get_tv_number_chk(&argvars[2], &error);
15152 if (error || start_idx >= (int)STRLEN(haystack))
Bram Moolenaar33570922005-01-25 22:26:29 +000015153 return;
Bram Moolenaar532c7802005-01-27 14:44:31 +000015154 if (start_idx >= 0)
15155 haystack += start_idx;
Bram Moolenaar33570922005-01-25 22:26:29 +000015156 }
15157
15158 pos = (char_u *)strstr((char *)haystack, (char *)needle);
15159 if (pos != NULL)
15160 rettv->vval.v_number = (varnumber_T)(pos - save_haystack);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015161}
15162
15163/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015164 * "string()" function
15165 */
15166 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015167f_string(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015168 typval_T *argvars;
15169 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015170{
15171 char_u *tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015172 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015173
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015174 rettv->v_type = VAR_STRING;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +000015175 rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf, 0);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015176 if (tofree == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015177 rettv->vval.v_string = vim_strsave(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015178}
15179
15180/*
15181 * "strlen()" function
15182 */
15183 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015184f_strlen(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015185 typval_T *argvars;
15186 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015187{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015188 rettv->vval.v_number = (varnumber_T)(STRLEN(
15189 get_tv_string(&argvars[0])));
Bram Moolenaar071d4272004-06-13 20:20:40 +000015190}
15191
15192/*
15193 * "strpart()" function
15194 */
15195 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015196f_strpart(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015197 typval_T *argvars;
15198 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015199{
15200 char_u *p;
15201 int n;
15202 int len;
15203 int slen;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015204 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015205
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015206 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015207 slen = (int)STRLEN(p);
15208
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015209 n = get_tv_number_chk(&argvars[1], &error);
15210 if (error)
15211 len = 0;
15212 else if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015213 len = get_tv_number(&argvars[2]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015214 else
15215 len = slen - n; /* default len: all bytes that are available. */
15216
15217 /*
15218 * Only return the overlap between the specified part and the actual
15219 * string.
15220 */
15221 if (n < 0)
15222 {
15223 len += n;
15224 n = 0;
15225 }
15226 else if (n > slen)
15227 n = slen;
15228 if (len < 0)
15229 len = 0;
15230 else if (n + len > slen)
15231 len = slen - n;
15232
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015233 rettv->v_type = VAR_STRING;
15234 rettv->vval.v_string = vim_strnsave(p + n, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015235}
15236
15237/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000015238 * "strridx()" function
15239 */
15240 static void
15241f_strridx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015242 typval_T *argvars;
15243 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015244{
15245 char_u buf[NUMBUFLEN];
15246 char_u *needle;
15247 char_u *haystack;
15248 char_u *rest;
15249 char_u *lastmatch = NULL;
Bram Moolenaar532c7802005-01-27 14:44:31 +000015250 int haystack_len, end_idx;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015251
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015252 needle = get_tv_string_chk(&argvars[1]);
15253 haystack = get_tv_string_buf_chk(&argvars[0], buf);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015254
15255 rettv->vval.v_number = -1;
15256 if (needle == NULL || haystack == NULL)
15257 return; /* type error; errmsg already given */
Bram Moolenaareb3593b2006-04-22 22:33:57 +000015258
15259 haystack_len = (int)STRLEN(haystack);
Bram Moolenaar05159a02005-02-26 23:04:13 +000015260 if (argvars[2].v_type != VAR_UNKNOWN)
15261 {
15262 /* Third argument: upper limit for index */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015263 end_idx = get_tv_number_chk(&argvars[2], NULL);
Bram Moolenaar05159a02005-02-26 23:04:13 +000015264 if (end_idx < 0)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015265 return; /* can never find a match */
Bram Moolenaar05159a02005-02-26 23:04:13 +000015266 }
15267 else
15268 end_idx = haystack_len;
15269
Bram Moolenaar0d660222005-01-07 21:51:51 +000015270 if (*needle == NUL)
Bram Moolenaar05159a02005-02-26 23:04:13 +000015271 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000015272 /* Empty string matches past the end. */
Bram Moolenaar05159a02005-02-26 23:04:13 +000015273 lastmatch = haystack + end_idx;
15274 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000015275 else
Bram Moolenaar532c7802005-01-27 14:44:31 +000015276 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000015277 for (rest = haystack; *rest != '\0'; ++rest)
15278 {
15279 rest = (char_u *)strstr((char *)rest, (char *)needle);
Bram Moolenaar532c7802005-01-27 14:44:31 +000015280 if (rest == NULL || rest > haystack + end_idx)
Bram Moolenaar0d660222005-01-07 21:51:51 +000015281 break;
15282 lastmatch = rest;
15283 }
Bram Moolenaar532c7802005-01-27 14:44:31 +000015284 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000015285
15286 if (lastmatch == NULL)
15287 rettv->vval.v_number = -1;
15288 else
15289 rettv->vval.v_number = (varnumber_T)(lastmatch - haystack);
15290}
15291
15292/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000015293 * "strtrans()" function
15294 */
15295 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015296f_strtrans(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015297 typval_T *argvars;
15298 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015299{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015300 rettv->v_type = VAR_STRING;
15301 rettv->vval.v_string = transstr(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000015302}
15303
15304/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000015305 * "submatch()" function
15306 */
15307 static void
15308f_submatch(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015309 typval_T *argvars;
15310 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015311{
15312 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015313 rettv->vval.v_string =
15314 reg_submatch((int)get_tv_number_chk(&argvars[0], NULL));
Bram Moolenaar0d660222005-01-07 21:51:51 +000015315}
15316
15317/*
15318 * "substitute()" function
15319 */
15320 static void
15321f_substitute(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015322 typval_T *argvars;
15323 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000015324{
15325 char_u patbuf[NUMBUFLEN];
15326 char_u subbuf[NUMBUFLEN];
15327 char_u flagsbuf[NUMBUFLEN];
15328
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015329 char_u *str = get_tv_string_chk(&argvars[0]);
15330 char_u *pat = get_tv_string_buf_chk(&argvars[1], patbuf);
15331 char_u *sub = get_tv_string_buf_chk(&argvars[2], subbuf);
15332 char_u *flg = get_tv_string_buf_chk(&argvars[3], flagsbuf);
15333
Bram Moolenaar0d660222005-01-07 21:51:51 +000015334 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015335 if (str == NULL || pat == NULL || sub == NULL || flg == NULL)
15336 rettv->vval.v_string = NULL;
15337 else
15338 rettv->vval.v_string = do_string_sub(str, pat, sub, flg);
Bram Moolenaar0d660222005-01-07 21:51:51 +000015339}
15340
15341/*
Bram Moolenaar54ff3412005-04-20 19:48:33 +000015342 * "synID(lnum, col, trans)" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000015343 */
15344/*ARGSUSED*/
15345 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015346f_synID(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015347 typval_T *argvars;
15348 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015349{
15350 int id = 0;
15351#ifdef FEAT_SYN_HL
Bram Moolenaar54ff3412005-04-20 19:48:33 +000015352 long lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015353 long col;
15354 int trans;
Bram Moolenaar92124a32005-06-17 22:03:40 +000015355 int transerr = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015356
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015357 lnum = get_tv_lnum(argvars); /* -1 on type error */
15358 col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */
15359 trans = get_tv_number_chk(&argvars[2], &transerr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015360
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015361 if (!transerr && lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
Bram Moolenaar54ff3412005-04-20 19:48:33 +000015362 && col >= 0 && col < (long)STRLEN(ml_get(lnum)))
Bram Moolenaar81f1ecb2005-08-25 21:27:31 +000015363 id = syn_get_id(curwin, lnum, (colnr_T)col, trans, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015364#endif
15365
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015366 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015367}
15368
15369/*
15370 * "synIDattr(id, what [, mode])" function
15371 */
15372/*ARGSUSED*/
15373 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015374f_synIDattr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015375 typval_T *argvars;
15376 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015377{
15378 char_u *p = NULL;
15379#ifdef FEAT_SYN_HL
15380 int id;
15381 char_u *what;
15382 char_u *mode;
15383 char_u modebuf[NUMBUFLEN];
15384 int modec;
15385
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015386 id = get_tv_number(&argvars[0]);
15387 what = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015388 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015389 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015390 mode = get_tv_string_buf(&argvars[2], modebuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015391 modec = TOLOWER_ASC(mode[0]);
15392 if (modec != 't' && modec != 'c'
15393#ifdef FEAT_GUI
15394 && modec != 'g'
15395#endif
15396 )
15397 modec = 0; /* replace invalid with current */
15398 }
15399 else
15400 {
15401#ifdef FEAT_GUI
15402 if (gui.in_use)
15403 modec = 'g';
15404 else
15405#endif
15406 if (t_colors > 1)
15407 modec = 'c';
15408 else
15409 modec = 't';
15410 }
15411
15412
15413 switch (TOLOWER_ASC(what[0]))
15414 {
15415 case 'b':
15416 if (TOLOWER_ASC(what[1]) == 'g') /* bg[#] */
15417 p = highlight_color(id, what, modec);
15418 else /* bold */
15419 p = highlight_has_attr(id, HL_BOLD, modec);
15420 break;
15421
15422 case 'f': /* fg[#] */
15423 p = highlight_color(id, what, modec);
15424 break;
15425
15426 case 'i':
15427 if (TOLOWER_ASC(what[1]) == 'n') /* inverse */
15428 p = highlight_has_attr(id, HL_INVERSE, modec);
15429 else /* italic */
15430 p = highlight_has_attr(id, HL_ITALIC, modec);
15431 break;
15432
15433 case 'n': /* name */
15434 p = get_highlight_name(NULL, id - 1);
15435 break;
15436
15437 case 'r': /* reverse */
15438 p = highlight_has_attr(id, HL_INVERSE, modec);
15439 break;
15440
15441 case 's': /* standout */
15442 p = highlight_has_attr(id, HL_STANDOUT, modec);
15443 break;
15444
Bram Moolenaar5b743bf2005-03-15 22:50:43 +000015445 case 'u':
15446 if (STRLEN(what) <= 5 || TOLOWER_ASC(what[5]) != 'c')
15447 /* underline */
15448 p = highlight_has_attr(id, HL_UNDERLINE, modec);
15449 else
15450 /* undercurl */
15451 p = highlight_has_attr(id, HL_UNDERCURL, modec);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015452 break;
15453 }
15454
15455 if (p != NULL)
15456 p = vim_strsave(p);
15457#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015458 rettv->v_type = VAR_STRING;
15459 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015460}
15461
15462/*
15463 * "synIDtrans(id)" function
15464 */
15465/*ARGSUSED*/
15466 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015467f_synIDtrans(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015468 typval_T *argvars;
15469 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015470{
15471 int id;
15472
15473#ifdef FEAT_SYN_HL
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015474 id = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015475
15476 if (id > 0)
15477 id = syn_get_final_id(id);
15478 else
15479#endif
15480 id = 0;
15481
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015482 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015483}
15484
15485/*
15486 * "system()" function
15487 */
15488 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015489f_system(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015490 typval_T *argvars;
15491 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015492{
Bram Moolenaarc0197e22004-09-13 20:26:32 +000015493 char_u *res = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015494 char_u *p;
Bram Moolenaarc0197e22004-09-13 20:26:32 +000015495 char_u *infile = NULL;
15496 char_u buf[NUMBUFLEN];
15497 int err = FALSE;
15498 FILE *fd;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015499
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015500 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc0197e22004-09-13 20:26:32 +000015501 {
15502 /*
15503 * Write the string to a temp file, to be used for input of the shell
15504 * command.
15505 */
15506 if ((infile = vim_tempname('i')) == NULL)
15507 {
15508 EMSG(_(e_notmp));
15509 return;
15510 }
15511
15512 fd = mch_fopen((char *)infile, WRITEBIN);
15513 if (fd == NULL)
15514 {
15515 EMSG2(_(e_notopen), infile);
15516 goto done;
15517 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015518 p = get_tv_string_buf_chk(&argvars[1], buf);
15519 if (p == NULL)
Bram Moolenaareb3593b2006-04-22 22:33:57 +000015520 {
15521 fclose(fd);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015522 goto done; /* type error; errmsg already given */
Bram Moolenaareb3593b2006-04-22 22:33:57 +000015523 }
Bram Moolenaarc0197e22004-09-13 20:26:32 +000015524 if (fwrite(p, STRLEN(p), 1, fd) != 1)
15525 err = TRUE;
15526 if (fclose(fd) != 0)
15527 err = TRUE;
15528 if (err)
15529 {
15530 EMSG(_("E677: Error writing temp file"));
15531 goto done;
15532 }
15533 }
15534
Bram Moolenaare580b0c2006-03-21 21:33:03 +000015535 res = get_cmd_output(get_tv_string(&argvars[0]), infile,
15536 SHELL_SILENT | SHELL_COOKED);
Bram Moolenaarc0197e22004-09-13 20:26:32 +000015537
Bram Moolenaar071d4272004-06-13 20:20:40 +000015538#ifdef USE_CR
15539 /* translate <CR> into <NL> */
Bram Moolenaarc0197e22004-09-13 20:26:32 +000015540 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015541 {
15542 char_u *s;
15543
Bram Moolenaarc0197e22004-09-13 20:26:32 +000015544 for (s = res; *s; ++s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015545 {
15546 if (*s == CAR)
15547 *s = NL;
15548 }
15549 }
15550#else
15551# ifdef USE_CRNL
15552 /* translate <CR><NL> into <NL> */
Bram Moolenaarc0197e22004-09-13 20:26:32 +000015553 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015554 {
15555 char_u *s, *d;
15556
Bram Moolenaarc0197e22004-09-13 20:26:32 +000015557 d = res;
15558 for (s = res; *s; ++s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015559 {
15560 if (s[0] == CAR && s[1] == NL)
15561 ++s;
15562 *d++ = *s;
15563 }
15564 *d = NUL;
15565 }
15566# endif
15567#endif
Bram Moolenaarc0197e22004-09-13 20:26:32 +000015568
15569done:
15570 if (infile != NULL)
15571 {
15572 mch_remove(infile);
15573 vim_free(infile);
15574 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015575 rettv->v_type = VAR_STRING;
15576 rettv->vval.v_string = res;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015577}
15578
15579/*
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000015580 * "tabpagebuflist()" function
15581 */
15582/* ARGSUSED */
15583 static void
15584f_tabpagebuflist(argvars, rettv)
15585 typval_T *argvars;
15586 typval_T *rettv;
15587{
15588#ifndef FEAT_WINDOWS
15589 rettv->vval.v_number = 0;
15590#else
15591 tabpage_T *tp;
15592 win_T *wp = NULL;
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000015593
15594 if (argvars[0].v_type == VAR_UNKNOWN)
15595 wp = firstwin;
15596 else
15597 {
15598 tp = find_tabpage((int)get_tv_number(&argvars[0]));
15599 if (tp != NULL)
Bram Moolenaar238a5642006-02-21 22:12:05 +000015600 wp = (tp == curtab) ? firstwin : tp->tp_firstwin;
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000015601 }
15602 if (wp == NULL)
15603 rettv->vval.v_number = 0;
15604 else
15605 {
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015606 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000015607 rettv->vval.v_number = 0;
15608 else
15609 {
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000015610 for (; wp != NULL; wp = wp->w_next)
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015611 if (list_append_number(rettv->vval.v_list,
15612 wp->w_buffer->b_fnum) == FAIL)
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000015613 break;
15614 }
15615 }
15616#endif
15617}
15618
15619
15620/*
Bram Moolenaar7e8fd632006-02-18 22:14:51 +000015621 * "tabpagenr()" function
15622 */
15623/* ARGSUSED */
15624 static void
15625f_tabpagenr(argvars, rettv)
15626 typval_T *argvars;
15627 typval_T *rettv;
15628{
15629 int nr = 1;
15630#ifdef FEAT_WINDOWS
Bram Moolenaar7e8fd632006-02-18 22:14:51 +000015631 char_u *arg;
15632
15633 if (argvars[0].v_type != VAR_UNKNOWN)
15634 {
15635 arg = get_tv_string_chk(&argvars[0]);
15636 nr = 0;
15637 if (arg != NULL)
15638 {
15639 if (STRCMP(arg, "$") == 0)
Bram Moolenaara5621492006-02-25 21:55:24 +000015640 nr = tabpage_index(NULL) - 1;
Bram Moolenaar7e8fd632006-02-18 22:14:51 +000015641 else
15642 EMSG2(_(e_invexpr2), arg);
15643 }
15644 }
15645 else
Bram Moolenaar32466aa2006-02-24 23:53:04 +000015646 nr = tabpage_index(curtab);
Bram Moolenaar7e8fd632006-02-18 22:14:51 +000015647#endif
15648 rettv->vval.v_number = nr;
15649}
15650
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000015651
15652#ifdef FEAT_WINDOWS
15653static int get_winnr __ARGS((tabpage_T *tp, typval_T *argvar));
15654
15655/*
15656 * Common code for tabpagewinnr() and winnr().
15657 */
15658 static int
15659get_winnr(tp, argvar)
15660 tabpage_T *tp;
15661 typval_T *argvar;
15662{
15663 win_T *twin;
15664 int nr = 1;
15665 win_T *wp;
15666 char_u *arg;
15667
15668 twin = (tp == curtab) ? curwin : tp->tp_curwin;
15669 if (argvar->v_type != VAR_UNKNOWN)
15670 {
15671 arg = get_tv_string_chk(argvar);
15672 if (arg == NULL)
15673 nr = 0; /* type error; errmsg already given */
15674 else if (STRCMP(arg, "$") == 0)
15675 twin = (tp == curtab) ? lastwin : tp->tp_lastwin;
15676 else if (STRCMP(arg, "#") == 0)
15677 {
15678 twin = (tp == curtab) ? prevwin : tp->tp_prevwin;
15679 if (twin == NULL)
15680 nr = 0;
15681 }
15682 else
15683 {
15684 EMSG2(_(e_invexpr2), arg);
15685 nr = 0;
15686 }
15687 }
15688
15689 if (nr > 0)
15690 for (wp = (tp == curtab) ? firstwin : tp->tp_firstwin;
15691 wp != twin; wp = wp->w_next)
15692 ++nr;
15693 return nr;
15694}
15695#endif
15696
15697/*
15698 * "tabpagewinnr()" function
15699 */
15700/* ARGSUSED */
15701 static void
15702f_tabpagewinnr(argvars, rettv)
15703 typval_T *argvars;
15704 typval_T *rettv;
15705{
15706 int nr = 1;
15707#ifdef FEAT_WINDOWS
15708 tabpage_T *tp;
15709
15710 tp = find_tabpage((int)get_tv_number(&argvars[0]));
15711 if (tp == NULL)
15712 nr = 0;
15713 else
15714 nr = get_winnr(tp, &argvars[1]);
15715#endif
15716 rettv->vval.v_number = nr;
15717}
15718
15719
Bram Moolenaar7e8fd632006-02-18 22:14:51 +000015720/*
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000015721 * "tagfiles()" function
15722 */
15723/*ARGSUSED*/
15724 static void
15725f_tagfiles(argvars, rettv)
15726 typval_T *argvars;
15727 typval_T *rettv;
15728{
15729 char_u fname[MAXPATHL + 1];
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015730 tagname_T tn;
15731 int first;
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000015732
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015733 if (rettv_list_alloc(rettv) == FAIL)
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000015734 {
15735 rettv->vval.v_number = 0;
15736 return;
15737 }
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000015738
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015739 for (first = TRUE; ; first = FALSE)
15740 if (get_tagfname(&tn, first, fname) == FAIL
15741 || list_append_string(rettv->vval.v_list, fname, -1) == FAIL)
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000015742 break;
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015743 tagname_free(&tn);
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000015744}
15745
15746/*
Bram Moolenaare2ac10d2005-03-07 23:26:06 +000015747 * "taglist()" function
Bram Moolenaar19a09a12005-03-04 23:39:37 +000015748 */
15749 static void
15750f_taglist(argvars, rettv)
15751 typval_T *argvars;
15752 typval_T *rettv;
15753{
15754 char_u *tag_pattern;
Bram Moolenaar19a09a12005-03-04 23:39:37 +000015755
15756 tag_pattern = get_tv_string(&argvars[0]);
15757
15758 rettv->vval.v_number = FALSE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015759 if (*tag_pattern == NUL)
15760 return;
Bram Moolenaar19a09a12005-03-04 23:39:37 +000015761
Bram Moolenaareddf53b2006-02-27 00:11:10 +000015762 if (rettv_list_alloc(rettv) == OK)
15763 (void)get_tags(rettv->vval.v_list, tag_pattern);
Bram Moolenaar19a09a12005-03-04 23:39:37 +000015764}
15765
15766/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000015767 * "tempname()" function
15768 */
15769/*ARGSUSED*/
15770 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015771f_tempname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015772 typval_T *argvars;
15773 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015774{
15775 static int x = 'A';
15776
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015777 rettv->v_type = VAR_STRING;
15778 rettv->vval.v_string = vim_tempname(x);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015779
15780 /* Advance 'x' to use A-Z and 0-9, so that there are at least 34 different
15781 * names. Skip 'I' and 'O', they are used for shell redirection. */
15782 do
15783 {
15784 if (x == 'Z')
15785 x = '0';
15786 else if (x == '9')
15787 x = 'A';
15788 else
15789 {
15790#ifdef EBCDIC
15791 if (x == 'I')
15792 x = 'J';
15793 else if (x == 'R')
15794 x = 'S';
15795 else
15796#endif
15797 ++x;
15798 }
15799 } while (x == 'I' || x == 'O');
15800}
15801
15802/*
Bram Moolenaard52d9742005-08-21 22:20:28 +000015803 * "test(list)" function: Just checking the walls...
15804 */
15805/*ARGSUSED*/
15806 static void
15807f_test(argvars, rettv)
15808 typval_T *argvars;
15809 typval_T *rettv;
15810{
15811 /* Used for unit testing. Change the code below to your liking. */
15812#if 0
15813 listitem_T *li;
15814 list_T *l;
15815 char_u *bad, *good;
15816
15817 if (argvars[0].v_type != VAR_LIST)
15818 return;
15819 l = argvars[0].vval.v_list;
15820 if (l == NULL)
15821 return;
15822 li = l->lv_first;
15823 if (li == NULL)
15824 return;
15825 bad = get_tv_string(&li->li_tv);
15826 li = li->li_next;
15827 if (li == NULL)
15828 return;
15829 good = get_tv_string(&li->li_tv);
15830 rettv->vval.v_number = test_edit_score(bad, good);
15831#endif
15832}
15833
15834/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000015835 * "tolower(string)" function
15836 */
15837 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015838f_tolower(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015839 typval_T *argvars;
15840 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015841{
15842 char_u *p;
15843
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015844 p = vim_strsave(get_tv_string(&argvars[0]));
15845 rettv->v_type = VAR_STRING;
15846 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015847
15848 if (p != NULL)
15849 while (*p != NUL)
15850 {
15851#ifdef FEAT_MBYTE
15852 int l;
15853
15854 if (enc_utf8)
15855 {
15856 int c, lc;
15857
15858 c = utf_ptr2char(p);
15859 lc = utf_tolower(c);
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000015860 l = utf_ptr2len(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015861 /* TODO: reallocate string when byte count changes. */
15862 if (utf_char2len(lc) == l)
15863 utf_char2bytes(lc, p);
15864 p += l;
15865 }
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000015866 else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015867 p += l; /* skip multi-byte character */
15868 else
15869#endif
15870 {
15871 *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */
15872 ++p;
15873 }
15874 }
15875}
15876
15877/*
15878 * "toupper(string)" function
15879 */
15880 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015881f_toupper(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015882 typval_T *argvars;
15883 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015884{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015885 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015886 rettv->vval.v_string = strup_save(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000015887}
15888
15889/*
Bram Moolenaar8299df92004-07-10 09:47:34 +000015890 * "tr(string, fromstr, tostr)" function
15891 */
15892 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015893f_tr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015894 typval_T *argvars;
15895 typval_T *rettv;
Bram Moolenaar8299df92004-07-10 09:47:34 +000015896{
15897 char_u *instr;
15898 char_u *fromstr;
15899 char_u *tostr;
15900 char_u *p;
15901#ifdef FEAT_MBYTE
Bram Moolenaar342337a2005-07-21 21:11:17 +000015902 int inlen;
15903 int fromlen;
15904 int tolen;
Bram Moolenaar8299df92004-07-10 09:47:34 +000015905 int idx;
15906 char_u *cpstr;
15907 int cplen;
15908 int first = TRUE;
15909#endif
15910 char_u buf[NUMBUFLEN];
15911 char_u buf2[NUMBUFLEN];
15912 garray_T ga;
15913
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015914 instr = get_tv_string(&argvars[0]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015915 fromstr = get_tv_string_buf_chk(&argvars[1], buf);
15916 tostr = get_tv_string_buf_chk(&argvars[2], buf2);
Bram Moolenaar8299df92004-07-10 09:47:34 +000015917
15918 /* Default return value: empty string. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015919 rettv->v_type = VAR_STRING;
15920 rettv->vval.v_string = NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015921 if (fromstr == NULL || tostr == NULL)
15922 return; /* type error; errmsg already given */
Bram Moolenaar8299df92004-07-10 09:47:34 +000015923 ga_init2(&ga, (int)sizeof(char), 80);
15924
15925#ifdef FEAT_MBYTE
15926 if (!has_mbyte)
15927#endif
15928 /* not multi-byte: fromstr and tostr must be the same length */
15929 if (STRLEN(fromstr) != STRLEN(tostr))
15930 {
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000015931#ifdef FEAT_MBYTE
Bram Moolenaar8299df92004-07-10 09:47:34 +000015932error:
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000015933#endif
Bram Moolenaar8299df92004-07-10 09:47:34 +000015934 EMSG2(_(e_invarg2), fromstr);
15935 ga_clear(&ga);
15936 return;
15937 }
15938
15939 /* fromstr and tostr have to contain the same number of chars */
15940 while (*instr != NUL)
15941 {
15942#ifdef FEAT_MBYTE
15943 if (has_mbyte)
15944 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000015945 inlen = (*mb_ptr2len)(instr);
Bram Moolenaar8299df92004-07-10 09:47:34 +000015946 cpstr = instr;
15947 cplen = inlen;
15948 idx = 0;
15949 for (p = fromstr; *p != NUL; p += fromlen)
15950 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000015951 fromlen = (*mb_ptr2len)(p);
Bram Moolenaar8299df92004-07-10 09:47:34 +000015952 if (fromlen == inlen && STRNCMP(instr, p, inlen) == 0)
15953 {
15954 for (p = tostr; *p != NUL; p += tolen)
15955 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000015956 tolen = (*mb_ptr2len)(p);
Bram Moolenaar8299df92004-07-10 09:47:34 +000015957 if (idx-- == 0)
15958 {
15959 cplen = tolen;
15960 cpstr = p;
15961 break;
15962 }
15963 }
15964 if (*p == NUL) /* tostr is shorter than fromstr */
15965 goto error;
15966 break;
15967 }
15968 ++idx;
15969 }
15970
15971 if (first && cpstr == instr)
15972 {
15973 /* Check that fromstr and tostr have the same number of
15974 * (multi-byte) characters. Done only once when a character
15975 * of instr doesn't appear in fromstr. */
15976 first = FALSE;
15977 for (p = tostr; *p != NUL; p += tolen)
15978 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000015979 tolen = (*mb_ptr2len)(p);
Bram Moolenaar8299df92004-07-10 09:47:34 +000015980 --idx;
15981 }
15982 if (idx != 0)
15983 goto error;
15984 }
15985
15986 ga_grow(&ga, cplen);
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +000015987 mch_memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen);
Bram Moolenaar8299df92004-07-10 09:47:34 +000015988 ga.ga_len += cplen;
Bram Moolenaar8299df92004-07-10 09:47:34 +000015989
15990 instr += inlen;
15991 }
15992 else
15993#endif
15994 {
15995 /* When not using multi-byte chars we can do it faster. */
15996 p = vim_strchr(fromstr, *instr);
15997 if (p != NULL)
15998 ga_append(&ga, tostr[p - fromstr]);
15999 else
16000 ga_append(&ga, *instr);
16001 ++instr;
16002 }
16003 }
16004
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016005 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar8299df92004-07-10 09:47:34 +000016006}
16007
16008/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000016009 * "type(expr)" function
16010 */
16011 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016012f_type(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000016013 typval_T *argvars;
16014 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016015{
Bram Moolenaar6cc16192005-01-08 21:49:45 +000016016 int n;
16017
16018 switch (argvars[0].v_type)
16019 {
16020 case VAR_NUMBER: n = 0; break;
16021 case VAR_STRING: n = 1; break;
16022 case VAR_FUNC: n = 2; break;
16023 case VAR_LIST: n = 3; break;
Bram Moolenaar758711c2005-02-02 23:11:38 +000016024 case VAR_DICT: n = 4; break;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000016025 default: EMSG2(_(e_intern2), "f_type()"); n = 0; break;
16026 }
16027 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016028}
16029
16030/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000016031 * "values(dict)" function
16032 */
16033 static void
16034f_values(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000016035 typval_T *argvars;
16036 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000016037{
16038 dict_list(argvars, rettv, 1);
16039}
16040
16041/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000016042 * "virtcol(string)" function
16043 */
16044 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016045f_virtcol(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000016046 typval_T *argvars;
16047 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016048{
16049 colnr_T vcol = 0;
16050 pos_T *fp;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016051 int fnum = curbuf->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016052
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016053 fp = var2fpos(&argvars[0], FALSE, &fnum);
16054 if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count
16055 && fnum == curbuf->b_fnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016056 {
16057 getvvcol(curwin, fp, NULL, NULL, &vcol);
16058 ++vcol;
16059 }
16060
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016061 rettv->vval.v_number = vcol;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016062}
16063
16064/*
16065 * "visualmode()" function
16066 */
16067/*ARGSUSED*/
16068 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016069f_visualmode(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000016070 typval_T *argvars;
16071 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016072{
16073#ifdef FEAT_VISUAL
16074 char_u str[2];
16075
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016076 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016077 str[0] = curbuf->b_visual_mode_eval;
16078 str[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016079 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016080
16081 /* A non-zero number or non-empty string argument: reset mode. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016082 if ((argvars[0].v_type == VAR_NUMBER
16083 && argvars[0].vval.v_number != 0)
16084 || (argvars[0].v_type == VAR_STRING
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016085 && *get_tv_string(&argvars[0]) != NUL))
Bram Moolenaar071d4272004-06-13 20:20:40 +000016086 curbuf->b_visual_mode_eval = NUL;
16087#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016088 rettv->vval.v_number = 0; /* return anything, it won't work anyway */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016089#endif
16090}
16091
16092/*
16093 * "winbufnr(nr)" function
16094 */
16095 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016096f_winbufnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000016097 typval_T *argvars;
16098 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016099{
16100 win_T *wp;
16101
Bram Moolenaar99ebf042006-04-15 20:28:54 +000016102 wp = find_win_by_nr(&argvars[0], NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016103 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016104 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016105 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016106 rettv->vval.v_number = wp->w_buffer->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016107}
16108
16109/*
16110 * "wincol()" function
16111 */
16112/*ARGSUSED*/
16113 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016114f_wincol(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000016115 typval_T *argvars;
16116 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016117{
16118 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016119 rettv->vval.v_number = curwin->w_wcol + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016120}
16121
16122/*
16123 * "winheight(nr)" function
16124 */
16125 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016126f_winheight(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000016127 typval_T *argvars;
16128 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016129{
16130 win_T *wp;
16131
Bram Moolenaar99ebf042006-04-15 20:28:54 +000016132 wp = find_win_by_nr(&argvars[0], NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016133 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016134 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016135 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016136 rettv->vval.v_number = wp->w_height;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016137}
16138
16139/*
16140 * "winline()" function
16141 */
16142/*ARGSUSED*/
16143 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016144f_winline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000016145 typval_T *argvars;
16146 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016147{
16148 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016149 rettv->vval.v_number = curwin->w_wrow + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016150}
16151
16152/*
16153 * "winnr()" function
16154 */
16155/* ARGSUSED */
16156 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016157f_winnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000016158 typval_T *argvars;
16159 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016160{
16161 int nr = 1;
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000016162
Bram Moolenaar071d4272004-06-13 20:20:40 +000016163#ifdef FEAT_WINDOWS
Bram Moolenaarfaa959a2006-02-20 21:37:40 +000016164 nr = get_winnr(curtab, &argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016165#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016166 rettv->vval.v_number = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016167}
16168
16169/*
16170 * "winrestcmd()" function
16171 */
16172/* ARGSUSED */
16173 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016174f_winrestcmd(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000016175 typval_T *argvars;
16176 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016177{
16178#ifdef FEAT_WINDOWS
16179 win_T *wp;
16180 int winnr = 1;
16181 garray_T ga;
16182 char_u buf[50];
16183
16184 ga_init2(&ga, (int)sizeof(char), 70);
16185 for (wp = firstwin; wp != NULL; wp = wp->w_next)
16186 {
16187 sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height);
16188 ga_concat(&ga, buf);
16189# ifdef FEAT_VERTSPLIT
16190 sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width);
16191 ga_concat(&ga, buf);
16192# endif
16193 ++winnr;
16194 }
Bram Moolenaar269ec652004-07-29 08:43:53 +000016195 ga_append(&ga, NUL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016196
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016197 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016198#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016199 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016200#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016201 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016202}
16203
16204/*
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016205 * "winrestview()" function
16206 */
16207/* ARGSUSED */
16208 static void
16209f_winrestview(argvars, rettv)
16210 typval_T *argvars;
16211 typval_T *rettv;
16212{
16213 dict_T *dict;
16214
16215 if (argvars[0].v_type != VAR_DICT
16216 || (dict = argvars[0].vval.v_dict) == NULL)
16217 EMSG(_(e_invarg));
16218 else
16219 {
16220 curwin->w_cursor.lnum = get_dict_number(dict, (char_u *)"lnum");
16221 curwin->w_cursor.col = get_dict_number(dict, (char_u *)"col");
16222#ifdef FEAT_VIRTUALEDIT
16223 curwin->w_cursor.coladd = get_dict_number(dict, (char_u *)"coladd");
16224#endif
16225 curwin->w_curswant = get_dict_number(dict, (char_u *)"curswant");
Bram Moolenaar362e1a32006-03-06 23:29:24 +000016226 curwin->w_set_curswant = FALSE;
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016227
16228 curwin->w_topline = get_dict_number(dict, (char_u *)"topline");
16229#ifdef FEAT_DIFF
16230 curwin->w_topfill = get_dict_number(dict, (char_u *)"topfill");
16231#endif
16232 curwin->w_leftcol = get_dict_number(dict, (char_u *)"leftcol");
16233 curwin->w_skipcol = get_dict_number(dict, (char_u *)"skipcol");
16234
16235 check_cursor();
16236 changed_cline_bef_curs();
16237 invalidate_botline();
16238 redraw_later(VALID);
16239
16240 if (curwin->w_topline == 0)
16241 curwin->w_topline = 1;
16242 if (curwin->w_topline > curbuf->b_ml.ml_line_count)
16243 curwin->w_topline = curbuf->b_ml.ml_line_count;
16244#ifdef FEAT_DIFF
16245 check_topfill(curwin, TRUE);
16246#endif
16247 }
16248}
16249
16250/*
16251 * "winsaveview()" function
16252 */
16253/* ARGSUSED */
16254 static void
16255f_winsaveview(argvars, rettv)
16256 typval_T *argvars;
16257 typval_T *rettv;
16258{
16259 dict_T *dict;
16260
16261 dict = dict_alloc();
16262 if (dict == NULL)
16263 return;
16264 rettv->v_type = VAR_DICT;
16265 rettv->vval.v_dict = dict;
16266 ++dict->dv_refcount;
16267
16268 dict_add_nr_str(dict, "lnum", (long)curwin->w_cursor.lnum, NULL);
16269 dict_add_nr_str(dict, "col", (long)curwin->w_cursor.col, NULL);
16270#ifdef FEAT_VIRTUALEDIT
16271 dict_add_nr_str(dict, "coladd", (long)curwin->w_cursor.coladd, NULL);
16272#endif
Bram Moolenaar9af1ba92006-08-29 19:55:53 +000016273 update_curswant();
Bram Moolenaar768b8c42006-03-04 21:58:33 +000016274 dict_add_nr_str(dict, "curswant", (long)curwin->w_curswant, NULL);
16275
16276 dict_add_nr_str(dict, "topline", (long)curwin->w_topline, NULL);
16277#ifdef FEAT_DIFF
16278 dict_add_nr_str(dict, "topfill", (long)curwin->w_topfill, NULL);
16279#endif
16280 dict_add_nr_str(dict, "leftcol", (long)curwin->w_leftcol, NULL);
16281 dict_add_nr_str(dict, "skipcol", (long)curwin->w_skipcol, NULL);
16282}
16283
16284/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000016285 * "winwidth(nr)" function
16286 */
16287 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016288f_winwidth(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000016289 typval_T *argvars;
16290 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016291{
16292 win_T *wp;
16293
Bram Moolenaar99ebf042006-04-15 20:28:54 +000016294 wp = find_win_by_nr(&argvars[0], NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016295 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016296 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016297 else
16298#ifdef FEAT_VERTSPLIT
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016299 rettv->vval.v_number = wp->w_width;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016300#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016301 rettv->vval.v_number = Columns;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016302#endif
16303}
16304
Bram Moolenaar071d4272004-06-13 20:20:40 +000016305/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000016306 * "writefile()" function
16307 */
16308 static void
16309f_writefile(argvars, rettv)
16310 typval_T *argvars;
16311 typval_T *rettv;
16312{
16313 int binary = FALSE;
16314 char_u *fname;
16315 FILE *fd;
16316 listitem_T *li;
16317 char_u *s;
16318 int ret = 0;
16319 int c;
16320
16321 if (argvars[0].v_type != VAR_LIST)
16322 {
16323 EMSG2(_(e_listarg), "writefile()");
16324 return;
16325 }
16326 if (argvars[0].vval.v_list == NULL)
16327 return;
16328
16329 if (argvars[2].v_type != VAR_UNKNOWN
16330 && STRCMP(get_tv_string(&argvars[2]), "b") == 0)
16331 binary = TRUE;
16332
16333 /* Always open the file in binary mode, library functions have a mind of
16334 * their own about CR-LF conversion. */
16335 fname = get_tv_string(&argvars[1]);
16336 if (*fname == NUL || (fd = mch_fopen((char *)fname, WRITEBIN)) == NULL)
16337 {
16338 EMSG2(_(e_notcreate), *fname == NUL ? (char_u *)_("<empty>") : fname);
16339 ret = -1;
16340 }
16341 else
16342 {
16343 for (li = argvars[0].vval.v_list->lv_first; li != NULL;
16344 li = li->li_next)
16345 {
16346 for (s = get_tv_string(&li->li_tv); *s != NUL; ++s)
16347 {
16348 if (*s == '\n')
16349 c = putc(NUL, fd);
16350 else
16351 c = putc(*s, fd);
16352 if (c == EOF)
16353 {
16354 ret = -1;
16355 break;
16356 }
16357 }
16358 if (!binary || li->li_next != NULL)
16359 if (putc('\n', fd) == EOF)
16360 {
16361 ret = -1;
16362 break;
16363 }
16364 if (ret < 0)
16365 {
16366 EMSG(_(e_write));
16367 break;
16368 }
16369 }
16370 fclose(fd);
16371 }
16372
16373 rettv->vval.v_number = ret;
16374}
16375
16376/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000016377 * Translate a String variable into a position.
Bram Moolenaar32466aa2006-02-24 23:53:04 +000016378 * Returns NULL when there is an error.
Bram Moolenaar071d4272004-06-13 20:20:40 +000016379 */
16380 static pos_T *
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016381var2fpos(varp, lnum, fnum)
Bram Moolenaar33570922005-01-25 22:26:29 +000016382 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016383 int lnum; /* TRUE when $ is last line */
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016384 int *fnum; /* set to fnum for '0, 'A, etc. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016385{
Bram Moolenaar261bfea2006-03-01 22:12:31 +000016386 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016387 static pos_T pos;
Bram Moolenaar261bfea2006-03-01 22:12:31 +000016388 pos_T *pp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016389
Bram Moolenaara5525202006-03-02 22:52:09 +000016390 /* Argument can be [lnum, col, coladd]. */
Bram Moolenaar32466aa2006-02-24 23:53:04 +000016391 if (varp->v_type == VAR_LIST)
16392 {
16393 list_T *l;
Bram Moolenaar32466aa2006-02-24 23:53:04 +000016394 int len;
Bram Moolenaara5525202006-03-02 22:52:09 +000016395 int error = FALSE;
Bram Moolenaar32466aa2006-02-24 23:53:04 +000016396
16397 l = varp->vval.v_list;
16398 if (l == NULL)
16399 return NULL;
16400
16401 /* Get the line number */
Bram Moolenaara5525202006-03-02 22:52:09 +000016402 pos.lnum = list_find_nr(l, 0L, &error);
16403 if (error || pos.lnum <= 0 || pos.lnum > curbuf->b_ml.ml_line_count)
Bram Moolenaar32466aa2006-02-24 23:53:04 +000016404 return NULL; /* invalid line number */
16405
16406 /* Get the column number */
Bram Moolenaara5525202006-03-02 22:52:09 +000016407 pos.col = list_find_nr(l, 1L, &error);
16408 if (error)
Bram Moolenaar32466aa2006-02-24 23:53:04 +000016409 return NULL;
Bram Moolenaar32466aa2006-02-24 23:53:04 +000016410 len = (long)STRLEN(ml_get(pos.lnum));
Bram Moolenaara5525202006-03-02 22:52:09 +000016411 /* Accept a position up to the NUL after the line. */
Bram Moolenaar4c3f5362006-04-11 21:38:50 +000016412 if (pos.col == 0 || (int)pos.col > len + 1)
Bram Moolenaar32466aa2006-02-24 23:53:04 +000016413 return NULL; /* invalid column number */
Bram Moolenaara5525202006-03-02 22:52:09 +000016414 --pos.col;
Bram Moolenaar32466aa2006-02-24 23:53:04 +000016415
Bram Moolenaara5525202006-03-02 22:52:09 +000016416#ifdef FEAT_VIRTUALEDIT
16417 /* Get the virtual offset. Defaults to zero. */
16418 pos.coladd = list_find_nr(l, 2L, &error);
16419 if (error)
16420 pos.coladd = 0;
16421#endif
16422
Bram Moolenaar32466aa2006-02-24 23:53:04 +000016423 return &pos;
16424 }
16425
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016426 name = get_tv_string_chk(varp);
16427 if (name == NULL)
16428 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016429 if (name[0] == '.') /* cursor */
16430 return &curwin->w_cursor;
16431 if (name[0] == '\'') /* mark */
16432 {
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016433 pp = getmark_fnum(name[1], FALSE, fnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016434 if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
16435 return NULL;
16436 return pp;
16437 }
Bram Moolenaara5525202006-03-02 22:52:09 +000016438
16439#ifdef FEAT_VIRTUALEDIT
16440 pos.coladd = 0;
16441#endif
16442
Bram Moolenaarf52c7252006-02-10 23:23:57 +000016443 if (name[0] == 'w' && lnum)
16444 {
16445 pos.col = 0;
16446 if (name[1] == '0') /* "w0": first visible line */
16447 {
Bram Moolenaarf740b292006-02-16 22:11:02 +000016448 update_topline();
Bram Moolenaarf52c7252006-02-10 23:23:57 +000016449 pos.lnum = curwin->w_topline;
16450 return &pos;
16451 }
16452 else if (name[1] == '$') /* "w$": last visible line */
16453 {
Bram Moolenaarf740b292006-02-16 22:11:02 +000016454 validate_botline();
Bram Moolenaarf52c7252006-02-10 23:23:57 +000016455 pos.lnum = curwin->w_botline - 1;
16456 return &pos;
16457 }
16458 }
16459 else if (name[0] == '$') /* last column or line */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016460 {
16461 if (lnum)
16462 {
16463 pos.lnum = curbuf->b_ml.ml_line_count;
16464 pos.col = 0;
16465 }
16466 else
16467 {
16468 pos.lnum = curwin->w_cursor.lnum;
16469 pos.col = (colnr_T)STRLEN(ml_get_curline());
16470 }
16471 return &pos;
16472 }
16473 return NULL;
16474}
16475
16476/*
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016477 * Convert list in "arg" into a position and optional file number.
16478 * When "fnump" is NULL there is no file number, only 3 items.
16479 * Note that the column is passed on as-is, the caller may want to decrement
16480 * it to use 1 for the first column.
16481 * Return FAIL when conversion is not possible, doesn't check the position for
16482 * validity.
16483 */
16484 static int
16485list2fpos(arg, posp, fnump)
16486 typval_T *arg;
16487 pos_T *posp;
16488 int *fnump;
16489{
16490 list_T *l = arg->vval.v_list;
16491 long i = 0;
16492 long n;
16493
Bram Moolenaarbde35262006-07-23 20:12:24 +000016494 /* List must be: [fnum, lnum, col, coladd], where "fnum" is only there
16495 * when "fnump" isn't NULL and "coladd" is optional. */
16496 if (arg->v_type != VAR_LIST
16497 || l == NULL
16498 || l->lv_len < (fnump == NULL ? 2 : 3)
16499 || l->lv_len > (fnump == NULL ? 3 : 4))
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016500 return FAIL;
16501
16502 if (fnump != NULL)
16503 {
16504 n = list_find_nr(l, i++, NULL); /* fnum */
16505 if (n < 0)
16506 return FAIL;
16507 if (n == 0)
16508 n = curbuf->b_fnum; /* current buffer */
16509 *fnump = n;
16510 }
16511
16512 n = list_find_nr(l, i++, NULL); /* lnum */
16513 if (n < 0)
16514 return FAIL;
16515 posp->lnum = n;
16516
16517 n = list_find_nr(l, i++, NULL); /* col */
16518 if (n < 0)
16519 return FAIL;
16520 posp->col = n;
16521
16522#ifdef FEAT_VIRTUALEDIT
16523 n = list_find_nr(l, i, NULL);
16524 if (n < 0)
Bram Moolenaarbde35262006-07-23 20:12:24 +000016525 posp->coladd = 0;
16526 else
16527 posp->coladd = n;
Bram Moolenaar0e34f622006-03-03 23:00:03 +000016528#endif
16529
16530 return OK;
16531}
16532
16533/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000016534 * Get the length of an environment variable name.
16535 * Advance "arg" to the first character after the name.
16536 * Return 0 for error.
16537 */
16538 static int
16539get_env_len(arg)
16540 char_u **arg;
16541{
16542 char_u *p;
16543 int len;
16544
16545 for (p = *arg; vim_isIDc(*p); ++p)
16546 ;
16547 if (p == *arg) /* no name found */
16548 return 0;
16549
16550 len = (int)(p - *arg);
16551 *arg = p;
16552 return len;
16553}
16554
16555/*
16556 * Get the length of the name of a function or internal variable.
16557 * "arg" is advanced to the first non-white character after the name.
16558 * Return 0 if something is wrong.
16559 */
16560 static int
16561get_id_len(arg)
16562 char_u **arg;
16563{
16564 char_u *p;
16565 int len;
16566
16567 /* Find the end of the name. */
16568 for (p = *arg; eval_isnamec(*p); ++p)
16569 ;
16570 if (p == *arg) /* no name found */
16571 return 0;
16572
16573 len = (int)(p - *arg);
16574 *arg = skipwhite(p);
16575
16576 return len;
16577}
16578
16579/*
Bram Moolenaara7043832005-01-21 11:56:39 +000016580 * Get the length of the name of a variable or function.
16581 * Only the name is recognized, does not handle ".key" or "[idx]".
Bram Moolenaar071d4272004-06-13 20:20:40 +000016582 * "arg" is advanced to the first non-white character after the name.
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000016583 * Return -1 if curly braces expansion failed.
16584 * Return 0 if something else is wrong.
Bram Moolenaar071d4272004-06-13 20:20:40 +000016585 * If the name contains 'magic' {}'s, expand them and return the
16586 * expanded name in an allocated string via 'alias' - caller must free.
16587 */
16588 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000016589get_name_len(arg, alias, evaluate, verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016590 char_u **arg;
16591 char_u **alias;
16592 int evaluate;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000016593 int verbose;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016594{
16595 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016596 char_u *p;
16597 char_u *expr_start;
16598 char_u *expr_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016599
16600 *alias = NULL; /* default to no alias */
16601
16602 if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
16603 && (*arg)[2] == (int)KE_SNR)
16604 {
16605 /* hard coded <SNR>, already translated */
16606 *arg += 3;
16607 return get_id_len(arg) + 3;
16608 }
16609 len = eval_fname_script(*arg);
16610 if (len > 0)
16611 {
16612 /* literal "<SID>", "s:" or "<SNR>" */
16613 *arg += len;
16614 }
16615
Bram Moolenaar071d4272004-06-13 20:20:40 +000016616 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016617 * Find the end of the name; check for {} construction.
Bram Moolenaar071d4272004-06-13 20:20:40 +000016618 */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000016619 p = find_name_end(*arg, &expr_start, &expr_end,
16620 len > 0 ? 0 : FNE_CHECK_START);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016621 if (expr_start != NULL)
16622 {
16623 char_u *temp_string;
16624
16625 if (!evaluate)
16626 {
16627 len += (int)(p - *arg);
16628 *arg = skipwhite(p);
16629 return len;
16630 }
16631
16632 /*
16633 * Include any <SID> etc in the expanded string:
16634 * Thus the -len here.
16635 */
16636 temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
16637 if (temp_string == NULL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000016638 return -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016639 *alias = temp_string;
16640 *arg = skipwhite(p);
16641 return (int)STRLEN(temp_string);
16642 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016643
16644 len += get_id_len(arg);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000016645 if (len == 0 && verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016646 EMSG2(_(e_invexpr2), *arg);
16647
16648 return len;
16649}
16650
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016651/*
16652 * Find the end of a variable or function name, taking care of magic braces.
16653 * If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the
16654 * start and end of the first magic braces item.
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000016655 * "flags" can have FNE_INCL_BR and FNE_CHECK_START.
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016656 * Return a pointer to just after the name. Equal to "arg" if there is no
16657 * valid name.
16658 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016659 static char_u *
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000016660find_name_end(arg, expr_start, expr_end, flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016661 char_u *arg;
16662 char_u **expr_start;
16663 char_u **expr_end;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000016664 int flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016665{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016666 int mb_nest = 0;
16667 int br_nest = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016668 char_u *p;
16669
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016670 if (expr_start != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016671 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016672 *expr_start = NULL;
16673 *expr_end = NULL;
16674 }
16675
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000016676 /* Quick check for valid starting character. */
16677 if ((flags & FNE_CHECK_START) && !eval_isnamec1(*arg) && *arg != '{')
16678 return arg;
16679
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016680 for (p = arg; *p != NUL
16681 && (eval_isnamec(*p)
Bram Moolenaare9a41262005-01-15 22:18:47 +000016682 || *p == '{'
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000016683 || ((flags & FNE_INCL_BR) && (*p == '[' || *p == '.'))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016684 || mb_nest != 0
Bram Moolenaar8af24422005-08-08 22:06:28 +000016685 || br_nest != 0); mb_ptr_adv(p))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016686 {
Bram Moolenaar8af24422005-08-08 22:06:28 +000016687 if (*p == '\'')
16688 {
16689 /* skip over 'string' to avoid counting [ and ] inside it. */
16690 for (p = p + 1; *p != NUL && *p != '\''; mb_ptr_adv(p))
16691 ;
16692 if (*p == NUL)
16693 break;
16694 }
16695 else if (*p == '"')
16696 {
16697 /* skip over "str\"ing" to avoid counting [ and ] inside it. */
16698 for (p = p + 1; *p != NUL && *p != '"'; mb_ptr_adv(p))
16699 if (*p == '\\' && p[1] != NUL)
16700 ++p;
16701 if (*p == NUL)
16702 break;
16703 }
16704
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016705 if (mb_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016706 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016707 if (*p == '[')
16708 ++br_nest;
16709 else if (*p == ']')
16710 --br_nest;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016711 }
Bram Moolenaar8af24422005-08-08 22:06:28 +000016712
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016713 if (br_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016714 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016715 if (*p == '{')
16716 {
16717 mb_nest++;
16718 if (expr_start != NULL && *expr_start == NULL)
16719 *expr_start = p;
16720 }
16721 else if (*p == '}')
16722 {
16723 mb_nest--;
16724 if (expr_start != NULL && mb_nest == 0 && *expr_end == NULL)
16725 *expr_end = p;
16726 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016727 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016728 }
16729
16730 return p;
16731}
16732
16733/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000016734 * Expands out the 'magic' {}'s in a variable/function name.
16735 * Note that this can call itself recursively, to deal with
16736 * constructs like foo{bar}{baz}{bam}
16737 * The four pointer arguments point to "foo{expre}ss{ion}bar"
16738 * "in_start" ^
16739 * "expr_start" ^
16740 * "expr_end" ^
16741 * "in_end" ^
16742 *
16743 * Returns a new allocated string, which the caller must free.
16744 * Returns NULL for failure.
16745 */
16746 static char_u *
16747make_expanded_name(in_start, expr_start, expr_end, in_end)
16748 char_u *in_start;
16749 char_u *expr_start;
16750 char_u *expr_end;
16751 char_u *in_end;
16752{
16753 char_u c1;
16754 char_u *retval = NULL;
16755 char_u *temp_result;
16756 char_u *nextcmd = NULL;
16757
16758 if (expr_end == NULL || in_end == NULL)
16759 return NULL;
16760 *expr_start = NUL;
16761 *expr_end = NUL;
16762 c1 = *in_end;
16763 *in_end = NUL;
16764
Bram Moolenaar362e1a32006-03-06 23:29:24 +000016765 temp_result = eval_to_string(expr_start + 1, &nextcmd, FALSE);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000016766 if (temp_result != NULL && nextcmd == NULL)
16767 {
16768 retval = alloc((unsigned)(STRLEN(temp_result) + (expr_start - in_start)
16769 + (in_end - expr_end) + 1));
16770 if (retval != NULL)
16771 {
16772 STRCPY(retval, in_start);
16773 STRCAT(retval, temp_result);
16774 STRCAT(retval, expr_end + 1);
16775 }
16776 }
16777 vim_free(temp_result);
16778
16779 *in_end = c1; /* put char back for error messages */
16780 *expr_start = '{';
16781 *expr_end = '}';
16782
16783 if (retval != NULL)
16784 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000016785 temp_result = find_name_end(retval, &expr_start, &expr_end, 0);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000016786 if (expr_start != NULL)
16787 {
16788 /* Further expansion! */
16789 temp_result = make_expanded_name(retval, expr_start,
16790 expr_end, temp_result);
16791 vim_free(retval);
16792 retval = temp_result;
16793 }
16794 }
16795
16796 return retval;
16797}
16798
16799/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000016800 * Return TRUE if character "c" can be used in a variable or function name.
Bram Moolenaare9a41262005-01-15 22:18:47 +000016801 * Does not include '{' or '}' for magic braces.
Bram Moolenaar071d4272004-06-13 20:20:40 +000016802 */
16803 static int
16804eval_isnamec(c)
16805 int c;
16806{
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000016807 return (ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR);
16808}
16809
16810/*
16811 * Return TRUE if character "c" can be used as the first character in a
16812 * variable or function name (excluding '{' and '}').
16813 */
16814 static int
16815eval_isnamec1(c)
16816 int c;
16817{
16818 return (ASCII_ISALPHA(c) || c == '_');
Bram Moolenaar071d4272004-06-13 20:20:40 +000016819}
16820
16821/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000016822 * Set number v: variable to "val".
16823 */
16824 void
16825set_vim_var_nr(idx, val)
16826 int idx;
16827 long val;
16828{
Bram Moolenaare9a41262005-01-15 22:18:47 +000016829 vimvars[idx].vv_nr = val;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016830}
16831
16832/*
Bram Moolenaar19a09a12005-03-04 23:39:37 +000016833 * Get number v: variable value.
Bram Moolenaar071d4272004-06-13 20:20:40 +000016834 */
16835 long
16836get_vim_var_nr(idx)
16837 int idx;
16838{
Bram Moolenaare9a41262005-01-15 22:18:47 +000016839 return vimvars[idx].vv_nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016840}
16841
Bram Moolenaar19a09a12005-03-04 23:39:37 +000016842#if defined(FEAT_AUTOCMD) || defined(PROTO)
16843/*
16844 * Get string v: variable value. Uses a static buffer, can only be used once.
16845 */
16846 char_u *
16847get_vim_var_str(idx)
16848 int idx;
16849{
16850 return get_tv_string(&vimvars[idx].vv_tv);
16851}
16852#endif
16853
Bram Moolenaar071d4272004-06-13 20:20:40 +000016854/*
16855 * Set v:count, v:count1 and v:prevcount.
16856 */
16857 void
16858set_vcount(count, count1)
16859 long count;
16860 long count1;
16861{
Bram Moolenaare9a41262005-01-15 22:18:47 +000016862 vimvars[VV_PREVCOUNT].vv_nr = vimvars[VV_COUNT].vv_nr;
16863 vimvars[VV_COUNT].vv_nr = count;
16864 vimvars[VV_COUNT1].vv_nr = count1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016865}
16866
16867/*
16868 * Set string v: variable to a copy of "val".
16869 */
16870 void
16871set_vim_var_string(idx, val, len)
16872 int idx;
16873 char_u *val;
16874 int len; /* length of "val" to use or -1 (whole string) */
16875{
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016876 /* Need to do this (at least) once, since we can't initialize a union.
16877 * Will always be invoked when "v:progname" is set. */
16878 vimvars[VV_VERSION].vv_nr = VIM_VERSION_100;
16879
Bram Moolenaare9a41262005-01-15 22:18:47 +000016880 vim_free(vimvars[idx].vv_str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016881 if (val == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000016882 vimvars[idx].vv_str = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016883 else if (len == -1)
Bram Moolenaare9a41262005-01-15 22:18:47 +000016884 vimvars[idx].vv_str = vim_strsave(val);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016885 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000016886 vimvars[idx].vv_str = vim_strnsave(val, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016887}
16888
16889/*
16890 * Set v:register if needed.
16891 */
16892 void
16893set_reg_var(c)
16894 int c;
16895{
16896 char_u regname;
16897
16898 if (c == 0 || c == ' ')
16899 regname = '"';
16900 else
16901 regname = c;
16902 /* Avoid free/alloc when the value is already right. */
Bram Moolenaare9a41262005-01-15 22:18:47 +000016903 if (vimvars[VV_REG].vv_str == NULL || vimvars[VV_REG].vv_str[0] != c)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016904 set_vim_var_string(VV_REG, &regname, 1);
16905}
16906
16907/*
16908 * Get or set v:exception. If "oldval" == NULL, return the current value.
16909 * Otherwise, restore the value to "oldval" and return NULL.
16910 * Must always be called in pairs to save and restore v:exception! Does not
16911 * take care of memory allocations.
16912 */
16913 char_u *
16914v_exception(oldval)
16915 char_u *oldval;
16916{
16917 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000016918 return vimvars[VV_EXCEPTION].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016919
Bram Moolenaare9a41262005-01-15 22:18:47 +000016920 vimvars[VV_EXCEPTION].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016921 return NULL;
16922}
16923
16924/*
16925 * Get or set v:throwpoint. If "oldval" == NULL, return the current value.
16926 * Otherwise, restore the value to "oldval" and return NULL.
16927 * Must always be called in pairs to save and restore v:throwpoint! Does not
16928 * take care of memory allocations.
16929 */
16930 char_u *
16931v_throwpoint(oldval)
16932 char_u *oldval;
16933{
16934 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000016935 return vimvars[VV_THROWPOINT].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016936
Bram Moolenaare9a41262005-01-15 22:18:47 +000016937 vimvars[VV_THROWPOINT].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016938 return NULL;
16939}
16940
16941#if defined(FEAT_AUTOCMD) || defined(PROTO)
16942/*
16943 * Set v:cmdarg.
16944 * If "eap" != NULL, use "eap" to generate the value and return the old value.
16945 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
16946 * Must always be called in pairs!
16947 */
16948 char_u *
16949set_cmdarg(eap, oldarg)
16950 exarg_T *eap;
16951 char_u *oldarg;
16952{
16953 char_u *oldval;
16954 char_u *newval;
16955 unsigned len;
16956
Bram Moolenaare9a41262005-01-15 22:18:47 +000016957 oldval = vimvars[VV_CMDARG].vv_str;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000016958 if (eap == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016959 {
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000016960 vim_free(oldval);
Bram Moolenaare9a41262005-01-15 22:18:47 +000016961 vimvars[VV_CMDARG].vv_str = oldarg;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000016962 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016963 }
16964
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000016965 if (eap->force_bin == FORCE_BIN)
16966 len = 6;
16967 else if (eap->force_bin == FORCE_NOBIN)
16968 len = 8;
16969 else
16970 len = 0;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000016971
16972 if (eap->read_edit)
16973 len += 7;
16974
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000016975 if (eap->force_ff != 0)
16976 len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6;
16977# ifdef FEAT_MBYTE
16978 if (eap->force_enc != 0)
16979 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
Bram Moolenaarb2c2efa2005-12-13 20:09:08 +000016980 if (eap->bad_char != 0)
16981 len += (unsigned)STRLEN(eap->cmd + eap->bad_char) + 7;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000016982# endif
16983
16984 newval = alloc(len + 1);
16985 if (newval == NULL)
16986 return NULL;
16987
16988 if (eap->force_bin == FORCE_BIN)
16989 sprintf((char *)newval, " ++bin");
16990 else if (eap->force_bin == FORCE_NOBIN)
16991 sprintf((char *)newval, " ++nobin");
16992 else
16993 *newval = NUL;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000016994
16995 if (eap->read_edit)
16996 STRCAT(newval, " ++edit");
16997
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000016998 if (eap->force_ff != 0)
16999 sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
17000 eap->cmd + eap->force_ff);
17001# ifdef FEAT_MBYTE
17002 if (eap->force_enc != 0)
17003 sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
17004 eap->cmd + eap->force_enc);
Bram Moolenaarb2c2efa2005-12-13 20:09:08 +000017005 if (eap->bad_char != 0)
17006 sprintf((char *)newval + STRLEN(newval), " ++bad=%s",
17007 eap->cmd + eap->bad_char);
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000017008# endif
Bram Moolenaare9a41262005-01-15 22:18:47 +000017009 vimvars[VV_CMDARG].vv_str = newval;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000017010 return oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017011}
17012#endif
17013
17014/*
17015 * Get the value of internal variable "name".
17016 * Return OK or FAIL.
17017 */
17018 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000017019get_var_tv(name, len, rettv, verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017020 char_u *name;
17021 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +000017022 typval_T *rettv; /* NULL when only checking existence */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000017023 int verbose; /* may give error message */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017024{
17025 int ret = OK;
Bram Moolenaar33570922005-01-25 22:26:29 +000017026 typval_T *tv = NULL;
17027 typval_T atv;
17028 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017029 int cc;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017030
17031 /* truncate the name, so that we can use strcmp() */
17032 cc = name[len];
17033 name[len] = NUL;
17034
17035 /*
17036 * Check for "b:changedtick".
17037 */
17038 if (STRCMP(name, "b:changedtick") == 0)
17039 {
Bram Moolenaare9a41262005-01-15 22:18:47 +000017040 atv.v_type = VAR_NUMBER;
17041 atv.vval.v_number = curbuf->b_changedtick;
17042 tv = &atv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017043 }
17044
17045 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +000017046 * Check for user-defined variables.
17047 */
17048 else
17049 {
Bram Moolenaara7043832005-01-21 11:56:39 +000017050 v = find_var(name, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017051 if (v != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000017052 tv = &v->di_tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017053 }
17054
Bram Moolenaare9a41262005-01-15 22:18:47 +000017055 if (tv == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017056 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000017057 if (rettv != NULL && verbose)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017058 EMSG2(_(e_undefvar), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017059 ret = FAIL;
17060 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017061 else if (rettv != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000017062 copy_tv(tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017063
17064 name[len] = cc;
17065
17066 return ret;
17067}
17068
17069/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000017070 * Handle expr[expr], expr[expr:expr] subscript and .name lookup.
17071 * Also handle function call with Funcref variable: func(expr)
17072 * Can all be combined: dict.func(expr)[idx]['func'](expr)
17073 */
17074 static int
17075handle_subscript(arg, rettv, evaluate, verbose)
17076 char_u **arg;
17077 typval_T *rettv;
17078 int evaluate; /* do more than finding the end */
17079 int verbose; /* give error messages */
17080{
17081 int ret = OK;
17082 dict_T *selfdict = NULL;
17083 char_u *s;
17084 int len;
Bram Moolenaard9fba312005-06-26 22:34:35 +000017085 typval_T functv;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000017086
17087 while (ret == OK
17088 && (**arg == '['
17089 || (**arg == '.' && rettv->v_type == VAR_DICT)
17090 || (**arg == '(' && rettv->v_type == VAR_FUNC))
17091 && !vim_iswhite(*(*arg - 1)))
17092 {
17093 if (**arg == '(')
17094 {
Bram Moolenaard9fba312005-06-26 22:34:35 +000017095 /* need to copy the funcref so that we can clear rettv */
17096 functv = *rettv;
17097 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000017098
17099 /* Invoke the function. Recursive! */
Bram Moolenaard9fba312005-06-26 22:34:35 +000017100 s = functv.vval.v_string;
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000017101 ret = get_func_tv(s, (int)STRLEN(s), rettv, arg,
Bram Moolenaard9fba312005-06-26 22:34:35 +000017102 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
17103 &len, evaluate, selfdict);
17104
17105 /* Clear the funcref afterwards, so that deleting it while
17106 * evaluating the arguments is possible (see test55). */
17107 clear_tv(&functv);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000017108
17109 /* Stop the expression evaluation when immediately aborting on
17110 * error, or when an interrupt occurred or an exception was thrown
17111 * but not caught. */
17112 if (aborting())
17113 {
17114 if (ret == OK)
17115 clear_tv(rettv);
17116 ret = FAIL;
17117 }
17118 dict_unref(selfdict);
17119 selfdict = NULL;
17120 }
17121 else /* **arg == '[' || **arg == '.' */
17122 {
17123 dict_unref(selfdict);
17124 if (rettv->v_type == VAR_DICT)
17125 {
17126 selfdict = rettv->vval.v_dict;
17127 if (selfdict != NULL)
17128 ++selfdict->dv_refcount;
17129 }
17130 else
17131 selfdict = NULL;
17132 if (eval_index(arg, rettv, evaluate, verbose) == FAIL)
17133 {
17134 clear_tv(rettv);
17135 ret = FAIL;
17136 }
17137 }
17138 }
17139 dict_unref(selfdict);
17140 return ret;
17141}
17142
17143/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017144 * Allocate memory for a variable type-value, and make it emtpy (0 or NULL
17145 * value).
17146 */
Bram Moolenaar33570922005-01-25 22:26:29 +000017147 static typval_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017148alloc_tv()
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017149{
Bram Moolenaar33570922005-01-25 22:26:29 +000017150 return (typval_T *)alloc_clear((unsigned)sizeof(typval_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017151}
17152
17153/*
17154 * Allocate memory for a variable type-value, and assign a string to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000017155 * The string "s" must have been allocated, it is consumed.
17156 * Return NULL for out of memory, the variable otherwise.
17157 */
Bram Moolenaar33570922005-01-25 22:26:29 +000017158 static typval_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017159alloc_string_tv(s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017160 char_u *s;
17161{
Bram Moolenaar33570922005-01-25 22:26:29 +000017162 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017163
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017164 rettv = alloc_tv();
17165 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017166 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017167 rettv->v_type = VAR_STRING;
17168 rettv->vval.v_string = s;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017169 }
17170 else
17171 vim_free(s);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017172 return rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017173}
17174
17175/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017176 * Free the memory for a variable type-value.
Bram Moolenaar071d4272004-06-13 20:20:40 +000017177 */
Bram Moolenaar4770d092006-01-12 23:22:24 +000017178 void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017179free_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000017180 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017181{
17182 if (varp != NULL)
17183 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017184 switch (varp->v_type)
17185 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017186 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017187 func_unref(varp->vval.v_string);
17188 /*FALLTHROUGH*/
17189 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017190 vim_free(varp->vval.v_string);
17191 break;
17192 case VAR_LIST:
17193 list_unref(varp->vval.v_list);
17194 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017195 case VAR_DICT:
17196 dict_unref(varp->vval.v_dict);
17197 break;
Bram Moolenaar758711c2005-02-02 23:11:38 +000017198 case VAR_NUMBER:
17199 case VAR_UNKNOWN:
17200 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017201 default:
Bram Moolenaar758711c2005-02-02 23:11:38 +000017202 EMSG2(_(e_intern2), "free_tv()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017203 break;
17204 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017205 vim_free(varp);
17206 }
17207}
17208
17209/*
17210 * Free the memory for a variable value and set the value to NULL or 0.
17211 */
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000017212 void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017213clear_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000017214 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017215{
17216 if (varp != NULL)
17217 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017218 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017219 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017220 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017221 func_unref(varp->vval.v_string);
17222 /*FALLTHROUGH*/
17223 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017224 vim_free(varp->vval.v_string);
17225 varp->vval.v_string = NULL;
17226 break;
17227 case VAR_LIST:
17228 list_unref(varp->vval.v_list);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000017229 varp->vval.v_list = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017230 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000017231 case VAR_DICT:
17232 dict_unref(varp->vval.v_dict);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000017233 varp->vval.v_dict = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +000017234 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017235 case VAR_NUMBER:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017236 varp->vval.v_number = 0;
17237 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017238 case VAR_UNKNOWN:
17239 break;
17240 default:
17241 EMSG2(_(e_intern2), "clear_tv()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000017242 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017243 varp->v_lock = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017244 }
17245}
17246
17247/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017248 * Set the value of a variable to NULL without freeing items.
17249 */
17250 static void
17251init_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000017252 typval_T *varp;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017253{
17254 if (varp != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000017255 vim_memset(varp, 0, sizeof(typval_T));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017256}
17257
17258/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000017259 * Get the number value of a variable.
17260 * If it is a String variable, uses vim_str2nr().
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017261 * For incompatible types, return 0.
17262 * get_tv_number_chk() is similar to get_tv_number(), but informs the
17263 * caller of incompatible types: it sets *denote to TRUE if "denote"
17264 * is not NULL or returns -1 otherwise.
Bram Moolenaar071d4272004-06-13 20:20:40 +000017265 */
17266 static long
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017267get_tv_number(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000017268 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017269{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017270 int error = FALSE;
17271
17272 return get_tv_number_chk(varp, &error); /* return 0L on error */
17273}
17274
Bram Moolenaar4be06f92005-07-29 22:36:03 +000017275 long
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017276get_tv_number_chk(varp, denote)
17277 typval_T *varp;
17278 int *denote;
17279{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017280 long n = 0L;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017281
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017282 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017283 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017284 case VAR_NUMBER:
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017285 return (long)(varp->vval.v_number);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017286 case VAR_FUNC:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000017287 EMSG(_("E703: Using a Funcref as a number"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017288 break;
17289 case VAR_STRING:
17290 if (varp->vval.v_string != NULL)
17291 vim_str2nr(varp->vval.v_string, NULL, NULL,
17292 TRUE, TRUE, &n, NULL);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017293 return n;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000017294 case VAR_LIST:
Bram Moolenaar758711c2005-02-02 23:11:38 +000017295 EMSG(_("E745: Using a List as a number"));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000017296 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017297 case VAR_DICT:
17298 EMSG(_("E728: Using a Dictionary as a number"));
17299 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017300 default:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017301 EMSG2(_(e_intern2), "get_tv_number()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017302 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017303 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017304 if (denote == NULL) /* useful for values that must be unsigned */
17305 n = -1;
17306 else
17307 *denote = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017308 return n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017309}
17310
17311/*
Bram Moolenaar661b1822005-07-28 22:36:45 +000017312 * Get the lnum from the first argument.
17313 * Also accepts ".", "$", etc., but that only works for the current buffer.
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017314 * Returns -1 on error.
Bram Moolenaar071d4272004-06-13 20:20:40 +000017315 */
17316 static linenr_T
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017317get_tv_lnum(argvars)
Bram Moolenaar33570922005-01-25 22:26:29 +000017318 typval_T *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017319{
Bram Moolenaar33570922005-01-25 22:26:29 +000017320 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017321 linenr_T lnum;
17322
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017323 lnum = get_tv_number_chk(&argvars[0], NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017324 if (lnum == 0) /* no valid number, try using line() */
17325 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017326 rettv.v_type = VAR_NUMBER;
17327 f_line(argvars, &rettv);
17328 lnum = rettv.vval.v_number;
17329 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017330 }
17331 return lnum;
17332}
17333
17334/*
Bram Moolenaar661b1822005-07-28 22:36:45 +000017335 * Get the lnum from the first argument.
17336 * Also accepts "$", then "buf" is used.
17337 * Returns 0 on error.
17338 */
17339 static linenr_T
17340get_tv_lnum_buf(argvars, buf)
17341 typval_T *argvars;
17342 buf_T *buf;
17343{
17344 if (argvars[0].v_type == VAR_STRING
17345 && argvars[0].vval.v_string != NULL
17346 && argvars[0].vval.v_string[0] == '$'
17347 && buf != NULL)
17348 return buf->b_ml.ml_line_count;
17349 return get_tv_number_chk(&argvars[0], NULL);
17350}
17351
17352/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000017353 * Get the string value of a variable.
17354 * If it is a Number variable, the number is converted into a string.
Bram Moolenaara7043832005-01-21 11:56:39 +000017355 * get_tv_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
17356 * get_tv_string_buf() uses a given buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +000017357 * If the String variable has never been set, return an empty string.
17358 * Never returns NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017359 * get_tv_string_chk() and get_tv_string_buf_chk() are similar, but return
17360 * NULL on error.
Bram Moolenaar071d4272004-06-13 20:20:40 +000017361 */
17362 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017363get_tv_string(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000017364 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017365{
17366 static char_u mybuf[NUMBUFLEN];
17367
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017368 return get_tv_string_buf(varp, mybuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017369}
17370
17371 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017372get_tv_string_buf(varp, buf)
Bram Moolenaar33570922005-01-25 22:26:29 +000017373 typval_T *varp;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017374 char_u *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017375{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017376 char_u *res = get_tv_string_buf_chk(varp, buf);
17377
17378 return res != NULL ? res : (char_u *)"";
17379}
17380
Bram Moolenaar4be06f92005-07-29 22:36:03 +000017381 char_u *
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017382get_tv_string_chk(varp)
17383 typval_T *varp;
17384{
17385 static char_u mybuf[NUMBUFLEN];
17386
17387 return get_tv_string_buf_chk(varp, mybuf);
17388}
17389
17390 static char_u *
17391get_tv_string_buf_chk(varp, buf)
17392 typval_T *varp;
17393 char_u *buf;
17394{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017395 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017396 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017397 case VAR_NUMBER:
17398 sprintf((char *)buf, "%ld", (long)varp->vval.v_number);
17399 return buf;
17400 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017401 EMSG(_("E729: using Funcref as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017402 break;
17403 case VAR_LIST:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017404 EMSG(_("E730: using List as a String"));
Bram Moolenaar8c711452005-01-14 21:53:12 +000017405 break;
17406 case VAR_DICT:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017407 EMSG(_("E731: using Dictionary as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017408 break;
17409 case VAR_STRING:
17410 if (varp->vval.v_string != NULL)
17411 return varp->vval.v_string;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017412 return (char_u *)"";
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017413 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017414 EMSG2(_(e_intern2), "get_tv_string_buf()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017415 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017416 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000017417 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017418}
17419
17420/*
17421 * Find variable "name" in the list of variables.
17422 * Return a pointer to it if found, NULL if not found.
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017423 * Careful: "a:0" variables don't have a name.
Bram Moolenaara7043832005-01-21 11:56:39 +000017424 * When "htp" is not NULL we are writing to the variable, set "htp" to the
Bram Moolenaar33570922005-01-25 22:26:29 +000017425 * hashtab_T used.
Bram Moolenaar071d4272004-06-13 20:20:40 +000017426 */
Bram Moolenaar33570922005-01-25 22:26:29 +000017427 static dictitem_T *
Bram Moolenaara7043832005-01-21 11:56:39 +000017428find_var(name, htp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017429 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000017430 hashtab_T **htp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017431{
Bram Moolenaar071d4272004-06-13 20:20:40 +000017432 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000017433 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017434
Bram Moolenaara7043832005-01-21 11:56:39 +000017435 ht = find_var_ht(name, &varname);
17436 if (htp != NULL)
17437 *htp = ht;
17438 if (ht == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017439 return NULL;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017440 return find_var_in_ht(ht, varname, htp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017441}
17442
17443/*
Bram Moolenaar33570922005-01-25 22:26:29 +000017444 * Find variable "varname" in hashtab "ht".
Bram Moolenaara7043832005-01-21 11:56:39 +000017445 * Returns NULL if not found.
Bram Moolenaar071d4272004-06-13 20:20:40 +000017446 */
Bram Moolenaar33570922005-01-25 22:26:29 +000017447 static dictitem_T *
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017448find_var_in_ht(ht, varname, writing)
Bram Moolenaar33570922005-01-25 22:26:29 +000017449 hashtab_T *ht;
Bram Moolenaara7043832005-01-21 11:56:39 +000017450 char_u *varname;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017451 int writing;
Bram Moolenaara7043832005-01-21 11:56:39 +000017452{
Bram Moolenaar33570922005-01-25 22:26:29 +000017453 hashitem_T *hi;
17454
17455 if (*varname == NUL)
17456 {
17457 /* Must be something like "s:", otherwise "ht" would be NULL. */
17458 switch (varname[-2])
17459 {
17460 case 's': return &SCRIPT_SV(current_SID).sv_var;
17461 case 'g': return &globvars_var;
17462 case 'v': return &vimvars_var;
17463 case 'b': return &curbuf->b_bufvar;
17464 case 'w': return &curwin->w_winvar;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000017465#ifdef FEAT_WINDOWS
17466 case 't': return &curtab->tp_winvar;
17467#endif
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000017468 case 'l': return current_funccal == NULL
17469 ? NULL : &current_funccal->l_vars_var;
17470 case 'a': return current_funccal == NULL
17471 ? NULL : &current_funccal->l_avars_var;
Bram Moolenaar33570922005-01-25 22:26:29 +000017472 }
17473 return NULL;
17474 }
Bram Moolenaara7043832005-01-21 11:56:39 +000017475
17476 hi = hash_find(ht, varname);
17477 if (HASHITEM_EMPTY(hi))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017478 {
17479 /* For global variables we may try auto-loading the script. If it
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000017480 * worked find the variable again. Don't auto-load a script if it was
17481 * loaded already, otherwise it would be loaded every time when
17482 * checking if a function name is a Funcref variable. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017483 if (ht == &globvarht && !writing
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000017484 && script_autoload(varname, FALSE) && !aborting())
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017485 hi = hash_find(ht, varname);
17486 if (HASHITEM_EMPTY(hi))
17487 return NULL;
17488 }
Bram Moolenaar33570922005-01-25 22:26:29 +000017489 return HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +000017490}
17491
17492/*
Bram Moolenaar33570922005-01-25 22:26:29 +000017493 * Find the hashtab used for a variable name.
Bram Moolenaara7043832005-01-21 11:56:39 +000017494 * Set "varname" to the start of name without ':'.
17495 */
Bram Moolenaar33570922005-01-25 22:26:29 +000017496 static hashtab_T *
Bram Moolenaara7043832005-01-21 11:56:39 +000017497find_var_ht(name, varname)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017498 char_u *name;
17499 char_u **varname;
17500{
Bram Moolenaar75c50c42005-06-04 22:06:24 +000017501 hashitem_T *hi;
17502
Bram Moolenaar071d4272004-06-13 20:20:40 +000017503 if (name[1] != ':')
17504 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017505 /* The name must not start with a colon or #. */
17506 if (name[0] == ':' || name[0] == AUTOLOAD_CHAR)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017507 return NULL;
17508 *varname = name;
Bram Moolenaar532c7802005-01-27 14:44:31 +000017509
17510 /* "version" is "v:version" in all scopes */
Bram Moolenaar75c50c42005-06-04 22:06:24 +000017511 hi = hash_find(&compat_hashtab, name);
17512 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar532c7802005-01-27 14:44:31 +000017513 return &compat_hashtab;
17514
Bram Moolenaar071d4272004-06-13 20:20:40 +000017515 if (current_funccal == NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000017516 return &globvarht; /* global variable */
17517 return &current_funccal->l_vars.dv_hashtab; /* l: variable */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017518 }
17519 *varname = name + 2;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017520 if (*name == 'g') /* global variable */
17521 return &globvarht;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017522 /* There must be no ':' or '#' in the rest of the name, unless g: is used
17523 */
17524 if (vim_strchr(name + 2, ':') != NULL
17525 || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017526 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017527 if (*name == 'b') /* buffer variable */
Bram Moolenaar33570922005-01-25 22:26:29 +000017528 return &curbuf->b_vars.dv_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017529 if (*name == 'w') /* window variable */
Bram Moolenaar33570922005-01-25 22:26:29 +000017530 return &curwin->w_vars.dv_hashtab;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000017531#ifdef FEAT_WINDOWS
17532 if (*name == 't') /* tab page variable */
17533 return &curtab->tp_vars.dv_hashtab;
17534#endif
Bram Moolenaar33570922005-01-25 22:26:29 +000017535 if (*name == 'v') /* v: variable */
17536 return &vimvarht;
17537 if (*name == 'a' && current_funccal != NULL) /* function argument */
17538 return &current_funccal->l_avars.dv_hashtab;
17539 if (*name == 'l' && current_funccal != NULL) /* local function variable */
17540 return &current_funccal->l_vars.dv_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017541 if (*name == 's' /* script variable */
17542 && current_SID > 0 && current_SID <= ga_scripts.ga_len)
17543 return &SCRIPT_VARS(current_SID);
17544 return NULL;
17545}
17546
17547/*
17548 * Get the string value of a (global/local) variable.
17549 * Returns NULL when it doesn't exist.
17550 */
17551 char_u *
17552get_var_value(name)
17553 char_u *name;
17554{
Bram Moolenaar33570922005-01-25 22:26:29 +000017555 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017556
Bram Moolenaara7043832005-01-21 11:56:39 +000017557 v = find_var(name, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017558 if (v == NULL)
17559 return NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +000017560 return get_tv_string(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017561}
17562
17563/*
Bram Moolenaar33570922005-01-25 22:26:29 +000017564 * Allocate a new hashtab for a sourced script. It will be used while
Bram Moolenaar071d4272004-06-13 20:20:40 +000017565 * sourcing this script and when executing functions defined in the script.
17566 */
17567 void
17568new_script_vars(id)
17569 scid_T id;
17570{
Bram Moolenaara7043832005-01-21 11:56:39 +000017571 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +000017572 hashtab_T *ht;
17573 scriptvar_T *sv;
Bram Moolenaara7043832005-01-21 11:56:39 +000017574
Bram Moolenaar071d4272004-06-13 20:20:40 +000017575 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
17576 {
Bram Moolenaara7043832005-01-21 11:56:39 +000017577 /* Re-allocating ga_data means that an ht_array pointing to
17578 * ht_smallarray becomes invalid. We can recognize this: ht_mask is
Bram Moolenaar33570922005-01-25 22:26:29 +000017579 * at its init value. Also reset "v_dict", it's always the same. */
Bram Moolenaara7043832005-01-21 11:56:39 +000017580 for (i = 1; i <= ga_scripts.ga_len; ++i)
17581 {
17582 ht = &SCRIPT_VARS(i);
17583 if (ht->ht_mask == HT_INIT_SIZE - 1)
17584 ht->ht_array = ht->ht_smallarray;
Bram Moolenaar33570922005-01-25 22:26:29 +000017585 sv = &SCRIPT_SV(i);
17586 sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict;
Bram Moolenaara7043832005-01-21 11:56:39 +000017587 }
17588
Bram Moolenaar071d4272004-06-13 20:20:40 +000017589 while (ga_scripts.ga_len < id)
17590 {
Bram Moolenaar33570922005-01-25 22:26:29 +000017591 sv = &SCRIPT_SV(ga_scripts.ga_len + 1);
17592 init_var_dict(&sv->sv_dict, &sv->sv_var);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017593 ++ga_scripts.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017594 }
17595 }
17596}
17597
17598/*
Bram Moolenaar33570922005-01-25 22:26:29 +000017599 * Initialize dictionary "dict" as a scope and set variable "dict_var" to
17600 * point to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000017601 */
17602 void
Bram Moolenaar33570922005-01-25 22:26:29 +000017603init_var_dict(dict, dict_var)
17604 dict_T *dict;
17605 dictitem_T *dict_var;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017606{
Bram Moolenaar33570922005-01-25 22:26:29 +000017607 hash_init(&dict->dv_hashtab);
17608 dict->dv_refcount = 99999;
17609 dict_var->di_tv.vval.v_dict = dict;
17610 dict_var->di_tv.v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017611 dict_var->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000017612 dict_var->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
17613 dict_var->di_key[0] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017614}
17615
17616/*
17617 * Clean up a list of internal variables.
Bram Moolenaar33570922005-01-25 22:26:29 +000017618 * Frees all allocated variables and the value they contain.
17619 * Clears hashtab "ht", does not free it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000017620 */
17621 void
Bram Moolenaara7043832005-01-21 11:56:39 +000017622vars_clear(ht)
Bram Moolenaar33570922005-01-25 22:26:29 +000017623 hashtab_T *ht;
17624{
17625 vars_clear_ext(ht, TRUE);
17626}
17627
17628/*
17629 * Like vars_clear(), but only free the value if "free_val" is TRUE.
17630 */
17631 static void
17632vars_clear_ext(ht, free_val)
17633 hashtab_T *ht;
17634 int free_val;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017635{
Bram Moolenaara7043832005-01-21 11:56:39 +000017636 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000017637 hashitem_T *hi;
17638 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017639
Bram Moolenaar33570922005-01-25 22:26:29 +000017640 hash_lock(ht);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000017641 todo = (int)ht->ht_used;
Bram Moolenaara7043832005-01-21 11:56:39 +000017642 for (hi = ht->ht_array; todo > 0; ++hi)
17643 {
17644 if (!HASHITEM_EMPTY(hi))
17645 {
17646 --todo;
17647
Bram Moolenaar33570922005-01-25 22:26:29 +000017648 /* Free the variable. Don't remove it from the hashtab,
Bram Moolenaara7043832005-01-21 11:56:39 +000017649 * ht_array might change then. hash_clear() takes care of it
17650 * later. */
Bram Moolenaar33570922005-01-25 22:26:29 +000017651 v = HI2DI(hi);
17652 if (free_val)
17653 clear_tv(&v->di_tv);
17654 if ((v->di_flags & DI_FLAGS_FIX) == 0)
17655 vim_free(v);
Bram Moolenaara7043832005-01-21 11:56:39 +000017656 }
17657 }
17658 hash_clear(ht);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000017659 ht->ht_used = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017660}
17661
Bram Moolenaara7043832005-01-21 11:56:39 +000017662/*
Bram Moolenaar33570922005-01-25 22:26:29 +000017663 * Delete a variable from hashtab "ht" at item "hi".
17664 * Clear the variable value and free the dictitem.
Bram Moolenaara7043832005-01-21 11:56:39 +000017665 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017666 static void
Bram Moolenaara7043832005-01-21 11:56:39 +000017667delete_var(ht, hi)
Bram Moolenaar33570922005-01-25 22:26:29 +000017668 hashtab_T *ht;
17669 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017670{
Bram Moolenaar33570922005-01-25 22:26:29 +000017671 dictitem_T *di = HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +000017672
17673 hash_remove(ht, hi);
Bram Moolenaar33570922005-01-25 22:26:29 +000017674 clear_tv(&di->di_tv);
17675 vim_free(di);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017676}
17677
17678/*
17679 * List the value of one internal variable.
17680 */
17681 static void
17682list_one_var(v, prefix)
Bram Moolenaar33570922005-01-25 22:26:29 +000017683 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017684 char_u *prefix;
17685{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017686 char_u *tofree;
17687 char_u *s;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000017688 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017689
Bram Moolenaarb71eaae2006-01-20 23:10:18 +000017690 s = echo_string(&v->di_tv, &tofree, numbuf, ++current_copyID);
Bram Moolenaar33570922005-01-25 22:26:29 +000017691 list_one_var_a(prefix, v->di_key, v->di_tv.v_type,
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017692 s == NULL ? (char_u *)"" : s);
17693 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017694}
17695
Bram Moolenaar071d4272004-06-13 20:20:40 +000017696 static void
17697list_one_var_a(prefix, name, type, string)
17698 char_u *prefix;
17699 char_u *name;
17700 int type;
17701 char_u *string;
17702{
17703 msg_attr(prefix, 0); /* don't use msg(), it overwrites "v:statusmsg" */
17704 if (name != NULL) /* "a:" vars don't have a name stored */
17705 msg_puts(name);
17706 msg_putchar(' ');
17707 msg_advance(22);
17708 if (type == VAR_NUMBER)
17709 msg_putchar('#');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017710 else if (type == VAR_FUNC)
17711 msg_putchar('*');
17712 else if (type == VAR_LIST)
17713 {
17714 msg_putchar('[');
17715 if (*string == '[')
17716 ++string;
17717 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000017718 else if (type == VAR_DICT)
17719 {
17720 msg_putchar('{');
17721 if (*string == '{')
17722 ++string;
17723 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017724 else
17725 msg_putchar(' ');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017726
Bram Moolenaar071d4272004-06-13 20:20:40 +000017727 msg_outtrans(string);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017728
17729 if (type == VAR_FUNC)
17730 msg_puts((char_u *)"()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000017731}
17732
17733/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017734 * Set variable "name" to value in "tv".
Bram Moolenaar071d4272004-06-13 20:20:40 +000017735 * If the variable already exists, the value is updated.
17736 * Otherwise the variable is created.
17737 */
17738 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017739set_var(name, tv, copy)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017740 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000017741 typval_T *tv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017742 int copy; /* make copy of value in "tv" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017743{
Bram Moolenaar33570922005-01-25 22:26:29 +000017744 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017745 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000017746 hashtab_T *ht;
Bram Moolenaar92124a32005-06-17 22:03:40 +000017747 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017748
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017749 if (tv->v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017750 {
17751 if (!(vim_strchr((char_u *)"wbs", name[0]) != NULL && name[1] == ':')
17752 && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
17753 ? name[2] : name[0]))
17754 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +000017755 EMSG2(_("E704: Funcref variable name must start with a capital: %s"), name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017756 return;
17757 }
17758 if (function_exists(name))
17759 {
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000017760 EMSG2(_("E705: Variable name conflicts with existing function: %s"),
Bram Moolenaar81bf7082005-02-12 14:31:42 +000017761 name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017762 return;
17763 }
17764 }
17765
Bram Moolenaara7043832005-01-21 11:56:39 +000017766 ht = find_var_ht(name, &varname);
Bram Moolenaar33570922005-01-25 22:26:29 +000017767 if (ht == NULL || *varname == NUL)
Bram Moolenaara7043832005-01-21 11:56:39 +000017768 {
Bram Moolenaar92124a32005-06-17 22:03:40 +000017769 EMSG2(_(e_illvar), name);
Bram Moolenaara7043832005-01-21 11:56:39 +000017770 return;
17771 }
17772
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017773 v = find_var_in_ht(ht, varname, TRUE);
Bram Moolenaar33570922005-01-25 22:26:29 +000017774 if (v != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017775 {
Bram Moolenaar33570922005-01-25 22:26:29 +000017776 /* existing variable, need to clear the value */
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017777 if (var_check_ro(v->di_flags, name)
17778 || tv_check_lock(v->di_tv.v_lock, name))
Bram Moolenaar33570922005-01-25 22:26:29 +000017779 return;
17780 if (v->di_tv.v_type != tv->v_type
17781 && !((v->di_tv.v_type == VAR_STRING
17782 || v->di_tv.v_type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017783 && (tv->v_type == VAR_STRING
17784 || tv->v_type == VAR_NUMBER)))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017785 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +000017786 EMSG2(_("E706: Variable type mismatch for: %s"), name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017787 return;
17788 }
Bram Moolenaar33570922005-01-25 22:26:29 +000017789
17790 /*
Bram Moolenaar758711c2005-02-02 23:11:38 +000017791 * Handle setting internal v: variables separately: we don't change
17792 * the type.
Bram Moolenaar33570922005-01-25 22:26:29 +000017793 */
17794 if (ht == &vimvarht)
17795 {
17796 if (v->di_tv.v_type == VAR_STRING)
17797 {
17798 vim_free(v->di_tv.vval.v_string);
17799 if (copy || tv->v_type != VAR_STRING)
17800 v->di_tv.vval.v_string = vim_strsave(get_tv_string(tv));
17801 else
17802 {
17803 /* Take over the string to avoid an extra alloc/free. */
17804 v->di_tv.vval.v_string = tv->vval.v_string;
17805 tv->vval.v_string = NULL;
17806 }
17807 }
17808 else if (v->di_tv.v_type != VAR_NUMBER)
17809 EMSG2(_(e_intern2), "set_var()");
17810 else
17811 v->di_tv.vval.v_number = get_tv_number(tv);
17812 return;
17813 }
17814
17815 clear_tv(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017816 }
17817 else /* add a new variable */
17818 {
Bram Moolenaar5fcc3fe2006-06-22 15:35:14 +000017819 /* Can't add "v:" variable. */
17820 if (ht == &vimvarht)
17821 {
17822 EMSG2(_(e_illvar), name);
17823 return;
17824 }
17825
Bram Moolenaar92124a32005-06-17 22:03:40 +000017826 /* Make sure the variable name is valid. */
17827 for (p = varname; *p != NUL; ++p)
Bram Moolenaara5792f52005-11-23 21:25:05 +000017828 if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p))
17829 && *p != AUTOLOAD_CHAR)
Bram Moolenaar92124a32005-06-17 22:03:40 +000017830 {
17831 EMSG2(_(e_illvar), varname);
17832 return;
17833 }
17834
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017835 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
17836 + STRLEN(varname)));
Bram Moolenaara7043832005-01-21 11:56:39 +000017837 if (v == NULL)
17838 return;
Bram Moolenaar33570922005-01-25 22:26:29 +000017839 STRCPY(v->di_key, varname);
Bram Moolenaar33570922005-01-25 22:26:29 +000017840 if (hash_add(ht, DI2HIKEY(v)) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017841 {
Bram Moolenaara7043832005-01-21 11:56:39 +000017842 vim_free(v);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017843 return;
17844 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017845 v->di_flags = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017846 }
Bram Moolenaara7043832005-01-21 11:56:39 +000017847
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017848 if (copy || tv->v_type == VAR_NUMBER)
Bram Moolenaar33570922005-01-25 22:26:29 +000017849 copy_tv(tv, &v->di_tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000017850 else
17851 {
Bram Moolenaar33570922005-01-25 22:26:29 +000017852 v->di_tv = *tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017853 v->di_tv.v_lock = 0;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017854 init_tv(tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000017855 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017856}
17857
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017858/*
Bram Moolenaar4e957af2006-09-02 11:41:07 +000017859 * Return TRUE if di_flags "flags" indicates variable "name" is read-only.
Bram Moolenaar33570922005-01-25 22:26:29 +000017860 * Also give an error message.
17861 */
17862 static int
17863var_check_ro(flags, name)
17864 int flags;
17865 char_u *name;
17866{
17867 if (flags & DI_FLAGS_RO)
17868 {
17869 EMSG2(_(e_readonlyvar), name);
17870 return TRUE;
17871 }
17872 if ((flags & DI_FLAGS_RO_SBX) && sandbox)
17873 {
17874 EMSG2(_(e_readonlysbx), name);
17875 return TRUE;
17876 }
17877 return FALSE;
17878}
17879
17880/*
Bram Moolenaar4e957af2006-09-02 11:41:07 +000017881 * Return TRUE if di_flags "flags" indicates variable "name" is fixed.
17882 * Also give an error message.
17883 */
17884 static int
17885var_check_fixed(flags, name)
17886 int flags;
17887 char_u *name;
17888{
17889 if (flags & DI_FLAGS_FIX)
17890 {
17891 EMSG2(_("E795: Cannot delete variable %s"), name);
17892 return TRUE;
17893 }
17894 return FALSE;
17895}
17896
17897/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017898 * Return TRUE if typeval "tv" is set to be locked (immutable).
17899 * Also give an error message, using "name".
17900 */
17901 static int
17902tv_check_lock(lock, name)
17903 int lock;
17904 char_u *name;
17905{
17906 if (lock & VAR_LOCKED)
17907 {
17908 EMSG2(_("E741: Value is locked: %s"),
17909 name == NULL ? (char_u *)_("Unknown") : name);
17910 return TRUE;
17911 }
17912 if (lock & VAR_FIXED)
17913 {
17914 EMSG2(_("E742: Cannot change value of %s"),
17915 name == NULL ? (char_u *)_("Unknown") : name);
17916 return TRUE;
17917 }
17918 return FALSE;
17919}
17920
17921/*
Bram Moolenaar33570922005-01-25 22:26:29 +000017922 * Copy the values from typval_T "from" to typval_T "to".
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017923 * When needed allocates string or increases reference count.
Bram Moolenaare9a41262005-01-15 22:18:47 +000017924 * Does not make a copy of a list or dict but copies the reference!
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017925 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017926 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017927copy_tv(from, to)
Bram Moolenaar33570922005-01-25 22:26:29 +000017928 typval_T *from;
17929 typval_T *to;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017930{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017931 to->v_type = from->v_type;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017932 to->v_lock = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017933 switch (from->v_type)
17934 {
17935 case VAR_NUMBER:
17936 to->vval.v_number = from->vval.v_number;
17937 break;
17938 case VAR_STRING:
17939 case VAR_FUNC:
17940 if (from->vval.v_string == NULL)
17941 to->vval.v_string = NULL;
17942 else
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017943 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017944 to->vval.v_string = vim_strsave(from->vval.v_string);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017945 if (from->v_type == VAR_FUNC)
17946 func_ref(to->vval.v_string);
17947 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017948 break;
17949 case VAR_LIST:
17950 if (from->vval.v_list == NULL)
17951 to->vval.v_list = NULL;
17952 else
17953 {
17954 to->vval.v_list = from->vval.v_list;
17955 ++to->vval.v_list->lv_refcount;
17956 }
17957 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000017958 case VAR_DICT:
17959 if (from->vval.v_dict == NULL)
17960 to->vval.v_dict = NULL;
17961 else
17962 {
17963 to->vval.v_dict = from->vval.v_dict;
17964 ++to->vval.v_dict->dv_refcount;
17965 }
17966 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017967 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017968 EMSG2(_(e_intern2), "copy_tv()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017969 break;
17970 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017971}
17972
17973/*
Bram Moolenaare9a41262005-01-15 22:18:47 +000017974 * Make a copy of an item.
17975 * Lists and Dictionaries are also copied. A deep copy if "deep" is set.
Bram Moolenaar81bf7082005-02-12 14:31:42 +000017976 * For deepcopy() "copyID" is zero for a full copy or the ID for when a
17977 * reference to an already copied list/dict can be used.
17978 * Returns FAIL or OK.
Bram Moolenaare9a41262005-01-15 22:18:47 +000017979 */
Bram Moolenaar81bf7082005-02-12 14:31:42 +000017980 static int
17981item_copy(from, to, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +000017982 typval_T *from;
17983 typval_T *to;
Bram Moolenaare9a41262005-01-15 22:18:47 +000017984 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000017985 int copyID;
Bram Moolenaare9a41262005-01-15 22:18:47 +000017986{
17987 static int recurse = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000017988 int ret = OK;
Bram Moolenaare9a41262005-01-15 22:18:47 +000017989
Bram Moolenaar33570922005-01-25 22:26:29 +000017990 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +000017991 {
17992 EMSG(_("E698: variable nested too deep for making a copy"));
Bram Moolenaar81bf7082005-02-12 14:31:42 +000017993 return FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000017994 }
17995 ++recurse;
17996
17997 switch (from->v_type)
17998 {
17999 case VAR_NUMBER:
18000 case VAR_STRING:
18001 case VAR_FUNC:
18002 copy_tv(from, to);
18003 break;
18004 case VAR_LIST:
18005 to->v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000018006 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018007 if (from->vval.v_list == NULL)
18008 to->vval.v_list = NULL;
18009 else if (copyID != 0 && from->vval.v_list->lv_copyID == copyID)
18010 {
18011 /* use the copy made earlier */
18012 to->vval.v_list = from->vval.v_list->lv_copylist;
18013 ++to->vval.v_list->lv_refcount;
18014 }
18015 else
18016 to->vval.v_list = list_copy(from->vval.v_list, deep, copyID);
18017 if (to->vval.v_list == NULL)
18018 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000018019 break;
18020 case VAR_DICT:
18021 to->v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000018022 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018023 if (from->vval.v_dict == NULL)
18024 to->vval.v_dict = NULL;
18025 else if (copyID != 0 && from->vval.v_dict->dv_copyID == copyID)
18026 {
18027 /* use the copy made earlier */
18028 to->vval.v_dict = from->vval.v_dict->dv_copydict;
18029 ++to->vval.v_dict->dv_refcount;
18030 }
18031 else
18032 to->vval.v_dict = dict_copy(from->vval.v_dict, deep, copyID);
18033 if (to->vval.v_dict == NULL)
18034 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000018035 break;
18036 default:
18037 EMSG2(_(e_intern2), "item_copy()");
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018038 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000018039 }
18040 --recurse;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018041 return ret;
Bram Moolenaare9a41262005-01-15 22:18:47 +000018042}
18043
18044/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000018045 * ":echo expr1 ..." print each argument separated with a space, add a
18046 * newline at the end.
18047 * ":echon expr1 ..." print each argument plain.
18048 */
18049 void
18050ex_echo(eap)
18051 exarg_T *eap;
18052{
18053 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000018054 typval_T rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000018055 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018056 char_u *p;
18057 int needclr = TRUE;
18058 int atstart = TRUE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000018059 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000018060
18061 if (eap->skip)
18062 ++emsg_skip;
18063 while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int)
18064 {
18065 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018066 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018067 {
18068 /*
18069 * Report the invalid expression unless the expression evaluation
18070 * has been cancelled due to an aborting error, an interrupt, or an
18071 * exception.
18072 */
18073 if (!aborting())
18074 EMSG2(_(e_invexpr2), p);
18075 break;
18076 }
18077 if (!eap->skip)
18078 {
18079 if (atstart)
18080 {
18081 atstart = FALSE;
18082 /* Call msg_start() after eval1(), evaluating the expression
18083 * may cause a message to appear. */
18084 if (eap->cmdidx == CMD_echo)
18085 msg_start();
18086 }
18087 else if (eap->cmdidx == CMD_echo)
18088 msg_puts_attr((char_u *)" ", echo_attr);
Bram Moolenaarb71eaae2006-01-20 23:10:18 +000018089 p = echo_string(&rettv, &tofree, numbuf, ++current_copyID);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018090 if (p != NULL)
18091 for ( ; *p != NUL && !got_int; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018092 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018093 if (*p == '\n' || *p == '\r' || *p == TAB)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018094 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018095 if (*p != TAB && needclr)
18096 {
18097 /* remove any text still there from the command */
18098 msg_clr_eos();
18099 needclr = FALSE;
18100 }
18101 msg_putchar_attr(*p, echo_attr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018102 }
18103 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018104 {
18105#ifdef FEAT_MBYTE
18106 if (has_mbyte)
18107 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000018108 int i = (*mb_ptr2len)(p);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018109
18110 (void)msg_outtrans_len_attr(p, i, echo_attr);
18111 p += i - 1;
18112 }
18113 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000018114#endif
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018115 (void)msg_outtrans_len_attr(p, 1, echo_attr);
18116 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018117 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000018118 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018119 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018120 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018121 arg = skipwhite(arg);
18122 }
18123 eap->nextcmd = check_nextcmd(arg);
18124
18125 if (eap->skip)
18126 --emsg_skip;
18127 else
18128 {
18129 /* remove text that may still be there from the command */
18130 if (needclr)
18131 msg_clr_eos();
18132 if (eap->cmdidx == CMD_echo)
18133 msg_end();
18134 }
18135}
18136
18137/*
18138 * ":echohl {name}".
18139 */
18140 void
18141ex_echohl(eap)
18142 exarg_T *eap;
18143{
18144 int id;
18145
18146 id = syn_name2id(eap->arg);
18147 if (id == 0)
18148 echo_attr = 0;
18149 else
18150 echo_attr = syn_id2attr(id);
18151}
18152
18153/*
18154 * ":execute expr1 ..." execute the result of an expression.
18155 * ":echomsg expr1 ..." Print a message
18156 * ":echoerr expr1 ..." Print an error
18157 * Each gets spaces around each argument and a newline at the end for
18158 * echo commands
18159 */
18160 void
18161ex_execute(eap)
18162 exarg_T *eap;
18163{
18164 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000018165 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018166 int ret = OK;
18167 char_u *p;
18168 garray_T ga;
18169 int len;
18170 int save_did_emsg;
18171
18172 ga_init2(&ga, 1, 80);
18173
18174 if (eap->skip)
18175 ++emsg_skip;
18176 while (*arg != NUL && *arg != '|' && *arg != '\n')
18177 {
18178 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018179 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018180 {
18181 /*
18182 * Report the invalid expression unless the expression evaluation
18183 * has been cancelled due to an aborting error, an interrupt, or an
18184 * exception.
18185 */
18186 if (!aborting())
18187 EMSG2(_(e_invexpr2), p);
18188 ret = FAIL;
18189 break;
18190 }
18191
18192 if (!eap->skip)
18193 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018194 p = get_tv_string(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018195 len = (int)STRLEN(p);
18196 if (ga_grow(&ga, len + 2) == FAIL)
18197 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018198 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018199 ret = FAIL;
18200 break;
18201 }
18202 if (ga.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018203 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
Bram Moolenaar071d4272004-06-13 20:20:40 +000018204 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018205 ga.ga_len += len;
18206 }
18207
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018208 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018209 arg = skipwhite(arg);
18210 }
18211
18212 if (ret != FAIL && ga.ga_data != NULL)
18213 {
18214 if (eap->cmdidx == CMD_echomsg)
Bram Moolenaar4770d092006-01-12 23:22:24 +000018215 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000018216 MSG_ATTR(ga.ga_data, echo_attr);
Bram Moolenaar4770d092006-01-12 23:22:24 +000018217 out_flush();
18218 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018219 else if (eap->cmdidx == CMD_echoerr)
18220 {
18221 /* We don't want to abort following commands, restore did_emsg. */
18222 save_did_emsg = did_emsg;
18223 EMSG((char_u *)ga.ga_data);
18224 if (!force_abort)
18225 did_emsg = save_did_emsg;
18226 }
18227 else if (eap->cmdidx == CMD_execute)
18228 do_cmdline((char_u *)ga.ga_data,
18229 eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE);
18230 }
18231
18232 ga_clear(&ga);
18233
18234 if (eap->skip)
18235 --emsg_skip;
18236
18237 eap->nextcmd = check_nextcmd(arg);
18238}
18239
18240/*
18241 * Skip over the name of an option: "&option", "&g:option" or "&l:option".
18242 * "arg" points to the "&" or '+' when called, to "option" when returning.
18243 * Returns NULL when no option name found. Otherwise pointer to the char
18244 * after the option name.
18245 */
18246 static char_u *
18247find_option_end(arg, opt_flags)
18248 char_u **arg;
18249 int *opt_flags;
18250{
18251 char_u *p = *arg;
18252
18253 ++p;
18254 if (*p == 'g' && p[1] == ':')
18255 {
18256 *opt_flags = OPT_GLOBAL;
18257 p += 2;
18258 }
18259 else if (*p == 'l' && p[1] == ':')
18260 {
18261 *opt_flags = OPT_LOCAL;
18262 p += 2;
18263 }
18264 else
18265 *opt_flags = 0;
18266
18267 if (!ASCII_ISALPHA(*p))
18268 return NULL;
18269 *arg = p;
18270
18271 if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL)
18272 p += 4; /* termcap option */
18273 else
18274 while (ASCII_ISALPHA(*p))
18275 ++p;
18276 return p;
18277}
18278
18279/*
18280 * ":function"
18281 */
18282 void
18283ex_function(eap)
18284 exarg_T *eap;
18285{
18286 char_u *theline;
18287 int j;
18288 int c;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018289 int saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018290 char_u *name = NULL;
18291 char_u *p;
18292 char_u *arg;
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000018293 char_u *line_arg = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018294 garray_T newargs;
18295 garray_T newlines;
18296 int varargs = FALSE;
18297 int mustend = FALSE;
18298 int flags = 0;
18299 ufunc_T *fp;
18300 int indent;
18301 int nesting;
18302 char_u *skip_until = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +000018303 dictitem_T *v;
18304 funcdict_T fudi;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018305 static int func_nr = 0; /* number for nameless function */
18306 int paren;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018307 hashtab_T *ht;
18308 int todo;
18309 hashitem_T *hi;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000018310 int sourcing_lnum_off;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018311
18312 /*
18313 * ":function" without argument: list functions.
18314 */
18315 if (ends_excmd(*eap->arg))
18316 {
18317 if (!eap->skip)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018318 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000018319 todo = (int)func_hashtab.ht_used;
Bram Moolenaar038eb0e2005-02-27 22:43:26 +000018320 for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018321 {
18322 if (!HASHITEM_EMPTY(hi))
18323 {
18324 --todo;
18325 fp = HI2UF(hi);
18326 if (!isdigit(*fp->uf_name))
18327 list_func_head(fp, FALSE);
18328 }
18329 }
18330 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018331 eap->nextcmd = check_nextcmd(eap->arg);
18332 return;
18333 }
18334
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018335 /*
Bram Moolenaardd2436f2005-09-05 22:14:46 +000018336 * ":function /pat": list functions matching pattern.
18337 */
18338 if (*eap->arg == '/')
18339 {
18340 p = skip_regexp(eap->arg + 1, '/', TRUE, NULL);
18341 if (!eap->skip)
18342 {
18343 regmatch_T regmatch;
18344
18345 c = *p;
18346 *p = NUL;
18347 regmatch.regprog = vim_regcomp(eap->arg + 1, RE_MAGIC);
18348 *p = c;
18349 if (regmatch.regprog != NULL)
18350 {
18351 regmatch.rm_ic = p_ic;
18352
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000018353 todo = (int)func_hashtab.ht_used;
Bram Moolenaardd2436f2005-09-05 22:14:46 +000018354 for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
18355 {
18356 if (!HASHITEM_EMPTY(hi))
18357 {
18358 --todo;
18359 fp = HI2UF(hi);
18360 if (!isdigit(*fp->uf_name)
18361 && vim_regexec(&regmatch, fp->uf_name, 0))
18362 list_func_head(fp, FALSE);
18363 }
18364 }
18365 }
18366 }
18367 if (*p == '/')
18368 ++p;
18369 eap->nextcmd = check_nextcmd(p);
18370 return;
18371 }
18372
18373 /*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018374 * Get the function name. There are these situations:
18375 * func normal function name
18376 * "name" == func, "fudi.fd_dict" == NULL
18377 * dict.func new dictionary entry
18378 * "name" == NULL, "fudi.fd_dict" set,
18379 * "fudi.fd_di" == NULL, "fudi.fd_newkey" == func
18380 * dict.func existing dict entry with a Funcref
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018381 * "name" == func, "fudi.fd_dict" set,
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018382 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL
18383 * dict.func existing dict entry that's not a Funcref
18384 * "name" == NULL, "fudi.fd_dict" set,
18385 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL
18386 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018387 p = eap->arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018388 name = trans_function_name(&p, eap->skip, 0, &fudi);
18389 paren = (vim_strchr(p, '(') != NULL);
18390 if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018391 {
18392 /*
18393 * Return on an invalid expression in braces, unless the expression
18394 * evaluation has been cancelled due to an aborting error, an
18395 * interrupt, or an exception.
18396 */
18397 if (!aborting())
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018398 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000018399 if (!eap->skip && fudi.fd_newkey != NULL)
18400 EMSG2(_(e_dictkey), fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018401 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018402 return;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018403 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018404 else
18405 eap->skip = TRUE;
18406 }
Bram Moolenaar1f35bf92006-03-07 22:38:47 +000018407
Bram Moolenaar071d4272004-06-13 20:20:40 +000018408 /* An error in a function call during evaluation of an expression in magic
18409 * braces should not cause the function not to be defined. */
18410 saved_did_emsg = did_emsg;
18411 did_emsg = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018412
18413 /*
18414 * ":function func" with only function name: list function.
18415 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018416 if (!paren)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018417 {
18418 if (!ends_excmd(*skipwhite(p)))
18419 {
18420 EMSG(_(e_trailing));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018421 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018422 }
18423 eap->nextcmd = check_nextcmd(p);
18424 if (eap->nextcmd != NULL)
18425 *p = NUL;
18426 if (!eap->skip && !got_int)
18427 {
18428 fp = find_func(name);
18429 if (fp != NULL)
18430 {
18431 list_func_head(fp, TRUE);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018432 for (j = 0; j < fp->uf_lines.ga_len && !got_int; ++j)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018433 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000018434 if (FUNCLINE(fp, j) == NULL)
18435 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018436 msg_putchar('\n');
18437 msg_outnum((long)(j + 1));
18438 if (j < 9)
18439 msg_putchar(' ');
18440 if (j < 99)
18441 msg_putchar(' ');
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018442 msg_prt_line(FUNCLINE(fp, j), FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018443 out_flush(); /* show a line at a time */
18444 ui_breakcheck();
18445 }
18446 if (!got_int)
18447 {
18448 msg_putchar('\n');
18449 msg_puts((char_u *)" endfunction");
18450 }
18451 }
18452 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018453 emsg_funcname("E123: Undefined function: %s", name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018454 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018455 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018456 }
18457
18458 /*
18459 * ":function name(arg1, arg2)" Define function.
18460 */
18461 p = skipwhite(p);
18462 if (*p != '(')
18463 {
18464 if (!eap->skip)
18465 {
18466 EMSG2(_("E124: Missing '(': %s"), eap->arg);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018467 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018468 }
18469 /* attempt to continue by skipping some text */
18470 if (vim_strchr(p, '(') != NULL)
18471 p = vim_strchr(p, '(');
18472 }
18473 p = skipwhite(p + 1);
18474
18475 ga_init2(&newargs, (int)sizeof(char_u *), 3);
18476 ga_init2(&newlines, (int)sizeof(char_u *), 3);
18477
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018478 if (!eap->skip)
18479 {
18480 /* Check the name of the function. */
18481 if (name != NULL)
18482 arg = name;
18483 else
18484 arg = fudi.fd_newkey;
18485 if (arg != NULL)
18486 {
18487 if (*arg == K_SPECIAL)
18488 j = 3;
18489 else
18490 j = 0;
18491 while (arg[j] != NUL && (j == 0 ? eval_isnamec1(arg[j])
18492 : eval_isnamec(arg[j])))
18493 ++j;
18494 if (arg[j] != NUL)
18495 emsg_funcname(_(e_invarg2), arg);
18496 }
18497 }
18498
Bram Moolenaar071d4272004-06-13 20:20:40 +000018499 /*
18500 * Isolate the arguments: "arg1, arg2, ...)"
18501 */
18502 while (*p != ')')
18503 {
18504 if (p[0] == '.' && p[1] == '.' && p[2] == '.')
18505 {
18506 varargs = TRUE;
18507 p += 3;
18508 mustend = TRUE;
18509 }
18510 else
18511 {
18512 arg = p;
18513 while (ASCII_ISALNUM(*p) || *p == '_')
18514 ++p;
18515 if (arg == p || isdigit(*arg)
18516 || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0)
18517 || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0))
18518 {
18519 if (!eap->skip)
18520 EMSG2(_("E125: Illegal argument: %s"), arg);
18521 break;
18522 }
18523 if (ga_grow(&newargs, 1) == FAIL)
18524 goto erret;
18525 c = *p;
18526 *p = NUL;
18527 arg = vim_strsave(arg);
18528 if (arg == NULL)
18529 goto erret;
18530 ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg;
18531 *p = c;
18532 newargs.ga_len++;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018533 if (*p == ',')
18534 ++p;
18535 else
18536 mustend = TRUE;
18537 }
18538 p = skipwhite(p);
18539 if (mustend && *p != ')')
18540 {
18541 if (!eap->skip)
18542 EMSG2(_(e_invarg2), eap->arg);
18543 break;
18544 }
18545 }
18546 ++p; /* skip the ')' */
18547
Bram Moolenaare9a41262005-01-15 22:18:47 +000018548 /* find extra arguments "range", "dict" and "abort" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018549 for (;;)
18550 {
18551 p = skipwhite(p);
18552 if (STRNCMP(p, "range", 5) == 0)
18553 {
18554 flags |= FC_RANGE;
18555 p += 5;
18556 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000018557 else if (STRNCMP(p, "dict", 4) == 0)
18558 {
18559 flags |= FC_DICT;
18560 p += 4;
18561 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018562 else if (STRNCMP(p, "abort", 5) == 0)
18563 {
18564 flags |= FC_ABORT;
18565 p += 5;
18566 }
18567 else
18568 break;
18569 }
18570
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000018571 /* When there is a line break use what follows for the function body.
18572 * Makes 'exe "func Test()\n...\nendfunc"' work. */
18573 if (*p == '\n')
18574 line_arg = p + 1;
18575 else if (*p != NUL && *p != '"' && !eap->skip && !did_emsg)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018576 EMSG(_(e_trailing));
18577
18578 /*
18579 * Read the body of the function, until ":endfunction" is found.
18580 */
18581 if (KeyTyped)
18582 {
18583 /* Check if the function already exists, don't let the user type the
18584 * whole function before telling him it doesn't work! For a script we
18585 * need to skip the body to be able to find what follows. */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018586 if (!eap->skip && !eap->forceit)
18587 {
18588 if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL)
18589 EMSG(_(e_funcdict));
18590 else if (name != NULL && find_func(name) != NULL)
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018591 emsg_funcname(e_funcexts, name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018592 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018593
Bram Moolenaard857f0e2005-06-21 22:37:39 +000018594 if (!eap->skip && did_emsg)
18595 goto erret;
18596
Bram Moolenaar071d4272004-06-13 20:20:40 +000018597 msg_putchar('\n'); /* don't overwrite the function name */
18598 cmdline_row = msg_row;
18599 }
18600
18601 indent = 2;
18602 nesting = 0;
18603 for (;;)
18604 {
18605 msg_scroll = TRUE;
18606 need_wait_return = FALSE;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000018607 sourcing_lnum_off = sourcing_lnum;
18608
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000018609 if (line_arg != NULL)
18610 {
18611 /* Use eap->arg, split up in parts by line breaks. */
18612 theline = line_arg;
18613 p = vim_strchr(theline, '\n');
18614 if (p == NULL)
18615 line_arg += STRLEN(line_arg);
18616 else
18617 {
18618 *p = NUL;
18619 line_arg = p + 1;
18620 }
18621 }
18622 else if (eap->getline == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018623 theline = getcmdline(':', 0L, indent);
18624 else
18625 theline = eap->getline(':', eap->cookie, indent);
18626 if (KeyTyped)
18627 lines_left = Rows - 1;
18628 if (theline == NULL)
18629 {
18630 EMSG(_("E126: Missing :endfunction"));
18631 goto erret;
18632 }
18633
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000018634 /* Detect line continuation: sourcing_lnum increased more than one. */
18635 if (sourcing_lnum > sourcing_lnum_off + 1)
18636 sourcing_lnum_off = sourcing_lnum - sourcing_lnum_off - 1;
18637 else
18638 sourcing_lnum_off = 0;
18639
Bram Moolenaar071d4272004-06-13 20:20:40 +000018640 if (skip_until != NULL)
18641 {
18642 /* between ":append" and "." and between ":python <<EOF" and "EOF"
18643 * don't check for ":endfunc". */
18644 if (STRCMP(theline, skip_until) == 0)
18645 {
18646 vim_free(skip_until);
18647 skip_until = NULL;
18648 }
18649 }
18650 else
18651 {
18652 /* skip ':' and blanks*/
18653 for (p = theline; vim_iswhite(*p) || *p == ':'; ++p)
18654 ;
18655
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000018656 /* Check for "endfunction". */
18657 if (checkforcmd(&p, "endfunction", 4) && nesting-- == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018658 {
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000018659 if (line_arg == NULL)
18660 vim_free(theline);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018661 break;
18662 }
18663
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000018664 /* Increase indent inside "if", "while", "for" and "try", decrease
Bram Moolenaar071d4272004-06-13 20:20:40 +000018665 * at "end". */
18666 if (indent > 2 && STRNCMP(p, "end", 3) == 0)
18667 indent -= 2;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000018668 else if (STRNCMP(p, "if", 2) == 0
18669 || STRNCMP(p, "wh", 2) == 0
18670 || STRNCMP(p, "for", 3) == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +000018671 || STRNCMP(p, "try", 3) == 0)
18672 indent += 2;
18673
18674 /* Check for defining a function inside this function. */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000018675 if (checkforcmd(&p, "function", 2))
Bram Moolenaar071d4272004-06-13 20:20:40 +000018676 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000018677 if (*p == '!')
18678 p = skipwhite(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018679 p += eval_fname_script(p);
18680 if (ASCII_ISALPHA(*p))
18681 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018682 vim_free(trans_function_name(&p, TRUE, 0, NULL));
Bram Moolenaar071d4272004-06-13 20:20:40 +000018683 if (*skipwhite(p) == '(')
18684 {
18685 ++nesting;
18686 indent += 2;
18687 }
18688 }
18689 }
18690
18691 /* Check for ":append" or ":insert". */
18692 p = skip_range(p, NULL);
18693 if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
18694 || (p[0] == 'i'
18695 && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
18696 && (!ASCII_ISALPHA(p[2]) || (p[2] == 's'))))))
18697 skip_until = vim_strsave((char_u *)".");
18698
18699 /* Check for ":python <<EOF", ":tcl <<EOF", etc. */
18700 arg = skipwhite(skiptowhite(p));
18701 if (arg[0] == '<' && arg[1] =='<'
18702 && ((p[0] == 'p' && p[1] == 'y'
18703 && (!ASCII_ISALPHA(p[2]) || p[2] == 't'))
18704 || (p[0] == 'p' && p[1] == 'e'
18705 && (!ASCII_ISALPHA(p[2]) || p[2] == 'r'))
18706 || (p[0] == 't' && p[1] == 'c'
18707 && (!ASCII_ISALPHA(p[2]) || p[2] == 'l'))
18708 || (p[0] == 'r' && p[1] == 'u' && p[2] == 'b'
18709 && (!ASCII_ISALPHA(p[3]) || p[3] == 'y'))
Bram Moolenaar325b7a22004-07-05 15:58:32 +000018710 || (p[0] == 'm' && p[1] == 'z'
18711 && (!ASCII_ISALPHA(p[2]) || p[2] == 's'))
Bram Moolenaar071d4272004-06-13 20:20:40 +000018712 ))
18713 {
18714 /* ":python <<" continues until a dot, like ":append" */
18715 p = skipwhite(arg + 2);
18716 if (*p == NUL)
18717 skip_until = vim_strsave((char_u *)".");
18718 else
18719 skip_until = vim_strsave(p);
18720 }
18721 }
18722
18723 /* Add the line to the function. */
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000018724 if (ga_grow(&newlines, 1 + sourcing_lnum_off) == FAIL)
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000018725 {
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000018726 if (line_arg == NULL)
18727 vim_free(theline);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018728 goto erret;
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000018729 }
18730
18731 /* Copy the line to newly allocated memory. get_one_sourceline()
18732 * allocates 250 bytes per line, this saves 80% on average. The cost
18733 * is an extra alloc/free. */
18734 p = vim_strsave(theline);
18735 if (p != NULL)
18736 {
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000018737 if (line_arg == NULL)
18738 vim_free(theline);
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000018739 theline = p;
18740 }
18741
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000018742 ((char_u **)(newlines.ga_data))[newlines.ga_len++] = theline;
18743
18744 /* Add NULL lines for continuation lines, so that the line count is
18745 * equal to the index in the growarray. */
18746 while (sourcing_lnum_off-- > 0)
18747 ((char_u **)(newlines.ga_data))[newlines.ga_len++] = NULL;
Bram Moolenaar997fb4b2006-02-17 21:53:23 +000018748
18749 /* Check for end of eap->arg. */
18750 if (line_arg != NULL && *line_arg == NUL)
18751 line_arg = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018752 }
18753
18754 /* Don't define the function when skipping commands or when an error was
18755 * detected. */
18756 if (eap->skip || did_emsg)
18757 goto erret;
18758
18759 /*
18760 * If there are no errors, add the function
18761 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018762 if (fudi.fd_dict == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000018763 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018764 v = find_var(name, &ht);
Bram Moolenaar33570922005-01-25 22:26:29 +000018765 if (v != NULL && v->di_tv.v_type == VAR_FUNC)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018766 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018767 emsg_funcname("E707: Function name conflicts with variable: %s",
18768 name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018769 goto erret;
18770 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000018771
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018772 fp = find_func(name);
18773 if (fp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018774 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018775 if (!eap->forceit)
18776 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018777 emsg_funcname(e_funcexts, name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018778 goto erret;
18779 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018780 if (fp->uf_calls > 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018781 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018782 emsg_funcname("E127: Cannot redefine function %s: It is in use",
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018783 name);
18784 goto erret;
18785 }
18786 /* redefine existing function */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018787 ga_clear_strings(&(fp->uf_args));
18788 ga_clear_strings(&(fp->uf_lines));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018789 vim_free(name);
18790 name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018791 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018792 }
18793 else
18794 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018795 char numbuf[20];
18796
18797 fp = NULL;
18798 if (fudi.fd_newkey == NULL && !eap->forceit)
18799 {
18800 EMSG(_(e_funcdict));
18801 goto erret;
18802 }
Bram Moolenaar758711c2005-02-02 23:11:38 +000018803 if (fudi.fd_di == NULL)
18804 {
18805 /* Can't add a function to a locked dictionary */
18806 if (tv_check_lock(fudi.fd_dict->dv_lock, eap->arg))
18807 goto erret;
18808 }
18809 /* Can't change an existing function if it is locked */
18810 else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg))
18811 goto erret;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018812
18813 /* Give the function a sequential number. Can only be used with a
18814 * Funcref! */
18815 vim_free(name);
18816 sprintf(numbuf, "%d", ++func_nr);
18817 name = vim_strsave((char_u *)numbuf);
18818 if (name == NULL)
18819 goto erret;
18820 }
18821
18822 if (fp == NULL)
18823 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000018824 if (fudi.fd_dict == NULL && vim_strchr(name, AUTOLOAD_CHAR) != NULL)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018825 {
18826 int slen, plen;
18827 char_u *scriptname;
18828
18829 /* Check that the autoload name matches the script name. */
18830 j = FAIL;
18831 if (sourcing_name != NULL)
18832 {
18833 scriptname = autoload_name(name);
18834 if (scriptname != NULL)
18835 {
18836 p = vim_strchr(scriptname, '/');
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000018837 plen = (int)STRLEN(p);
18838 slen = (int)STRLEN(sourcing_name);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018839 if (slen > plen && fnamecmp(p,
18840 sourcing_name + slen - plen) == 0)
18841 j = OK;
18842 vim_free(scriptname);
18843 }
18844 }
18845 if (j == FAIL)
18846 {
18847 EMSG2(_("E746: Function name does not match script file name: %s"), name);
18848 goto erret;
18849 }
18850 }
18851
18852 fp = (ufunc_T *)alloc((unsigned)(sizeof(ufunc_T) + STRLEN(name)));
Bram Moolenaar071d4272004-06-13 20:20:40 +000018853 if (fp == NULL)
18854 goto erret;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018855
18856 if (fudi.fd_dict != NULL)
18857 {
18858 if (fudi.fd_di == NULL)
18859 {
18860 /* add new dict entry */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000018861 fudi.fd_di = dictitem_alloc(fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018862 if (fudi.fd_di == NULL)
18863 {
18864 vim_free(fp);
18865 goto erret;
18866 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000018867 if (dict_add(fudi.fd_dict, fudi.fd_di) == FAIL)
18868 {
18869 vim_free(fudi.fd_di);
Bram Moolenaar0a5fd8b2006-08-16 20:02:22 +000018870 vim_free(fp);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000018871 goto erret;
18872 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018873 }
18874 else
18875 /* overwrite existing dict entry */
18876 clear_tv(&fudi.fd_di->di_tv);
18877 fudi.fd_di->di_tv.v_type = VAR_FUNC;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000018878 fudi.fd_di->di_tv.v_lock = 0;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018879 fudi.fd_di->di_tv.vval.v_string = vim_strsave(name);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018880 fp->uf_refcount = 1;
Bram Moolenaar910f66f2006-04-05 20:41:53 +000018881
18882 /* behave like "dict" was used */
18883 flags |= FC_DICT;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018884 }
18885
Bram Moolenaar071d4272004-06-13 20:20:40 +000018886 /* insert the new function in the function list */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018887 STRCPY(fp->uf_name, name);
18888 hash_add(&func_hashtab, UF2HIKEY(fp));
Bram Moolenaar071d4272004-06-13 20:20:40 +000018889 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018890 fp->uf_args = newargs;
18891 fp->uf_lines = newlines;
Bram Moolenaar05159a02005-02-26 23:04:13 +000018892#ifdef FEAT_PROFILE
18893 fp->uf_tml_count = NULL;
18894 fp->uf_tml_total = NULL;
18895 fp->uf_tml_self = NULL;
18896 fp->uf_profiling = FALSE;
18897 if (prof_def_func())
18898 func_do_profile(fp);
18899#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018900 fp->uf_varargs = varargs;
18901 fp->uf_flags = flags;
18902 fp->uf_calls = 0;
18903 fp->uf_script_ID = current_SID;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018904 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018905
18906erret:
Bram Moolenaar071d4272004-06-13 20:20:40 +000018907 ga_clear_strings(&newargs);
18908 ga_clear_strings(&newlines);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018909ret_free:
18910 vim_free(skip_until);
18911 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018912 vim_free(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018913 did_emsg |= saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018914}
18915
18916/*
18917 * Get a function name, translating "<SID>" and "<SNR>".
Bram Moolenaara7043832005-01-21 11:56:39 +000018918 * Also handles a Funcref in a List or Dictionary.
Bram Moolenaar071d4272004-06-13 20:20:40 +000018919 * Returns the function name in allocated memory, or NULL for failure.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018920 * flags:
18921 * TFN_INT: internal function name OK
18922 * TFN_QUIET: be quiet
Bram Moolenaar071d4272004-06-13 20:20:40 +000018923 * Advances "pp" to just after the function name (if no error).
18924 */
18925 static char_u *
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018926trans_function_name(pp, skip, flags, fdp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018927 char_u **pp;
18928 int skip; /* only find the end, don't evaluate */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018929 int flags;
Bram Moolenaar33570922005-01-25 22:26:29 +000018930 funcdict_T *fdp; /* return: info about dictionary used */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018931{
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000018932 char_u *name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018933 char_u *start;
18934 char_u *end;
18935 int lead;
18936 char_u sid_buf[20];
Bram Moolenaar071d4272004-06-13 20:20:40 +000018937 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +000018938 lval_T lv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018939
18940 if (fdp != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000018941 vim_memset(fdp, 0, sizeof(funcdict_T));
Bram Moolenaar071d4272004-06-13 20:20:40 +000018942 start = *pp;
Bram Moolenaara7043832005-01-21 11:56:39 +000018943
18944 /* Check for hard coded <SNR>: already translated function ID (from a user
18945 * command). */
18946 if ((*pp)[0] == K_SPECIAL && (*pp)[1] == KS_EXTRA
18947 && (*pp)[2] == (int)KE_SNR)
18948 {
18949 *pp += 3;
18950 len = get_id_len(pp) + 3;
18951 return vim_strnsave(start, len);
18952 }
18953
18954 /* A name starting with "<SID>" or "<SNR>" is local to a script. But
18955 * don't skip over "s:", get_lval() needs it for "s:dict.func". */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018956 lead = eval_fname_script(start);
Bram Moolenaara7043832005-01-21 11:56:39 +000018957 if (lead > 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018958 start += lead;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000018959
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000018960 end = get_lval(start, NULL, &lv, FALSE, skip, flags & TFN_QUIET,
18961 lead > 2 ? 0 : FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000018962 if (end == start)
18963 {
18964 if (!skip)
18965 EMSG(_("E129: Function name required"));
18966 goto theend;
18967 }
Bram Moolenaara7043832005-01-21 11:56:39 +000018968 if (end == NULL || (lv.ll_tv != NULL && (lead > 2 || lv.ll_range)))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000018969 {
18970 /*
18971 * Report an invalid expression in braces, unless the expression
18972 * evaluation has been cancelled due to an aborting error, an
18973 * interrupt, or an exception.
18974 */
18975 if (!aborting())
18976 {
18977 if (end != NULL)
18978 EMSG2(_(e_invarg2), start);
18979 }
18980 else
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000018981 *pp = find_name_end(start, NULL, NULL, FNE_INCL_BR);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000018982 goto theend;
18983 }
18984
18985 if (lv.ll_tv != NULL)
18986 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018987 if (fdp != NULL)
18988 {
18989 fdp->fd_dict = lv.ll_dict;
18990 fdp->fd_newkey = lv.ll_newkey;
18991 lv.ll_newkey = NULL;
18992 fdp->fd_di = lv.ll_di;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018993 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000018994 if (lv.ll_tv->v_type == VAR_FUNC && lv.ll_tv->vval.v_string != NULL)
18995 {
18996 name = vim_strsave(lv.ll_tv->vval.v_string);
18997 *pp = end;
18998 }
18999 else
19000 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000019001 if (!skip && !(flags & TFN_QUIET) && (fdp == NULL
19002 || lv.ll_dict == NULL || fdp->fd_newkey == NULL))
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000019003 EMSG(_(e_funcref));
19004 else
19005 *pp = end;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000019006 name = NULL;
19007 }
19008 goto theend;
19009 }
19010
19011 if (lv.ll_name == NULL)
19012 {
19013 /* Error found, but continue after the function name. */
19014 *pp = end;
19015 goto theend;
19016 }
19017
19018 if (lv.ll_exp_name != NULL)
Bram Moolenaarc32840f2006-01-14 21:23:38 +000019019 {
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000019020 len = (int)STRLEN(lv.ll_exp_name);
Bram Moolenaarc32840f2006-01-14 21:23:38 +000019021 if (lead <= 2 && lv.ll_name == lv.ll_exp_name
19022 && STRNCMP(lv.ll_name, "s:", 2) == 0)
19023 {
19024 /* When there was "s:" already or the name expanded to get a
19025 * leading "s:" then remove it. */
19026 lv.ll_name += 2;
19027 len -= 2;
19028 lead = 2;
19029 }
19030 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000019031 else
Bram Moolenaara7043832005-01-21 11:56:39 +000019032 {
19033 if (lead == 2) /* skip over "s:" */
19034 lv.ll_name += 2;
19035 len = (int)(end - lv.ll_name);
19036 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000019037
19038 /*
19039 * Copy the function name to allocated memory.
19040 * Accept <SID>name() inside a script, translate into <SNR>123_name().
19041 * Accept <SNR>123_name() outside a script.
19042 */
19043 if (skip)
19044 lead = 0; /* do nothing */
19045 else if (lead > 0)
19046 {
19047 lead = 3;
Bram Moolenaar86c9ee22006-05-13 11:33:27 +000019048 if ((lv.ll_exp_name != NULL && eval_fname_sid(lv.ll_exp_name))
19049 || eval_fname_sid(*pp))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000019050 {
Bram Moolenaar899dddf2006-03-26 21:06:50 +000019051 /* It's "s:" or "<SID>" */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000019052 if (current_SID <= 0)
19053 {
19054 EMSG(_(e_usingsid));
19055 goto theend;
19056 }
19057 sprintf((char *)sid_buf, "%ld_", (long)current_SID);
19058 lead += (int)STRLEN(sid_buf);
19059 }
19060 }
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000019061 else if (!(flags & TFN_INT) && builtin_function(lv.ll_name))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000019062 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000019063 EMSG2(_("E128: Function name must start with a capital or contain a colon: %s"), lv.ll_name);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000019064 goto theend;
19065 }
19066 name = alloc((unsigned)(len + lead + 1));
19067 if (name != NULL)
19068 {
19069 if (lead > 0)
19070 {
19071 name[0] = K_SPECIAL;
19072 name[1] = KS_EXTRA;
19073 name[2] = (int)KE_SNR;
Bram Moolenaara7043832005-01-21 11:56:39 +000019074 if (lead > 3) /* If it's "<SID>" */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000019075 STRCPY(name + 3, sid_buf);
19076 }
19077 mch_memmove(name + lead, lv.ll_name, (size_t)len);
19078 name[len + lead] = NUL;
19079 }
19080 *pp = end;
19081
19082theend:
19083 clear_lval(&lv);
19084 return name;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019085}
19086
19087/*
19088 * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case).
19089 * Return 2 if "p" starts with "s:".
19090 * Return 0 otherwise.
19091 */
19092 static int
19093eval_fname_script(p)
19094 char_u *p;
19095{
19096 if (p[0] == '<' && (STRNICMP(p + 1, "SID>", 4) == 0
19097 || STRNICMP(p + 1, "SNR>", 4) == 0))
19098 return 5;
19099 if (p[0] == 's' && p[1] == ':')
19100 return 2;
19101 return 0;
19102}
19103
19104/*
19105 * Return TRUE if "p" starts with "<SID>" or "s:".
19106 * Only works if eval_fname_script() returned non-zero for "p"!
19107 */
19108 static int
19109eval_fname_sid(p)
19110 char_u *p;
19111{
19112 return (*p == 's' || TOUPPER_ASC(p[2]) == 'I');
19113}
19114
19115/*
19116 * List the head of the function: "name(arg1, arg2)".
19117 */
19118 static void
19119list_func_head(fp, indent)
19120 ufunc_T *fp;
19121 int indent;
19122{
19123 int j;
19124
19125 msg_start();
19126 if (indent)
19127 MSG_PUTS(" ");
19128 MSG_PUTS("function ");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019129 if (fp->uf_name[0] == K_SPECIAL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019130 {
19131 MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019132 msg_puts(fp->uf_name + 3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019133 }
19134 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019135 msg_puts(fp->uf_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019136 msg_putchar('(');
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019137 for (j = 0; j < fp->uf_args.ga_len; ++j)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019138 {
19139 if (j)
19140 MSG_PUTS(", ");
19141 msg_puts(FUNCARG(fp, j));
19142 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019143 if (fp->uf_varargs)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019144 {
19145 if (j)
19146 MSG_PUTS(", ");
19147 MSG_PUTS("...");
19148 }
19149 msg_putchar(')');
Bram Moolenaarcafda4f2005-09-06 19:25:11 +000019150 msg_clr_eos();
Bram Moolenaar5b8d8fd2005-08-16 23:01:50 +000019151 if (p_verbose > 0)
19152 last_set_msg(fp->uf_script_ID);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019153}
19154
19155/*
19156 * Find a function by name, return pointer to it in ufuncs.
19157 * Return NULL for unknown function.
19158 */
19159 static ufunc_T *
19160find_func(name)
19161 char_u *name;
19162{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019163 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019164
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019165 hi = hash_find(&func_hashtab, name);
19166 if (!HASHITEM_EMPTY(hi))
19167 return HI2UF(hi);
19168 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019169}
19170
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000019171#if defined(EXITFREE) || defined(PROTO)
19172 void
19173free_all_functions()
19174{
19175 hashitem_T *hi;
19176
19177 /* Need to start all over every time, because func_free() may change the
19178 * hash table. */
19179 while (func_hashtab.ht_used > 0)
19180 for (hi = func_hashtab.ht_array; ; ++hi)
19181 if (!HASHITEM_EMPTY(hi))
19182 {
19183 func_free(HI2UF(hi));
19184 break;
19185 }
19186}
19187#endif
19188
Bram Moolenaar49cd9572005-01-03 21:06:01 +000019189/*
19190 * Return TRUE if a function "name" exists.
19191 */
19192 static int
19193function_exists(name)
19194 char_u *name;
19195{
Bram Moolenaaraa35dd12006-04-29 22:03:41 +000019196 char_u *nm = name;
19197 char_u *p;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000019198 int n = FALSE;
19199
Bram Moolenaaraa35dd12006-04-29 22:03:41 +000019200 p = trans_function_name(&nm, FALSE, TFN_INT|TFN_QUIET, NULL);
Bram Moolenaar79783442006-05-05 21:18:03 +000019201 nm = skipwhite(nm);
19202
19203 /* Only accept "funcname", "funcname ", "funcname (..." and
19204 * "funcname(...", not "funcname!...". */
19205 if (p != NULL && (*nm == NUL || *nm == '('))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000019206 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000019207 if (builtin_function(p))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000019208 n = (find_internal_func(p) >= 0);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000019209 else
19210 n = (find_func(p) != NULL);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000019211 }
Bram Moolenaar79783442006-05-05 21:18:03 +000019212 vim_free(p);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000019213 return n;
19214}
19215
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000019216/*
19217 * Return TRUE if "name" looks like a builtin function name: starts with a
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000019218 * lower case letter and doesn't contain a ':' or AUTOLOAD_CHAR.
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000019219 */
19220 static int
19221builtin_function(name)
19222 char_u *name;
19223{
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000019224 return ASCII_ISLOWER(name[0]) && vim_strchr(name, ':') == NULL
19225 && vim_strchr(name, AUTOLOAD_CHAR) == NULL;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000019226}
19227
Bram Moolenaar05159a02005-02-26 23:04:13 +000019228#if defined(FEAT_PROFILE) || defined(PROTO)
19229/*
19230 * Start profiling function "fp".
19231 */
19232 static void
19233func_do_profile(fp)
19234 ufunc_T *fp;
19235{
19236 fp->uf_tm_count = 0;
19237 profile_zero(&fp->uf_tm_self);
19238 profile_zero(&fp->uf_tm_total);
19239 if (fp->uf_tml_count == NULL)
19240 fp->uf_tml_count = (int *)alloc_clear((unsigned)
19241 (sizeof(int) * fp->uf_lines.ga_len));
19242 if (fp->uf_tml_total == NULL)
19243 fp->uf_tml_total = (proftime_T *)alloc_clear((unsigned)
19244 (sizeof(proftime_T) * fp->uf_lines.ga_len));
19245 if (fp->uf_tml_self == NULL)
19246 fp->uf_tml_self = (proftime_T *)alloc_clear((unsigned)
19247 (sizeof(proftime_T) * fp->uf_lines.ga_len));
19248 fp->uf_tml_idx = -1;
19249 if (fp->uf_tml_count == NULL || fp->uf_tml_total == NULL
19250 || fp->uf_tml_self == NULL)
19251 return; /* out of memory */
19252
19253 fp->uf_profiling = TRUE;
19254}
19255
19256/*
19257 * Dump the profiling results for all functions in file "fd".
19258 */
19259 void
19260func_dump_profile(fd)
19261 FILE *fd;
19262{
19263 hashitem_T *hi;
19264 int todo;
19265 ufunc_T *fp;
19266 int i;
Bram Moolenaar73830342005-02-28 22:48:19 +000019267 ufunc_T **sorttab;
19268 int st_len = 0;
Bram Moolenaar05159a02005-02-26 23:04:13 +000019269
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000019270 todo = (int)func_hashtab.ht_used;
Bram Moolenaar73830342005-02-28 22:48:19 +000019271 sorttab = (ufunc_T **)alloc((unsigned)(sizeof(ufunc_T) * todo));
19272
Bram Moolenaar05159a02005-02-26 23:04:13 +000019273 for (hi = func_hashtab.ht_array; todo > 0; ++hi)
19274 {
19275 if (!HASHITEM_EMPTY(hi))
19276 {
19277 --todo;
19278 fp = HI2UF(hi);
19279 if (fp->uf_profiling)
19280 {
Bram Moolenaar73830342005-02-28 22:48:19 +000019281 if (sorttab != NULL)
19282 sorttab[st_len++] = fp;
19283
Bram Moolenaar05159a02005-02-26 23:04:13 +000019284 if (fp->uf_name[0] == K_SPECIAL)
19285 fprintf(fd, "FUNCTION <SNR>%s()\n", fp->uf_name + 3);
19286 else
19287 fprintf(fd, "FUNCTION %s()\n", fp->uf_name);
19288 if (fp->uf_tm_count == 1)
19289 fprintf(fd, "Called 1 time\n");
19290 else
19291 fprintf(fd, "Called %d times\n", fp->uf_tm_count);
19292 fprintf(fd, "Total time: %s\n", profile_msg(&fp->uf_tm_total));
19293 fprintf(fd, " Self time: %s\n", profile_msg(&fp->uf_tm_self));
19294 fprintf(fd, "\n");
19295 fprintf(fd, "count total (s) self (s)\n");
19296
19297 for (i = 0; i < fp->uf_lines.ga_len; ++i)
19298 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000019299 if (FUNCLINE(fp, i) == NULL)
19300 continue;
Bram Moolenaar73830342005-02-28 22:48:19 +000019301 prof_func_line(fd, fp->uf_tml_count[i],
19302 &fp->uf_tml_total[i], &fp->uf_tml_self[i], TRUE);
Bram Moolenaar05159a02005-02-26 23:04:13 +000019303 fprintf(fd, "%s\n", FUNCLINE(fp, i));
19304 }
19305 fprintf(fd, "\n");
19306 }
19307 }
19308 }
Bram Moolenaar73830342005-02-28 22:48:19 +000019309
19310 if (sorttab != NULL && st_len > 0)
19311 {
19312 qsort((void *)sorttab, (size_t)st_len, sizeof(ufunc_T *),
19313 prof_total_cmp);
19314 prof_sort_list(fd, sorttab, st_len, "TOTAL", FALSE);
19315 qsort((void *)sorttab, (size_t)st_len, sizeof(ufunc_T *),
19316 prof_self_cmp);
19317 prof_sort_list(fd, sorttab, st_len, "SELF", TRUE);
19318 }
Bram Moolenaar05159a02005-02-26 23:04:13 +000019319}
Bram Moolenaar73830342005-02-28 22:48:19 +000019320
19321 static void
19322prof_sort_list(fd, sorttab, st_len, title, prefer_self)
19323 FILE *fd;
19324 ufunc_T **sorttab;
19325 int st_len;
19326 char *title;
19327 int prefer_self; /* when equal print only self time */
19328{
19329 int i;
19330 ufunc_T *fp;
19331
19332 fprintf(fd, "FUNCTIONS SORTED ON %s TIME\n", title);
19333 fprintf(fd, "count total (s) self (s) function\n");
19334 for (i = 0; i < 20 && i < st_len; ++i)
19335 {
19336 fp = sorttab[i];
19337 prof_func_line(fd, fp->uf_tm_count, &fp->uf_tm_total, &fp->uf_tm_self,
19338 prefer_self);
19339 if (fp->uf_name[0] == K_SPECIAL)
19340 fprintf(fd, " <SNR>%s()\n", fp->uf_name + 3);
19341 else
19342 fprintf(fd, " %s()\n", fp->uf_name);
19343 }
19344 fprintf(fd, "\n");
19345}
19346
19347/*
19348 * Print the count and times for one function or function line.
19349 */
19350 static void
19351prof_func_line(fd, count, total, self, prefer_self)
19352 FILE *fd;
19353 int count;
19354 proftime_T *total;
19355 proftime_T *self;
19356 int prefer_self; /* when equal print only self time */
19357{
19358 if (count > 0)
19359 {
19360 fprintf(fd, "%5d ", count);
19361 if (prefer_self && profile_equal(total, self))
19362 fprintf(fd, " ");
19363 else
19364 fprintf(fd, "%s ", profile_msg(total));
19365 if (!prefer_self && profile_equal(total, self))
19366 fprintf(fd, " ");
19367 else
19368 fprintf(fd, "%s ", profile_msg(self));
19369 }
19370 else
19371 fprintf(fd, " ");
19372}
19373
19374/*
19375 * Compare function for total time sorting.
19376 */
19377 static int
19378#ifdef __BORLANDC__
19379_RTLENTRYF
19380#endif
19381prof_total_cmp(s1, s2)
19382 const void *s1;
19383 const void *s2;
19384{
19385 ufunc_T *p1, *p2;
19386
19387 p1 = *(ufunc_T **)s1;
19388 p2 = *(ufunc_T **)s2;
19389 return profile_cmp(&p1->uf_tm_total, &p2->uf_tm_total);
19390}
19391
19392/*
19393 * Compare function for self time sorting.
19394 */
19395 static int
19396#ifdef __BORLANDC__
19397_RTLENTRYF
19398#endif
19399prof_self_cmp(s1, s2)
19400 const void *s1;
19401 const void *s2;
19402{
19403 ufunc_T *p1, *p2;
19404
19405 p1 = *(ufunc_T **)s1;
19406 p2 = *(ufunc_T **)s2;
19407 return profile_cmp(&p1->uf_tm_self, &p2->uf_tm_self);
19408}
19409
Bram Moolenaar05159a02005-02-26 23:04:13 +000019410#endif
19411
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000019412/*
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019413 * If "name" has a package name try autoloading the script for it.
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000019414 * Return TRUE if a package was loaded.
19415 */
19416 static int
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000019417script_autoload(name, reload)
19418 char_u *name;
19419 int reload; /* load script again when already loaded */
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000019420{
19421 char_u *p;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000019422 char_u *scriptname, *tofree;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000019423 int ret = FALSE;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000019424 int i;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000019425
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000019426 /* If there is no '#' after name[0] there is no package name. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000019427 p = vim_strchr(name, AUTOLOAD_CHAR);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000019428 if (p == NULL || p == name)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000019429 return FALSE;
19430
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000019431 tofree = scriptname = autoload_name(name);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019432
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000019433 /* Find the name in the list of previously loaded package names. Skip
19434 * "autoload/", it's always the same. */
19435 for (i = 0; i < ga_loaded.ga_len; ++i)
19436 if (STRCMP(((char_u **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0)
19437 break;
19438 if (!reload && i < ga_loaded.ga_len)
19439 ret = FALSE; /* was loaded already */
19440 else
19441 {
19442 /* Remember the name if it wasn't loaded already. */
19443 if (i == ga_loaded.ga_len && ga_grow(&ga_loaded, 1) == OK)
19444 {
19445 ((char_u **)ga_loaded.ga_data)[ga_loaded.ga_len++] = scriptname;
19446 tofree = NULL;
19447 }
19448
19449 /* Try loading the package from $VIMRUNTIME/autoload/<name>.vim */
Bram Moolenaar90cfdbe2005-08-12 19:59:19 +000019450 if (source_runtime(scriptname, FALSE) == OK)
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000019451 ret = TRUE;
19452 }
19453
19454 vim_free(tofree);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019455 return ret;
19456}
19457
19458/*
19459 * Return the autoload script name for a function or variable name.
19460 * Returns NULL when out of memory.
19461 */
19462 static char_u *
19463autoload_name(name)
19464 char_u *name;
19465{
19466 char_u *p;
19467 char_u *scriptname;
19468
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000019469 /* Get the script file name: replace '#' with '/', append ".vim". */
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000019470 scriptname = alloc((unsigned)(STRLEN(name) + 14));
19471 if (scriptname == NULL)
19472 return FALSE;
19473 STRCPY(scriptname, "autoload/");
19474 STRCAT(scriptname, name);
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000019475 *vim_strrchr(scriptname, AUTOLOAD_CHAR) = NUL;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000019476 STRCAT(scriptname, ".vim");
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000019477 while ((p = vim_strchr(scriptname, AUTOLOAD_CHAR)) != NULL)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000019478 *p = '/';
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019479 return scriptname;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000019480}
19481
Bram Moolenaar071d4272004-06-13 20:20:40 +000019482#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
19483
19484/*
19485 * Function given to ExpandGeneric() to obtain the list of user defined
19486 * function names.
19487 */
19488 char_u *
19489get_user_func_name(xp, idx)
19490 expand_T *xp;
19491 int idx;
19492{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019493 static long_u done;
19494 static hashitem_T *hi;
19495 ufunc_T *fp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019496
19497 if (idx == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019498 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019499 done = 0;
19500 hi = func_hashtab.ht_array;
19501 }
19502 if (done < func_hashtab.ht_used)
19503 {
19504 if (done++ > 0)
19505 ++hi;
19506 while (HASHITEM_EMPTY(hi))
19507 ++hi;
19508 fp = HI2UF(hi);
19509
19510 if (STRLEN(fp->uf_name) + 4 >= IOSIZE)
19511 return fp->uf_name; /* prevents overflow */
Bram Moolenaar071d4272004-06-13 20:20:40 +000019512
19513 cat_func_name(IObuff, fp);
19514 if (xp->xp_context != EXPAND_USER_FUNC)
19515 {
19516 STRCAT(IObuff, "(");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019517 if (!fp->uf_varargs && fp->uf_args.ga_len == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019518 STRCAT(IObuff, ")");
19519 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000019520 return IObuff;
19521 }
19522 return NULL;
19523}
19524
19525#endif /* FEAT_CMDL_COMPL */
19526
19527/*
19528 * Copy the function name of "fp" to buffer "buf".
19529 * "buf" must be able to hold the function name plus three bytes.
19530 * Takes care of script-local function names.
19531 */
19532 static void
19533cat_func_name(buf, fp)
19534 char_u *buf;
19535 ufunc_T *fp;
19536{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019537 if (fp->uf_name[0] == K_SPECIAL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019538 {
19539 STRCPY(buf, "<SNR>");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019540 STRCAT(buf, fp->uf_name + 3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019541 }
19542 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019543 STRCPY(buf, fp->uf_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019544}
19545
19546/*
19547 * ":delfunction {name}"
19548 */
19549 void
19550ex_delfunction(eap)
19551 exarg_T *eap;
19552{
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000019553 ufunc_T *fp = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019554 char_u *p;
19555 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000019556 funcdict_T fudi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019557
19558 p = eap->arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000019559 name = trans_function_name(&p, eap->skip, 0, &fudi);
19560 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019561 if (name == NULL)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000019562 {
19563 if (fudi.fd_dict != NULL && !eap->skip)
19564 EMSG(_(e_funcref));
Bram Moolenaar071d4272004-06-13 20:20:40 +000019565 return;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000019566 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000019567 if (!ends_excmd(*skipwhite(p)))
19568 {
19569 vim_free(name);
19570 EMSG(_(e_trailing));
19571 return;
19572 }
19573 eap->nextcmd = check_nextcmd(p);
19574 if (eap->nextcmd != NULL)
19575 *p = NUL;
19576
19577 if (!eap->skip)
19578 fp = find_func(name);
19579 vim_free(name);
19580
19581 if (!eap->skip)
19582 {
19583 if (fp == NULL)
19584 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000019585 EMSG2(_(e_nofunc), eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019586 return;
19587 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019588 if (fp->uf_calls > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019589 {
19590 EMSG2(_("E131: Cannot delete function %s: It is in use"), eap->arg);
19591 return;
19592 }
19593
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000019594 if (fudi.fd_dict != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019595 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000019596 /* Delete the dict item that refers to the function, it will
19597 * invoke func_unref() and possibly delete the function. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000019598 dictitem_remove(fudi.fd_dict, fudi.fd_di);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019599 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000019600 else
19601 func_free(fp);
19602 }
19603}
19604
19605/*
19606 * Free a function and remove it from the list of functions.
19607 */
19608 static void
19609func_free(fp)
19610 ufunc_T *fp;
19611{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019612 hashitem_T *hi;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000019613
19614 /* clear this function */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019615 ga_clear_strings(&(fp->uf_args));
19616 ga_clear_strings(&(fp->uf_lines));
Bram Moolenaar05159a02005-02-26 23:04:13 +000019617#ifdef FEAT_PROFILE
19618 vim_free(fp->uf_tml_count);
19619 vim_free(fp->uf_tml_total);
19620 vim_free(fp->uf_tml_self);
19621#endif
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000019622
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019623 /* remove the function from the function hashtable */
19624 hi = hash_find(&func_hashtab, UF2HIKEY(fp));
19625 if (HASHITEM_EMPTY(hi))
19626 EMSG2(_(e_intern2), "func_free()");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000019627 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019628 hash_remove(&func_hashtab, hi);
19629
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000019630 vim_free(fp);
19631}
19632
19633/*
19634 * Unreference a Function: decrement the reference count and free it when it
19635 * becomes zero. Only for numbered functions.
19636 */
19637 static void
19638func_unref(name)
19639 char_u *name;
19640{
19641 ufunc_T *fp;
19642
19643 if (name != NULL && isdigit(*name))
19644 {
19645 fp = find_func(name);
19646 if (fp == NULL)
19647 EMSG2(_(e_intern2), "func_unref()");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019648 else if (--fp->uf_refcount <= 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000019649 {
19650 /* Only delete it when it's not being used. Otherwise it's done
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019651 * when "uf_calls" becomes zero. */
19652 if (fp->uf_calls == 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000019653 func_free(fp);
19654 }
19655 }
19656}
19657
19658/*
19659 * Count a reference to a Function.
19660 */
19661 static void
19662func_ref(name)
19663 char_u *name;
19664{
19665 ufunc_T *fp;
19666
19667 if (name != NULL && isdigit(*name))
19668 {
19669 fp = find_func(name);
19670 if (fp == NULL)
19671 EMSG2(_(e_intern2), "func_ref()");
19672 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019673 ++fp->uf_refcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019674 }
19675}
19676
19677/*
19678 * Call a user function.
19679 */
19680 static void
Bram Moolenaare9a41262005-01-15 22:18:47 +000019681call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019682 ufunc_T *fp; /* pointer to function */
19683 int argcount; /* nr of args */
Bram Moolenaar33570922005-01-25 22:26:29 +000019684 typval_T *argvars; /* arguments */
19685 typval_T *rettv; /* return value */
Bram Moolenaar071d4272004-06-13 20:20:40 +000019686 linenr_T firstline; /* first line of range */
19687 linenr_T lastline; /* last line of range */
Bram Moolenaar33570922005-01-25 22:26:29 +000019688 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000019689{
Bram Moolenaar33570922005-01-25 22:26:29 +000019690 char_u *save_sourcing_name;
19691 linenr_T save_sourcing_lnum;
19692 scid_T save_current_SID;
19693 funccall_T fc;
Bram Moolenaar33570922005-01-25 22:26:29 +000019694 int save_did_emsg;
19695 static int depth = 0;
19696 dictitem_T *v;
19697 int fixvar_idx = 0; /* index in fixvar[] */
19698 int i;
19699 int ai;
19700 char_u numbuf[NUMBUFLEN];
19701 char_u *name;
Bram Moolenaar05159a02005-02-26 23:04:13 +000019702#ifdef FEAT_PROFILE
19703 proftime_T wait_start;
19704#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000019705
19706 /* If depth of calling is getting too high, don't execute the function */
19707 if (depth >= p_mfd)
19708 {
19709 EMSG(_("E132: Function call depth is higher than 'maxfuncdepth'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019710 rettv->v_type = VAR_NUMBER;
19711 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019712 return;
19713 }
19714 ++depth;
19715
19716 line_breakcheck(); /* check for CTRL-C hit */
19717
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000019718 fc.caller = current_funccal;
Bram Moolenaar33570922005-01-25 22:26:29 +000019719 current_funccal = &fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019720 fc.func = fp;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019721 fc.rettv = rettv;
19722 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019723 fc.linenr = 0;
19724 fc.returned = FALSE;
19725 fc.level = ex_nesting_level;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019726 /* Check if this function has a breakpoint. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019727 fc.breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019728 fc.dbg_tick = debug_tick;
19729
Bram Moolenaar33570922005-01-25 22:26:29 +000019730 /*
19731 * Note about using fc.fixvar[]: This is an array of FIXVAR_CNT variables
19732 * with names up to VAR_SHORT_LEN long. This avoids having to alloc/free
19733 * each argument variable and saves a lot of time.
19734 */
19735 /*
19736 * Init l: variables.
19737 */
19738 init_var_dict(&fc.l_vars, &fc.l_vars_var);
Bram Moolenaara7043832005-01-21 11:56:39 +000019739 if (selfdict != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000019740 {
Bram Moolenaar76b92b22006-03-24 22:46:53 +000019741 /* Set l:self to "selfdict". Use "name" to avoid a warning from
19742 * some compiler that checks the destination size. */
Bram Moolenaar33570922005-01-25 22:26:29 +000019743 v = &fc.fixvar[fixvar_idx++].var;
Bram Moolenaar76b92b22006-03-24 22:46:53 +000019744 name = v->di_key;
19745 STRCPY(name, "self");
Bram Moolenaar33570922005-01-25 22:26:29 +000019746 v->di_flags = DI_FLAGS_RO + DI_FLAGS_FIX;
19747 hash_add(&fc.l_vars.dv_hashtab, DI2HIKEY(v));
19748 v->di_tv.v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000019749 v->di_tv.v_lock = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000019750 v->di_tv.vval.v_dict = selfdict;
19751 ++selfdict->dv_refcount;
19752 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000019753
Bram Moolenaar33570922005-01-25 22:26:29 +000019754 /*
19755 * Init a: variables.
19756 * Set a:0 to "argcount".
19757 * Set a:000 to a list with room for the "..." arguments.
19758 */
19759 init_var_dict(&fc.l_avars, &fc.l_avars_var);
19760 add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "0",
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019761 (varnumber_T)(argcount - fp->uf_args.ga_len));
Bram Moolenaar33570922005-01-25 22:26:29 +000019762 v = &fc.fixvar[fixvar_idx++].var;
19763 STRCPY(v->di_key, "000");
19764 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
19765 hash_add(&fc.l_avars.dv_hashtab, DI2HIKEY(v));
19766 v->di_tv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000019767 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000019768 v->di_tv.vval.v_list = &fc.l_varlist;
19769 vim_memset(&fc.l_varlist, 0, sizeof(list_T));
19770 fc.l_varlist.lv_refcount = 99999;
Bram Moolenaar9dfb0f82006-06-22 16:03:05 +000019771 fc.l_varlist.lv_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000019772
19773 /*
19774 * Set a:firstline to "firstline" and a:lastline to "lastline".
19775 * Set a:name to named arguments.
19776 * Set a:N to the "..." arguments.
19777 */
19778 add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "firstline",
19779 (varnumber_T)firstline);
19780 add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "lastline",
19781 (varnumber_T)lastline);
19782 for (i = 0; i < argcount; ++i)
19783 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019784 ai = i - fp->uf_args.ga_len;
Bram Moolenaar33570922005-01-25 22:26:29 +000019785 if (ai < 0)
19786 /* named argument a:name */
19787 name = FUNCARG(fp, i);
19788 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000019789 {
Bram Moolenaar33570922005-01-25 22:26:29 +000019790 /* "..." argument a:1, a:2, etc. */
19791 sprintf((char *)numbuf, "%d", ai + 1);
19792 name = numbuf;
19793 }
19794 if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN)
19795 {
19796 v = &fc.fixvar[fixvar_idx++].var;
19797 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
19798 }
19799 else
19800 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000019801 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
19802 + STRLEN(name)));
Bram Moolenaar33570922005-01-25 22:26:29 +000019803 if (v == NULL)
19804 break;
19805 v->di_flags = DI_FLAGS_RO;
19806 }
19807 STRCPY(v->di_key, name);
19808 hash_add(&fc.l_avars.dv_hashtab, DI2HIKEY(v));
19809
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000019810 /* Note: the values are copied directly to avoid alloc/free.
19811 * "argvars" must have VAR_FIXED for v_lock. */
Bram Moolenaar33570922005-01-25 22:26:29 +000019812 v->di_tv = argvars[i];
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000019813 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000019814
19815 if (ai >= 0 && ai < MAX_FUNC_ARGS)
19816 {
19817 list_append(&fc.l_varlist, &fc.l_listitems[ai]);
19818 fc.l_listitems[ai].li_tv = argvars[i];
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000019819 fc.l_listitems[ai].li_tv.v_lock = VAR_FIXED;
Bram Moolenaare9a41262005-01-15 22:18:47 +000019820 }
19821 }
19822
Bram Moolenaar071d4272004-06-13 20:20:40 +000019823 /* Don't redraw while executing the function. */
19824 ++RedrawingDisabled;
19825 save_sourcing_name = sourcing_name;
19826 save_sourcing_lnum = sourcing_lnum;
19827 sourcing_lnum = 1;
19828 sourcing_name = alloc((unsigned)((save_sourcing_name == NULL ? 0
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019829 : STRLEN(save_sourcing_name)) + STRLEN(fp->uf_name) + 13));
Bram Moolenaar071d4272004-06-13 20:20:40 +000019830 if (sourcing_name != NULL)
19831 {
19832 if (save_sourcing_name != NULL
19833 && STRNCMP(save_sourcing_name, "function ", 9) == 0)
19834 sprintf((char *)sourcing_name, "%s..", save_sourcing_name);
19835 else
19836 STRCPY(sourcing_name, "function ");
19837 cat_func_name(sourcing_name + STRLEN(sourcing_name), fp);
19838
19839 if (p_verbose >= 12)
19840 {
19841 ++no_wait_return;
Bram Moolenaar54ee7752005-05-31 22:22:17 +000019842 verbose_enter_scroll();
19843
Bram Moolenaar555b2802005-05-19 21:08:39 +000019844 smsg((char_u *)_("calling %s"), sourcing_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019845 if (p_verbose >= 14)
19846 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000019847 char_u buf[MSG_BUF_LEN];
Bram Moolenaar89d40322006-08-29 15:30:07 +000019848 char_u numbuf2[NUMBUFLEN];
Bram Moolenaar758711c2005-02-02 23:11:38 +000019849 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019850
19851 msg_puts((char_u *)"(");
19852 for (i = 0; i < argcount; ++i)
19853 {
19854 if (i > 0)
19855 msg_puts((char_u *)", ");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000019856 if (argvars[i].v_type == VAR_NUMBER)
19857 msg_outnum((long)argvars[i].vval.v_number);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019858 else
19859 {
Bram Moolenaar89d40322006-08-29 15:30:07 +000019860 trunc_string(tv2string(&argvars[i], &tofree,
19861 numbuf2, 0), buf, MSG_BUF_CLEN);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019862 msg_puts(buf);
Bram Moolenaar758711c2005-02-02 23:11:38 +000019863 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019864 }
19865 }
19866 msg_puts((char_u *)")");
19867 }
19868 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaar54ee7752005-05-31 22:22:17 +000019869
19870 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000019871 --no_wait_return;
19872 }
19873 }
Bram Moolenaar05159a02005-02-26 23:04:13 +000019874#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +000019875 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +000019876 {
19877 if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL))
19878 func_do_profile(fp);
19879 if (fp->uf_profiling
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000019880 || (fc.caller != NULL && &fc.caller->func->uf_profiling))
Bram Moolenaar05159a02005-02-26 23:04:13 +000019881 {
19882 ++fp->uf_tm_count;
19883 profile_start(&fp->uf_tm_start);
19884 profile_zero(&fp->uf_tm_children);
19885 }
19886 script_prof_save(&wait_start);
19887 }
19888#endif
19889
Bram Moolenaar071d4272004-06-13 20:20:40 +000019890 save_current_SID = current_SID;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019891 current_SID = fp->uf_script_ID;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019892 save_did_emsg = did_emsg;
19893 did_emsg = FALSE;
19894
19895 /* call do_cmdline() to execute the lines */
19896 do_cmdline(NULL, get_func_line, (void *)&fc,
19897 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
19898
19899 --RedrawingDisabled;
19900
19901 /* when the function was aborted because of an error, return -1 */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000019902 if ((did_emsg && (fp->uf_flags & FC_ABORT)) || rettv->v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019903 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019904 clear_tv(rettv);
19905 rettv->v_type = VAR_NUMBER;
19906 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019907 }
19908
Bram Moolenaar05159a02005-02-26 23:04:13 +000019909#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +000019910 if (do_profiling == PROF_YES && (fp->uf_profiling
19911 || (fc.caller != NULL && &fc.caller->func->uf_profiling)))
Bram Moolenaar05159a02005-02-26 23:04:13 +000019912 {
19913 profile_end(&fp->uf_tm_start);
19914 profile_sub_wait(&wait_start, &fp->uf_tm_start);
19915 profile_add(&fp->uf_tm_total, &fp->uf_tm_start);
Bram Moolenaar1056d982006-03-09 22:37:52 +000019916 profile_self(&fp->uf_tm_self, &fp->uf_tm_start, &fp->uf_tm_children);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000019917 if (fc.caller != NULL && &fc.caller->func->uf_profiling)
Bram Moolenaar05159a02005-02-26 23:04:13 +000019918 {
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000019919 profile_add(&fc.caller->func->uf_tm_children, &fp->uf_tm_start);
19920 profile_add(&fc.caller->func->uf_tml_children, &fp->uf_tm_start);
Bram Moolenaar05159a02005-02-26 23:04:13 +000019921 }
19922 }
19923#endif
19924
Bram Moolenaar071d4272004-06-13 20:20:40 +000019925 /* when being verbose, mention the return value */
19926 if (p_verbose >= 12)
19927 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000019928 ++no_wait_return;
Bram Moolenaar54ee7752005-05-31 22:22:17 +000019929 verbose_enter_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000019930
Bram Moolenaar071d4272004-06-13 20:20:40 +000019931 if (aborting())
Bram Moolenaar555b2802005-05-19 21:08:39 +000019932 smsg((char_u *)_("%s aborted"), sourcing_name);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019933 else if (fc.rettv->v_type == VAR_NUMBER)
Bram Moolenaar555b2802005-05-19 21:08:39 +000019934 smsg((char_u *)_("%s returning #%ld"), sourcing_name,
19935 (long)fc.rettv->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +000019936 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000019937 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000019938 char_u buf[MSG_BUF_LEN];
Bram Moolenaar89d40322006-08-29 15:30:07 +000019939 char_u numbuf2[NUMBUFLEN];
Bram Moolenaar758711c2005-02-02 23:11:38 +000019940 char_u *tofree;
19941
Bram Moolenaar555b2802005-05-19 21:08:39 +000019942 /* The value may be very long. Skip the middle part, so that we
19943 * have some idea how it starts and ends. smsg() would always
19944 * truncate it at the end. */
Bram Moolenaar89d40322006-08-29 15:30:07 +000019945 trunc_string(tv2string(fc.rettv, &tofree, numbuf2, 0),
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000019946 buf, MSG_BUF_CLEN);
Bram Moolenaar555b2802005-05-19 21:08:39 +000019947 smsg((char_u *)_("%s returning %s"), sourcing_name, buf);
Bram Moolenaar758711c2005-02-02 23:11:38 +000019948 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019949 }
19950 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaar54ee7752005-05-31 22:22:17 +000019951
19952 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000019953 --no_wait_return;
19954 }
19955
19956 vim_free(sourcing_name);
19957 sourcing_name = save_sourcing_name;
19958 sourcing_lnum = save_sourcing_lnum;
19959 current_SID = save_current_SID;
Bram Moolenaar05159a02005-02-26 23:04:13 +000019960#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +000019961 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +000019962 script_prof_restore(&wait_start);
19963#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000019964
19965 if (p_verbose >= 12 && sourcing_name != NULL)
19966 {
19967 ++no_wait_return;
Bram Moolenaar54ee7752005-05-31 22:22:17 +000019968 verbose_enter_scroll();
19969
Bram Moolenaar555b2802005-05-19 21:08:39 +000019970 smsg((char_u *)_("continuing in %s"), sourcing_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019971 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaar54ee7752005-05-31 22:22:17 +000019972
19973 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000019974 --no_wait_return;
19975 }
19976
19977 did_emsg |= save_did_emsg;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000019978 current_funccal = fc.caller;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019979
Bram Moolenaar33570922005-01-25 22:26:29 +000019980 /* The a: variables typevals were not alloced, only free the allocated
19981 * variables. */
19982 vars_clear_ext(&fc.l_avars.dv_hashtab, FALSE);
19983
19984 vars_clear(&fc.l_vars.dv_hashtab); /* free all l: variables */
Bram Moolenaar071d4272004-06-13 20:20:40 +000019985 --depth;
19986}
19987
19988/*
Bram Moolenaar33570922005-01-25 22:26:29 +000019989 * Add a number variable "name" to dict "dp" with value "nr".
19990 */
19991 static void
19992add_nr_var(dp, v, name, nr)
19993 dict_T *dp;
19994 dictitem_T *v;
19995 char *name;
19996 varnumber_T nr;
19997{
19998 STRCPY(v->di_key, name);
19999 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
20000 hash_add(&dp->dv_hashtab, DI2HIKEY(v));
20001 v->di_tv.v_type = VAR_NUMBER;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000020002 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000020003 v->di_tv.vval.v_number = nr;
20004}
20005
20006/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000020007 * ":return [expr]"
20008 */
20009 void
20010ex_return(eap)
20011 exarg_T *eap;
20012{
20013 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000020014 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020015 int returning = FALSE;
20016
20017 if (current_funccal == NULL)
20018 {
20019 EMSG(_("E133: :return not inside a function"));
20020 return;
20021 }
20022
20023 if (eap->skip)
20024 ++emsg_skip;
20025
20026 eap->nextcmd = NULL;
20027 if ((*arg != NUL && *arg != '|' && *arg != '\n')
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020028 && eval0(arg, &rettv, &eap->nextcmd, !eap->skip) != FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020029 {
20030 if (!eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020031 returning = do_return(eap, FALSE, TRUE, &rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020032 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020033 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020034 }
20035 /* It's safer to return also on error. */
20036 else if (!eap->skip)
20037 {
20038 /*
20039 * Return unless the expression evaluation has been cancelled due to an
20040 * aborting error, an interrupt, or an exception.
20041 */
20042 if (!aborting())
20043 returning = do_return(eap, FALSE, TRUE, NULL);
20044 }
20045
20046 /* When skipping or the return gets pending, advance to the next command
20047 * in this line (!returning). Otherwise, ignore the rest of the line.
20048 * Following lines will be ignored by get_func_line(). */
20049 if (returning)
20050 eap->nextcmd = NULL;
20051 else if (eap->nextcmd == NULL) /* no argument */
20052 eap->nextcmd = check_nextcmd(arg);
20053
20054 if (eap->skip)
20055 --emsg_skip;
20056}
20057
20058/*
20059 * Return from a function. Possibly makes the return pending. Also called
20060 * for a pending return at the ":endtry" or after returning from an extra
20061 * do_cmdline(). "reanimate" is used in the latter case. "is_cmd" is set
Bram Moolenaar33570922005-01-25 22:26:29 +000020062 * when called due to a ":return" command. "rettv" may point to a typval_T
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020063 * with the return rettv. Returns TRUE when the return can be carried out,
Bram Moolenaar071d4272004-06-13 20:20:40 +000020064 * FALSE when the return gets pending.
20065 */
20066 int
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020067do_return(eap, reanimate, is_cmd, rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020068 exarg_T *eap;
20069 int reanimate;
20070 int is_cmd;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020071 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020072{
20073 int idx;
20074 struct condstack *cstack = eap->cstack;
20075
20076 if (reanimate)
20077 /* Undo the return. */
20078 current_funccal->returned = FALSE;
20079
20080 /*
20081 * Cleanup (and inactivate) conditionals, but stop when a try conditional
20082 * not in its finally clause (which then is to be executed next) is found.
20083 * In this case, make the ":return" pending for execution at the ":endtry".
20084 * Otherwise, return normally.
20085 */
20086 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
20087 if (idx >= 0)
20088 {
20089 cstack->cs_pending[idx] = CSTP_RETURN;
20090
20091 if (!is_cmd && !reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020092 /* A pending return again gets pending. "rettv" points to an
20093 * allocated variable with the rettv of the original ":return"'s
Bram Moolenaar071d4272004-06-13 20:20:40 +000020094 * argument if present or is NULL else. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020095 cstack->cs_rettv[idx] = rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020096 else
20097 {
20098 /* When undoing a return in order to make it pending, get the stored
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020099 * return rettv. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000020100 if (reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020101 rettv = current_funccal->rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020102
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020103 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020104 {
20105 /* Store the value of the pending return. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020106 if ((cstack->cs_rettv[idx] = alloc_tv()) != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000020107 *(typval_T *)cstack->cs_rettv[idx] = *(typval_T *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020108 else
20109 EMSG(_(e_outofmem));
20110 }
20111 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020112 cstack->cs_rettv[idx] = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020113
20114 if (reanimate)
20115 {
20116 /* The pending return value could be overwritten by a ":return"
20117 * without argument in a finally clause; reset the default
20118 * return value. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020119 current_funccal->rettv->v_type = VAR_NUMBER;
20120 current_funccal->rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020121 }
20122 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020123 report_make_pending(CSTP_RETURN, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020124 }
20125 else
20126 {
20127 current_funccal->returned = TRUE;
20128
20129 /* If the return is carried out now, store the return value. For
20130 * a return immediately after reanimation, the value is already
20131 * there. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020132 if (!reanimate && rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020133 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020134 clear_tv(current_funccal->rettv);
Bram Moolenaar33570922005-01-25 22:26:29 +000020135 *current_funccal->rettv = *(typval_T *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020136 if (!is_cmd)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020137 vim_free(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020138 }
20139 }
20140
20141 return idx < 0;
20142}
20143
20144/*
20145 * Free the variable with a pending return value.
20146 */
20147 void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020148discard_pending_return(rettv)
20149 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020150{
Bram Moolenaar33570922005-01-25 22:26:29 +000020151 free_tv((typval_T *)rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020152}
20153
20154/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020155 * Generate a return command for producing the value of "rettv". The result
Bram Moolenaar071d4272004-06-13 20:20:40 +000020156 * is an allocated string. Used by report_pending() for verbose messages.
20157 */
20158 char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020159get_return_cmd(rettv)
20160 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020161{
Bram Moolenaar81bf7082005-02-12 14:31:42 +000020162 char_u *s = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020163 char_u *tofree = NULL;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000020164 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000020165
Bram Moolenaar81bf7082005-02-12 14:31:42 +000020166 if (rettv != NULL)
Bram Moolenaarb71eaae2006-01-20 23:10:18 +000020167 s = echo_string((typval_T *)rettv, &tofree, numbuf, 0);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000020168 if (s == NULL)
20169 s = (char_u *)"";
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020170
20171 STRCPY(IObuff, ":return ");
20172 STRNCPY(IObuff + 8, s, IOSIZE - 8);
20173 if (STRLEN(s) + 8 >= IOSIZE)
20174 STRCPY(IObuff + IOSIZE - 4, "...");
20175 vim_free(tofree);
20176 return vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020177}
20178
20179/*
20180 * Get next function line.
20181 * Called by do_cmdline() to get the next line.
20182 * Returns allocated string, or NULL for end of function.
20183 */
20184/* ARGSUSED */
20185 char_u *
20186get_func_line(c, cookie, indent)
20187 int c; /* not used */
20188 void *cookie;
20189 int indent; /* not used */
20190{
Bram Moolenaar33570922005-01-25 22:26:29 +000020191 funccall_T *fcp = (funccall_T *)cookie;
Bram Moolenaar05159a02005-02-26 23:04:13 +000020192 ufunc_T *fp = fcp->func;
20193 char_u *retval;
20194 garray_T *gap; /* growarray with function lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +000020195
20196 /* If breakpoints have been added/deleted need to check for it. */
20197 if (fcp->dbg_tick != debug_tick)
20198 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000020199 fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
Bram Moolenaar071d4272004-06-13 20:20:40 +000020200 sourcing_lnum);
20201 fcp->dbg_tick = debug_tick;
20202 }
Bram Moolenaar05159a02005-02-26 23:04:13 +000020203#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +000020204 if (do_profiling == PROF_YES)
Bram Moolenaar05159a02005-02-26 23:04:13 +000020205 func_line_end(cookie);
20206#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000020207
Bram Moolenaar05159a02005-02-26 23:04:13 +000020208 gap = &fp->uf_lines;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000020209 if (((fp->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
20210 || fcp->returned)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020211 retval = NULL;
20212 else
20213 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000020214 /* Skip NULL lines (continuation lines). */
20215 while (fcp->linenr < gap->ga_len
20216 && ((char_u **)(gap->ga_data))[fcp->linenr] == NULL)
20217 ++fcp->linenr;
20218 if (fcp->linenr >= gap->ga_len)
20219 retval = NULL;
20220 else
20221 {
20222 retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]);
20223 sourcing_lnum = fcp->linenr;
Bram Moolenaar05159a02005-02-26 23:04:13 +000020224#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +000020225 if (do_profiling == PROF_YES)
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000020226 func_line_start(cookie);
Bram Moolenaar05159a02005-02-26 23:04:13 +000020227#endif
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000020228 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000020229 }
20230
20231 /* Did we encounter a breakpoint? */
20232 if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum)
20233 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000020234 dbg_breakpoint(fp->uf_name, sourcing_lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020235 /* Find next breakpoint. */
Bram Moolenaar05159a02005-02-26 23:04:13 +000020236 fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
Bram Moolenaar071d4272004-06-13 20:20:40 +000020237 sourcing_lnum);
20238 fcp->dbg_tick = debug_tick;
20239 }
20240
20241 return retval;
20242}
20243
Bram Moolenaar05159a02005-02-26 23:04:13 +000020244#if defined(FEAT_PROFILE) || defined(PROTO)
20245/*
20246 * Called when starting to read a function line.
20247 * "sourcing_lnum" must be correct!
20248 * When skipping lines it may not actually be executed, but we won't find out
20249 * until later and we need to store the time now.
20250 */
20251 void
20252func_line_start(cookie)
20253 void *cookie;
20254{
20255 funccall_T *fcp = (funccall_T *)cookie;
20256 ufunc_T *fp = fcp->func;
20257
20258 if (fp->uf_profiling && sourcing_lnum >= 1
20259 && sourcing_lnum <= fp->uf_lines.ga_len)
20260 {
20261 fp->uf_tml_idx = sourcing_lnum - 1;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000020262 /* Skip continuation lines. */
20263 while (fp->uf_tml_idx > 0 && FUNCLINE(fp, fp->uf_tml_idx) == NULL)
20264 --fp->uf_tml_idx;
Bram Moolenaar05159a02005-02-26 23:04:13 +000020265 fp->uf_tml_execed = FALSE;
20266 profile_start(&fp->uf_tml_start);
20267 profile_zero(&fp->uf_tml_children);
20268 profile_get_wait(&fp->uf_tml_wait);
20269 }
20270}
20271
20272/*
20273 * Called when actually executing a function line.
20274 */
20275 void
20276func_line_exec(cookie)
20277 void *cookie;
20278{
20279 funccall_T *fcp = (funccall_T *)cookie;
20280 ufunc_T *fp = fcp->func;
20281
20282 if (fp->uf_profiling && fp->uf_tml_idx >= 0)
20283 fp->uf_tml_execed = TRUE;
20284}
20285
20286/*
20287 * Called when done with a function line.
20288 */
20289 void
20290func_line_end(cookie)
20291 void *cookie;
20292{
20293 funccall_T *fcp = (funccall_T *)cookie;
20294 ufunc_T *fp = fcp->func;
20295
20296 if (fp->uf_profiling && fp->uf_tml_idx >= 0)
20297 {
20298 if (fp->uf_tml_execed)
20299 {
20300 ++fp->uf_tml_count[fp->uf_tml_idx];
20301 profile_end(&fp->uf_tml_start);
20302 profile_sub_wait(&fp->uf_tml_wait, &fp->uf_tml_start);
Bram Moolenaar05159a02005-02-26 23:04:13 +000020303 profile_add(&fp->uf_tml_total[fp->uf_tml_idx], &fp->uf_tml_start);
Bram Moolenaar1056d982006-03-09 22:37:52 +000020304 profile_self(&fp->uf_tml_self[fp->uf_tml_idx], &fp->uf_tml_start,
20305 &fp->uf_tml_children);
Bram Moolenaar05159a02005-02-26 23:04:13 +000020306 }
20307 fp->uf_tml_idx = -1;
20308 }
20309}
20310#endif
20311
Bram Moolenaar071d4272004-06-13 20:20:40 +000020312/*
20313 * Return TRUE if the currently active function should be ended, because a
20314 * return was encountered or an error occured. Used inside a ":while".
20315 */
20316 int
20317func_has_ended(cookie)
20318 void *cookie;
20319{
Bram Moolenaar33570922005-01-25 22:26:29 +000020320 funccall_T *fcp = (funccall_T *)cookie;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020321
20322 /* Ignore the "abort" flag if the abortion behavior has been changed due to
20323 * an error inside a try conditional. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000020324 return (((fcp->func->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
Bram Moolenaar071d4272004-06-13 20:20:40 +000020325 || fcp->returned);
20326}
20327
20328/*
20329 * return TRUE if cookie indicates a function which "abort"s on errors.
20330 */
20331 int
20332func_has_abort(cookie)
20333 void *cookie;
20334{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000020335 return ((funccall_T *)cookie)->func->uf_flags & FC_ABORT;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020336}
20337
20338#if defined(FEAT_VIMINFO) || defined(FEAT_SESSION)
20339typedef enum
20340{
20341 VAR_FLAVOUR_DEFAULT,
20342 VAR_FLAVOUR_SESSION,
20343 VAR_FLAVOUR_VIMINFO
20344} var_flavour_T;
20345
20346static var_flavour_T var_flavour __ARGS((char_u *varname));
20347
20348 static var_flavour_T
20349var_flavour(varname)
20350 char_u *varname;
20351{
20352 char_u *p = varname;
20353
20354 if (ASCII_ISUPPER(*p))
20355 {
20356 while (*(++p))
20357 if (ASCII_ISLOWER(*p))
20358 return VAR_FLAVOUR_SESSION;
20359 return VAR_FLAVOUR_VIMINFO;
20360 }
20361 else
20362 return VAR_FLAVOUR_DEFAULT;
20363}
20364#endif
20365
20366#if defined(FEAT_VIMINFO) || defined(PROTO)
20367/*
20368 * Restore global vars that start with a capital from the viminfo file
20369 */
20370 int
20371read_viminfo_varlist(virp, writing)
20372 vir_T *virp;
20373 int writing;
20374{
20375 char_u *tab;
20376 int is_string = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +000020377 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020378
20379 if (!writing && (find_viminfo_parameter('!') != NULL))
20380 {
20381 tab = vim_strchr(virp->vir_line + 1, '\t');
20382 if (tab != NULL)
20383 {
20384 *tab++ = '\0'; /* isolate the variable name */
20385 if (*tab == 'S') /* string var */
20386 is_string = TRUE;
20387
20388 tab = vim_strchr(tab, '\t');
20389 if (tab != NULL)
20390 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000020391 if (is_string)
20392 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000020393 tv.v_type = VAR_STRING;
20394 tv.vval.v_string = viminfo_readstring(virp,
Bram Moolenaar071d4272004-06-13 20:20:40 +000020395 (int)(tab - virp->vir_line + 1), TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020396 }
20397 else
20398 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000020399 tv.v_type = VAR_NUMBER;
20400 tv.vval.v_number = atol((char *)tab + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020401 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000020402 set_var(virp->vir_line + 1, &tv, FALSE);
20403 if (is_string)
20404 vim_free(tv.vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020405 }
20406 }
20407 }
20408
20409 return viminfo_readline(virp);
20410}
20411
20412/*
20413 * Write global vars that start with a capital to the viminfo file
20414 */
20415 void
20416write_viminfo_varlist(fp)
20417 FILE *fp;
20418{
Bram Moolenaar33570922005-01-25 22:26:29 +000020419 hashitem_T *hi;
20420 dictitem_T *this_var;
Bram Moolenaara7043832005-01-21 11:56:39 +000020421 int todo;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020422 char *s;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000020423 char_u *p;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020424 char_u *tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000020425 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000020426
20427 if (find_viminfo_parameter('!') == NULL)
20428 return;
20429
20430 fprintf(fp, _("\n# global variables:\n"));
Bram Moolenaara7043832005-01-21 11:56:39 +000020431
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000020432 todo = (int)globvarht.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +000020433 for (hi = globvarht.ht_array; todo > 0; ++hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020434 {
Bram Moolenaara7043832005-01-21 11:56:39 +000020435 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar071d4272004-06-13 20:20:40 +000020436 {
Bram Moolenaara7043832005-01-21 11:56:39 +000020437 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000020438 this_var = HI2DI(hi);
20439 if (var_flavour(this_var->di_key) == VAR_FLAVOUR_VIMINFO)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000020440 {
Bram Moolenaar33570922005-01-25 22:26:29 +000020441 switch (this_var->di_tv.v_type)
Bram Moolenaara7043832005-01-21 11:56:39 +000020442 {
20443 case VAR_STRING: s = "STR"; break;
20444 case VAR_NUMBER: s = "NUM"; break;
20445 default: continue;
20446 }
Bram Moolenaar33570922005-01-25 22:26:29 +000020447 fprintf(fp, "!%s\t%s\t", this_var->di_key, s);
Bram Moolenaarb71eaae2006-01-20 23:10:18 +000020448 p = echo_string(&this_var->di_tv, &tofree, numbuf, 0);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000020449 if (p != NULL)
20450 viminfo_writestring(fp, p);
Bram Moolenaara7043832005-01-21 11:56:39 +000020451 vim_free(tofree);
20452 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000020453 }
20454 }
20455}
20456#endif
20457
20458#if defined(FEAT_SESSION) || defined(PROTO)
20459 int
20460store_session_globals(fd)
20461 FILE *fd;
20462{
Bram Moolenaar33570922005-01-25 22:26:29 +000020463 hashitem_T *hi;
20464 dictitem_T *this_var;
Bram Moolenaara7043832005-01-21 11:56:39 +000020465 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020466 char_u *p, *t;
20467
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000020468 todo = (int)globvarht.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +000020469 for (hi = globvarht.ht_array; todo > 0; ++hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000020470 {
Bram Moolenaara7043832005-01-21 11:56:39 +000020471 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar071d4272004-06-13 20:20:40 +000020472 {
Bram Moolenaara7043832005-01-21 11:56:39 +000020473 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000020474 this_var = HI2DI(hi);
20475 if ((this_var->di_tv.v_type == VAR_NUMBER
20476 || this_var->di_tv.v_type == VAR_STRING)
20477 && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000020478 {
Bram Moolenaara7043832005-01-21 11:56:39 +000020479 /* Escape special characters with a backslash. Turn a LF and
20480 * CR into \n and \r. */
Bram Moolenaar33570922005-01-25 22:26:29 +000020481 p = vim_strsave_escaped(get_tv_string(&this_var->di_tv),
Bram Moolenaara7043832005-01-21 11:56:39 +000020482 (char_u *)"\\\"\n\r");
20483 if (p == NULL) /* out of memory */
20484 break;
20485 for (t = p; *t != NUL; ++t)
20486 if (*t == '\n')
20487 *t = 'n';
20488 else if (*t == '\r')
20489 *t = 'r';
20490 if ((fprintf(fd, "let %s = %c%s%c",
Bram Moolenaar33570922005-01-25 22:26:29 +000020491 this_var->di_key,
20492 (this_var->di_tv.v_type == VAR_STRING) ? '"'
20493 : ' ',
20494 p,
20495 (this_var->di_tv.v_type == VAR_STRING) ? '"'
20496 : ' ') < 0)
Bram Moolenaara7043832005-01-21 11:56:39 +000020497 || put_eol(fd) == FAIL)
20498 {
20499 vim_free(p);
20500 return FAIL;
20501 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000020502 vim_free(p);
20503 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000020504 }
20505 }
20506 return OK;
20507}
20508#endif
20509
Bram Moolenaar661b1822005-07-28 22:36:45 +000020510/*
20511 * Display script name where an item was last set.
20512 * Should only be invoked when 'verbose' is non-zero.
20513 */
20514 void
20515last_set_msg(scriptID)
20516 scid_T scriptID;
20517{
Bram Moolenaarcafda4f2005-09-06 19:25:11 +000020518 char_u *p;
20519
Bram Moolenaar661b1822005-07-28 22:36:45 +000020520 if (scriptID != 0)
20521 {
Bram Moolenaarcafda4f2005-09-06 19:25:11 +000020522 p = home_replace_save(NULL, get_scriptname(scriptID));
20523 if (p != NULL)
20524 {
20525 verbose_enter();
20526 MSG_PUTS(_("\n\tLast set from "));
20527 MSG_PUTS(p);
20528 vim_free(p);
20529 verbose_leave();
20530 }
Bram Moolenaar661b1822005-07-28 22:36:45 +000020531 }
20532}
20533
Bram Moolenaar071d4272004-06-13 20:20:40 +000020534#endif /* FEAT_EVAL */
20535
20536#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
20537
20538
20539#ifdef WIN3264
20540/*
20541 * Functions for ":8" filename modifier: get 8.3 version of a filename.
20542 */
20543static int get_short_pathname __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
20544static int shortpath_for_invalid_fname __ARGS((char_u **fname, char_u **bufp, int *fnamelen));
20545static int shortpath_for_partial __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
20546
20547/*
20548 * Get the short pathname of a file.
20549 * Returns 1 on success. *fnamelen is 0 for nonexistant path.
20550 */
20551 static int
20552get_short_pathname(fnamep, bufp, fnamelen)
20553 char_u **fnamep;
20554 char_u **bufp;
20555 int *fnamelen;
20556{
20557 int l,len;
20558 char_u *newbuf;
20559
20560 len = *fnamelen;
20561
20562 l = GetShortPathName(*fnamep, *fnamep, len);
20563 if (l > len - 1)
20564 {
20565 /* If that doesn't work (not enough space), then save the string
20566 * and try again with a new buffer big enough
20567 */
20568 newbuf = vim_strnsave(*fnamep, l);
20569 if (newbuf == NULL)
20570 return 0;
20571
20572 vim_free(*bufp);
20573 *fnamep = *bufp = newbuf;
20574
20575 l = GetShortPathName(*fnamep,*fnamep,l+1);
20576
20577 /* Really should always succeed, as the buffer is big enough */
20578 }
20579
20580 *fnamelen = l;
20581 return 1;
20582}
20583
20584/*
20585 * Create a short path name. Returns the length of the buffer it needs.
20586 * Doesn't copy over the end of the buffer passed in.
20587 */
20588 static int
20589shortpath_for_invalid_fname(fname, bufp, fnamelen)
20590 char_u **fname;
20591 char_u **bufp;
20592 int *fnamelen;
20593{
20594 char_u *s, *p, *pbuf2, *pbuf3;
20595 char_u ch;
Bram Moolenaar75c50c42005-06-04 22:06:24 +000020596 int len, len2, plen, slen;
Bram Moolenaar071d4272004-06-13 20:20:40 +000020597
20598 /* Make a copy */
20599 len2 = *fnamelen;
20600 pbuf2 = vim_strnsave(*fname, len2);
20601 pbuf3 = NULL;
20602
20603 s = pbuf2 + len2 - 1; /* Find the end */
20604 slen = 1;
20605 plen = len2;
20606
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000020607 if (after_pathsep(pbuf2, s + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +000020608 {
20609 --s;
20610 ++slen;
20611 --plen;
20612 }
20613
20614 do
20615 {
20616 /* Go back one path-seperator */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000020617 while (s > pbuf2 && !after_pathsep(pbuf2, s + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +000020618 {
20619 --s;
20620 ++slen;
20621 --plen;
20622 }
20623 if (s <= pbuf2)
20624 break;
20625
20626 /* Remeber the character that is about to be blatted */
20627 ch = *s;
20628 *s = 0; /* get_short_pathname requires a null-terminated string */
20629
20630 /* Try it in situ */
20631 p = pbuf2;
20632 if (!get_short_pathname(&p, &pbuf3, &plen))
20633 {
20634 vim_free(pbuf2);
20635 return -1;
20636 }
20637 *s = ch; /* Preserve the string */
20638 } while (plen == 0);
20639
20640 if (plen > 0)
20641 {
20642 /* Remeber the length of the new string. */
20643 *fnamelen = len = plen + slen;
20644 vim_free(*bufp);
20645 if (len > len2)
20646 {
20647 /* If there's not enough space in the currently allocated string,
20648 * then copy it to a buffer big enough.
20649 */
20650 *fname= *bufp = vim_strnsave(p, len);
20651 if (*fname == NULL)
20652 return -1;
20653 }
20654 else
20655 {
20656 /* Transfer pbuf2 to being the main buffer (it's big enough) */
20657 *fname = *bufp = pbuf2;
20658 if (p != pbuf2)
20659 strncpy(*fname, p, plen);
20660 pbuf2 = NULL;
20661 }
20662 /* Concat the next bit */
20663 strncpy(*fname + plen, s, slen);
20664 (*fname)[len] = '\0';
20665 }
20666 vim_free(pbuf3);
20667 vim_free(pbuf2);
20668 return 0;
20669}
20670
20671/*
20672 * Get a pathname for a partial path.
20673 */
20674 static int
20675shortpath_for_partial(fnamep, bufp, fnamelen)
20676 char_u **fnamep;
20677 char_u **bufp;
20678 int *fnamelen;
20679{
20680 int sepcount, len, tflen;
20681 char_u *p;
20682 char_u *pbuf, *tfname;
20683 int hasTilde;
20684
20685 /* Count up the path seperators from the RHS.. so we know which part
20686 * of the path to return.
20687 */
20688 sepcount = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000020689 for (p = *fnamep; p < *fnamep + *fnamelen; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000020690 if (vim_ispathsep(*p))
20691 ++sepcount;
20692
20693 /* Need full path first (use expand_env() to remove a "~/") */
20694 hasTilde = (**fnamep == '~');
20695 if (hasTilde)
20696 pbuf = tfname = expand_env_save(*fnamep);
20697 else
20698 pbuf = tfname = FullName_save(*fnamep, FALSE);
20699
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000020700 len = tflen = (int)STRLEN(tfname);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020701
20702 if (!get_short_pathname(&tfname, &pbuf, &len))
20703 return -1;
20704
20705 if (len == 0)
20706 {
20707 /* Don't have a valid filename, so shorten the rest of the
20708 * path if we can. This CAN give us invalid 8.3 filenames, but
20709 * there's not a lot of point in guessing what it might be.
20710 */
20711 len = tflen;
20712 if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == -1)
20713 return -1;
20714 }
20715
20716 /* Count the paths backward to find the beginning of the desired string. */
20717 for (p = tfname + len - 1; p >= tfname; --p)
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000020718 {
20719#ifdef FEAT_MBYTE
20720 if (has_mbyte)
20721 p -= mb_head_off(tfname, p);
20722#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000020723 if (vim_ispathsep(*p))
20724 {
20725 if (sepcount == 0 || (hasTilde && sepcount == 1))
20726 break;
20727 else
20728 sepcount --;
20729 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000020730 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000020731 if (hasTilde)
20732 {
20733 --p;
20734 if (p >= tfname)
20735 *p = '~';
20736 else
20737 return -1;
20738 }
20739 else
20740 ++p;
20741
20742 /* Copy in the string - p indexes into tfname - allocated at pbuf */
20743 vim_free(*bufp);
20744 *fnamelen = (int)STRLEN(p);
20745 *bufp = pbuf;
20746 *fnamep = p;
20747
20748 return 0;
20749}
20750#endif /* WIN3264 */
20751
20752/*
20753 * Adjust a filename, according to a string of modifiers.
20754 * *fnamep must be NUL terminated when called. When returning, the length is
20755 * determined by *fnamelen.
20756 * Returns valid flags.
20757 * When there is an error, *fnamep is set to NULL.
20758 */
20759 int
20760modify_fname(src, usedlen, fnamep, bufp, fnamelen)
20761 char_u *src; /* string with modifiers */
20762 int *usedlen; /* characters after src that are used */
20763 char_u **fnamep; /* file name so far */
20764 char_u **bufp; /* buffer for allocated file name or NULL */
20765 int *fnamelen; /* length of fnamep */
20766{
20767 int valid = 0;
20768 char_u *tail;
20769 char_u *s, *p, *pbuf;
20770 char_u dirname[MAXPATHL];
20771 int c;
20772 int has_fullname = 0;
20773#ifdef WIN3264
20774 int has_shortname = 0;
20775#endif
20776
20777repeat:
20778 /* ":p" - full path/file_name */
20779 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p')
20780 {
20781 has_fullname = 1;
20782
20783 valid |= VALID_PATH;
20784 *usedlen += 2;
20785
20786 /* Expand "~/path" for all systems and "~user/path" for Unix and VMS */
20787 if ((*fnamep)[0] == '~'
20788#if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME))
20789 && ((*fnamep)[1] == '/'
20790# ifdef BACKSLASH_IN_FILENAME
20791 || (*fnamep)[1] == '\\'
20792# endif
20793 || (*fnamep)[1] == NUL)
20794
20795#endif
20796 )
20797 {
20798 *fnamep = expand_env_save(*fnamep);
20799 vim_free(*bufp); /* free any allocated file name */
20800 *bufp = *fnamep;
20801 if (*fnamep == NULL)
20802 return -1;
20803 }
20804
20805 /* When "/." or "/.." is used: force expansion to get rid of it. */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000020806 for (p = *fnamep; *p != NUL; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000020807 {
20808 if (vim_ispathsep(*p)
20809 && p[1] == '.'
20810 && (p[2] == NUL
20811 || vim_ispathsep(p[2])
20812 || (p[2] == '.'
20813 && (p[3] == NUL || vim_ispathsep(p[3])))))
20814 break;
20815 }
20816
20817 /* FullName_save() is slow, don't use it when not needed. */
20818 if (*p != NUL || !vim_isAbsName(*fnamep))
20819 {
20820 *fnamep = FullName_save(*fnamep, *p != NUL);
20821 vim_free(*bufp); /* free any allocated file name */
20822 *bufp = *fnamep;
20823 if (*fnamep == NULL)
20824 return -1;
20825 }
20826
20827 /* Append a path separator to a directory. */
20828 if (mch_isdir(*fnamep))
20829 {
20830 /* Make room for one or two extra characters. */
20831 *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2);
20832 vim_free(*bufp); /* free any allocated file name */
20833 *bufp = *fnamep;
20834 if (*fnamep == NULL)
20835 return -1;
20836 add_pathsep(*fnamep);
20837 }
20838 }
20839
20840 /* ":." - path relative to the current directory */
20841 /* ":~" - path relative to the home directory */
20842 /* ":8" - shortname path - postponed till after */
20843 while (src[*usedlen] == ':'
20844 && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8'))
20845 {
20846 *usedlen += 2;
20847 if (c == '8')
20848 {
20849#ifdef WIN3264
20850 has_shortname = 1; /* Postpone this. */
20851#endif
20852 continue;
20853 }
20854 pbuf = NULL;
20855 /* Need full path first (use expand_env() to remove a "~/") */
20856 if (!has_fullname)
20857 {
20858 if (c == '.' && **fnamep == '~')
20859 p = pbuf = expand_env_save(*fnamep);
20860 else
20861 p = pbuf = FullName_save(*fnamep, FALSE);
20862 }
20863 else
20864 p = *fnamep;
20865
20866 has_fullname = 0;
20867
20868 if (p != NULL)
20869 {
20870 if (c == '.')
20871 {
20872 mch_dirname(dirname, MAXPATHL);
20873 s = shorten_fname(p, dirname);
20874 if (s != NULL)
20875 {
20876 *fnamep = s;
20877 if (pbuf != NULL)
20878 {
20879 vim_free(*bufp); /* free any allocated file name */
20880 *bufp = pbuf;
20881 pbuf = NULL;
20882 }
20883 }
20884 }
20885 else
20886 {
20887 home_replace(NULL, p, dirname, MAXPATHL, TRUE);
20888 /* Only replace it when it starts with '~' */
20889 if (*dirname == '~')
20890 {
20891 s = vim_strsave(dirname);
20892 if (s != NULL)
20893 {
20894 *fnamep = s;
20895 vim_free(*bufp);
20896 *bufp = s;
20897 }
20898 }
20899 }
20900 vim_free(pbuf);
20901 }
20902 }
20903
20904 tail = gettail(*fnamep);
20905 *fnamelen = (int)STRLEN(*fnamep);
20906
20907 /* ":h" - head, remove "/file_name", can be repeated */
20908 /* Don't remove the first "/" or "c:\" */
20909 while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h')
20910 {
20911 valid |= VALID_HEAD;
20912 *usedlen += 2;
20913 s = get_past_head(*fnamep);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000020914 while (tail > s && after_pathsep(s, tail))
Bram Moolenaar071d4272004-06-13 20:20:40 +000020915 --tail;
20916 *fnamelen = (int)(tail - *fnamep);
20917#ifdef VMS
20918 if (*fnamelen > 0)
20919 *fnamelen += 1; /* the path separator is part of the path */
20920#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000020921 while (tail > s && !after_pathsep(s, tail))
20922 mb_ptr_back(*fnamep, tail);
Bram Moolenaar071d4272004-06-13 20:20:40 +000020923 }
20924
20925 /* ":8" - shortname */
20926 if (src[*usedlen] == ':' && src[*usedlen + 1] == '8')
20927 {
20928 *usedlen += 2;
20929#ifdef WIN3264
20930 has_shortname = 1;
20931#endif
20932 }
20933
20934#ifdef WIN3264
20935 /* Check shortname after we have done 'heads' and before we do 'tails'
20936 */
20937 if (has_shortname)
20938 {
20939 pbuf = NULL;
20940 /* Copy the string if it is shortened by :h */
20941 if (*fnamelen < (int)STRLEN(*fnamep))
20942 {
20943 p = vim_strnsave(*fnamep, *fnamelen);
20944 if (p == 0)
20945 return -1;
20946 vim_free(*bufp);
20947 *bufp = *fnamep = p;
20948 }
20949
20950 /* Split into two implementations - makes it easier. First is where
20951 * there isn't a full name already, second is where there is.
20952 */
20953 if (!has_fullname && !vim_isAbsName(*fnamep))
20954 {
20955 if (shortpath_for_partial(fnamep, bufp, fnamelen) == -1)
20956 return -1;
20957 }
20958 else
20959 {
20960 int l;
20961
20962 /* Simple case, already have the full-name
20963 * Nearly always shorter, so try first time. */
20964 l = *fnamelen;
20965 if (!get_short_pathname(fnamep, bufp, &l))
20966 return -1;
20967
20968 if (l == 0)
20969 {
20970 /* Couldn't find the filename.. search the paths.
20971 */
20972 l = *fnamelen;
20973 if (shortpath_for_invalid_fname(fnamep, bufp, &l ) == -1)
20974 return -1;
20975 }
20976 *fnamelen = l;
20977 }
20978 }
20979#endif /* WIN3264 */
20980
20981 /* ":t" - tail, just the basename */
20982 if (src[*usedlen] == ':' && src[*usedlen + 1] == 't')
20983 {
20984 *usedlen += 2;
20985 *fnamelen -= (int)(tail - *fnamep);
20986 *fnamep = tail;
20987 }
20988
20989 /* ":e" - extension, can be repeated */
20990 /* ":r" - root, without extension, can be repeated */
20991 while (src[*usedlen] == ':'
20992 && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r'))
20993 {
20994 /* find a '.' in the tail:
20995 * - for second :e: before the current fname
20996 * - otherwise: The last '.'
20997 */
20998 if (src[*usedlen + 1] == 'e' && *fnamep > tail)
20999 s = *fnamep - 2;
21000 else
21001 s = *fnamep + *fnamelen - 1;
21002 for ( ; s > tail; --s)
21003 if (s[0] == '.')
21004 break;
21005 if (src[*usedlen + 1] == 'e') /* :e */
21006 {
21007 if (s > tail)
21008 {
21009 *fnamelen += (int)(*fnamep - (s + 1));
21010 *fnamep = s + 1;
21011#ifdef VMS
21012 /* cut version from the extension */
21013 s = *fnamep + *fnamelen - 1;
21014 for ( ; s > *fnamep; --s)
21015 if (s[0] == ';')
21016 break;
21017 if (s > *fnamep)
21018 *fnamelen = s - *fnamep;
21019#endif
21020 }
21021 else if (*fnamep <= tail)
21022 *fnamelen = 0;
21023 }
21024 else /* :r */
21025 {
21026 if (s > tail) /* remove one extension */
21027 *fnamelen = (int)(s - *fnamep);
21028 }
21029 *usedlen += 2;
21030 }
21031
21032 /* ":s?pat?foo?" - substitute */
21033 /* ":gs?pat?foo?" - global substitute */
21034 if (src[*usedlen] == ':'
21035 && (src[*usedlen + 1] == 's'
21036 || (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's')))
21037 {
21038 char_u *str;
21039 char_u *pat;
21040 char_u *sub;
21041 int sep;
21042 char_u *flags;
21043 int didit = FALSE;
21044
21045 flags = (char_u *)"";
21046 s = src + *usedlen + 2;
21047 if (src[*usedlen + 1] == 'g')
21048 {
21049 flags = (char_u *)"g";
21050 ++s;
21051 }
21052
21053 sep = *s++;
21054 if (sep)
21055 {
21056 /* find end of pattern */
21057 p = vim_strchr(s, sep);
21058 if (p != NULL)
21059 {
21060 pat = vim_strnsave(s, (int)(p - s));
21061 if (pat != NULL)
21062 {
21063 s = p + 1;
21064 /* find end of substitution */
21065 p = vim_strchr(s, sep);
21066 if (p != NULL)
21067 {
21068 sub = vim_strnsave(s, (int)(p - s));
21069 str = vim_strnsave(*fnamep, *fnamelen);
21070 if (sub != NULL && str != NULL)
21071 {
21072 *usedlen = (int)(p + 1 - src);
21073 s = do_string_sub(str, pat, sub, flags);
21074 if (s != NULL)
21075 {
21076 *fnamep = s;
21077 *fnamelen = (int)STRLEN(s);
21078 vim_free(*bufp);
21079 *bufp = s;
21080 didit = TRUE;
21081 }
21082 }
21083 vim_free(sub);
21084 vim_free(str);
21085 }
21086 vim_free(pat);
21087 }
21088 }
21089 /* after using ":s", repeat all the modifiers */
21090 if (didit)
21091 goto repeat;
21092 }
21093 }
21094
21095 return valid;
21096}
21097
21098/*
21099 * Perform a substitution on "str" with pattern "pat" and substitute "sub".
21100 * "flags" can be "g" to do a global substitute.
21101 * Returns an allocated string, NULL for error.
21102 */
21103 char_u *
21104do_string_sub(str, pat, sub, flags)
21105 char_u *str;
21106 char_u *pat;
21107 char_u *sub;
21108 char_u *flags;
21109{
21110 int sublen;
21111 regmatch_T regmatch;
21112 int i;
21113 int do_all;
21114 char_u *tail;
21115 garray_T ga;
21116 char_u *ret;
21117 char_u *save_cpo;
21118
21119 /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */
21120 save_cpo = p_cpo;
21121 p_cpo = (char_u *)"";
21122
21123 ga_init2(&ga, 1, 200);
21124
21125 do_all = (flags[0] == 'g');
21126
21127 regmatch.rm_ic = p_ic;
21128 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
21129 if (regmatch.regprog != NULL)
21130 {
21131 tail = str;
21132 while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
21133 {
21134 /*
21135 * Get some space for a temporary buffer to do the substitution
21136 * into. It will contain:
21137 * - The text up to where the match is.
21138 * - The substituted text.
21139 * - The text after the match.
21140 */
21141 sublen = vim_regsub(&regmatch, sub, tail, FALSE, TRUE, FALSE);
21142 if (ga_grow(&ga, (int)(STRLEN(tail) + sublen -
21143 (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
21144 {
21145 ga_clear(&ga);
21146 break;
21147 }
21148
21149 /* copy the text up to where the match is */
21150 i = (int)(regmatch.startp[0] - tail);
21151 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
21152 /* add the substituted text */
21153 (void)vim_regsub(&regmatch, sub, (char_u *)ga.ga_data
21154 + ga.ga_len + i, TRUE, TRUE, FALSE);
21155 ga.ga_len += i + sublen - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021156 /* avoid getting stuck on a match with an empty string */
21157 if (tail == regmatch.endp[0])
21158 {
21159 if (*tail == NUL)
21160 break;
21161 *((char_u *)ga.ga_data + ga.ga_len) = *tail++;
21162 ++ga.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000021163 }
21164 else
21165 {
21166 tail = regmatch.endp[0];
21167 if (*tail == NUL)
21168 break;
21169 }
21170 if (!do_all)
21171 break;
21172 }
21173
21174 if (ga.ga_data != NULL)
21175 STRCPY((char *)ga.ga_data + ga.ga_len, tail);
21176
21177 vim_free(regmatch.regprog);
21178 }
21179
21180 ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data);
21181 ga_clear(&ga);
21182 p_cpo = save_cpo;
21183
21184 return ret;
21185}
21186
21187#endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */