blob: 0e9a2ba17934b327afcbccd8e91af865d6aa302b [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)
14# include <io.h> /* for mch_open(), must be before vim.h */
15#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 Moolenaar9a50b1b2005-06-27 22:48:21 +0000201/* list heads for garbage collection */
202static dict_T *first_dict = NULL; /* list of all dicts */
203static list_T *first_list = NULL; /* list of all lists */
204
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000205/* From user function to hashitem and back. */
206static ufunc_T dumuf;
207#define UF2HIKEY(fp) ((fp)->uf_name)
208#define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf)))
209#define HI2UF(hi) HIKEY2UF((hi)->hi_key)
210
211#define FUNCARG(fp, j) ((char_u **)(fp->uf_args.ga_data))[j]
212#define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j]
Bram Moolenaar071d4272004-06-13 20:20:40 +0000213
Bram Moolenaar33570922005-01-25 22:26:29 +0000214#define MAX_FUNC_ARGS 20 /* maximum number of function arguments */
215#define VAR_SHORT_LEN 20 /* short variable name length */
216#define FIXVAR_CNT 12 /* number of fixed variables */
217
Bram Moolenaar071d4272004-06-13 20:20:40 +0000218/* structure to hold info for a function that is currently being executed. */
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000219typedef struct funccall_S funccall_T;
220
221struct funccall_S
Bram Moolenaar071d4272004-06-13 20:20:40 +0000222{
223 ufunc_T *func; /* function being called */
224 int linenr; /* next line to be executed */
225 int returned; /* ":return" used */
Bram Moolenaar33570922005-01-25 22:26:29 +0000226 struct /* fixed variables for arguments */
227 {
228 dictitem_T var; /* variable (without room for name) */
229 char_u room[VAR_SHORT_LEN]; /* room for the name */
230 } fixvar[FIXVAR_CNT];
231 dict_T l_vars; /* l: local function variables */
232 dictitem_T l_vars_var; /* variable for l: scope */
233 dict_T l_avars; /* a: argument variables */
234 dictitem_T l_avars_var; /* variable for a: scope */
235 list_T l_varlist; /* list for a:000 */
236 listitem_T l_listitems[MAX_FUNC_ARGS]; /* listitems for a:000 */
237 typval_T *rettv; /* return value */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000238 linenr_T breakpoint; /* next line with breakpoint or zero */
239 int dbg_tick; /* debug_tick when breakpoint was set */
240 int level; /* top nesting level of executed function */
Bram Moolenaar05159a02005-02-26 23:04:13 +0000241#ifdef FEAT_PROFILE
242 proftime_T prof_child; /* time spent in a child */
243#endif
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000244 funccall_T *caller; /* calling function or NULL */
245};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000246
247/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000248 * Info used by a ":for" loop.
249 */
Bram Moolenaar33570922005-01-25 22:26:29 +0000250typedef struct
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000251{
252 int fi_semicolon; /* TRUE if ending in '; var]' */
253 int fi_varcount; /* nr of variables in the list */
Bram Moolenaar33570922005-01-25 22:26:29 +0000254 listwatch_T fi_lw; /* keep an eye on the item used. */
255 list_T *fi_list; /* list being used */
256} forinfo_T;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000257
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000258/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000259 * Struct used by trans_function_name()
260 */
261typedef struct
262{
Bram Moolenaar33570922005-01-25 22:26:29 +0000263 dict_T *fd_dict; /* Dictionary used */
Bram Moolenaar532c7802005-01-27 14:44:31 +0000264 char_u *fd_newkey; /* new key in "dict" in allocated memory */
Bram Moolenaar33570922005-01-25 22:26:29 +0000265 dictitem_T *fd_di; /* Dictionary item used */
266} funcdict_T;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000267
Bram Moolenaara7043832005-01-21 11:56:39 +0000268
269/*
Bram Moolenaar33570922005-01-25 22:26:29 +0000270 * Array to hold the value of v: variables.
271 * The value is in a dictitem, so that it can also be used in the v: scope.
272 * The reason to use this table anyway is for very quick access to the
273 * variables with the VV_ defines.
274 */
275#include "version.h"
276
277/* values for vv_flags: */
278#define VV_COMPAT 1 /* compatible, also used without "v:" */
279#define VV_RO 2 /* read-only */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000280#define VV_RO_SBX 4 /* read-only in the sandbox */
Bram Moolenaar33570922005-01-25 22:26:29 +0000281
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +0000282#define VV_NAME(s, t) s, {{t}}, {0}
Bram Moolenaar33570922005-01-25 22:26:29 +0000283
284static struct vimvar
285{
286 char *vv_name; /* name of variable, without v: */
Bram Moolenaar33570922005-01-25 22:26:29 +0000287 dictitem_T vv_di; /* value and name for key */
288 char vv_filler[16]; /* space for LONGEST name below!!! */
289 char vv_flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */
290} vimvars[VV_LEN] =
291{
292 /*
293 * The order here must match the VV_ defines in vim.h!
294 * Initializing a union does not work, leave tv.vval empty to get zero's.
295 */
296 {VV_NAME("count", VAR_NUMBER), VV_COMPAT+VV_RO},
297 {VV_NAME("count1", VAR_NUMBER), VV_RO},
298 {VV_NAME("prevcount", VAR_NUMBER), VV_RO},
299 {VV_NAME("errmsg", VAR_STRING), VV_COMPAT},
300 {VV_NAME("warningmsg", VAR_STRING), 0},
301 {VV_NAME("statusmsg", VAR_STRING), 0},
302 {VV_NAME("shell_error", VAR_NUMBER), VV_COMPAT+VV_RO},
303 {VV_NAME("this_session", VAR_STRING), VV_COMPAT},
304 {VV_NAME("version", VAR_NUMBER), VV_COMPAT+VV_RO},
305 {VV_NAME("lnum", VAR_NUMBER), VV_RO_SBX},
306 {VV_NAME("termresponse", VAR_STRING), VV_RO},
307 {VV_NAME("fname", VAR_STRING), VV_RO},
308 {VV_NAME("lang", VAR_STRING), VV_RO},
309 {VV_NAME("lc_time", VAR_STRING), VV_RO},
310 {VV_NAME("ctype", VAR_STRING), VV_RO},
311 {VV_NAME("charconvert_from", VAR_STRING), VV_RO},
312 {VV_NAME("charconvert_to", VAR_STRING), VV_RO},
313 {VV_NAME("fname_in", VAR_STRING), VV_RO},
314 {VV_NAME("fname_out", VAR_STRING), VV_RO},
315 {VV_NAME("fname_new", VAR_STRING), VV_RO},
316 {VV_NAME("fname_diff", VAR_STRING), VV_RO},
317 {VV_NAME("cmdarg", VAR_STRING), VV_RO},
318 {VV_NAME("foldstart", VAR_NUMBER), VV_RO_SBX},
319 {VV_NAME("foldend", VAR_NUMBER), VV_RO_SBX},
320 {VV_NAME("folddashes", VAR_STRING), VV_RO_SBX},
321 {VV_NAME("foldlevel", VAR_NUMBER), VV_RO_SBX},
322 {VV_NAME("progname", VAR_STRING), VV_RO},
323 {VV_NAME("servername", VAR_STRING), VV_RO},
324 {VV_NAME("dying", VAR_NUMBER), VV_RO},
325 {VV_NAME("exception", VAR_STRING), VV_RO},
326 {VV_NAME("throwpoint", VAR_STRING), VV_RO},
327 {VV_NAME("register", VAR_STRING), VV_RO},
328 {VV_NAME("cmdbang", VAR_NUMBER), VV_RO},
329 {VV_NAME("insertmode", VAR_STRING), VV_RO},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000330 {VV_NAME("val", VAR_UNKNOWN), VV_RO},
331 {VV_NAME("key", VAR_UNKNOWN), VV_RO},
Bram Moolenaar05159a02005-02-26 23:04:13 +0000332 {VV_NAME("profiling", VAR_NUMBER), VV_RO},
Bram Moolenaar19a09a12005-03-04 23:39:37 +0000333 {VV_NAME("fcs_reason", VAR_STRING), VV_RO},
334 {VV_NAME("fcs_choice", VAR_STRING), 0},
Bram Moolenaare2ac10d2005-03-07 23:26:06 +0000335 {VV_NAME("beval_bufnr", VAR_NUMBER), VV_RO},
336 {VV_NAME("beval_winnr", VAR_NUMBER), VV_RO},
337 {VV_NAME("beval_lnum", VAR_NUMBER), VV_RO},
338 {VV_NAME("beval_col", VAR_NUMBER), VV_RO},
339 {VV_NAME("beval_text", VAR_STRING), VV_RO},
Bram Moolenaar33570922005-01-25 22:26:29 +0000340};
341
342/* shorthand */
343#define vv_type vv_di.di_tv.v_type
344#define vv_nr vv_di.di_tv.vval.v_number
345#define vv_str vv_di.di_tv.vval.v_string
346#define vv_tv vv_di.di_tv
347
348/*
349 * The v: variables are stored in dictionary "vimvardict".
350 * "vimvars_var" is the variable that is used for the "l:" scope.
351 */
352static dict_T vimvardict;
353static dictitem_T vimvars_var;
354#define vimvarht vimvardict.dv_hashtab
355
356static int eval0 __ARGS((char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate));
357static int eval1 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
358static int eval2 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
359static int eval3 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
360static int eval4 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
361static int eval5 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
362static int eval6 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
363static int eval7 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000364static int eval_index __ARGS((char_u **arg, typval_T *rettv, int evaluate, int verbose));
Bram Moolenaar33570922005-01-25 22:26:29 +0000365static int get_option_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
366static int get_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
367static int get_lit_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
368static int get_list_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
369static list_T *list_alloc __ARGS((void));
370static void list_unref __ARGS((list_T *l));
371static void list_free __ARGS((list_T *l));
372static listitem_T *listitem_alloc __ARGS((void));
373static void listitem_free __ARGS((listitem_T *item));
374static void listitem_remove __ARGS((list_T *l, listitem_T *item));
375static long list_len __ARGS((list_T *l));
376static int list_equal __ARGS((list_T *l1, list_T *l2, int ic));
377static int dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic));
378static int tv_equal __ARGS((typval_T *tv1, typval_T *tv2, int ic));
379static int string_isa_number __ARGS((char_u *s));
380static listitem_T *list_find __ARGS((list_T *l, long n));
381static long list_idx_of_item __ARGS((list_T *l, listitem_T *item));
Bram Moolenaar33570922005-01-25 22:26:29 +0000382static void list_append __ARGS((list_T *l, listitem_T *item));
383static int list_append_tv __ARGS((list_T *l, typval_T *tv));
384static int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item));
385static int list_extend __ARGS((list_T *l1, list_T *l2, listitem_T *bef));
386static int list_concat __ARGS((list_T *l1, list_T *l2, typval_T *tv));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000387static list_T *list_copy __ARGS((list_T *orig, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000388static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));
389static char_u *list2string __ARGS((typval_T *tv));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000390static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo));
Bram Moolenaar33570922005-01-25 22:26:29 +0000391
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000392static void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID));
393static void set_ref_in_list __ARGS((list_T *l, int copyID));
394static void set_ref_in_item __ARGS((typval_T *tv, int copyID));
Bram Moolenaard9fba312005-06-26 22:34:35 +0000395
Bram Moolenaar33570922005-01-25 22:26:29 +0000396static void dict_unref __ARGS((dict_T *d));
397static void dict_free __ARGS((dict_T *d));
398static dictitem_T *dictitem_alloc __ARGS((char_u *key));
399static dictitem_T *dictitem_copy __ARGS((dictitem_T *org));
400static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item));
401static void dictitem_free __ARGS((dictitem_T *item));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000402static dict_T *dict_copy __ARGS((dict_T *orig, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000403static int dict_add __ARGS((dict_T *d, dictitem_T *item));
404static long dict_len __ARGS((dict_T *d));
405static dictitem_T *dict_find __ARGS((dict_T *d, char_u *key, int len));
406static char_u *dict2string __ARGS((typval_T *tv));
407static int get_dict_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
408
409static char_u *echo_string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf));
410static char_u *tv2string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf));
411static char_u *string_quote __ARGS((char_u *str, int function));
412static int get_env_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
413static int find_internal_func __ARGS((char_u *name));
414static char_u *deref_func_name __ARGS((char_u *name, int *lenp));
415static 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));
416static 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 Moolenaar81bf7082005-02-12 14:31:42 +0000417static void emsg_funcname __ARGS((char *msg, char_u *name));
Bram Moolenaar33570922005-01-25 22:26:29 +0000418
419static void f_add __ARGS((typval_T *argvars, typval_T *rettv));
420static void f_append __ARGS((typval_T *argvars, typval_T *rettv));
421static void f_argc __ARGS((typval_T *argvars, typval_T *rettv));
422static void f_argidx __ARGS((typval_T *argvars, typval_T *rettv));
423static void f_argv __ARGS((typval_T *argvars, typval_T *rettv));
424static void f_browse __ARGS((typval_T *argvars, typval_T *rettv));
425static void f_browsedir __ARGS((typval_T *argvars, typval_T *rettv));
426static void f_bufexists __ARGS((typval_T *argvars, typval_T *rettv));
427static void f_buflisted __ARGS((typval_T *argvars, typval_T *rettv));
428static void f_bufloaded __ARGS((typval_T *argvars, typval_T *rettv));
429static void f_bufname __ARGS((typval_T *argvars, typval_T *rettv));
430static void f_bufnr __ARGS((typval_T *argvars, typval_T *rettv));
431static void f_bufwinnr __ARGS((typval_T *argvars, typval_T *rettv));
432static void f_byte2line __ARGS((typval_T *argvars, typval_T *rettv));
433static void f_byteidx __ARGS((typval_T *argvars, typval_T *rettv));
434static void f_call __ARGS((typval_T *argvars, typval_T *rettv));
435static void f_char2nr __ARGS((typval_T *argvars, typval_T *rettv));
436static void f_cindent __ARGS((typval_T *argvars, typval_T *rettv));
437static void f_col __ARGS((typval_T *argvars, typval_T *rettv));
438static void f_confirm __ARGS((typval_T *argvars, typval_T *rettv));
439static void f_copy __ARGS((typval_T *argvars, typval_T *rettv));
440static void f_count __ARGS((typval_T *argvars, typval_T *rettv));
441static void f_cscope_connection __ARGS((typval_T *argvars, typval_T *rettv));
442static void f_cursor __ARGS((typval_T *argsvars, typval_T *rettv));
443static void f_deepcopy __ARGS((typval_T *argvars, typval_T *rettv));
444static void f_delete __ARGS((typval_T *argvars, typval_T *rettv));
445static void f_did_filetype __ARGS((typval_T *argvars, typval_T *rettv));
446static void f_diff_filler __ARGS((typval_T *argvars, typval_T *rettv));
447static void f_diff_hlID __ARGS((typval_T *argvars, typval_T *rettv));
448static void f_empty __ARGS((typval_T *argvars, typval_T *rettv));
449static void f_escape __ARGS((typval_T *argvars, typval_T *rettv));
450static void f_eval __ARGS((typval_T *argvars, typval_T *rettv));
451static void f_eventhandler __ARGS((typval_T *argvars, typval_T *rettv));
452static void f_executable __ARGS((typval_T *argvars, typval_T *rettv));
453static void f_exists __ARGS((typval_T *argvars, typval_T *rettv));
454static void f_expand __ARGS((typval_T *argvars, typval_T *rettv));
455static void f_extend __ARGS((typval_T *argvars, typval_T *rettv));
456static void f_filereadable __ARGS((typval_T *argvars, typval_T *rettv));
457static void f_filewritable __ARGS((typval_T *argvars, typval_T *rettv));
458static void f_filter __ARGS((typval_T *argvars, typval_T *rettv));
459static void f_finddir __ARGS((typval_T *argvars, typval_T *rettv));
460static void f_findfile __ARGS((typval_T *argvars, typval_T *rettv));
461static void f_fnamemodify __ARGS((typval_T *argvars, typval_T *rettv));
462static void f_foldclosed __ARGS((typval_T *argvars, typval_T *rettv));
463static void f_foldclosedend __ARGS((typval_T *argvars, typval_T *rettv));
464static void f_foldlevel __ARGS((typval_T *argvars, typval_T *rettv));
465static void f_foldtext __ARGS((typval_T *argvars, typval_T *rettv));
466static void f_foldtextresult __ARGS((typval_T *argvars, typval_T *rettv));
467static void f_foreground __ARGS((typval_T *argvars, typval_T *rettv));
468static void f_function __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000469static void f_garbagecollect __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000470static void f_get __ARGS((typval_T *argvars, typval_T *rettv));
471static void f_getbufvar __ARGS((typval_T *argvars, typval_T *rettv));
472static void f_getchar __ARGS((typval_T *argvars, typval_T *rettv));
473static void f_getcharmod __ARGS((typval_T *argvars, typval_T *rettv));
474static void f_getcmdline __ARGS((typval_T *argvars, typval_T *rettv));
475static void f_getcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
476static void f_getcwd __ARGS((typval_T *argvars, typval_T *rettv));
477static void f_getfontname __ARGS((typval_T *argvars, typval_T *rettv));
478static void f_getfperm __ARGS((typval_T *argvars, typval_T *rettv));
479static void f_getfsize __ARGS((typval_T *argvars, typval_T *rettv));
480static void f_getftime __ARGS((typval_T *argvars, typval_T *rettv));
481static void f_getftype __ARGS((typval_T *argvars, typval_T *rettv));
482static void f_getline __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2641f772005-03-25 21:58:17 +0000483static void f_getqflist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000484static void f_getreg __ARGS((typval_T *argvars, typval_T *rettv));
485static void f_getregtype __ARGS((typval_T *argvars, typval_T *rettv));
486static void f_getwinposx __ARGS((typval_T *argvars, typval_T *rettv));
487static void f_getwinposy __ARGS((typval_T *argvars, typval_T *rettv));
488static void f_getwinvar __ARGS((typval_T *argvars, typval_T *rettv));
489static void f_glob __ARGS((typval_T *argvars, typval_T *rettv));
490static void f_globpath __ARGS((typval_T *argvars, typval_T *rettv));
491static void f_has __ARGS((typval_T *argvars, typval_T *rettv));
492static void f_has_key __ARGS((typval_T *argvars, typval_T *rettv));
493static void f_hasmapto __ARGS((typval_T *argvars, typval_T *rettv));
494static void f_histadd __ARGS((typval_T *argvars, typval_T *rettv));
495static void f_histdel __ARGS((typval_T *argvars, typval_T *rettv));
496static void f_histget __ARGS((typval_T *argvars, typval_T *rettv));
497static void f_histnr __ARGS((typval_T *argvars, typval_T *rettv));
498static void f_hlID __ARGS((typval_T *argvars, typval_T *rettv));
499static void f_hlexists __ARGS((typval_T *argvars, typval_T *rettv));
500static void f_hostname __ARGS((typval_T *argvars, typval_T *rettv));
501static void f_iconv __ARGS((typval_T *argvars, typval_T *rettv));
502static void f_indent __ARGS((typval_T *argvars, typval_T *rettv));
503static void f_index __ARGS((typval_T *argvars, typval_T *rettv));
504static void f_input __ARGS((typval_T *argvars, typval_T *rettv));
505static void f_inputdialog __ARGS((typval_T *argvars, typval_T *rettv));
506static void f_inputrestore __ARGS((typval_T *argvars, typval_T *rettv));
507static void f_inputsave __ARGS((typval_T *argvars, typval_T *rettv));
508static void f_inputsecret __ARGS((typval_T *argvars, typval_T *rettv));
509static void f_insert __ARGS((typval_T *argvars, typval_T *rettv));
510static void f_isdirectory __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000511static void f_islocked __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000512static void f_items __ARGS((typval_T *argvars, typval_T *rettv));
513static void f_join __ARGS((typval_T *argvars, typval_T *rettv));
514static void f_keys __ARGS((typval_T *argvars, typval_T *rettv));
515static void f_last_buffer_nr __ARGS((typval_T *argvars, typval_T *rettv));
516static void f_len __ARGS((typval_T *argvars, typval_T *rettv));
517static void f_libcall __ARGS((typval_T *argvars, typval_T *rettv));
518static void f_libcallnr __ARGS((typval_T *argvars, typval_T *rettv));
519static void f_line __ARGS((typval_T *argvars, typval_T *rettv));
520static void f_line2byte __ARGS((typval_T *argvars, typval_T *rettv));
521static void f_lispindent __ARGS((typval_T *argvars, typval_T *rettv));
522static void f_localtime __ARGS((typval_T *argvars, typval_T *rettv));
523static void f_map __ARGS((typval_T *argvars, typval_T *rettv));
524static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv));
525static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv));
526static void f_match __ARGS((typval_T *argvars, typval_T *rettv));
527static void f_matchend __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000528static void f_matchlist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000529static void f_matchstr __ARGS((typval_T *argvars, typval_T *rettv));
530static void f_max __ARGS((typval_T *argvars, typval_T *rettv));
531static void f_min __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000532#ifdef vim_mkdir
533static void f_mkdir __ARGS((typval_T *argvars, typval_T *rettv));
534#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000535static void f_mode __ARGS((typval_T *argvars, typval_T *rettv));
536static void f_nextnonblank __ARGS((typval_T *argvars, typval_T *rettv));
537static void f_nr2char __ARGS((typval_T *argvars, typval_T *rettv));
538static void f_prevnonblank __ARGS((typval_T *argvars, typval_T *rettv));
539static void f_range __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000540static void f_readfile __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000541static void f_remote_expr __ARGS((typval_T *argvars, typval_T *rettv));
542static void f_remote_foreground __ARGS((typval_T *argvars, typval_T *rettv));
543static void f_remote_peek __ARGS((typval_T *argvars, typval_T *rettv));
544static void f_remote_read __ARGS((typval_T *argvars, typval_T *rettv));
545static void f_remote_send __ARGS((typval_T *argvars, typval_T *rettv));
546static void f_remove __ARGS((typval_T *argvars, typval_T *rettv));
547static void f_rename __ARGS((typval_T *argvars, typval_T *rettv));
548static void f_repeat __ARGS((typval_T *argvars, typval_T *rettv));
549static void f_resolve __ARGS((typval_T *argvars, typval_T *rettv));
550static void f_reverse __ARGS((typval_T *argvars, typval_T *rettv));
551static void f_search __ARGS((typval_T *argvars, typval_T *rettv));
552static void f_searchpair __ARGS((typval_T *argvars, typval_T *rettv));
553static void f_server2client __ARGS((typval_T *argvars, typval_T *rettv));
554static void f_serverlist __ARGS((typval_T *argvars, typval_T *rettv));
555static void f_setbufvar __ARGS((typval_T *argvars, typval_T *rettv));
556static void f_setcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
557static void f_setline __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2641f772005-03-25 21:58:17 +0000558static void f_setqflist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000559static void f_setreg __ARGS((typval_T *argvars, typval_T *rettv));
560static void f_setwinvar __ARGS((typval_T *argvars, typval_T *rettv));
561static void f_simplify __ARGS((typval_T *argvars, typval_T *rettv));
562static void f_sort __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaard857f0e2005-06-21 22:37:39 +0000563static void f_spellbadword __ARGS((typval_T *argvars, typval_T *rettv));
564static void f_spellsuggest __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000565static void f_split __ARGS((typval_T *argvars, typval_T *rettv));
566#ifdef HAVE_STRFTIME
567static void f_strftime __ARGS((typval_T *argvars, typval_T *rettv));
568#endif
569static void f_stridx __ARGS((typval_T *argvars, typval_T *rettv));
570static void f_string __ARGS((typval_T *argvars, typval_T *rettv));
571static void f_strlen __ARGS((typval_T *argvars, typval_T *rettv));
572static void f_strpart __ARGS((typval_T *argvars, typval_T *rettv));
573static void f_strridx __ARGS((typval_T *argvars, typval_T *rettv));
574static void f_strtrans __ARGS((typval_T *argvars, typval_T *rettv));
575static void f_submatch __ARGS((typval_T *argvars, typval_T *rettv));
576static void f_substitute __ARGS((typval_T *argvars, typval_T *rettv));
577static void f_synID __ARGS((typval_T *argvars, typval_T *rettv));
578static void f_synIDattr __ARGS((typval_T *argvars, typval_T *rettv));
579static void f_synIDtrans __ARGS((typval_T *argvars, typval_T *rettv));
580static void f_system __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar19a09a12005-03-04 23:39:37 +0000581static void f_taglist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000582static void f_tempname __ARGS((typval_T *argvars, typval_T *rettv));
583static void f_tolower __ARGS((typval_T *argvars, typval_T *rettv));
584static void f_toupper __ARGS((typval_T *argvars, typval_T *rettv));
585static void f_tr __ARGS((typval_T *argvars, typval_T *rettv));
586static void f_type __ARGS((typval_T *argvars, typval_T *rettv));
587static void f_values __ARGS((typval_T *argvars, typval_T *rettv));
588static void f_virtcol __ARGS((typval_T *argvars, typval_T *rettv));
589static void f_visualmode __ARGS((typval_T *argvars, typval_T *rettv));
590static void f_winbufnr __ARGS((typval_T *argvars, typval_T *rettv));
591static void f_wincol __ARGS((typval_T *argvars, typval_T *rettv));
592static void f_winheight __ARGS((typval_T *argvars, typval_T *rettv));
593static void f_winline __ARGS((typval_T *argvars, typval_T *rettv));
594static void f_winnr __ARGS((typval_T *argvars, typval_T *rettv));
595static void f_winrestcmd __ARGS((typval_T *argvars, typval_T *rettv));
596static void f_winwidth __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000597static void f_writefile __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000598
599static win_T *find_win_by_nr __ARGS((typval_T *vp));
600static pos_T *var2fpos __ARGS((typval_T *varp, int lnum));
601static int get_env_len __ARGS((char_u **arg));
602static int get_id_len __ARGS((char_u **arg));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000603static int get_name_len __ARGS((char_u **arg, char_u **alias, int evaluate, int verbose));
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000604static char_u *find_name_end __ARGS((char_u *arg, char_u **expr_start, char_u **expr_end, int flags));
605#define FNE_INCL_BR 1 /* find_name_end(): include [] in name */
606#define FNE_CHECK_START 2 /* find_name_end(): check name starts with
607 valid character */
Bram Moolenaar33570922005-01-25 22:26:29 +0000608static int eval_isnamec __ARGS((int c));
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000609static int eval_isnamec1 __ARGS((int c));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000610static int get_var_tv __ARGS((char_u *name, int len, typval_T *rettv, int verbose));
611static int handle_subscript __ARGS((char_u **arg, typval_T *rettv, int evaluate, int verbose));
Bram Moolenaar33570922005-01-25 22:26:29 +0000612static typval_T *alloc_tv __ARGS((void));
613static typval_T *alloc_string_tv __ARGS((char_u *string));
614static void free_tv __ARGS((typval_T *varp));
615static void clear_tv __ARGS((typval_T *varp));
616static void init_tv __ARGS((typval_T *varp));
617static long get_tv_number __ARGS((typval_T *varp));
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +0000618static long get_tv_number_chk __ARGS((typval_T *varp, int *denote));
Bram Moolenaar33570922005-01-25 22:26:29 +0000619static linenr_T get_tv_lnum __ARGS((typval_T *argvars));
620static char_u *get_tv_string __ARGS((typval_T *varp));
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +0000621static char_u *get_tv_string_chk __ARGS((typval_T *varp));
Bram Moolenaar33570922005-01-25 22:26:29 +0000622static char_u *get_tv_string_buf __ARGS((typval_T *varp, char_u *buf));
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +0000623static char_u *get_tv_string_buf_chk __ARGS((typval_T *varp, char_u *buf));
Bram Moolenaar33570922005-01-25 22:26:29 +0000624static dictitem_T *find_var __ARGS((char_u *name, hashtab_T **htp));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000625static dictitem_T *find_var_in_ht __ARGS((hashtab_T *ht, char_u *varname, int writing));
Bram Moolenaar33570922005-01-25 22:26:29 +0000626static hashtab_T *find_var_ht __ARGS((char_u *name, char_u **varname));
627static void vars_clear_ext __ARGS((hashtab_T *ht, int free_val));
628static void delete_var __ARGS((hashtab_T *ht, hashitem_T *hi));
629static void list_one_var __ARGS((dictitem_T *v, char_u *prefix));
630static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string));
631static void set_var __ARGS((char_u *name, typval_T *varp, int copy));
632static int var_check_ro __ARGS((int flags, char_u *name));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000633static int tv_check_lock __ARGS((int lock, char_u *name));
Bram Moolenaar33570922005-01-25 22:26:29 +0000634static void copy_tv __ARGS((typval_T *from, typval_T *to));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000635static int item_copy __ARGS((typval_T *from, typval_T *to, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000636static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags));
637static char_u *trans_function_name __ARGS((char_u **pp, int skip, int flags, funcdict_T *fd));
638static int eval_fname_script __ARGS((char_u *p));
639static int eval_fname_sid __ARGS((char_u *p));
640static void list_func_head __ARGS((ufunc_T *fp, int indent));
641static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp));
642static ufunc_T *find_func __ARGS((char_u *name));
643static int function_exists __ARGS((char_u *name));
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +0000644static int builtin_function __ARGS((char_u *name));
Bram Moolenaar05159a02005-02-26 23:04:13 +0000645#ifdef FEAT_PROFILE
646static void func_do_profile __ARGS((ufunc_T *fp));
Bram Moolenaar73830342005-02-28 22:48:19 +0000647static void prof_sort_list __ARGS((FILE *fd, ufunc_T **sorttab, int st_len, char *title, int prefer_self));
648static void prof_func_line __ARGS((FILE *fd, int count, proftime_T *total, proftime_T *self, int prefer_self));
649static int
650# ifdef __BORLANDC__
651 _RTLENTRYF
652# endif
653 prof_total_cmp __ARGS((const void *s1, const void *s2));
654static int
655# ifdef __BORLANDC__
656 _RTLENTRYF
657# endif
658 prof_self_cmp __ARGS((const void *s1, const void *s2));
Bram Moolenaar05159a02005-02-26 23:04:13 +0000659#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000660static int script_autoload __ARGS((char_u *name));
661static char_u *autoload_name __ARGS((char_u *name));
Bram Moolenaar33570922005-01-25 22:26:29 +0000662static void func_free __ARGS((ufunc_T *fp));
663static void func_unref __ARGS((char_u *name));
664static void func_ref __ARGS((char_u *name));
665static 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));
666static void add_nr_var __ARGS((dict_T *dp, dictitem_T *v, char *name, varnumber_T nr));
667
668static char_u * make_expanded_name __ARGS((char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end));
669
670static int ex_let_vars __ARGS((char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, char_u *nextchars));
671static char_u *skip_var_list __ARGS((char_u *arg, int *var_count, int *semicolon));
672static char_u *skip_var_one __ARGS((char_u *arg));
673static void list_hashtable_vars __ARGS((hashtab_T *ht, char_u *prefix, int empty));
674static void list_glob_vars __ARGS((void));
675static void list_buf_vars __ARGS((void));
676static void list_win_vars __ARGS((void));
677static void list_vim_vars __ARGS((void));
678static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg));
679static char_u *ex_let_one __ARGS((char_u *arg, typval_T *tv, int copy, char_u *endchars, char_u *op));
680static int check_changedtick __ARGS((char_u *arg));
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000681static char_u *get_lval __ARGS((char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int quiet, int fne_flags));
Bram Moolenaar33570922005-01-25 22:26:29 +0000682static void clear_lval __ARGS((lval_T *lp));
683static void set_var_lval __ARGS((lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op));
684static int tv_op __ARGS((typval_T *tv1, typval_T *tv2, char_u *op));
685static void list_add_watch __ARGS((list_T *l, listwatch_T *lw));
686static void list_rem_watch __ARGS((list_T *l, listwatch_T *lwrem));
687static void list_fix_watch __ARGS((list_T *l, listitem_T *item));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000688static void ex_unletlock __ARGS((exarg_T *eap, char_u *argstart, int deep));
Bram Moolenaar33570922005-01-25 22:26:29 +0000689static int do_unlet_var __ARGS((lval_T *lp, char_u *name_end, int forceit));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000690static int do_lock_var __ARGS((lval_T *lp, char_u *name_end, int deep, int lock));
691static void item_lock __ARGS((typval_T *tv, int deep, int lock));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000692static int tv_islocked __ARGS((typval_T *tv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000693
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000694/* Character used as separated in autoload function/variable names. */
695#define AUTOLOAD_CHAR '#'
696
Bram Moolenaar33570922005-01-25 22:26:29 +0000697/*
698 * Initialize the global and v: variables.
Bram Moolenaara7043832005-01-21 11:56:39 +0000699 */
700 void
701eval_init()
702{
Bram Moolenaar33570922005-01-25 22:26:29 +0000703 int i;
704 struct vimvar *p;
705
706 init_var_dict(&globvardict, &globvars_var);
707 init_var_dict(&vimvardict, &vimvars_var);
Bram Moolenaar532c7802005-01-27 14:44:31 +0000708 hash_init(&compat_hashtab);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000709 hash_init(&func_hashtab);
Bram Moolenaar33570922005-01-25 22:26:29 +0000710
711 for (i = 0; i < VV_LEN; ++i)
712 {
713 p = &vimvars[i];
714 STRCPY(p->vv_di.di_key, p->vv_name);
715 if (p->vv_flags & VV_RO)
716 p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
717 else if (p->vv_flags & VV_RO_SBX)
718 p->vv_di.di_flags = DI_FLAGS_RO_SBX | DI_FLAGS_FIX;
719 else
720 p->vv_di.di_flags = DI_FLAGS_FIX;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000721
722 /* add to v: scope dict, unless the value is not always available */
723 if (p->vv_type != VAR_UNKNOWN)
724 hash_add(&vimvarht, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000725 if (p->vv_flags & VV_COMPAT)
Bram Moolenaar532c7802005-01-27 14:44:31 +0000726 /* add to compat scope dict */
727 hash_add(&compat_hashtab, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000728 }
Bram Moolenaara7043832005-01-21 11:56:39 +0000729}
730
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000731#if defined(EXITFREE) || defined(PROTO)
732 void
733eval_clear()
734{
735 int i;
736 struct vimvar *p;
737
738 for (i = 0; i < VV_LEN; ++i)
739 {
740 p = &vimvars[i];
741 if (p->vv_di.di_tv.v_type == VAR_STRING)
Bram Moolenaard9fba312005-06-26 22:34:35 +0000742 {
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000743 vim_free(p->vv_di.di_tv.vval.v_string);
Bram Moolenaard9fba312005-06-26 22:34:35 +0000744 p->vv_di.di_tv.vval.v_string = NULL;
745 }
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000746 }
747 hash_clear(&vimvarht);
748 hash_clear(&compat_hashtab);
749
750 /* script-local variables */
751 for (i = 1; i <= ga_scripts.ga_len; ++i)
752 vars_clear(&SCRIPT_VARS(i));
753 ga_clear(&ga_scripts);
Bram Moolenaard9fba312005-06-26 22:34:35 +0000754 free_scriptnames();
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000755
756 /* global variables */
757 vars_clear(&globvarht);
Bram Moolenaard9fba312005-06-26 22:34:35 +0000758
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000759 /* functions */
Bram Moolenaard9fba312005-06-26 22:34:35 +0000760 free_all_functions();
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000761 hash_clear(&func_hashtab);
762
763 /* unreferenced lists and dicts */
764 (void)garbage_collect();
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000765}
766#endif
767
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000768/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000769 * Return the name of the executed function.
770 */
771 char_u *
772func_name(cookie)
773 void *cookie;
774{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000775 return ((funccall_T *)cookie)->func->uf_name;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000776}
777
778/*
779 * Return the address holding the next breakpoint line for a funccall cookie.
780 */
781 linenr_T *
782func_breakpoint(cookie)
783 void *cookie;
784{
Bram Moolenaar33570922005-01-25 22:26:29 +0000785 return &((funccall_T *)cookie)->breakpoint;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000786}
787
788/*
789 * Return the address holding the debug tick for a funccall cookie.
790 */
791 int *
792func_dbg_tick(cookie)
793 void *cookie;
794{
Bram Moolenaar33570922005-01-25 22:26:29 +0000795 return &((funccall_T *)cookie)->dbg_tick;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000796}
797
798/*
799 * Return the nesting level for a funccall cookie.
800 */
801 int
802func_level(cookie)
803 void *cookie;
804{
Bram Moolenaar33570922005-01-25 22:26:29 +0000805 return ((funccall_T *)cookie)->level;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000806}
807
808/* pointer to funccal for currently active function */
Bram Moolenaar33570922005-01-25 22:26:29 +0000809funccall_T *current_funccal = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000810
811/*
812 * Return TRUE when a function was ended by a ":return" command.
813 */
814 int
815current_func_returned()
816{
817 return current_funccal->returned;
818}
819
820
821/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000822 * Set an internal variable to a string value. Creates the variable if it does
823 * not already exist.
824 */
825 void
826set_internal_string_var(name, value)
827 char_u *name;
828 char_u *value;
829{
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000830 char_u *val;
Bram Moolenaar33570922005-01-25 22:26:29 +0000831 typval_T *tvp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000832
833 val = vim_strsave(value);
834 if (val != NULL)
835 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000836 tvp = alloc_string_tv(val);
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000837 if (tvp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000838 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000839 set_var(name, tvp, FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000840 free_tv(tvp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000841 }
842 }
843}
844
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000845static lval_T *redir_lval = NULL;
846static char_u *redir_endp = NULL;
847static char_u *redir_varname = NULL;
848
849/*
850 * Start recording command output to a variable
851 * Returns OK if successfully completed the setup. FAIL otherwise.
852 */
853 int
854var_redir_start(name, append)
855 char_u *name;
856 int append; /* append to an existing variable */
857{
858 int save_emsg;
859 int err;
860 typval_T tv;
861
862 /* Make sure a valid variable name is specified */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000863 if (!eval_isnamec1(*name))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000864 {
865 EMSG(_(e_invarg));
866 return FAIL;
867 }
868
869 redir_varname = vim_strsave(name);
870 if (redir_varname == NULL)
871 return FAIL;
872
873 redir_lval = (lval_T *)alloc_clear((unsigned)sizeof(lval_T));
874 if (redir_lval == NULL)
875 {
876 var_redir_stop();
877 return FAIL;
878 }
879
880 /* Parse the variable name (can be a dict or list entry). */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000881 redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, FALSE,
882 FNE_CHECK_START);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000883 if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != NUL)
884 {
885 if (redir_endp != NULL && *redir_endp != NUL)
886 /* Trailing characters are present after the variable name */
887 EMSG(_(e_trailing));
888 else
889 EMSG(_(e_invarg));
890 var_redir_stop();
891 return FAIL;
892 }
893
894 /* check if we can write to the variable: set it to or append an empty
895 * string */
896 save_emsg = did_emsg;
897 did_emsg = FALSE;
898 tv.v_type = VAR_STRING;
899 tv.vval.v_string = (char_u *)"";
900 if (append)
901 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)".");
902 else
903 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)"=");
904 err = did_emsg;
905 did_emsg += save_emsg;
906 if (err)
907 {
908 var_redir_stop();
909 return FAIL;
910 }
911 if (redir_lval->ll_newkey != NULL)
912 {
913 /* Dictionary item was created, don't do it again. */
914 vim_free(redir_lval->ll_newkey);
915 redir_lval->ll_newkey = NULL;
916 }
917
918 return OK;
919}
920
921/*
922 * Append "value[len]" to the variable set by var_redir_start().
923 */
924 void
925var_redir_str(value, len)
926 char_u *value;
927 int len;
928{
929 char_u *val;
930 typval_T tv;
931 int save_emsg;
932 int err;
933
934 if (redir_lval == NULL)
935 return;
936
937 if (len == -1)
938 /* Append the entire string */
939 val = vim_strsave(value);
940 else
941 /* Append only the specified number of characters */
942 val = vim_strnsave(value, len);
943 if (val == NULL)
944 return;
945
946 tv.v_type = VAR_STRING;
947 tv.vval.v_string = val;
948
949 save_emsg = did_emsg;
950 did_emsg = FALSE;
951 set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)".");
952 err = did_emsg;
953 did_emsg += save_emsg;
954 if (err)
955 var_redir_stop();
956
957 vim_free(tv.vval.v_string);
958}
959
960/*
961 * Stop redirecting command output to a variable.
962 */
963 void
964var_redir_stop()
965{
966 if (redir_lval != NULL)
967 {
968 clear_lval(redir_lval);
969 vim_free(redir_lval);
970 redir_lval = NULL;
971 }
972 vim_free(redir_varname);
973 redir_varname = NULL;
974}
975
Bram Moolenaar071d4272004-06-13 20:20:40 +0000976# if defined(FEAT_MBYTE) || defined(PROTO)
977 int
978eval_charconvert(enc_from, enc_to, fname_from, fname_to)
979 char_u *enc_from;
980 char_u *enc_to;
981 char_u *fname_from;
982 char_u *fname_to;
983{
984 int err = FALSE;
985
986 set_vim_var_string(VV_CC_FROM, enc_from, -1);
987 set_vim_var_string(VV_CC_TO, enc_to, -1);
988 set_vim_var_string(VV_FNAME_IN, fname_from, -1);
989 set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
990 if (eval_to_bool(p_ccv, &err, NULL, FALSE))
991 err = TRUE;
992 set_vim_var_string(VV_CC_FROM, NULL, -1);
993 set_vim_var_string(VV_CC_TO, NULL, -1);
994 set_vim_var_string(VV_FNAME_IN, NULL, -1);
995 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
996
997 if (err)
998 return FAIL;
999 return OK;
1000}
1001# endif
1002
1003# if defined(FEAT_POSTSCRIPT) || defined(PROTO)
1004 int
1005eval_printexpr(fname, args)
1006 char_u *fname;
1007 char_u *args;
1008{
1009 int err = FALSE;
1010
1011 set_vim_var_string(VV_FNAME_IN, fname, -1);
1012 set_vim_var_string(VV_CMDARG, args, -1);
1013 if (eval_to_bool(p_pexpr, &err, NULL, FALSE))
1014 err = TRUE;
1015 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1016 set_vim_var_string(VV_CMDARG, NULL, -1);
1017
1018 if (err)
1019 {
1020 mch_remove(fname);
1021 return FAIL;
1022 }
1023 return OK;
1024}
1025# endif
1026
1027# if defined(FEAT_DIFF) || defined(PROTO)
1028 void
1029eval_diff(origfile, newfile, outfile)
1030 char_u *origfile;
1031 char_u *newfile;
1032 char_u *outfile;
1033{
1034 int err = FALSE;
1035
1036 set_vim_var_string(VV_FNAME_IN, origfile, -1);
1037 set_vim_var_string(VV_FNAME_NEW, newfile, -1);
1038 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
1039 (void)eval_to_bool(p_dex, &err, NULL, FALSE);
1040 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1041 set_vim_var_string(VV_FNAME_NEW, NULL, -1);
1042 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
1043}
1044
1045 void
1046eval_patch(origfile, difffile, outfile)
1047 char_u *origfile;
1048 char_u *difffile;
1049 char_u *outfile;
1050{
1051 int err;
1052
1053 set_vim_var_string(VV_FNAME_IN, origfile, -1);
1054 set_vim_var_string(VV_FNAME_DIFF, difffile, -1);
1055 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
1056 (void)eval_to_bool(p_pex, &err, NULL, FALSE);
1057 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1058 set_vim_var_string(VV_FNAME_DIFF, NULL, -1);
1059 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
1060}
1061# endif
1062
1063/*
1064 * Top level evaluation function, returning a boolean.
1065 * Sets "error" to TRUE if there was an error.
1066 * Return TRUE or FALSE.
1067 */
1068 int
1069eval_to_bool(arg, error, nextcmd, skip)
1070 char_u *arg;
1071 int *error;
1072 char_u **nextcmd;
1073 int skip; /* only parse, don't execute */
1074{
Bram Moolenaar33570922005-01-25 22:26:29 +00001075 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001076 int retval = FALSE;
1077
1078 if (skip)
1079 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001080 if (eval0(arg, &tv, nextcmd, !skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001081 *error = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001082 else
1083 {
1084 *error = FALSE;
1085 if (!skip)
1086 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001087 retval = (get_tv_number_chk(&tv, error) != 0);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001088 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001089 }
1090 }
1091 if (skip)
1092 --emsg_skip;
1093
1094 return retval;
1095}
1096
1097/*
1098 * Top level evaluation function, returning a string. If "skip" is TRUE,
1099 * only parsing to "nextcmd" is done, without reporting errors. Return
1100 * pointer to allocated memory, or NULL for failure or when "skip" is TRUE.
1101 */
1102 char_u *
1103eval_to_string_skip(arg, nextcmd, skip)
1104 char_u *arg;
1105 char_u **nextcmd;
1106 int skip; /* only parse, don't execute */
1107{
Bram Moolenaar33570922005-01-25 22:26:29 +00001108 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001109 char_u *retval;
1110
1111 if (skip)
1112 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001113 if (eval0(arg, &tv, nextcmd, !skip) == FAIL || skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001114 retval = NULL;
1115 else
1116 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001117 retval = vim_strsave(get_tv_string(&tv));
1118 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001119 }
1120 if (skip)
1121 --emsg_skip;
1122
1123 return retval;
1124}
1125
1126/*
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001127 * Skip over an expression at "*pp".
1128 * Return FAIL for an error, OK otherwise.
1129 */
1130 int
1131skip_expr(pp)
1132 char_u **pp;
1133{
Bram Moolenaar33570922005-01-25 22:26:29 +00001134 typval_T rettv;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001135
1136 *pp = skipwhite(*pp);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001137 return eval1(pp, &rettv, FALSE);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001138}
1139
1140/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00001141 * Top level evaluation function, returning a string.
1142 * Return pointer to allocated memory, or NULL for failure.
1143 */
1144 char_u *
1145eval_to_string(arg, nextcmd)
1146 char_u *arg;
1147 char_u **nextcmd;
1148{
Bram Moolenaar33570922005-01-25 22:26:29 +00001149 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001150 char_u *retval;
1151
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001152 if (eval0(arg, &tv, nextcmd, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001153 retval = NULL;
1154 else
1155 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001156 retval = vim_strsave(get_tv_string(&tv));
1157 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001158 }
1159
1160 return retval;
1161}
1162
1163/*
1164 * Call eval_to_string() with "sandbox" set and not using local variables.
1165 */
1166 char_u *
1167eval_to_string_safe(arg, nextcmd)
1168 char_u *arg;
1169 char_u **nextcmd;
1170{
1171 char_u *retval;
1172 void *save_funccalp;
1173
1174 save_funccalp = save_funccal();
1175 ++sandbox;
1176 retval = eval_to_string(arg, nextcmd);
1177 --sandbox;
1178 restore_funccal(save_funccalp);
1179 return retval;
1180}
1181
Bram Moolenaar071d4272004-06-13 20:20:40 +00001182/*
1183 * Top level evaluation function, returning a number.
1184 * Evaluates "expr" silently.
1185 * Returns -1 for an error.
1186 */
1187 int
1188eval_to_number(expr)
1189 char_u *expr;
1190{
Bram Moolenaar33570922005-01-25 22:26:29 +00001191 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001192 int retval;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00001193 char_u *p = skipwhite(expr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001194
1195 ++emsg_off;
1196
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001197 if (eval1(&p, &rettv, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001198 retval = -1;
1199 else
1200 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001201 retval = get_tv_number_chk(&rettv, NULL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001202 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001203 }
1204 --emsg_off;
1205
1206 return retval;
1207}
1208
1209#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO)
1210/*
1211 * Call some vimL function and return the result as a string
1212 * Uses argv[argc] for the function arguments.
1213 */
1214 char_u *
1215call_vim_function(func, argc, argv, safe)
1216 char_u *func;
1217 int argc;
1218 char_u **argv;
1219 int safe; /* use the sandbox */
1220{
1221 char_u *retval = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00001222 typval_T rettv;
1223 typval_T *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001224 long n;
1225 int len;
1226 int i;
1227 int doesrange;
1228 void *save_funccalp = NULL;
1229
Bram Moolenaar33570922005-01-25 22:26:29 +00001230 argvars = (typval_T *)alloc((unsigned)(argc * sizeof(typval_T)));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001231 if (argvars == NULL)
1232 return NULL;
1233
1234 for (i = 0; i < argc; i++)
1235 {
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00001236 /* Pass a NULL or empty argument as an empty string */
1237 if (argv[i] == NULL || *argv[i] == NUL)
1238 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001239 argvars[i].v_type = VAR_STRING;
1240 argvars[i].vval.v_string = (char_u *)"";
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00001241 continue;
1242 }
1243
Bram Moolenaar071d4272004-06-13 20:20:40 +00001244 /* Recognize a number argument, the others must be strings. */
1245 vim_str2nr(argv[i], NULL, &len, TRUE, TRUE, &n, NULL);
1246 if (len != 0 && len == (int)STRLEN(argv[i]))
1247 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001248 argvars[i].v_type = VAR_NUMBER;
1249 argvars[i].vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001250 }
1251 else
1252 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001253 argvars[i].v_type = VAR_STRING;
1254 argvars[i].vval.v_string = argv[i];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001255 }
1256 }
1257
1258 if (safe)
1259 {
1260 save_funccalp = save_funccal();
1261 ++sandbox;
1262 }
1263
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001264 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
1265 if (call_func(func, (int)STRLEN(func), &rettv, argc, argvars,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001266 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
Bram Moolenaare9a41262005-01-15 22:18:47 +00001267 &doesrange, TRUE, NULL) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001268 retval = vim_strsave(get_tv_string(&rettv));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001269
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001270 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001271 vim_free(argvars);
1272
1273 if (safe)
1274 {
1275 --sandbox;
1276 restore_funccal(save_funccalp);
1277 }
1278 return retval;
1279}
1280#endif
1281
1282/*
1283 * Save the current function call pointer, and set it to NULL.
1284 * Used when executing autocommands and for ":source".
1285 */
1286 void *
1287save_funccal()
1288{
Bram Moolenaar05159a02005-02-26 23:04:13 +00001289 funccall_T *fc = current_funccal;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001290
Bram Moolenaar071d4272004-06-13 20:20:40 +00001291 current_funccal = NULL;
1292 return (void *)fc;
1293}
1294
1295 void
Bram Moolenaar05159a02005-02-26 23:04:13 +00001296restore_funccal(vfc)
1297 void *vfc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001298{
Bram Moolenaar05159a02005-02-26 23:04:13 +00001299 funccall_T *fc = (funccall_T *)vfc;
1300
1301 current_funccal = fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001302}
1303
Bram Moolenaar05159a02005-02-26 23:04:13 +00001304#if defined(FEAT_PROFILE) || defined(PROTO)
1305/*
1306 * Prepare profiling for entering a child or something else that is not
1307 * counted for the script/function itself.
1308 * Should always be called in pair with prof_child_exit().
1309 */
1310 void
1311prof_child_enter(tm)
1312 proftime_T *tm; /* place to store waittime */
1313{
1314 funccall_T *fc = current_funccal;
1315
1316 if (fc != NULL && fc->func->uf_profiling)
1317 profile_start(&fc->prof_child);
1318 script_prof_save(tm);
1319}
1320
1321/*
1322 * Take care of time spent in a child.
1323 * Should always be called after prof_child_enter().
1324 */
1325 void
1326prof_child_exit(tm)
1327 proftime_T *tm; /* where waittime was stored */
1328{
1329 funccall_T *fc = current_funccal;
1330
1331 if (fc != NULL && fc->func->uf_profiling)
1332 {
1333 profile_end(&fc->prof_child);
1334 profile_sub_wait(tm, &fc->prof_child); /* don't count waiting time */
1335 profile_add(&fc->func->uf_tm_children, &fc->prof_child);
1336 profile_add(&fc->func->uf_tml_children, &fc->prof_child);
1337 }
1338 script_prof_restore(tm);
1339}
1340#endif
1341
1342
Bram Moolenaar071d4272004-06-13 20:20:40 +00001343#ifdef FEAT_FOLDING
1344/*
1345 * Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding
1346 * it in "*cp". Doesn't give error messages.
1347 */
1348 int
1349eval_foldexpr(arg, cp)
1350 char_u *arg;
1351 int *cp;
1352{
Bram Moolenaar33570922005-01-25 22:26:29 +00001353 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001354 int retval;
1355 char_u *s;
1356
1357 ++emsg_off;
1358 ++sandbox;
1359 *cp = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001360 if (eval0(arg, &tv, NULL, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001361 retval = 0;
1362 else
1363 {
1364 /* If the result is a number, just return the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001365 if (tv.v_type == VAR_NUMBER)
1366 retval = tv.vval.v_number;
Bram Moolenaar758711c2005-02-02 23:11:38 +00001367 else if (tv.v_type != VAR_STRING || tv.vval.v_string == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001368 retval = 0;
1369 else
1370 {
1371 /* If the result is a string, check if there is a non-digit before
1372 * the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001373 s = tv.vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001374 if (!VIM_ISDIGIT(*s) && *s != '-')
1375 *cp = *s++;
1376 retval = atol((char *)s);
1377 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001378 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001379 }
1380 --emsg_off;
1381 --sandbox;
1382
1383 return retval;
1384}
1385#endif
1386
Bram Moolenaar071d4272004-06-13 20:20:40 +00001387/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001388 * ":let" list all variable values
1389 * ":let var1 var2" list variable values
1390 * ":let var = expr" assignment command.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001391 * ":let var += expr" assignment command.
1392 * ":let var -= expr" assignment command.
1393 * ":let var .= expr" assignment command.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001394 * ":let [var1, var2] = expr" unpack list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001395 */
1396 void
1397ex_let(eap)
1398 exarg_T *eap;
1399{
1400 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001401 char_u *expr = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00001402 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001403 int i;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001404 int var_count = 0;
1405 int semicolon = 0;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001406 char_u op[2];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001407
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001408 expr = skip_var_list(arg, &var_count, &semicolon);
1409 if (expr == NULL)
1410 return;
1411 expr = vim_strchr(expr, '=');
1412 if (expr == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001413 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001414 /*
1415 * ":let" without "=": list variables
1416 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001417 if (*arg == '[')
1418 EMSG(_(e_invarg));
1419 else if (!ends_excmd(*arg))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001420 /* ":let var1 var2" */
1421 arg = list_arg_vars(eap, arg);
1422 else if (!eap->skip)
Bram Moolenaara7043832005-01-21 11:56:39 +00001423 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001424 /* ":let" */
Bram Moolenaara7043832005-01-21 11:56:39 +00001425 list_glob_vars();
1426 list_buf_vars();
1427 list_win_vars();
1428 list_vim_vars();
1429 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001430 eap->nextcmd = check_nextcmd(arg);
1431 }
1432 else
1433 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001434 op[0] = '=';
1435 op[1] = NUL;
1436 if (expr > arg)
1437 {
1438 if (vim_strchr((char_u *)"+-.", expr[-1]) != NULL)
1439 op[0] = expr[-1]; /* +=, -= or .= */
1440 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001441 expr = skipwhite(expr + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001442
Bram Moolenaar071d4272004-06-13 20:20:40 +00001443 if (eap->skip)
1444 ++emsg_skip;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001445 i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001446 if (eap->skip)
1447 {
1448 if (i != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001449 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001450 --emsg_skip;
1451 }
1452 else if (i != FAIL)
1453 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001454 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001455 op);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001456 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001457 }
1458 }
1459}
1460
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001461/*
1462 * Assign the typevalue "tv" to the variable or variables at "arg_start".
1463 * Handles both "var" with any type and "[var, var; var]" with a list type.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001464 * When "nextchars" is not NULL it points to a string with characters that
1465 * must appear after the variable(s). Use "+", "-" or "." for add, subtract
1466 * or concatenate.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001467 * Returns OK or FAIL;
1468 */
1469 static int
1470ex_let_vars(arg_start, tv, copy, semicolon, var_count, nextchars)
1471 char_u *arg_start;
Bram Moolenaar33570922005-01-25 22:26:29 +00001472 typval_T *tv;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001473 int copy; /* copy values from "tv", don't move */
1474 int semicolon; /* from skip_var_list() */
1475 int var_count; /* from skip_var_list() */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001476 char_u *nextchars;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001477{
1478 char_u *arg = arg_start;
Bram Moolenaar33570922005-01-25 22:26:29 +00001479 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001480 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00001481 listitem_T *item;
1482 typval_T ltv;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001483
1484 if (*arg != '[')
1485 {
1486 /*
1487 * ":let var = expr" or ":for var in list"
1488 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001489 if (ex_let_one(arg, tv, copy, nextchars, nextchars) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001490 return FAIL;
1491 return OK;
1492 }
1493
1494 /*
1495 * ":let [v1, v2] = list" or ":for [v1, v2] in listlist"
1496 */
Bram Moolenaar758711c2005-02-02 23:11:38 +00001497 if (tv->v_type != VAR_LIST || (l = tv->vval.v_list) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001498 {
1499 EMSG(_(e_listreq));
1500 return FAIL;
1501 }
1502
1503 i = list_len(l);
1504 if (semicolon == 0 && var_count < i)
1505 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00001506 EMSG(_("E687: Less targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001507 return FAIL;
1508 }
1509 if (var_count - semicolon > i)
1510 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00001511 EMSG(_("E688: More targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001512 return FAIL;
1513 }
1514
1515 item = l->lv_first;
1516 while (*arg != ']')
1517 {
1518 arg = skipwhite(arg + 1);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001519 arg = ex_let_one(arg, &item->li_tv, TRUE, (char_u *)",;]", nextchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001520 item = item->li_next;
1521 if (arg == NULL)
1522 return FAIL;
1523
1524 arg = skipwhite(arg);
1525 if (*arg == ';')
1526 {
1527 /* Put the rest of the list (may be empty) in the var after ';'.
1528 * Create a new list for this. */
1529 l = list_alloc();
1530 if (l == NULL)
1531 return FAIL;
1532 while (item != NULL)
1533 {
1534 list_append_tv(l, &item->li_tv);
1535 item = item->li_next;
1536 }
1537
1538 ltv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001539 ltv.v_lock = 0;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001540 ltv.vval.v_list = l;
1541 l->lv_refcount = 1;
1542
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001543 arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE,
1544 (char_u *)"]", nextchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001545 clear_tv(&ltv);
1546 if (arg == NULL)
1547 return FAIL;
1548 break;
1549 }
1550 else if (*arg != ',' && *arg != ']')
1551 {
1552 EMSG2(_(e_intern2), "ex_let_vars()");
1553 return FAIL;
1554 }
1555 }
1556
1557 return OK;
1558}
1559
1560/*
1561 * Skip over assignable variable "var" or list of variables "[var, var]".
1562 * Used for ":let varvar = expr" and ":for varvar in expr".
1563 * For "[var, var]" increment "*var_count" for each variable.
1564 * for "[var, var; var]" set "semicolon".
1565 * Return NULL for an error.
1566 */
1567 static char_u *
1568skip_var_list(arg, var_count, semicolon)
1569 char_u *arg;
1570 int *var_count;
1571 int *semicolon;
1572{
1573 char_u *p, *s;
1574
1575 if (*arg == '[')
1576 {
1577 /* "[var, var]": find the matching ']'. */
1578 p = arg;
1579 while (1)
1580 {
1581 p = skipwhite(p + 1); /* skip whites after '[', ';' or ',' */
1582 s = skip_var_one(p);
1583 if (s == p)
1584 {
1585 EMSG2(_(e_invarg2), p);
1586 return NULL;
1587 }
1588 ++*var_count;
1589
1590 p = skipwhite(s);
1591 if (*p == ']')
1592 break;
1593 else if (*p == ';')
1594 {
1595 if (*semicolon == 1)
1596 {
1597 EMSG(_("Double ; in list of variables"));
1598 return NULL;
1599 }
1600 *semicolon = 1;
1601 }
1602 else if (*p != ',')
1603 {
1604 EMSG2(_(e_invarg2), p);
1605 return NULL;
1606 }
1607 }
1608 return p + 1;
1609 }
1610 else
1611 return skip_var_one(arg);
1612}
1613
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001614/*
Bram Moolenaar92124a32005-06-17 22:03:40 +00001615 * Skip one (assignable) variable name, includig @r, $VAR, &option, d.key,
1616 * l[idx].
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001617 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001618 static char_u *
1619skip_var_one(arg)
1620 char_u *arg;
1621{
Bram Moolenaar92124a32005-06-17 22:03:40 +00001622 if (*arg == '@' && arg[1] != NUL)
1623 return arg + 2;
1624 return find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg,
1625 NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001626}
1627
Bram Moolenaara7043832005-01-21 11:56:39 +00001628/*
Bram Moolenaar33570922005-01-25 22:26:29 +00001629 * List variables for hashtab "ht" with prefix "prefix".
1630 * If "empty" is TRUE also list NULL strings as empty strings.
Bram Moolenaara7043832005-01-21 11:56:39 +00001631 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001632 static void
Bram Moolenaar33570922005-01-25 22:26:29 +00001633list_hashtable_vars(ht, prefix, empty)
1634 hashtab_T *ht;
Bram Moolenaara7043832005-01-21 11:56:39 +00001635 char_u *prefix;
Bram Moolenaar33570922005-01-25 22:26:29 +00001636 int empty;
Bram Moolenaara7043832005-01-21 11:56:39 +00001637{
Bram Moolenaar33570922005-01-25 22:26:29 +00001638 hashitem_T *hi;
1639 dictitem_T *di;
Bram Moolenaara7043832005-01-21 11:56:39 +00001640 int todo;
1641
1642 todo = ht->ht_used;
1643 for (hi = ht->ht_array; todo > 0 && !got_int; ++hi)
1644 {
1645 if (!HASHITEM_EMPTY(hi))
1646 {
1647 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00001648 di = HI2DI(hi);
1649 if (empty || di->di_tv.v_type != VAR_STRING
1650 || di->di_tv.vval.v_string != NULL)
1651 list_one_var(di, prefix);
Bram Moolenaara7043832005-01-21 11:56:39 +00001652 }
1653 }
1654}
1655
1656/*
1657 * List global variables.
1658 */
1659 static void
1660list_glob_vars()
1661{
Bram Moolenaar33570922005-01-25 22:26:29 +00001662 list_hashtable_vars(&globvarht, (char_u *)"", TRUE);
Bram Moolenaara7043832005-01-21 11:56:39 +00001663}
1664
1665/*
1666 * List buffer variables.
1667 */
1668 static void
1669list_buf_vars()
1670{
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001671 char_u numbuf[NUMBUFLEN];
1672
Bram Moolenaar33570922005-01-25 22:26:29 +00001673 list_hashtable_vars(&curbuf->b_vars.dv_hashtab, (char_u *)"b:", TRUE);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001674
1675 sprintf((char *)numbuf, "%ld", (long)curbuf->b_changedtick);
1676 list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER, numbuf);
Bram Moolenaara7043832005-01-21 11:56:39 +00001677}
1678
1679/*
1680 * List window variables.
1681 */
1682 static void
1683list_win_vars()
1684{
Bram Moolenaar33570922005-01-25 22:26:29 +00001685 list_hashtable_vars(&curwin->w_vars.dv_hashtab, (char_u *)"w:", TRUE);
Bram Moolenaara7043832005-01-21 11:56:39 +00001686}
1687
1688/*
1689 * List Vim variables.
1690 */
1691 static void
1692list_vim_vars()
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001693{
Bram Moolenaar33570922005-01-25 22:26:29 +00001694 list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001695}
1696
1697/*
1698 * List variables in "arg".
1699 */
1700 static char_u *
1701list_arg_vars(eap, arg)
1702 exarg_T *eap;
1703 char_u *arg;
1704{
1705 int error = FALSE;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001706 int len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001707 char_u *name;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001708 char_u *name_start;
1709 char_u *arg_subsc;
1710 char_u *tofree;
1711 typval_T tv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001712
1713 while (!ends_excmd(*arg) && !got_int)
1714 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001715 if (error || eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001716 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001717 arg = find_name_end(arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001718 if (!vim_iswhite(*arg) && !ends_excmd(*arg))
1719 {
1720 emsg_severe = TRUE;
1721 EMSG(_(e_trailing));
1722 break;
1723 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001724 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001725 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001726 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001727 /* get_name_len() takes care of expanding curly braces */
1728 name_start = name = arg;
1729 len = get_name_len(&arg, &tofree, TRUE, TRUE);
1730 if (len <= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001731 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001732 /* This is mainly to keep test 49 working: when expanding
1733 * curly braces fails overrule the exception error message. */
1734 if (len < 0 && !aborting())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001735 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001736 emsg_severe = TRUE;
1737 EMSG2(_(e_invarg2), arg);
1738 break;
1739 }
1740 error = TRUE;
1741 }
1742 else
1743 {
1744 if (tofree != NULL)
1745 name = tofree;
1746 if (get_var_tv(name, len, &tv, TRUE) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001747 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001748 else
1749 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001750 /* handle d.key, l[idx], f(expr) */
1751 arg_subsc = arg;
1752 if (handle_subscript(&arg, &tv, TRUE, TRUE) == FAIL)
Bram Moolenaara7043832005-01-21 11:56:39 +00001753 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001754 else
Bram Moolenaara7043832005-01-21 11:56:39 +00001755 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001756 if (arg == arg_subsc && len == 2 && name[1] == ':')
Bram Moolenaara7043832005-01-21 11:56:39 +00001757 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001758 switch (*name)
Bram Moolenaara7043832005-01-21 11:56:39 +00001759 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001760 case 'g': list_glob_vars(); break;
1761 case 'b': list_buf_vars(); break;
1762 case 'w': list_win_vars(); break;
1763 case 'v': list_vim_vars(); break;
1764 default:
1765 EMSG2(_("E738: Can't list variables for %s"), name);
Bram Moolenaara7043832005-01-21 11:56:39 +00001766 }
Bram Moolenaara7043832005-01-21 11:56:39 +00001767 }
1768 else
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001769 {
1770 char_u numbuf[NUMBUFLEN];
1771 char_u *tf;
1772 int c;
1773 char_u *s;
1774
1775 s = echo_string(&tv, &tf, numbuf);
1776 c = *arg;
1777 *arg = NUL;
1778 list_one_var_a((char_u *)"",
1779 arg == arg_subsc ? name : name_start,
1780 tv.v_type, s == NULL ? (char_u *)"" : s);
1781 *arg = c;
1782 vim_free(tf);
1783 }
1784 clear_tv(&tv);
Bram Moolenaara7043832005-01-21 11:56:39 +00001785 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001786 }
1787 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001788
1789 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001790 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001791
1792 arg = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001793 }
1794
1795 return arg;
1796}
1797
1798/*
1799 * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value.
1800 * Returns a pointer to the char just after the var name.
1801 * Returns NULL if there is an error.
1802 */
1803 static char_u *
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001804ex_let_one(arg, tv, copy, endchars, op)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001805 char_u *arg; /* points to variable name */
Bram Moolenaar33570922005-01-25 22:26:29 +00001806 typval_T *tv; /* value to assign to variable */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001807 int copy; /* copy value from "tv" */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001808 char_u *endchars; /* valid chars after variable name or NULL */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001809 char_u *op; /* "+", "-", "." or NULL*/
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001810{
1811 int c1;
1812 char_u *name;
1813 char_u *p;
1814 char_u *arg_end = NULL;
1815 int len;
1816 int opt_flags;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001817 char_u *tofree = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001818
1819 /*
1820 * ":let $VAR = expr": Set environment variable.
1821 */
1822 if (*arg == '$')
1823 {
1824 /* Find the end of the name. */
1825 ++arg;
1826 name = arg;
1827 len = get_env_len(&arg);
1828 if (len == 0)
1829 EMSG2(_(e_invarg2), name - 1);
1830 else
1831 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001832 if (op != NULL && (*op == '+' || *op == '-'))
1833 EMSG2(_(e_letwrong), op);
1834 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001835 && vim_strchr(endchars, *skipwhite(arg)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001836 EMSG(_(e_letunexp));
1837 else
1838 {
1839 c1 = name[len];
1840 name[len] = NUL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001841 p = get_tv_string_chk(tv);
1842 if (p != NULL && op != NULL && *op == '.')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001843 {
1844 int mustfree = FALSE;
1845 char_u *s = vim_getenv(name, &mustfree);
1846
1847 if (s != NULL)
1848 {
1849 p = tofree = concat_str(s, p);
1850 if (mustfree)
1851 vim_free(s);
1852 }
1853 }
1854 if (p != NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001855 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001856 vim_setenv(name, p);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001857 if (STRICMP(name, "HOME") == 0)
1858 init_homedir();
1859 else if (didset_vim && STRICMP(name, "VIM") == 0)
1860 didset_vim = FALSE;
1861 else if (didset_vimruntime
1862 && STRICMP(name, "VIMRUNTIME") == 0)
1863 didset_vimruntime = FALSE;
1864 arg_end = arg;
1865 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001866 name[len] = c1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001867 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001868 }
1869 }
1870 }
1871
1872 /*
1873 * ":let &option = expr": Set option value.
1874 * ":let &l:option = expr": Set local option value.
1875 * ":let &g:option = expr": Set global option value.
1876 */
1877 else if (*arg == '&')
1878 {
1879 /* Find the end of the name. */
1880 p = find_option_end(&arg, &opt_flags);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001881 if (p == NULL || (endchars != NULL
1882 && vim_strchr(endchars, *skipwhite(p)) == NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001883 EMSG(_(e_letunexp));
1884 else
1885 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001886 long n;
1887 int opt_type;
1888 long numval;
1889 char_u *stringval = NULL;
1890 char_u *s;
1891
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001892 c1 = *p;
1893 *p = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001894
1895 n = get_tv_number(tv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001896 s = get_tv_string_chk(tv); /* != NULL if number or string */
1897 if (s != NULL && op != NULL && *op != '=')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001898 {
1899 opt_type = get_option_value(arg, &numval,
1900 &stringval, opt_flags);
1901 if ((opt_type == 1 && *op == '.')
1902 || (opt_type == 0 && *op != '.'))
1903 EMSG2(_(e_letwrong), op);
1904 else
1905 {
1906 if (opt_type == 1) /* number */
1907 {
1908 if (*op == '+')
1909 n = numval + n;
1910 else
1911 n = numval - n;
1912 }
1913 else if (opt_type == 0 && stringval != NULL) /* string */
1914 {
1915 s = concat_str(stringval, s);
1916 vim_free(stringval);
1917 stringval = s;
1918 }
1919 }
1920 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001921 if (s != NULL)
1922 {
1923 set_option_value(arg, n, s, opt_flags);
1924 arg_end = p;
1925 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001926 *p = c1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001927 vim_free(stringval);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001928 }
1929 }
1930
1931 /*
1932 * ":let @r = expr": Set register contents.
1933 */
1934 else if (*arg == '@')
1935 {
1936 ++arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001937 if (op != NULL && (*op == '+' || *op == '-'))
1938 EMSG2(_(e_letwrong), op);
1939 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001940 && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001941 EMSG(_(e_letunexp));
1942 else
1943 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001944 char_u *tofree = NULL;
1945 char_u *s;
1946
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001947 p = get_tv_string_chk(tv);
1948 if (p != NULL && op != NULL && *op == '.')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001949 {
Bram Moolenaar92124a32005-06-17 22:03:40 +00001950 s = get_reg_contents(*arg == '@' ? '"' : *arg, TRUE, TRUE);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001951 if (s != NULL)
1952 {
1953 p = tofree = concat_str(s, p);
1954 vim_free(s);
1955 }
1956 }
1957 if (p != NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001958 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001959 write_reg_contents(*arg == '@' ? '"' : *arg, p, -1, FALSE);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001960 arg_end = arg + 1;
1961 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001962 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001963 }
1964 }
1965
1966 /*
1967 * ":let var = expr": Set internal variable.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001968 * ":let {expr} = expr": Idem, name made with curly braces
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001969 */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001970 else if (eval_isnamec1(*arg) || *arg == '{')
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001971 {
Bram Moolenaar33570922005-01-25 22:26:29 +00001972 lval_T lv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001973
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001974 p = get_lval(arg, tv, &lv, FALSE, FALSE, FALSE, FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001975 if (p != NULL && lv.ll_name != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001976 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001977 if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL)
1978 EMSG(_(e_letunexp));
1979 else
1980 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001981 set_var_lval(&lv, p, tv, copy, op);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001982 arg_end = p;
1983 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001984 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001985 clear_lval(&lv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001986 }
1987
1988 else
1989 EMSG2(_(e_invarg2), arg);
1990
1991 return arg_end;
1992}
1993
1994/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00001995 * If "arg" is equal to "b:changedtick" give an error and return TRUE.
1996 */
1997 static int
1998check_changedtick(arg)
1999 char_u *arg;
2000{
2001 if (STRNCMP(arg, "b:changedtick", 13) == 0 && !eval_isnamec(arg[13]))
2002 {
2003 EMSG2(_(e_readonlyvar), arg);
2004 return TRUE;
2005 }
2006 return FALSE;
2007}
2008
2009/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002010 * Get an lval: variable, Dict item or List item that can be assigned a value
2011 * to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]",
2012 * "name.key", "name.key[expr]" etc.
2013 * Indexing only works if "name" is an existing List or Dictionary.
2014 * "name" points to the start of the name.
2015 * If "rettv" is not NULL it points to the value to be assigned.
2016 * "unlet" is TRUE for ":unlet": slightly different behavior when something is
2017 * wrong; must end in space or cmd separator.
2018 *
2019 * Returns a pointer to just after the name, including indexes.
Bram Moolenaara7043832005-01-21 11:56:39 +00002020 * When an evaluation error occurs "lp->ll_name" is NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002021 * Returns NULL for a parsing error. Still need to free items in "lp"!
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002022 */
2023 static char_u *
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002024get_lval(name, rettv, lp, unlet, skip, quiet, fne_flags)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002025 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +00002026 typval_T *rettv;
2027 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002028 int unlet;
2029 int skip;
2030 int quiet; /* don't give error messages */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002031 int fne_flags; /* flags for find_name_end() */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002032{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002033 char_u *p;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002034 char_u *expr_start, *expr_end;
2035 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00002036 dictitem_T *v;
2037 typval_T var1;
2038 typval_T var2;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002039 int empty1 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00002040 listitem_T *ni;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002041 char_u *key = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002042 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +00002043 hashtab_T *ht;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002044
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002045 /* Clear everything in "lp". */
Bram Moolenaar33570922005-01-25 22:26:29 +00002046 vim_memset(lp, 0, sizeof(lval_T));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002047
2048 if (skip)
2049 {
2050 /* When skipping just find the end of the name. */
2051 lp->ll_name = name;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002052 return find_name_end(name, NULL, NULL, FNE_INCL_BR | fne_flags);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002053 }
2054
2055 /* Find the end of the name. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002056 p = find_name_end(name, &expr_start, &expr_end, fne_flags);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002057 if (expr_start != NULL)
2058 {
2059 /* Don't expand the name when we already know there is an error. */
2060 if (unlet && !vim_iswhite(*p) && !ends_excmd(*p)
2061 && *p != '[' && *p != '.')
2062 {
2063 EMSG(_(e_trailing));
2064 return NULL;
2065 }
2066
2067 lp->ll_exp_name = make_expanded_name(name, expr_start, expr_end, p);
2068 if (lp->ll_exp_name == NULL)
2069 {
2070 /* Report an invalid expression in braces, unless the
2071 * expression evaluation has been cancelled due to an
2072 * aborting error, an interrupt, or an exception. */
2073 if (!aborting() && !quiet)
2074 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002075 emsg_severe = TRUE;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002076 EMSG2(_(e_invarg2), name);
2077 return NULL;
2078 }
2079 }
2080 lp->ll_name = lp->ll_exp_name;
2081 }
2082 else
2083 lp->ll_name = name;
2084
2085 /* Without [idx] or .key we are done. */
2086 if ((*p != '[' && *p != '.') || lp->ll_name == NULL)
2087 return p;
2088
2089 cc = *p;
2090 *p = NUL;
Bram Moolenaara7043832005-01-21 11:56:39 +00002091 v = find_var(lp->ll_name, &ht);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002092 if (v == NULL && !quiet)
2093 EMSG2(_(e_undefvar), lp->ll_name);
2094 *p = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002095 if (v == NULL)
2096 return NULL;
2097
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002098 /*
2099 * Loop until no more [idx] or .key is following.
2100 */
Bram Moolenaar33570922005-01-25 22:26:29 +00002101 lp->ll_tv = &v->di_tv;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002102 while (*p == '[' || (*p == '.' && lp->ll_tv->v_type == VAR_DICT))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002103 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002104 if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL)
2105 && !(lp->ll_tv->v_type == VAR_DICT
2106 && lp->ll_tv->vval.v_dict != NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002107 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002108 if (!quiet)
2109 EMSG(_("E689: Can only index a List or Dictionary"));
2110 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002111 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002112 if (lp->ll_range)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002113 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002114 if (!quiet)
2115 EMSG(_("E708: [:] must come last"));
2116 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002117 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002118
Bram Moolenaar8c711452005-01-14 21:53:12 +00002119 len = -1;
2120 if (*p == '.')
2121 {
2122 key = p + 1;
2123 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
2124 ;
2125 if (len == 0)
2126 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002127 if (!quiet)
2128 EMSG(_(e_emptykey));
2129 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002130 }
2131 p = key + len;
2132 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002133 else
2134 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002135 /* Get the index [expr] or the first index [expr: ]. */
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002136 p = skipwhite(p + 1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002137 if (*p == ':')
2138 empty1 = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002139 else
2140 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002141 empty1 = FALSE;
2142 if (eval1(&p, &var1, TRUE) == FAIL) /* recursive! */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002143 return NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002144 if (get_tv_string_chk(&var1) == NULL)
2145 {
2146 /* not a number or string */
2147 clear_tv(&var1);
2148 return NULL;
2149 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002150 }
2151
2152 /* Optionally get the second index [ :expr]. */
2153 if (*p == ':')
2154 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002155 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002156 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002157 if (!quiet)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002158 EMSG(_(e_dictrange));
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002159 if (!empty1)
2160 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002161 return NULL;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002162 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002163 if (rettv != NULL && (rettv->v_type != VAR_LIST
2164 || rettv->vval.v_list == NULL))
Bram Moolenaar8c711452005-01-14 21:53:12 +00002165 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002166 if (!quiet)
2167 EMSG(_("E709: [:] requires a List value"));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002168 if (!empty1)
2169 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002170 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002171 }
2172 p = skipwhite(p + 1);
2173 if (*p == ']')
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002174 lp->ll_empty2 = TRUE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002175 else
2176 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002177 lp->ll_empty2 = FALSE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002178 if (eval1(&p, &var2, TRUE) == FAIL) /* recursive! */
2179 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002180 if (!empty1)
2181 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002182 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002183 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002184 if (get_tv_string_chk(&var2) == NULL)
2185 {
2186 /* not a number or string */
2187 if (!empty1)
2188 clear_tv(&var1);
2189 clear_tv(&var2);
2190 return NULL;
2191 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002192 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002193 lp->ll_range = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002194 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002195 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002196 lp->ll_range = FALSE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002197
Bram Moolenaar8c711452005-01-14 21:53:12 +00002198 if (*p != ']')
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002199 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002200 if (!quiet)
2201 EMSG(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002202 if (!empty1)
2203 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002204 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002205 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002206 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002207 }
2208
2209 /* Skip to past ']'. */
2210 ++p;
2211 }
2212
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002213 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002214 {
2215 if (len == -1)
2216 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002217 /* "[key]": get key from "var1" */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002218 key = get_tv_string(&var1); /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002219 if (*key == NUL)
2220 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002221 if (!quiet)
2222 EMSG(_(e_emptykey));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002223 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002224 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002225 }
2226 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002227 lp->ll_list = NULL;
2228 lp->ll_dict = lp->ll_tv->vval.v_dict;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002229 lp->ll_di = dict_find(lp->ll_dict, key, len);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002230 if (lp->ll_di == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002231 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002232 /* Key does not exist in dict: may need to add it. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002233 if (*p == '[' || *p == '.' || unlet)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002234 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002235 if (!quiet)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002236 EMSG2(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002237 if (len == -1)
2238 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002239 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002240 }
2241 if (len == -1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002242 lp->ll_newkey = vim_strsave(key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002243 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002244 lp->ll_newkey = vim_strnsave(key, len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002245 if (len == -1)
2246 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002247 if (lp->ll_newkey == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002248 p = NULL;
2249 break;
2250 }
2251 if (len == -1)
2252 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002253 lp->ll_tv = &lp->ll_di->di_tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002254 }
2255 else
2256 {
2257 /*
2258 * Get the number and item for the only or first index of the List.
2259 */
2260 if (empty1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002261 lp->ll_n1 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002262 else
2263 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002264 lp->ll_n1 = get_tv_number(&var1); /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002265 clear_tv(&var1);
2266 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002267 lp->ll_dict = NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002268 lp->ll_list = lp->ll_tv->vval.v_list;
2269 lp->ll_li = list_find(lp->ll_list, lp->ll_n1);
2270 if (lp->ll_li == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002271 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002272 if (!quiet)
2273 EMSGN(_(e_listidx), lp->ll_n1);
2274 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002275 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002276 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002277 }
2278
2279 /*
2280 * May need to find the item or absolute index for the second
2281 * index of a range.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002282 * When no index given: "lp->ll_empty2" is TRUE.
2283 * Otherwise "lp->ll_n2" is set to the second index.
Bram Moolenaar8c711452005-01-14 21:53:12 +00002284 */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002285 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002286 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002287 lp->ll_n2 = get_tv_number(&var2); /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002288 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002289 if (lp->ll_n2 < 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002290 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002291 ni = list_find(lp->ll_list, lp->ll_n2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002292 if (ni == NULL)
2293 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002294 if (!quiet)
2295 EMSGN(_(e_listidx), lp->ll_n2);
2296 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002297 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002298 lp->ll_n2 = list_idx_of_item(lp->ll_list, ni);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002299 }
2300
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002301 /* Check that lp->ll_n2 isn't before lp->ll_n1. */
2302 if (lp->ll_n1 < 0)
2303 lp->ll_n1 = list_idx_of_item(lp->ll_list, lp->ll_li);
2304 if (lp->ll_n2 < lp->ll_n1)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002305 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002306 if (!quiet)
2307 EMSGN(_(e_listidx), lp->ll_n2);
2308 return NULL;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002309 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002310 }
2311
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002312 lp->ll_tv = &lp->ll_li->li_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002313 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002314 }
2315
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002316 return p;
2317}
2318
2319/*
Bram Moolenaar33570922005-01-25 22:26:29 +00002320 * Clear lval "lp" that was filled by get_lval().
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002321 */
2322 static void
2323clear_lval(lp)
Bram Moolenaar33570922005-01-25 22:26:29 +00002324 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002325{
2326 vim_free(lp->ll_exp_name);
2327 vim_free(lp->ll_newkey);
2328}
2329
2330/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002331 * Set a variable that was parsed by get_lval() to "rettv".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002332 * "endp" points to just after the parsed name.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002333 * "op" is NULL, "+" for "+=", "-" for "-=", "." for ".=" or "=" for "=".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002334 */
2335 static void
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002336set_var_lval(lp, endp, rettv, copy, op)
Bram Moolenaar33570922005-01-25 22:26:29 +00002337 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002338 char_u *endp;
Bram Moolenaar33570922005-01-25 22:26:29 +00002339 typval_T *rettv;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002340 int copy;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002341 char_u *op;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002342{
2343 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00002344 listitem_T *ni;
2345 listitem_T *ri;
2346 dictitem_T *di;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002347
2348 if (lp->ll_tv == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002349 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002350 if (!check_changedtick(lp->ll_name))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002351 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002352 cc = *endp;
2353 *endp = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002354 if (op != NULL && *op != '=')
2355 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002356 typval_T tv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002357
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002358 /* handle +=, -= and .= */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002359 if (get_var_tv(lp->ll_name, STRLEN(lp->ll_name),
2360 &tv, TRUE) == OK)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002361 {
2362 if (tv_op(&tv, rettv, op) == OK)
2363 set_var(lp->ll_name, &tv, FALSE);
2364 clear_tv(&tv);
2365 }
2366 }
2367 else
2368 set_var(lp->ll_name, rettv, copy);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002369 *endp = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002370 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002371 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002372 else if (tv_check_lock(lp->ll_newkey == NULL
2373 ? lp->ll_tv->v_lock
2374 : lp->ll_tv->vval.v_dict->dv_lock, lp->ll_name))
2375 ;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002376 else if (lp->ll_range)
2377 {
2378 /*
2379 * Assign the List values to the list items.
2380 */
2381 for (ri = rettv->vval.v_list->lv_first; ri != NULL; )
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002382 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002383 if (op != NULL && *op != '=')
2384 tv_op(&lp->ll_li->li_tv, &ri->li_tv, op);
2385 else
2386 {
2387 clear_tv(&lp->ll_li->li_tv);
2388 copy_tv(&ri->li_tv, &lp->ll_li->li_tv);
2389 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002390 ri = ri->li_next;
2391 if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == lp->ll_n1))
2392 break;
2393 if (lp->ll_li->li_next == NULL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002394 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002395 /* Need to add an empty item. */
2396 ni = listitem_alloc();
2397 if (ni == NULL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002398 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002399 ri = NULL;
2400 break;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002401 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002402 ni->li_tv.v_type = VAR_NUMBER;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002403 ni->li_tv.v_lock = 0;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002404 ni->li_tv.vval.v_number = 0;
2405 list_append(lp->ll_list, ni);
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002406 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002407 lp->ll_li = lp->ll_li->li_next;
2408 ++lp->ll_n1;
2409 }
2410 if (ri != NULL)
2411 EMSG(_("E710: List value has more items than target"));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002412 else if (lp->ll_empty2
2413 ? (lp->ll_li != NULL && lp->ll_li->li_next != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002414 : lp->ll_n1 != lp->ll_n2)
2415 EMSG(_("E711: List value has not enough items"));
2416 }
2417 else
2418 {
2419 /*
2420 * Assign to a List or Dictionary item.
2421 */
2422 if (lp->ll_newkey != NULL)
2423 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002424 if (op != NULL && *op != '=')
2425 {
2426 EMSG2(_(e_letwrong), op);
2427 return;
2428 }
2429
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002430 /* Need to add an item to the Dictionary. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002431 di = dictitem_alloc(lp->ll_newkey);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002432 if (di == NULL)
2433 return;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002434 if (dict_add(lp->ll_tv->vval.v_dict, di) == FAIL)
2435 {
2436 vim_free(di);
2437 return;
2438 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002439 lp->ll_tv = &di->di_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002440 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002441 else if (op != NULL && *op != '=')
2442 {
2443 tv_op(lp->ll_tv, rettv, op);
2444 return;
2445 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002446 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002447 clear_tv(lp->ll_tv);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002448
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002449 /*
2450 * Assign the value to the variable or list item.
2451 */
2452 if (copy)
2453 copy_tv(rettv, lp->ll_tv);
2454 else
2455 {
2456 *lp->ll_tv = *rettv;
Bram Moolenaar758711c2005-02-02 23:11:38 +00002457 lp->ll_tv->v_lock = 0;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002458 init_tv(rettv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002459 }
2460 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002461}
2462
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002463/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002464 * Handle "tv1 += tv2", "tv1 -= tv2" and "tv1 .= tv2"
2465 * Returns OK or FAIL.
2466 */
2467 static int
2468tv_op(tv1, tv2, op)
Bram Moolenaar33570922005-01-25 22:26:29 +00002469 typval_T *tv1;
2470 typval_T *tv2;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002471 char_u *op;
2472{
2473 long n;
2474 char_u numbuf[NUMBUFLEN];
2475 char_u *s;
2476
2477 /* Can't do anything with a Funcref or a Dict on the right. */
2478 if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT)
2479 {
2480 switch (tv1->v_type)
2481 {
2482 case VAR_DICT:
2483 case VAR_FUNC:
2484 break;
2485
2486 case VAR_LIST:
2487 if (*op != '+' || tv2->v_type != VAR_LIST)
2488 break;
2489 /* List += List */
2490 if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL)
2491 list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL);
2492 return OK;
2493
2494 case VAR_NUMBER:
2495 case VAR_STRING:
2496 if (tv2->v_type == VAR_LIST)
2497 break;
2498 if (*op == '+' || *op == '-')
2499 {
2500 /* nr += nr or nr -= nr*/
2501 n = get_tv_number(tv1);
2502 if (*op == '+')
2503 n += get_tv_number(tv2);
2504 else
2505 n -= get_tv_number(tv2);
2506 clear_tv(tv1);
2507 tv1->v_type = VAR_NUMBER;
2508 tv1->vval.v_number = n;
2509 }
2510 else
2511 {
2512 /* str .= str */
2513 s = get_tv_string(tv1);
2514 s = concat_str(s, get_tv_string_buf(tv2, numbuf));
2515 clear_tv(tv1);
2516 tv1->v_type = VAR_STRING;
2517 tv1->vval.v_string = s;
2518 }
2519 return OK;
2520 }
2521 }
2522
2523 EMSG2(_(e_letwrong), op);
2524 return FAIL;
2525}
2526
2527/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002528 * Add a watcher to a list.
2529 */
2530 static void
2531list_add_watch(l, lw)
Bram Moolenaar33570922005-01-25 22:26:29 +00002532 list_T *l;
2533 listwatch_T *lw;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002534{
2535 lw->lw_next = l->lv_watch;
2536 l->lv_watch = lw;
2537}
2538
2539/*
Bram Moolenaar758711c2005-02-02 23:11:38 +00002540 * Remove a watcher from a list.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002541 * No warning when it isn't found...
2542 */
2543 static void
2544list_rem_watch(l, lwrem)
Bram Moolenaar33570922005-01-25 22:26:29 +00002545 list_T *l;
2546 listwatch_T *lwrem;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002547{
Bram Moolenaar33570922005-01-25 22:26:29 +00002548 listwatch_T *lw, **lwp;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002549
2550 lwp = &l->lv_watch;
2551 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
2552 {
2553 if (lw == lwrem)
2554 {
2555 *lwp = lw->lw_next;
2556 break;
2557 }
2558 lwp = &lw->lw_next;
2559 }
2560}
2561
2562/*
2563 * Just before removing an item from a list: advance watchers to the next
2564 * item.
2565 */
2566 static void
2567list_fix_watch(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00002568 list_T *l;
2569 listitem_T *item;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002570{
Bram Moolenaar33570922005-01-25 22:26:29 +00002571 listwatch_T *lw;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002572
2573 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
2574 if (lw->lw_item == item)
2575 lw->lw_item = item->li_next;
2576}
2577
2578/*
2579 * Evaluate the expression used in a ":for var in expr" command.
2580 * "arg" points to "var".
2581 * Set "*errp" to TRUE for an error, FALSE otherwise;
2582 * Return a pointer that holds the info. Null when there is an error.
2583 */
2584 void *
2585eval_for_line(arg, errp, nextcmdp, skip)
2586 char_u *arg;
2587 int *errp;
2588 char_u **nextcmdp;
2589 int skip;
2590{
Bram Moolenaar33570922005-01-25 22:26:29 +00002591 forinfo_T *fi;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002592 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +00002593 typval_T tv;
2594 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002595
2596 *errp = TRUE; /* default: there is an error */
2597
Bram Moolenaar33570922005-01-25 22:26:29 +00002598 fi = (forinfo_T *)alloc_clear(sizeof(forinfo_T));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002599 if (fi == NULL)
2600 return NULL;
2601
2602 expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
2603 if (expr == NULL)
2604 return fi;
2605
2606 expr = skipwhite(expr);
2607 if (expr[0] != 'i' || expr[1] != 'n' || !vim_iswhite(expr[2]))
2608 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00002609 EMSG(_("E690: Missing \"in\" after :for"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002610 return fi;
2611 }
2612
2613 if (skip)
2614 ++emsg_skip;
2615 if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK)
2616 {
2617 *errp = FALSE;
2618 if (!skip)
2619 {
2620 l = tv.vval.v_list;
2621 if (tv.v_type != VAR_LIST || l == NULL)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002622 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002623 EMSG(_(e_listreq));
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002624 clear_tv(&tv);
2625 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002626 else
2627 {
2628 fi->fi_list = l;
2629 list_add_watch(l, &fi->fi_lw);
2630 fi->fi_lw.lw_item = l->lv_first;
2631 }
2632 }
2633 }
2634 if (skip)
2635 --emsg_skip;
2636
2637 return fi;
2638}
2639
2640/*
2641 * Use the first item in a ":for" list. Advance to the next.
2642 * Assign the values to the variable (list). "arg" points to the first one.
2643 * Return TRUE when a valid item was found, FALSE when at end of list or
2644 * something wrong.
2645 */
2646 int
2647next_for_item(fi_void, arg)
2648 void *fi_void;
2649 char_u *arg;
2650{
Bram Moolenaar33570922005-01-25 22:26:29 +00002651 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002652 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00002653 listitem_T *item;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002654
2655 item = fi->fi_lw.lw_item;
2656 if (item == NULL)
2657 result = FALSE;
2658 else
2659 {
2660 fi->fi_lw.lw_item = item->li_next;
2661 result = (ex_let_vars(arg, &item->li_tv, TRUE,
2662 fi->fi_semicolon, fi->fi_varcount, NULL) == OK);
2663 }
2664 return result;
2665}
2666
2667/*
2668 * Free the structure used to store info used by ":for".
2669 */
2670 void
2671free_for_info(fi_void)
2672 void *fi_void;
2673{
Bram Moolenaar33570922005-01-25 22:26:29 +00002674 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002675
Bram Moolenaarab7013c2005-01-09 21:23:56 +00002676 if (fi != NULL && fi->fi_list != NULL)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002677 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002678 list_rem_watch(fi->fi_list, &fi->fi_lw);
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002679 list_unref(fi->fi_list);
2680 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002681 vim_free(fi);
2682}
2683
Bram Moolenaar071d4272004-06-13 20:20:40 +00002684#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
2685
2686 void
2687set_context_for_expression(xp, arg, cmdidx)
2688 expand_T *xp;
2689 char_u *arg;
2690 cmdidx_T cmdidx;
2691{
2692 int got_eq = FALSE;
2693 int c;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002694 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002695
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002696 if (cmdidx == CMD_let)
2697 {
2698 xp->xp_context = EXPAND_USER_VARS;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002699 if (vim_strpbrk(arg, (char_u *)"\"'+-*/%.=!?~|&$([<>,#") == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002700 {
2701 /* ":let var1 var2 ...": find last space. */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002702 for (p = arg + STRLEN(arg); p >= arg; )
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002703 {
2704 xp->xp_pattern = p;
Bram Moolenaar33570922005-01-25 22:26:29 +00002705 mb_ptr_back(arg, p);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002706 if (vim_iswhite(*p))
2707 break;
2708 }
2709 return;
2710 }
2711 }
2712 else
2713 xp->xp_context = cmdidx == CMD_call ? EXPAND_FUNCTIONS
2714 : EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002715 while ((xp->xp_pattern = vim_strpbrk(arg,
2716 (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL)
2717 {
2718 c = *xp->xp_pattern;
2719 if (c == '&')
2720 {
2721 c = xp->xp_pattern[1];
2722 if (c == '&')
2723 {
2724 ++xp->xp_pattern;
2725 xp->xp_context = cmdidx != CMD_let || got_eq
2726 ? EXPAND_EXPRESSION : EXPAND_NOTHING;
2727 }
2728 else if (c != ' ')
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00002729 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002730 xp->xp_context = EXPAND_SETTINGS;
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00002731 if ((c == 'l' || c == 'g') && xp->xp_pattern[2] == ':')
2732 xp->xp_pattern += 2;
2733
2734 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002735 }
2736 else if (c == '$')
2737 {
2738 /* environment variable */
2739 xp->xp_context = EXPAND_ENV_VARS;
2740 }
2741 else if (c == '=')
2742 {
2743 got_eq = TRUE;
2744 xp->xp_context = EXPAND_EXPRESSION;
2745 }
2746 else if (c == '<'
2747 && xp->xp_context == EXPAND_FUNCTIONS
2748 && vim_strchr(xp->xp_pattern, '(') == NULL)
2749 {
2750 /* Function name can start with "<SNR>" */
2751 break;
2752 }
2753 else if (cmdidx != CMD_let || got_eq)
2754 {
2755 if (c == '"') /* string */
2756 {
2757 while ((c = *++xp->xp_pattern) != NUL && c != '"')
2758 if (c == '\\' && xp->xp_pattern[1] != NUL)
2759 ++xp->xp_pattern;
2760 xp->xp_context = EXPAND_NOTHING;
2761 }
2762 else if (c == '\'') /* literal string */
2763 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002764 /* Trick: '' is like stopping and starting a literal string. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002765 while ((c = *++xp->xp_pattern) != NUL && c != '\'')
2766 /* skip */ ;
2767 xp->xp_context = EXPAND_NOTHING;
2768 }
2769 else if (c == '|')
2770 {
2771 if (xp->xp_pattern[1] == '|')
2772 {
2773 ++xp->xp_pattern;
2774 xp->xp_context = EXPAND_EXPRESSION;
2775 }
2776 else
2777 xp->xp_context = EXPAND_COMMANDS;
2778 }
2779 else
2780 xp->xp_context = EXPAND_EXPRESSION;
2781 }
2782 else
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002783 /* Doesn't look like something valid, expand as an expression
2784 * anyway. */
2785 xp->xp_context = EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002786 arg = xp->xp_pattern;
2787 if (*arg != NUL)
2788 while ((c = *++arg) != NUL && (c == ' ' || c == '\t'))
2789 /* skip */ ;
2790 }
2791 xp->xp_pattern = arg;
2792}
2793
2794#endif /* FEAT_CMDL_COMPL */
2795
2796/*
2797 * ":1,25call func(arg1, arg2)" function call.
2798 */
2799 void
2800ex_call(eap)
2801 exarg_T *eap;
2802{
2803 char_u *arg = eap->arg;
2804 char_u *startarg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002805 char_u *name;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002806 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002807 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +00002808 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002809 linenr_T lnum;
2810 int doesrange;
2811 int failed = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00002812 funcdict_T fudi;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002813
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002814 tofree = trans_function_name(&arg, eap->skip, TFN_INT, &fudi);
2815 vim_free(fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002816 if (tofree == NULL)
2817 return;
2818
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002819 /* Increase refcount on dictionary, it could get deleted when evaluating
2820 * the arguments. */
2821 if (fudi.fd_dict != NULL)
2822 ++fudi.fd_dict->dv_refcount;
2823
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002824 /* If it is the name of a variable of type VAR_FUNC use its contents. */
2825 len = STRLEN(tofree);
2826 name = deref_func_name(tofree, &len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002827
Bram Moolenaar532c7802005-01-27 14:44:31 +00002828 /* Skip white space to allow ":call func ()". Not good, but required for
2829 * backward compatibility. */
2830 startarg = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002831 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002832
2833 if (*startarg != '(')
2834 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00002835 EMSG2(_("E107: Missing braces: %s"), eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002836 goto end;
2837 }
2838
2839 /*
2840 * When skipping, evaluate the function once, to find the end of the
2841 * arguments.
2842 * When the function takes a range, this is discovered after the first
2843 * call, and the loop is broken.
2844 */
2845 if (eap->skip)
2846 {
2847 ++emsg_skip;
2848 lnum = eap->line2; /* do it once, also with an invalid range */
2849 }
2850 else
2851 lnum = eap->line1;
2852 for ( ; lnum <= eap->line2; ++lnum)
2853 {
2854 if (!eap->skip && eap->addr_count > 0)
2855 {
2856 curwin->w_cursor.lnum = lnum;
2857 curwin->w_cursor.col = 0;
2858 }
2859 arg = startarg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002860 if (get_func_tv(name, STRLEN(name), &rettv, &arg,
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002861 eap->line1, eap->line2, &doesrange,
2862 !eap->skip, fudi.fd_dict) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002863 {
2864 failed = TRUE;
2865 break;
2866 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002867 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002868 if (doesrange || eap->skip)
2869 break;
2870 /* Stop when immediately aborting on error, or when an interrupt
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002871 * occurred or an exception was thrown but not caught.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002872 * get_func_tv() returned OK, so that the check for trailing
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002873 * characters below is executed. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002874 if (aborting())
2875 break;
2876 }
2877 if (eap->skip)
2878 --emsg_skip;
2879
2880 if (!failed)
2881 {
2882 /* Check for trailing illegal characters and a following command. */
2883 if (!ends_excmd(*arg))
2884 {
2885 emsg_severe = TRUE;
2886 EMSG(_(e_trailing));
2887 }
2888 else
2889 eap->nextcmd = check_nextcmd(arg);
2890 }
2891
2892end:
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002893 dict_unref(fudi.fd_dict);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002894 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002895}
2896
2897/*
2898 * ":unlet[!] var1 ... " command.
2899 */
2900 void
2901ex_unlet(eap)
2902 exarg_T *eap;
2903{
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002904 ex_unletlock(eap, eap->arg, 0);
2905}
2906
2907/*
2908 * ":lockvar" and ":unlockvar" commands
2909 */
2910 void
2911ex_lockvar(eap)
2912 exarg_T *eap;
2913{
Bram Moolenaar071d4272004-06-13 20:20:40 +00002914 char_u *arg = eap->arg;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002915 int deep = 2;
2916
2917 if (eap->forceit)
2918 deep = -1;
2919 else if (vim_isdigit(*arg))
2920 {
2921 deep = getdigits(&arg);
2922 arg = skipwhite(arg);
2923 }
2924
2925 ex_unletlock(eap, arg, deep);
2926}
2927
2928/*
2929 * ":unlet", ":lockvar" and ":unlockvar" are quite similar.
2930 */
2931 static void
2932ex_unletlock(eap, argstart, deep)
2933 exarg_T *eap;
2934 char_u *argstart;
2935 int deep;
2936{
2937 char_u *arg = argstart;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002938 char_u *name_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002939 int error = FALSE;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002940 lval_T lv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002941
2942 do
2943 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002944 /* Parse the name and find the end. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002945 name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error, FALSE,
2946 FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002947 if (lv.ll_name == NULL)
2948 error = TRUE; /* error but continue parsing */
2949 if (name_end == NULL || (!vim_iswhite(*name_end)
2950 && !ends_excmd(*name_end)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002951 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002952 if (name_end != NULL)
2953 {
2954 emsg_severe = TRUE;
2955 EMSG(_(e_trailing));
2956 }
2957 if (!(eap->skip || error))
2958 clear_lval(&lv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002959 break;
2960 }
2961
2962 if (!error && !eap->skip)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002963 {
2964 if (eap->cmdidx == CMD_unlet)
2965 {
2966 if (do_unlet_var(&lv, name_end, eap->forceit) == FAIL)
2967 error = TRUE;
2968 }
2969 else
2970 {
2971 if (do_lock_var(&lv, name_end, deep,
2972 eap->cmdidx == CMD_lockvar) == FAIL)
2973 error = TRUE;
2974 }
2975 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002976
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002977 if (!eap->skip)
2978 clear_lval(&lv);
2979
Bram Moolenaar071d4272004-06-13 20:20:40 +00002980 arg = skipwhite(name_end);
2981 } while (!ends_excmd(*arg));
2982
2983 eap->nextcmd = check_nextcmd(arg);
2984}
2985
Bram Moolenaar8c711452005-01-14 21:53:12 +00002986 static int
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002987do_unlet_var(lp, name_end, forceit)
Bram Moolenaar33570922005-01-25 22:26:29 +00002988 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002989 char_u *name_end;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002990 int forceit;
2991{
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002992 int ret = OK;
2993 int cc;
2994
2995 if (lp->ll_tv == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002996 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002997 cc = *name_end;
2998 *name_end = NUL;
2999
3000 /* Normal name or expanded name. */
3001 if (check_changedtick(lp->ll_name))
3002 ret = FAIL;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003003 else if (do_unlet(lp->ll_name, forceit) == FAIL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003004 ret = FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003005 *name_end = cc;
Bram Moolenaar8c711452005-01-14 21:53:12 +00003006 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003007 else if (tv_check_lock(lp->ll_tv->v_lock, lp->ll_name))
3008 return FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003009 else if (lp->ll_range)
3010 {
Bram Moolenaar33570922005-01-25 22:26:29 +00003011 listitem_T *li;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003012
3013 /* Delete a range of List items. */
3014 while (lp->ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
3015 {
3016 li = lp->ll_li->li_next;
3017 listitem_remove(lp->ll_list, lp->ll_li);
3018 lp->ll_li = li;
3019 ++lp->ll_n1;
3020 }
3021 }
3022 else
3023 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003024 if (lp->ll_list != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003025 /* unlet a List item. */
3026 listitem_remove(lp->ll_list, lp->ll_li);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003027 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003028 /* unlet a Dictionary item. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003029 dictitem_remove(lp->ll_dict, lp->ll_di);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003030 }
3031
3032 return ret;
Bram Moolenaar8c711452005-01-14 21:53:12 +00003033}
3034
Bram Moolenaar071d4272004-06-13 20:20:40 +00003035/*
3036 * "unlet" a variable. Return OK if it existed, FAIL if not.
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003037 * When "forceit" is TRUE don't complain if the variable doesn't exist.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003038 */
3039 int
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003040do_unlet(name, forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003041 char_u *name;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003042 int forceit;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003043{
Bram Moolenaar33570922005-01-25 22:26:29 +00003044 hashtab_T *ht;
3045 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003046 char_u *varname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003047
Bram Moolenaar33570922005-01-25 22:26:29 +00003048 ht = find_var_ht(name, &varname);
3049 if (ht != NULL && *varname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003050 {
Bram Moolenaar33570922005-01-25 22:26:29 +00003051 hi = hash_find(ht, varname);
3052 if (!HASHITEM_EMPTY(hi))
Bram Moolenaara7043832005-01-21 11:56:39 +00003053 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003054 if (var_check_ro(HI2DI(hi)->di_flags, name))
3055 return FAIL;
3056 delete_var(ht, hi);
3057 return OK;
Bram Moolenaara7043832005-01-21 11:56:39 +00003058 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003059 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003060 if (forceit)
3061 return OK;
3062 EMSG2(_("E108: No such variable: \"%s\""), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003063 return FAIL;
3064}
3065
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003066/*
3067 * Lock or unlock variable indicated by "lp".
3068 * "deep" is the levels to go (-1 for unlimited);
3069 * "lock" is TRUE for ":lockvar", FALSE for ":unlockvar".
3070 */
3071 static int
3072do_lock_var(lp, name_end, deep, lock)
3073 lval_T *lp;
3074 char_u *name_end;
3075 int deep;
3076 int lock;
3077{
3078 int ret = OK;
3079 int cc;
3080 dictitem_T *di;
3081
3082 if (deep == 0) /* nothing to do */
3083 return OK;
3084
3085 if (lp->ll_tv == NULL)
3086 {
3087 cc = *name_end;
3088 *name_end = NUL;
3089
3090 /* Normal name or expanded name. */
3091 if (check_changedtick(lp->ll_name))
3092 ret = FAIL;
3093 else
3094 {
3095 di = find_var(lp->ll_name, NULL);
3096 if (di == NULL)
3097 ret = FAIL;
3098 else
3099 {
3100 if (lock)
3101 di->di_flags |= DI_FLAGS_LOCK;
3102 else
3103 di->di_flags &= ~DI_FLAGS_LOCK;
3104 item_lock(&di->di_tv, deep, lock);
3105 }
3106 }
3107 *name_end = cc;
3108 }
3109 else if (lp->ll_range)
3110 {
3111 listitem_T *li = lp->ll_li;
3112
3113 /* (un)lock a range of List items. */
3114 while (li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
3115 {
3116 item_lock(&li->li_tv, deep, lock);
3117 li = li->li_next;
3118 ++lp->ll_n1;
3119 }
3120 }
3121 else if (lp->ll_list != NULL)
3122 /* (un)lock a List item. */
3123 item_lock(&lp->ll_li->li_tv, deep, lock);
3124 else
3125 /* un(lock) a Dictionary item. */
3126 item_lock(&lp->ll_di->di_tv, deep, lock);
3127
3128 return ret;
3129}
3130
3131/*
3132 * Lock or unlock an item. "deep" is nr of levels to go.
3133 */
3134 static void
3135item_lock(tv, deep, lock)
3136 typval_T *tv;
3137 int deep;
3138 int lock;
3139{
3140 static int recurse = 0;
3141 list_T *l;
3142 listitem_T *li;
3143 dict_T *d;
3144 hashitem_T *hi;
3145 int todo;
3146
3147 if (recurse >= DICT_MAXNEST)
3148 {
3149 EMSG(_("E743: variable nested too deep for (un)lock"));
3150 return;
3151 }
3152 if (deep == 0)
3153 return;
3154 ++recurse;
3155
3156 /* lock/unlock the item itself */
3157 if (lock)
3158 tv->v_lock |= VAR_LOCKED;
3159 else
3160 tv->v_lock &= ~VAR_LOCKED;
3161
3162 switch (tv->v_type)
3163 {
3164 case VAR_LIST:
3165 if ((l = tv->vval.v_list) != NULL)
3166 {
3167 if (lock)
3168 l->lv_lock |= VAR_LOCKED;
3169 else
3170 l->lv_lock &= ~VAR_LOCKED;
3171 if (deep < 0 || deep > 1)
3172 /* recursive: lock/unlock the items the List contains */
3173 for (li = l->lv_first; li != NULL; li = li->li_next)
3174 item_lock(&li->li_tv, deep - 1, lock);
3175 }
3176 break;
3177 case VAR_DICT:
3178 if ((d = tv->vval.v_dict) != NULL)
3179 {
3180 if (lock)
3181 d->dv_lock |= VAR_LOCKED;
3182 else
3183 d->dv_lock &= ~VAR_LOCKED;
3184 if (deep < 0 || deep > 1)
3185 {
3186 /* recursive: lock/unlock the items the List contains */
3187 todo = d->dv_hashtab.ht_used;
3188 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
3189 {
3190 if (!HASHITEM_EMPTY(hi))
3191 {
3192 --todo;
3193 item_lock(&HI2DI(hi)->di_tv, deep - 1, lock);
3194 }
3195 }
3196 }
3197 }
3198 }
3199 --recurse;
3200}
3201
Bram Moolenaar071d4272004-06-13 20:20:40 +00003202#if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO)
3203/*
3204 * Delete all "menutrans_" variables.
3205 */
3206 void
3207del_menutrans_vars()
3208{
Bram Moolenaar33570922005-01-25 22:26:29 +00003209 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003210 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003211
Bram Moolenaar33570922005-01-25 22:26:29 +00003212 hash_lock(&globvarht);
3213 todo = globvarht.ht_used;
3214 for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaara7043832005-01-21 11:56:39 +00003215 {
3216 if (!HASHITEM_EMPTY(hi))
3217 {
3218 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00003219 if (STRNCMP(HI2DI(hi)->di_key, "menutrans_", 10) == 0)
3220 delete_var(&globvarht, hi);
Bram Moolenaara7043832005-01-21 11:56:39 +00003221 }
3222 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003223 hash_unlock(&globvarht);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003224}
3225#endif
3226
3227#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
3228
3229/*
3230 * Local string buffer for the next two functions to store a variable name
3231 * with its prefix. Allocated in cat_prefix_varname(), freed later in
3232 * get_user_var_name().
3233 */
3234
3235static char_u *cat_prefix_varname __ARGS((int prefix, char_u *name));
3236
3237static char_u *varnamebuf = NULL;
3238static int varnamebuflen = 0;
3239
3240/*
3241 * Function to concatenate a prefix and a variable name.
3242 */
3243 static char_u *
3244cat_prefix_varname(prefix, name)
3245 int prefix;
3246 char_u *name;
3247{
3248 int len;
3249
3250 len = (int)STRLEN(name) + 3;
3251 if (len > varnamebuflen)
3252 {
3253 vim_free(varnamebuf);
3254 len += 10; /* some additional space */
3255 varnamebuf = alloc(len);
3256 if (varnamebuf == NULL)
3257 {
3258 varnamebuflen = 0;
3259 return NULL;
3260 }
3261 varnamebuflen = len;
3262 }
3263 *varnamebuf = prefix;
3264 varnamebuf[1] = ':';
3265 STRCPY(varnamebuf + 2, name);
3266 return varnamebuf;
3267}
3268
3269/*
3270 * Function given to ExpandGeneric() to obtain the list of user defined
3271 * (global/buffer/window/built-in) variable names.
3272 */
3273/*ARGSUSED*/
3274 char_u *
3275get_user_var_name(xp, idx)
3276 expand_T *xp;
3277 int idx;
3278{
Bram Moolenaar532c7802005-01-27 14:44:31 +00003279 static long_u gdone;
3280 static long_u bdone;
3281 static long_u wdone;
3282 static int vidx;
3283 static hashitem_T *hi;
3284 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003285
3286 if (idx == 0)
Bram Moolenaara7043832005-01-21 11:56:39 +00003287 gdone = bdone = wdone = vidx = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00003288
3289 /* Global variables */
3290 if (gdone < globvarht.ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003291 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003292 if (gdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003293 hi = globvarht.ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003294 else
3295 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003296 while (HASHITEM_EMPTY(hi))
3297 ++hi;
3298 if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
3299 return cat_prefix_varname('g', hi->hi_key);
3300 return hi->hi_key;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003301 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003302
3303 /* b: variables */
3304 ht = &curbuf->b_vars.dv_hashtab;
3305 if (bdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003306 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003307 if (bdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003308 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003309 else
3310 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003311 while (HASHITEM_EMPTY(hi))
3312 ++hi;
3313 return cat_prefix_varname('b', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003314 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003315 if (bdone == ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003316 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003317 ++bdone;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003318 return (char_u *)"b:changedtick";
3319 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003320
3321 /* w: variables */
3322 ht = &curwin->w_vars.dv_hashtab;
3323 if (wdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003324 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00003325 if (wdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003326 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003327 else
3328 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003329 while (HASHITEM_EMPTY(hi))
3330 ++hi;
3331 return cat_prefix_varname('w', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003332 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003333
3334 /* v: variables */
3335 if (vidx < VV_LEN)
3336 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].vv_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003337
3338 vim_free(varnamebuf);
3339 varnamebuf = NULL;
3340 varnamebuflen = 0;
3341 return NULL;
3342}
3343
3344#endif /* FEAT_CMDL_COMPL */
3345
3346/*
3347 * types for expressions.
3348 */
3349typedef enum
3350{
3351 TYPE_UNKNOWN = 0
3352 , TYPE_EQUAL /* == */
3353 , TYPE_NEQUAL /* != */
3354 , TYPE_GREATER /* > */
3355 , TYPE_GEQUAL /* >= */
3356 , TYPE_SMALLER /* < */
3357 , TYPE_SEQUAL /* <= */
3358 , TYPE_MATCH /* =~ */
3359 , TYPE_NOMATCH /* !~ */
3360} exptype_T;
3361
3362/*
3363 * The "evaluate" argument: When FALSE, the argument is only parsed but not
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003364 * executed. The function may return OK, but the rettv will be of type
Bram Moolenaar071d4272004-06-13 20:20:40 +00003365 * VAR_UNKNOWN. The function still returns FAIL for a syntax error.
3366 */
3367
3368/*
3369 * Handle zero level expression.
3370 * This calls eval1() and handles error message and nextcmd.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003371 * Put the result in "rettv" when returning OK and "evaluate" is TRUE.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003372 * Return OK or FAIL.
3373 */
3374 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003375eval0(arg, rettv, nextcmd, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003376 char_u *arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003377 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003378 char_u **nextcmd;
3379 int evaluate;
3380{
3381 int ret;
3382 char_u *p;
3383
3384 p = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003385 ret = eval1(&p, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003386 if (ret == FAIL || !ends_excmd(*p))
3387 {
3388 if (ret != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003389 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003390 /*
3391 * Report the invalid expression unless the expression evaluation has
3392 * been cancelled due to an aborting error, an interrupt, or an
3393 * exception.
3394 */
3395 if (!aborting())
3396 EMSG2(_(e_invexpr2), arg);
3397 ret = FAIL;
3398 }
3399 if (nextcmd != NULL)
3400 *nextcmd = check_nextcmd(p);
3401
3402 return ret;
3403}
3404
3405/*
3406 * Handle top level expression:
3407 * expr1 ? expr0 : expr0
3408 *
3409 * "arg" must point to the first non-white of the expression.
3410 * "arg" is advanced to the next non-white after the recognized expression.
3411 *
3412 * Return OK or FAIL.
3413 */
3414 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003415eval1(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003416 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003417 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003418 int evaluate;
3419{
3420 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00003421 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003422
3423 /*
3424 * Get the first variable.
3425 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003426 if (eval2(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003427 return FAIL;
3428
3429 if ((*arg)[0] == '?')
3430 {
3431 result = FALSE;
3432 if (evaluate)
3433 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003434 int error = FALSE;
3435
3436 if (get_tv_number_chk(rettv, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003437 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003438 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003439 if (error)
3440 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003441 }
3442
3443 /*
3444 * Get the second variable.
3445 */
3446 *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003447 if (eval1(arg, rettv, evaluate && result) == FAIL) /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003448 return FAIL;
3449
3450 /*
3451 * Check for the ":".
3452 */
3453 if ((*arg)[0] != ':')
3454 {
3455 EMSG(_("E109: Missing ':' after '?'"));
3456 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003457 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003458 return FAIL;
3459 }
3460
3461 /*
3462 * Get the third variable.
3463 */
3464 *arg = skipwhite(*arg + 1);
3465 if (eval1(arg, &var2, evaluate && !result) == FAIL) /* recursive! */
3466 {
3467 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003468 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003469 return FAIL;
3470 }
3471 if (evaluate && !result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003472 *rettv = var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003473 }
3474
3475 return OK;
3476}
3477
3478/*
3479 * Handle first level expression:
3480 * expr2 || expr2 || expr2 logical OR
3481 *
3482 * "arg" must point to the first non-white of the expression.
3483 * "arg" is advanced to the next non-white after the recognized expression.
3484 *
3485 * Return OK or FAIL.
3486 */
3487 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003488eval2(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003489 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003490 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003491 int evaluate;
3492{
Bram Moolenaar33570922005-01-25 22:26:29 +00003493 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003494 long result;
3495 int first;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003496 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003497
3498 /*
3499 * Get the first variable.
3500 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003501 if (eval3(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003502 return FAIL;
3503
3504 /*
3505 * Repeat until there is no following "||".
3506 */
3507 first = TRUE;
3508 result = FALSE;
3509 while ((*arg)[0] == '|' && (*arg)[1] == '|')
3510 {
3511 if (evaluate && first)
3512 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003513 if (get_tv_number_chk(rettv, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003514 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003515 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003516 if (error)
3517 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003518 first = FALSE;
3519 }
3520
3521 /*
3522 * Get the second variable.
3523 */
3524 *arg = skipwhite(*arg + 2);
3525 if (eval3(arg, &var2, evaluate && !result) == FAIL)
3526 return FAIL;
3527
3528 /*
3529 * Compute the result.
3530 */
3531 if (evaluate && !result)
3532 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003533 if (get_tv_number_chk(&var2, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003534 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003535 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003536 if (error)
3537 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003538 }
3539 if (evaluate)
3540 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003541 rettv->v_type = VAR_NUMBER;
3542 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003543 }
3544 }
3545
3546 return OK;
3547}
3548
3549/*
3550 * Handle second level expression:
3551 * expr3 && expr3 && expr3 logical AND
3552 *
3553 * "arg" must point to the first non-white of the expression.
3554 * "arg" is advanced to the next non-white after the recognized expression.
3555 *
3556 * Return OK or FAIL.
3557 */
3558 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003559eval3(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003560 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003561 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003562 int evaluate;
3563{
Bram Moolenaar33570922005-01-25 22:26:29 +00003564 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003565 long result;
3566 int first;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003567 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003568
3569 /*
3570 * Get the first variable.
3571 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003572 if (eval4(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003573 return FAIL;
3574
3575 /*
3576 * Repeat until there is no following "&&".
3577 */
3578 first = TRUE;
3579 result = TRUE;
3580 while ((*arg)[0] == '&' && (*arg)[1] == '&')
3581 {
3582 if (evaluate && first)
3583 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003584 if (get_tv_number_chk(rettv, &error) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003585 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003586 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003587 if (error)
3588 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003589 first = FALSE;
3590 }
3591
3592 /*
3593 * Get the second variable.
3594 */
3595 *arg = skipwhite(*arg + 2);
3596 if (eval4(arg, &var2, evaluate && result) == FAIL)
3597 return FAIL;
3598
3599 /*
3600 * Compute the result.
3601 */
3602 if (evaluate && result)
3603 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003604 if (get_tv_number_chk(&var2, &error) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003605 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003606 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003607 if (error)
3608 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003609 }
3610 if (evaluate)
3611 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003612 rettv->v_type = VAR_NUMBER;
3613 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003614 }
3615 }
3616
3617 return OK;
3618}
3619
3620/*
3621 * Handle third level expression:
3622 * var1 == var2
3623 * var1 =~ var2
3624 * var1 != var2
3625 * var1 !~ var2
3626 * var1 > var2
3627 * var1 >= var2
3628 * var1 < var2
3629 * var1 <= var2
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003630 * var1 is var2
3631 * var1 isnot var2
Bram Moolenaar071d4272004-06-13 20:20:40 +00003632 *
3633 * "arg" must point to the first non-white of the expression.
3634 * "arg" is advanced to the next non-white after the recognized expression.
3635 *
3636 * Return OK or FAIL.
3637 */
3638 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003639eval4(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003640 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003641 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003642 int evaluate;
3643{
Bram Moolenaar33570922005-01-25 22:26:29 +00003644 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003645 char_u *p;
3646 int i;
3647 exptype_T type = TYPE_UNKNOWN;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003648 int type_is = FALSE; /* TRUE for "is" and "isnot" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003649 int len = 2;
3650 long n1, n2;
3651 char_u *s1, *s2;
3652 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
3653 regmatch_T regmatch;
3654 int ic;
3655 char_u *save_cpo;
3656
3657 /*
3658 * Get the first variable.
3659 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003660 if (eval5(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003661 return FAIL;
3662
3663 p = *arg;
3664 switch (p[0])
3665 {
3666 case '=': if (p[1] == '=')
3667 type = TYPE_EQUAL;
3668 else if (p[1] == '~')
3669 type = TYPE_MATCH;
3670 break;
3671 case '!': if (p[1] == '=')
3672 type = TYPE_NEQUAL;
3673 else if (p[1] == '~')
3674 type = TYPE_NOMATCH;
3675 break;
3676 case '>': if (p[1] != '=')
3677 {
3678 type = TYPE_GREATER;
3679 len = 1;
3680 }
3681 else
3682 type = TYPE_GEQUAL;
3683 break;
3684 case '<': if (p[1] != '=')
3685 {
3686 type = TYPE_SMALLER;
3687 len = 1;
3688 }
3689 else
3690 type = TYPE_SEQUAL;
3691 break;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003692 case 'i': if (p[1] == 's')
3693 {
3694 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3695 len = 5;
3696 if (!vim_isIDc(p[len]))
3697 {
3698 type = len == 2 ? TYPE_EQUAL : TYPE_NEQUAL;
3699 type_is = TRUE;
3700 }
3701 }
3702 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003703 }
3704
3705 /*
3706 * If there is a comparitive operator, use it.
3707 */
3708 if (type != TYPE_UNKNOWN)
3709 {
3710 /* extra question mark appended: ignore case */
3711 if (p[len] == '?')
3712 {
3713 ic = TRUE;
3714 ++len;
3715 }
3716 /* extra '#' appended: match case */
3717 else if (p[len] == '#')
3718 {
3719 ic = FALSE;
3720 ++len;
3721 }
3722 /* nothing appened: use 'ignorecase' */
3723 else
3724 ic = p_ic;
3725
3726 /*
3727 * Get the second variable.
3728 */
3729 *arg = skipwhite(p + len);
3730 if (eval5(arg, &var2, evaluate) == FAIL)
3731 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003732 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003733 return FAIL;
3734 }
3735
3736 if (evaluate)
3737 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003738 if (type_is && rettv->v_type != var2.v_type)
3739 {
3740 /* For "is" a different type always means FALSE, for "notis"
3741 * it means TRUE. */
3742 n1 = (type == TYPE_NEQUAL);
3743 }
3744 else if (rettv->v_type == VAR_LIST || var2.v_type == VAR_LIST)
3745 {
3746 if (type_is)
3747 {
3748 n1 = (rettv->v_type == var2.v_type
3749 && rettv->vval.v_list == var2.vval.v_list);
3750 if (type == TYPE_NEQUAL)
3751 n1 = !n1;
3752 }
3753 else if (rettv->v_type != var2.v_type
3754 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
3755 {
3756 if (rettv->v_type != var2.v_type)
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003757 EMSG(_("E691: Can only compare List with List"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003758 else
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003759 EMSG(_("E692: Invalid operation for Lists"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003760 clear_tv(rettv);
3761 clear_tv(&var2);
3762 return FAIL;
3763 }
3764 else
3765 {
3766 /* Compare two Lists for being equal or unequal. */
3767 n1 = list_equal(rettv->vval.v_list, var2.vval.v_list, ic);
3768 if (type == TYPE_NEQUAL)
3769 n1 = !n1;
3770 }
3771 }
3772
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003773 else if (rettv->v_type == VAR_DICT || var2.v_type == VAR_DICT)
3774 {
3775 if (type_is)
3776 {
3777 n1 = (rettv->v_type == var2.v_type
3778 && rettv->vval.v_dict == var2.vval.v_dict);
3779 if (type == TYPE_NEQUAL)
3780 n1 = !n1;
3781 }
3782 else if (rettv->v_type != var2.v_type
3783 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
3784 {
3785 if (rettv->v_type != var2.v_type)
3786 EMSG(_("E735: Can only compare Dictionary with Dictionary"));
3787 else
3788 EMSG(_("E736: Invalid operation for Dictionary"));
3789 clear_tv(rettv);
3790 clear_tv(&var2);
3791 return FAIL;
3792 }
3793 else
3794 {
3795 /* Compare two Dictionaries for being equal or unequal. */
3796 n1 = dict_equal(rettv->vval.v_dict, var2.vval.v_dict, ic);
3797 if (type == TYPE_NEQUAL)
3798 n1 = !n1;
3799 }
3800 }
3801
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003802 else if (rettv->v_type == VAR_FUNC || var2.v_type == VAR_FUNC)
3803 {
3804 if (rettv->v_type != var2.v_type
3805 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
3806 {
3807 if (rettv->v_type != var2.v_type)
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003808 EMSG(_("E693: Can only compare Funcref with Funcref"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003809 else
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003810 EMSG(_("E694: Invalid operation for Funcrefs"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003811 clear_tv(rettv);
3812 clear_tv(&var2);
3813 return FAIL;
3814 }
3815 else
3816 {
3817 /* Compare two Funcrefs for being equal or unequal. */
3818 if (rettv->vval.v_string == NULL
3819 || var2.vval.v_string == NULL)
3820 n1 = FALSE;
3821 else
3822 n1 = STRCMP(rettv->vval.v_string,
3823 var2.vval.v_string) == 0;
3824 if (type == TYPE_NEQUAL)
3825 n1 = !n1;
3826 }
3827 }
3828
Bram Moolenaar071d4272004-06-13 20:20:40 +00003829 /*
3830 * If one of the two variables is a number, compare as a number.
3831 * When using "=~" or "!~", always compare as string.
3832 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003833 else if ((rettv->v_type == VAR_NUMBER || var2.v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003834 && type != TYPE_MATCH && type != TYPE_NOMATCH)
3835 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003836 n1 = get_tv_number(rettv);
3837 n2 = get_tv_number(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003838 switch (type)
3839 {
3840 case TYPE_EQUAL: n1 = (n1 == n2); break;
3841 case TYPE_NEQUAL: n1 = (n1 != n2); break;
3842 case TYPE_GREATER: n1 = (n1 > n2); break;
3843 case TYPE_GEQUAL: n1 = (n1 >= n2); break;
3844 case TYPE_SMALLER: n1 = (n1 < n2); break;
3845 case TYPE_SEQUAL: n1 = (n1 <= n2); break;
3846 case TYPE_UNKNOWN:
3847 case TYPE_MATCH:
3848 case TYPE_NOMATCH: break; /* avoid gcc warning */
3849 }
3850 }
3851 else
3852 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003853 s1 = get_tv_string_buf(rettv, buf1);
3854 s2 = get_tv_string_buf(&var2, buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003855 if (type != TYPE_MATCH && type != TYPE_NOMATCH)
3856 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2);
3857 else
3858 i = 0;
3859 n1 = FALSE;
3860 switch (type)
3861 {
3862 case TYPE_EQUAL: n1 = (i == 0); break;
3863 case TYPE_NEQUAL: n1 = (i != 0); break;
3864 case TYPE_GREATER: n1 = (i > 0); break;
3865 case TYPE_GEQUAL: n1 = (i >= 0); break;
3866 case TYPE_SMALLER: n1 = (i < 0); break;
3867 case TYPE_SEQUAL: n1 = (i <= 0); break;
3868
3869 case TYPE_MATCH:
3870 case TYPE_NOMATCH:
3871 /* avoid 'l' flag in 'cpoptions' */
3872 save_cpo = p_cpo;
3873 p_cpo = (char_u *)"";
3874 regmatch.regprog = vim_regcomp(s2,
3875 RE_MAGIC + RE_STRING);
3876 regmatch.rm_ic = ic;
3877 if (regmatch.regprog != NULL)
3878 {
3879 n1 = vim_regexec_nl(&regmatch, s1, (colnr_T)0);
3880 vim_free(regmatch.regprog);
3881 if (type == TYPE_NOMATCH)
3882 n1 = !n1;
3883 }
3884 p_cpo = save_cpo;
3885 break;
3886
3887 case TYPE_UNKNOWN: break; /* avoid gcc warning */
3888 }
3889 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003890 clear_tv(rettv);
3891 clear_tv(&var2);
3892 rettv->v_type = VAR_NUMBER;
3893 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003894 }
3895 }
3896
3897 return OK;
3898}
3899
3900/*
3901 * Handle fourth level expression:
3902 * + number addition
3903 * - number subtraction
3904 * . string concatenation
3905 *
3906 * "arg" must point to the first non-white of the expression.
3907 * "arg" is advanced to the next non-white after the recognized expression.
3908 *
3909 * Return OK or FAIL.
3910 */
3911 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003912eval5(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003913 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003914 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003915 int evaluate;
3916{
Bram Moolenaar33570922005-01-25 22:26:29 +00003917 typval_T var2;
3918 typval_T var3;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003919 int op;
3920 long n1, n2;
3921 char_u *s1, *s2;
3922 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
3923 char_u *p;
3924
3925 /*
3926 * Get the first variable.
3927 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003928 if (eval6(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003929 return FAIL;
3930
3931 /*
3932 * Repeat computing, until no '+', '-' or '.' is following.
3933 */
3934 for (;;)
3935 {
3936 op = **arg;
3937 if (op != '+' && op != '-' && op != '.')
3938 break;
3939
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003940 if (op != '+' || rettv->v_type != VAR_LIST)
3941 {
3942 /* For "list + ...", an illegal use of the first operand as
3943 * a number cannot be determined before evaluating the 2nd
3944 * operand: if this is also a list, all is ok.
3945 * For "something . ...", "something - ..." or "non-list + ...",
3946 * we know that the first operand needs to be a string or number
3947 * without evaluating the 2nd operand. So check before to avoid
3948 * side effects after an error. */
3949 if (evaluate && get_tv_string_chk(rettv) == NULL)
3950 {
3951 clear_tv(rettv);
3952 return FAIL;
3953 }
3954 }
3955
Bram Moolenaar071d4272004-06-13 20:20:40 +00003956 /*
3957 * Get the second variable.
3958 */
3959 *arg = skipwhite(*arg + 1);
3960 if (eval6(arg, &var2, evaluate) == FAIL)
3961 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003962 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003963 return FAIL;
3964 }
3965
3966 if (evaluate)
3967 {
3968 /*
3969 * Compute the result.
3970 */
3971 if (op == '.')
3972 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003973 s1 = get_tv_string_buf(rettv, buf1); /* already checked */
3974 s2 = get_tv_string_buf_chk(&var2, buf2);
3975 if (s2 == NULL) /* type error ? */
3976 {
3977 clear_tv(rettv);
3978 clear_tv(&var2);
3979 return FAIL;
3980 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003981 p = concat_str(s1, s2);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003982 clear_tv(rettv);
3983 rettv->v_type = VAR_STRING;
3984 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003985 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00003986 else if (op == '+' && rettv->v_type == VAR_LIST
3987 && var2.v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003988 {
3989 /* concatenate Lists */
3990 if (list_concat(rettv->vval.v_list, var2.vval.v_list,
3991 &var3) == FAIL)
3992 {
3993 clear_tv(rettv);
3994 clear_tv(&var2);
3995 return FAIL;
3996 }
3997 clear_tv(rettv);
3998 *rettv = var3;
3999 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004000 else
4001 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004002 int error = FALSE;
4003
4004 n1 = get_tv_number_chk(rettv, &error);
4005 if (error)
4006 {
4007 /* This can only happen for "list + non-list".
4008 * For "non-list + ..." or "something - ...", we returned
4009 * before evaluating the 2nd operand. */
4010 clear_tv(rettv);
4011 return FAIL;
4012 }
4013 n2 = get_tv_number_chk(&var2, &error);
4014 if (error)
4015 {
4016 clear_tv(rettv);
4017 clear_tv(&var2);
4018 return FAIL;
4019 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004020 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004021 if (op == '+')
4022 n1 = n1 + n2;
4023 else
4024 n1 = n1 - n2;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004025 rettv->v_type = VAR_NUMBER;
4026 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004027 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004028 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004029 }
4030 }
4031 return OK;
4032}
4033
4034/*
4035 * Handle fifth level expression:
4036 * * number multiplication
4037 * / number division
4038 * % number modulo
4039 *
4040 * "arg" must point to the first non-white of the expression.
4041 * "arg" is advanced to the next non-white after the recognized expression.
4042 *
4043 * Return OK or FAIL.
4044 */
4045 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004046eval6(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004047 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004048 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004049 int evaluate;
4050{
Bram Moolenaar33570922005-01-25 22:26:29 +00004051 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004052 int op;
4053 long n1, n2;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004054 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004055
4056 /*
4057 * Get the first variable.
4058 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004059 if (eval7(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004060 return FAIL;
4061
4062 /*
4063 * Repeat computing, until no '*', '/' or '%' is following.
4064 */
4065 for (;;)
4066 {
4067 op = **arg;
4068 if (op != '*' && op != '/' && op != '%')
4069 break;
4070
4071 if (evaluate)
4072 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004073 n1 = get_tv_number_chk(rettv, &error);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004074 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004075 if (error)
4076 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004077 }
4078 else
4079 n1 = 0;
4080
4081 /*
4082 * Get the second variable.
4083 */
4084 *arg = skipwhite(*arg + 1);
4085 if (eval7(arg, &var2, evaluate) == FAIL)
4086 return FAIL;
4087
4088 if (evaluate)
4089 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004090 n2 = get_tv_number_chk(&var2, &error);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004091 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004092 if (error)
4093 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004094
4095 /*
4096 * Compute the result.
4097 */
4098 if (op == '*')
4099 n1 = n1 * n2;
4100 else if (op == '/')
4101 {
4102 if (n2 == 0) /* give an error message? */
4103 n1 = 0x7fffffffL;
4104 else
4105 n1 = n1 / n2;
4106 }
4107 else
4108 {
4109 if (n2 == 0) /* give an error message? */
4110 n1 = 0;
4111 else
4112 n1 = n1 % n2;
4113 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004114 rettv->v_type = VAR_NUMBER;
4115 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004116 }
4117 }
4118
4119 return OK;
4120}
4121
4122/*
4123 * Handle sixth level expression:
4124 * number number constant
4125 * "string" string contstant
4126 * 'string' literal string contstant
4127 * &option-name option value
4128 * @r register contents
4129 * identifier variable value
4130 * function() function call
4131 * $VAR environment variable
4132 * (expression) nested expression
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00004133 * [expr, expr] List
4134 * {key: val, key: val} Dictionary
Bram Moolenaar071d4272004-06-13 20:20:40 +00004135 *
4136 * Also handle:
4137 * ! in front logical NOT
4138 * - in front unary minus
4139 * + in front unary plus (ignored)
Bram Moolenaar8c711452005-01-14 21:53:12 +00004140 * trailing [] subscript in String or List
4141 * trailing .name entry in Dictionary
Bram Moolenaar071d4272004-06-13 20:20:40 +00004142 *
4143 * "arg" must point to the first non-white of the expression.
4144 * "arg" is advanced to the next non-white after the recognized expression.
4145 *
4146 * Return OK or FAIL.
4147 */
4148 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004149eval7(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004150 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004151 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004152 int evaluate;
4153{
Bram Moolenaar071d4272004-06-13 20:20:40 +00004154 long n;
4155 int len;
4156 char_u *s;
4157 int val;
4158 char_u *start_leader, *end_leader;
4159 int ret = OK;
4160 char_u *alias;
4161
4162 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004163 * Initialise variable so that clear_tv() can't mistake this for a
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004164 * string and free a string that isn't there.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004165 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004166 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004167
4168 /*
4169 * Skip '!' and '-' characters. They are handled later.
4170 */
4171 start_leader = *arg;
4172 while (**arg == '!' || **arg == '-' || **arg == '+')
4173 *arg = skipwhite(*arg + 1);
4174 end_leader = *arg;
4175
4176 switch (**arg)
4177 {
4178 /*
4179 * Number constant.
4180 */
4181 case '0':
4182 case '1':
4183 case '2':
4184 case '3':
4185 case '4':
4186 case '5':
4187 case '6':
4188 case '7':
4189 case '8':
4190 case '9':
4191 vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL);
4192 *arg += len;
4193 if (evaluate)
4194 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004195 rettv->v_type = VAR_NUMBER;
4196 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004197 }
4198 break;
4199
4200 /*
4201 * String constant: "string".
4202 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004203 case '"': ret = get_string_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004204 break;
4205
4206 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004207 * Literal string constant: 'str''ing'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004208 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004209 case '\'': ret = get_lit_string_tv(arg, rettv, evaluate);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004210 break;
4211
4212 /*
4213 * List: [expr, expr]
4214 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004215 case '[': ret = get_list_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004216 break;
4217
4218 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004219 * Dictionary: {key: val, key: val}
4220 */
4221 case '{': ret = get_dict_tv(arg, rettv, evaluate);
4222 break;
4223
4224 /*
Bram Moolenaare9a41262005-01-15 22:18:47 +00004225 * Option value: &name
Bram Moolenaar071d4272004-06-13 20:20:40 +00004226 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00004227 case '&': ret = get_option_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004228 break;
4229
4230 /*
4231 * Environment variable: $VAR.
4232 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004233 case '$': ret = get_env_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004234 break;
4235
4236 /*
4237 * Register contents: @r.
4238 */
4239 case '@': ++*arg;
4240 if (evaluate)
4241 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004242 rettv->v_type = VAR_STRING;
Bram Moolenaar92124a32005-06-17 22:03:40 +00004243 rettv->vval.v_string = get_reg_contents(**arg, TRUE, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004244 }
4245 if (**arg != NUL)
4246 ++*arg;
4247 break;
4248
4249 /*
4250 * nested expression: (expression).
4251 */
4252 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004253 ret = eval1(arg, rettv, evaluate); /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004254 if (**arg == ')')
4255 ++*arg;
4256 else if (ret == OK)
4257 {
4258 EMSG(_("E110: Missing ')'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004259 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004260 ret = FAIL;
4261 }
4262 break;
4263
Bram Moolenaar8c711452005-01-14 21:53:12 +00004264 default: ret = NOTDONE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004265 break;
4266 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004267
4268 if (ret == NOTDONE)
4269 {
4270 /*
4271 * Must be a variable or function name.
4272 * Can also be a curly-braces kind of name: {expr}.
4273 */
4274 s = *arg;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004275 len = get_name_len(arg, &alias, evaluate, TRUE);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004276 if (alias != NULL)
4277 s = alias;
4278
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004279 if (len <= 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00004280 ret = FAIL;
4281 else
4282 {
4283 if (**arg == '(') /* recursive! */
4284 {
4285 /* If "s" is the name of a variable of type VAR_FUNC
4286 * use its contents. */
4287 s = deref_func_name(s, &len);
4288
4289 /* Invoke the function. */
4290 ret = get_func_tv(s, len, rettv, arg,
4291 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
Bram Moolenaare9a41262005-01-15 22:18:47 +00004292 &len, evaluate, NULL);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004293 /* Stop the expression evaluation when immediately
4294 * aborting on error, or when an interrupt occurred or
4295 * an exception was thrown but not caught. */
4296 if (aborting())
4297 {
4298 if (ret == OK)
4299 clear_tv(rettv);
4300 ret = FAIL;
4301 }
4302 }
4303 else if (evaluate)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004304 ret = get_var_tv(s, len, rettv, TRUE);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004305 else
4306 ret = OK;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004307 }
4308
4309 if (alias != NULL)
4310 vim_free(alias);
4311 }
4312
Bram Moolenaar071d4272004-06-13 20:20:40 +00004313 *arg = skipwhite(*arg);
4314
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004315 /* Handle following '[', '(' and '.' for expr[expr], expr.name,
4316 * expr(expr). */
4317 if (ret == OK)
4318 ret = handle_subscript(arg, rettv, evaluate, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004319
4320 /*
4321 * Apply logical NOT and unary '-', from right to left, ignore '+'.
4322 */
4323 if (ret == OK && evaluate && end_leader > start_leader)
4324 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004325 int error = FALSE;
4326
4327 val = get_tv_number_chk(rettv, &error);
4328 if (error)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004329 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004330 clear_tv(rettv);
4331 ret = FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004332 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004333 else
4334 {
4335 while (end_leader > start_leader)
4336 {
4337 --end_leader;
4338 if (*end_leader == '!')
4339 val = !val;
4340 else if (*end_leader == '-')
4341 val = -val;
4342 }
4343 clear_tv(rettv);
4344 rettv->v_type = VAR_NUMBER;
4345 rettv->vval.v_number = val;
4346 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004347 }
4348
4349 return ret;
4350}
4351
4352/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004353 * Evaluate an "[expr]" or "[expr:expr]" index.
4354 * "*arg" points to the '['.
4355 * Returns FAIL or OK. "*arg" is advanced to after the ']'.
4356 */
4357 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004358eval_index(arg, rettv, evaluate, verbose)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004359 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004360 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004361 int evaluate;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004362 int verbose; /* give error messages */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004363{
4364 int empty1 = FALSE, empty2 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00004365 typval_T var1, var2;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004366 long n1, n2 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004367 long len = -1;
4368 int range = FALSE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004369 char_u *s;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004370 char_u *key = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004371
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004372 if (rettv->v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004373 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004374 if (verbose)
4375 EMSG(_("E695: Cannot index a Funcref"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004376 return FAIL;
4377 }
4378
Bram Moolenaar8c711452005-01-14 21:53:12 +00004379 if (**arg == '.')
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004380 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004381 /*
4382 * dict.name
4383 */
4384 key = *arg + 1;
4385 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
4386 ;
4387 if (len == 0)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004388 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004389 *arg = skipwhite(key + len);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004390 }
4391 else
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004392 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004393 /*
4394 * something[idx]
4395 *
4396 * Get the (first) variable from inside the [].
4397 */
4398 *arg = skipwhite(*arg + 1);
4399 if (**arg == ':')
4400 empty1 = TRUE;
4401 else if (eval1(arg, &var1, evaluate) == FAIL) /* recursive! */
4402 return FAIL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004403 else if (evaluate && get_tv_string_chk(&var1) == NULL)
4404 {
4405 /* not a number or string */
4406 clear_tv(&var1);
4407 return FAIL;
4408 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004409
4410 /*
4411 * Get the second variable from inside the [:].
4412 */
4413 if (**arg == ':')
4414 {
4415 range = TRUE;
4416 *arg = skipwhite(*arg + 1);
4417 if (**arg == ']')
4418 empty2 = TRUE;
4419 else if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */
4420 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004421 if (!empty1)
4422 clear_tv(&var1);
4423 return FAIL;
4424 }
4425 else if (evaluate && get_tv_string_chk(&var2) == NULL)
4426 {
4427 /* not a number or string */
4428 if (!empty1)
4429 clear_tv(&var1);
4430 clear_tv(&var2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004431 return FAIL;
4432 }
4433 }
4434
4435 /* Check for the ']'. */
4436 if (**arg != ']')
4437 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004438 if (verbose)
4439 EMSG(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004440 clear_tv(&var1);
4441 if (range)
4442 clear_tv(&var2);
4443 return FAIL;
4444 }
4445 *arg = skipwhite(*arg + 1); /* skip the ']' */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004446 }
4447
4448 if (evaluate)
4449 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004450 n1 = 0;
4451 if (!empty1 && rettv->v_type != VAR_DICT)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004452 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004453 n1 = get_tv_number(&var1);
4454 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004455 }
4456 if (range)
4457 {
4458 if (empty2)
4459 n2 = -1;
4460 else
4461 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004462 n2 = get_tv_number(&var2);
4463 clear_tv(&var2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004464 }
4465 }
4466
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004467 switch (rettv->v_type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004468 {
4469 case VAR_NUMBER:
4470 case VAR_STRING:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004471 s = get_tv_string(rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004472 len = (long)STRLEN(s);
4473 if (range)
4474 {
4475 /* The resulting variable is a substring. If the indexes
4476 * are out of range the result is empty. */
4477 if (n1 < 0)
4478 {
4479 n1 = len + n1;
4480 if (n1 < 0)
4481 n1 = 0;
4482 }
4483 if (n2 < 0)
4484 n2 = len + n2;
4485 else if (n2 >= len)
4486 n2 = len;
4487 if (n1 >= len || n2 < 0 || n1 > n2)
4488 s = NULL;
4489 else
4490 s = vim_strnsave(s + n1, (int)(n2 - n1 + 1));
4491 }
4492 else
4493 {
4494 /* The resulting variable is a string of a single
4495 * character. If the index is too big or negative the
4496 * result is empty. */
4497 if (n1 >= len || n1 < 0)
4498 s = NULL;
4499 else
4500 s = vim_strnsave(s + n1, 1);
4501 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004502 clear_tv(rettv);
4503 rettv->v_type = VAR_STRING;
4504 rettv->vval.v_string = s;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004505 break;
4506
4507 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004508 len = list_len(rettv->vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004509 if (n1 < 0)
4510 n1 = len + n1;
4511 if (!empty1 && (n1 < 0 || n1 >= len))
4512 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004513 if (verbose)
4514 EMSGN(_(e_listidx), n1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004515 return FAIL;
4516 }
4517 if (range)
4518 {
Bram Moolenaar33570922005-01-25 22:26:29 +00004519 list_T *l;
4520 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004521
4522 if (n2 < 0)
4523 n2 = len + n2;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004524 if (!empty2 && (n2 < 0 || n2 >= len || n2 + 1 < n1))
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004525 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004526 if (verbose)
4527 EMSGN(_(e_listidx), n2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004528 return FAIL;
4529 }
4530 l = list_alloc();
4531 if (l == NULL)
4532 return FAIL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004533 for (item = list_find(rettv->vval.v_list, n1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004534 n1 <= n2; ++n1)
4535 {
4536 if (list_append_tv(l, &item->li_tv) == FAIL)
4537 {
4538 list_free(l);
4539 return FAIL;
4540 }
4541 item = item->li_next;
4542 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004543 clear_tv(rettv);
4544 rettv->v_type = VAR_LIST;
4545 rettv->vval.v_list = l;
Bram Moolenaar0d660222005-01-07 21:51:51 +00004546 ++l->lv_refcount;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004547 }
4548 else
4549 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004550 copy_tv(&list_find(rettv->vval.v_list, n1)->li_tv,
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004551 &var1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004552 clear_tv(rettv);
4553 *rettv = var1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004554 }
4555 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004556
4557 case VAR_DICT:
4558 if (range)
4559 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004560 if (verbose)
4561 EMSG(_(e_dictrange));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004562 if (len == -1)
4563 clear_tv(&var1);
4564 return FAIL;
4565 }
4566 {
Bram Moolenaar33570922005-01-25 22:26:29 +00004567 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004568
4569 if (len == -1)
4570 {
4571 key = get_tv_string(&var1);
4572 if (*key == NUL)
4573 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004574 if (verbose)
4575 EMSG(_(e_emptykey));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004576 clear_tv(&var1);
4577 return FAIL;
4578 }
4579 }
4580
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00004581 item = dict_find(rettv->vval.v_dict, key, (int)len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004582
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004583 if (item == NULL && verbose)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004584 EMSG2(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004585 if (len == -1)
4586 clear_tv(&var1);
4587 if (item == NULL)
4588 return FAIL;
4589
4590 copy_tv(&item->di_tv, &var1);
4591 clear_tv(rettv);
4592 *rettv = var1;
4593 }
4594 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004595 }
4596 }
4597
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004598 return OK;
4599}
4600
4601/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00004602 * Get an option value.
4603 * "arg" points to the '&' or '+' before the option name.
4604 * "arg" is advanced to character after the option name.
4605 * Return OK or FAIL.
4606 */
4607 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004608get_option_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004609 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004610 typval_T *rettv; /* when NULL, only check if option exists */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004611 int evaluate;
4612{
4613 char_u *option_end;
4614 long numval;
4615 char_u *stringval;
4616 int opt_type;
4617 int c;
4618 int working = (**arg == '+'); /* has("+option") */
4619 int ret = OK;
4620 int opt_flags;
4621
4622 /*
4623 * Isolate the option name and find its value.
4624 */
4625 option_end = find_option_end(arg, &opt_flags);
4626 if (option_end == NULL)
4627 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004628 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004629 EMSG2(_("E112: Option name missing: %s"), *arg);
4630 return FAIL;
4631 }
4632
4633 if (!evaluate)
4634 {
4635 *arg = option_end;
4636 return OK;
4637 }
4638
4639 c = *option_end;
4640 *option_end = NUL;
4641 opt_type = get_option_value(*arg, &numval,
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004642 rettv == NULL ? NULL : &stringval, opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004643
4644 if (opt_type == -3) /* invalid name */
4645 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004646 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004647 EMSG2(_("E113: Unknown option: %s"), *arg);
4648 ret = FAIL;
4649 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004650 else if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004651 {
4652 if (opt_type == -2) /* hidden string option */
4653 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004654 rettv->v_type = VAR_STRING;
4655 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004656 }
4657 else if (opt_type == -1) /* hidden number option */
4658 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004659 rettv->v_type = VAR_NUMBER;
4660 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004661 }
4662 else if (opt_type == 1) /* number option */
4663 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004664 rettv->v_type = VAR_NUMBER;
4665 rettv->vval.v_number = numval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004666 }
4667 else /* string option */
4668 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004669 rettv->v_type = VAR_STRING;
4670 rettv->vval.v_string = stringval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004671 }
4672 }
4673 else if (working && (opt_type == -2 || opt_type == -1))
4674 ret = FAIL;
4675
4676 *option_end = c; /* put back for error messages */
4677 *arg = option_end;
4678
4679 return ret;
4680}
4681
4682/*
4683 * Allocate a variable for a string constant.
4684 * Return OK or FAIL.
4685 */
4686 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004687get_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004688 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004689 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004690 int evaluate;
4691{
4692 char_u *p;
4693 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004694 int extra = 0;
4695
4696 /*
4697 * Find the end of the string, skipping backslashed characters.
4698 */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004699 for (p = *arg + 1; *p != NUL && *p != '"'; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004700 {
4701 if (*p == '\\' && p[1] != NUL)
4702 {
4703 ++p;
4704 /* A "\<x>" form occupies at least 4 characters, and produces up
4705 * to 6 characters: reserve space for 2 extra */
4706 if (*p == '<')
4707 extra += 2;
4708 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004709 }
4710
4711 if (*p != '"')
4712 {
4713 EMSG2(_("E114: Missing quote: %s"), *arg);
4714 return FAIL;
4715 }
4716
4717 /* If only parsing, set *arg and return here */
4718 if (!evaluate)
4719 {
4720 *arg = p + 1;
4721 return OK;
4722 }
4723
4724 /*
4725 * Copy the string into allocated memory, handling backslashed
4726 * characters.
4727 */
4728 name = alloc((unsigned)(p - *arg + extra));
4729 if (name == NULL)
4730 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004731 rettv->v_type = VAR_STRING;
4732 rettv->vval.v_string = name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004733
Bram Moolenaar8c711452005-01-14 21:53:12 +00004734 for (p = *arg + 1; *p != NUL && *p != '"'; )
Bram Moolenaar071d4272004-06-13 20:20:40 +00004735 {
4736 if (*p == '\\')
4737 {
4738 switch (*++p)
4739 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004740 case 'b': *name++ = BS; ++p; break;
4741 case 'e': *name++ = ESC; ++p; break;
4742 case 'f': *name++ = FF; ++p; break;
4743 case 'n': *name++ = NL; ++p; break;
4744 case 'r': *name++ = CAR; ++p; break;
4745 case 't': *name++ = TAB; ++p; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004746
4747 case 'X': /* hex: "\x1", "\x12" */
4748 case 'x':
4749 case 'u': /* Unicode: "\u0023" */
4750 case 'U':
4751 if (vim_isxdigit(p[1]))
4752 {
4753 int n, nr;
4754 int c = toupper(*p);
4755
4756 if (c == 'X')
4757 n = 2;
4758 else
4759 n = 4;
4760 nr = 0;
4761 while (--n >= 0 && vim_isxdigit(p[1]))
4762 {
4763 ++p;
4764 nr = (nr << 4) + hex2nr(*p);
4765 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004766 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004767#ifdef FEAT_MBYTE
4768 /* For "\u" store the number according to
4769 * 'encoding'. */
4770 if (c != 'X')
Bram Moolenaar8c711452005-01-14 21:53:12 +00004771 name += (*mb_char2bytes)(nr, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004772 else
4773#endif
Bram Moolenaar8c711452005-01-14 21:53:12 +00004774 *name++ = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004775 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004776 break;
4777
4778 /* octal: "\1", "\12", "\123" */
4779 case '0':
4780 case '1':
4781 case '2':
4782 case '3':
4783 case '4':
4784 case '5':
4785 case '6':
Bram Moolenaar8c711452005-01-14 21:53:12 +00004786 case '7': *name = *p++ - '0';
4787 if (*p >= '0' && *p <= '7')
Bram Moolenaar071d4272004-06-13 20:20:40 +00004788 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004789 *name = (*name << 3) + *p++ - '0';
4790 if (*p >= '0' && *p <= '7')
4791 *name = (*name << 3) + *p++ - '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +00004792 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004793 ++name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004794 break;
4795
4796 /* Special key, e.g.: "\<C-W>" */
Bram Moolenaar8c711452005-01-14 21:53:12 +00004797 case '<': extra = trans_special(&p, name, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004798 if (extra != 0)
4799 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004800 name += extra;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004801 break;
4802 }
4803 /* FALLTHROUGH */
4804
Bram Moolenaar8c711452005-01-14 21:53:12 +00004805 default: MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004806 break;
4807 }
4808 }
4809 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00004810 MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004811
Bram Moolenaar071d4272004-06-13 20:20:40 +00004812 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004813 *name = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004814 *arg = p + 1;
4815
Bram Moolenaar071d4272004-06-13 20:20:40 +00004816 return OK;
4817}
4818
4819/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004820 * Allocate a variable for a 'str''ing' constant.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004821 * Return OK or FAIL.
4822 */
4823 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004824get_lit_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004825 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004826 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004827 int evaluate;
4828{
4829 char_u *p;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004830 char_u *str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004831 int reduce = 0;
4832
4833 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004834 * Find the end of the string, skipping ''.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004835 */
4836 for (p = *arg + 1; *p != NUL; mb_ptr_adv(p))
4837 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004838 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004839 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004840 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004841 break;
4842 ++reduce;
4843 ++p;
4844 }
4845 }
4846
Bram Moolenaar8c711452005-01-14 21:53:12 +00004847 if (*p != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004848 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004849 EMSG2(_("E115: Missing quote: %s"), *arg);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004850 return FAIL;
4851 }
4852
Bram Moolenaar8c711452005-01-14 21:53:12 +00004853 /* If only parsing return after setting "*arg" */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004854 if (!evaluate)
4855 {
4856 *arg = p + 1;
4857 return OK;
4858 }
4859
4860 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004861 * Copy the string into allocated memory, handling '' to ' reduction.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004862 */
4863 str = alloc((unsigned)((p - *arg) - reduce));
4864 if (str == NULL)
4865 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004866 rettv->v_type = VAR_STRING;
4867 rettv->vval.v_string = str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004868
Bram Moolenaar8c711452005-01-14 21:53:12 +00004869 for (p = *arg + 1; *p != NUL; )
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004870 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004871 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004872 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004873 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004874 break;
4875 ++p;
4876 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004877 MB_COPY_CHAR(p, str);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004878 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004879 *str = NUL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004880 *arg = p + 1;
4881
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004882 return OK;
4883}
4884
4885/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004886 * Allocate a variable for a List and fill it from "*arg".
4887 * Return OK or FAIL.
4888 */
4889 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004890get_list_tv(arg, rettv, evaluate)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004891 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004892 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004893 int evaluate;
4894{
Bram Moolenaar33570922005-01-25 22:26:29 +00004895 list_T *l = NULL;
4896 typval_T tv;
4897 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004898
4899 if (evaluate)
4900 {
4901 l = list_alloc();
4902 if (l == NULL)
4903 return FAIL;
4904 }
4905
4906 *arg = skipwhite(*arg + 1);
4907 while (**arg != ']' && **arg != NUL)
4908 {
4909 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
4910 goto failret;
4911 if (evaluate)
4912 {
4913 item = listitem_alloc();
4914 if (item != NULL)
4915 {
4916 item->li_tv = tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00004917 item->li_tv.v_lock = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004918 list_append(l, item);
4919 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00004920 else
4921 clear_tv(&tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004922 }
4923
4924 if (**arg == ']')
4925 break;
4926 if (**arg != ',')
4927 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004928 EMSG2(_("E696: Missing comma in List: %s"), *arg);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004929 goto failret;
4930 }
4931 *arg = skipwhite(*arg + 1);
4932 }
4933
4934 if (**arg != ']')
4935 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004936 EMSG2(_("E697: Missing end of List ']': %s"), *arg);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004937failret:
4938 if (evaluate)
4939 list_free(l);
4940 return FAIL;
4941 }
4942
4943 *arg = skipwhite(*arg + 1);
4944 if (evaluate)
4945 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004946 rettv->v_type = VAR_LIST;
4947 rettv->vval.v_list = l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004948 ++l->lv_refcount;
4949 }
4950
4951 return OK;
4952}
4953
4954/*
4955 * Allocate an empty header for a list.
4956 */
Bram Moolenaar33570922005-01-25 22:26:29 +00004957 static list_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004958list_alloc()
4959{
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00004960 list_T *l;
4961
4962 l = (list_T *)alloc_clear(sizeof(list_T));
4963 if (l != NULL)
4964 {
4965 /* Prepend the list to the list of lists for garbage collection. */
4966 if (first_list != NULL)
4967 first_list->lv_used_prev = l;
4968 l->lv_used_prev = NULL;
4969 l->lv_used_next = first_list;
4970 first_list = l;
4971 }
4972 return l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004973}
4974
4975/*
4976 * Unreference a list: decrement the reference count and free it when it
4977 * becomes zero.
4978 */
4979 static void
4980list_unref(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00004981 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004982{
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00004983 if (l != NULL && l->lv_refcount != DEL_REFCOUNT && --l->lv_refcount <= 0)
4984 list_free(l);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004985}
4986
4987/*
4988 * Free a list, including all items it points to.
4989 * Ignores the reference count.
4990 */
4991 static void
4992list_free(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00004993 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004994{
Bram Moolenaar33570922005-01-25 22:26:29 +00004995 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004996
Bram Moolenaard9fba312005-06-26 22:34:35 +00004997 /* Avoid that recursive reference to the list frees us again. */
4998 l->lv_refcount = DEL_REFCOUNT;
4999
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005000 /* Remove the list from the list of lists for garbage collection. */
5001 if (l->lv_used_prev == NULL)
5002 first_list = l->lv_used_next;
5003 else
5004 l->lv_used_prev->lv_used_next = l->lv_used_next;
5005 if (l->lv_used_next != NULL)
5006 l->lv_used_next->lv_used_prev = l->lv_used_prev;
5007
Bram Moolenaard9fba312005-06-26 22:34:35 +00005008 for (item = l->lv_first; item != NULL; item = l->lv_first)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005009 {
Bram Moolenaard9fba312005-06-26 22:34:35 +00005010 /* Remove the item before deleting it. */
5011 l->lv_first = item->li_next;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005012 listitem_free(item);
5013 }
5014 vim_free(l);
5015}
5016
5017/*
5018 * Allocate a list item.
5019 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005020 static listitem_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005021listitem_alloc()
5022{
Bram Moolenaar33570922005-01-25 22:26:29 +00005023 return (listitem_T *)alloc(sizeof(listitem_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005024}
5025
5026/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00005027 * Free a list item. Also clears the value. Does not notify watchers.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005028 */
5029 static void
5030listitem_free(item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005031 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005032{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005033 clear_tv(&item->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005034 vim_free(item);
5035}
5036
5037/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005038 * Remove a list item from a List and free it. Also clears the value.
5039 */
5040 static void
5041listitem_remove(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005042 list_T *l;
5043 listitem_T *item;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005044{
5045 list_remove(l, item, item);
5046 listitem_free(item);
5047}
5048
5049/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005050 * Get the number of items in a list.
5051 */
5052 static long
5053list_len(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00005054 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005055{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005056 if (l == NULL)
5057 return 0L;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005058 return l->lv_len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005059}
5060
5061/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005062 * Return TRUE when two lists have exactly the same values.
5063 */
5064 static int
5065list_equal(l1, l2, ic)
Bram Moolenaar33570922005-01-25 22:26:29 +00005066 list_T *l1;
5067 list_T *l2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005068 int ic; /* ignore case for strings */
5069{
Bram Moolenaar33570922005-01-25 22:26:29 +00005070 listitem_T *item1, *item2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005071
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005072 if (list_len(l1) != list_len(l2))
5073 return FALSE;
5074
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005075 for (item1 = l1->lv_first, item2 = l2->lv_first;
5076 item1 != NULL && item2 != NULL;
5077 item1 = item1->li_next, item2 = item2->li_next)
5078 if (!tv_equal(&item1->li_tv, &item2->li_tv, ic))
5079 return FALSE;
5080 return item1 == NULL && item2 == NULL;
5081}
5082
5083/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005084 * Return TRUE when two dictionaries have exactly the same key/values.
5085 */
5086 static int
5087dict_equal(d1, d2, ic)
Bram Moolenaar33570922005-01-25 22:26:29 +00005088 dict_T *d1;
5089 dict_T *d2;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005090 int ic; /* ignore case for strings */
5091{
Bram Moolenaar33570922005-01-25 22:26:29 +00005092 hashitem_T *hi;
5093 dictitem_T *item2;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005094 int todo;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005095
5096 if (dict_len(d1) != dict_len(d2))
5097 return FALSE;
5098
Bram Moolenaar33570922005-01-25 22:26:29 +00005099 todo = d1->dv_hashtab.ht_used;
5100 for (hi = d1->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005101 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005102 if (!HASHITEM_EMPTY(hi))
5103 {
5104 item2 = dict_find(d2, hi->hi_key, -1);
5105 if (item2 == NULL)
5106 return FALSE;
5107 if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic))
5108 return FALSE;
5109 --todo;
5110 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005111 }
5112 return TRUE;
5113}
5114
5115/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005116 * Return TRUE if "tv1" and "tv2" have the same value.
5117 * Compares the items just like "==" would compare them.
5118 */
5119 static int
5120tv_equal(tv1, tv2, ic)
Bram Moolenaar33570922005-01-25 22:26:29 +00005121 typval_T *tv1;
5122 typval_T *tv2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005123 int ic; /* ignore case */
5124{
5125 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005126 char_u *s1, *s2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005127
5128 if (tv1->v_type == VAR_LIST || tv2->v_type == VAR_LIST)
5129 {
5130 /* recursive! */
5131 if (tv1->v_type != tv2->v_type
5132 || !list_equal(tv1->vval.v_list, tv2->vval.v_list, ic))
5133 return FALSE;
5134 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005135 else if (tv1->v_type == VAR_DICT || tv2->v_type == VAR_DICT)
5136 {
5137 /* recursive! */
5138 if (tv1->v_type != tv2->v_type
5139 || !dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic))
5140 return FALSE;
5141 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005142 else if (tv1->v_type == VAR_FUNC || tv2->v_type == VAR_FUNC)
5143 {
5144 if (tv1->v_type != tv2->v_type
5145 || tv1->vval.v_string == NULL
5146 || tv2->vval.v_string == NULL
5147 || STRCMP(tv1->vval.v_string, tv2->vval.v_string) != 0)
5148 return FALSE;
5149 }
5150 else if (tv1->v_type == VAR_NUMBER || tv2->v_type == VAR_NUMBER)
5151 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005152 /* "4" is equal to 4. But don't consider 'a' and zero to be equal.
5153 * Don't consider "4x" to be equal to 4. */
5154 if ((tv1->v_type == VAR_STRING
5155 && !string_isa_number(tv1->vval.v_string))
5156 || (tv2->v_type == VAR_STRING
5157 && !string_isa_number(tv2->vval.v_string)))
5158 return FALSE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005159 if (get_tv_number(tv1) != get_tv_number(tv2))
5160 return FALSE;
5161 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005162 else
5163 {
5164 s1 = get_tv_string_buf(tv1, buf1);
5165 s2 = get_tv_string_buf(tv2, buf2);
5166 if ((ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2)) != 0)
5167 return FALSE;
5168 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005169 return TRUE;
5170}
5171
5172/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005173 * Return TRUE if "tv" is a number without other non-white characters.
5174 */
5175 static int
5176string_isa_number(s)
5177 char_u *s;
5178{
5179 int len;
5180
5181 vim_str2nr(s, NULL, &len, TRUE, TRUE, NULL, NULL);
5182 return len > 0 && *skipwhite(s + len) == NUL;
5183}
5184
5185/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005186 * Locate item with index "n" in list "l" and return it.
5187 * A negative index is counted from the end; -1 is the last item.
5188 * Returns NULL when "n" is out of range.
5189 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005190 static listitem_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005191list_find(l, n)
Bram Moolenaar33570922005-01-25 22:26:29 +00005192 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005193 long n;
5194{
Bram Moolenaar33570922005-01-25 22:26:29 +00005195 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005196 long idx;
5197
5198 if (l == NULL)
5199 return NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005200
5201 /* Negative index is relative to the end. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005202 if (n < 0)
Bram Moolenaar758711c2005-02-02 23:11:38 +00005203 n = l->lv_len + n;
5204
5205 /* Check for index out of range. */
5206 if (n < 0 || n >= l->lv_len)
5207 return NULL;
5208
5209 /* When there is a cached index may start search from there. */
5210 if (l->lv_idx_item != NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005211 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00005212 if (n < l->lv_idx / 2)
5213 {
5214 /* closest to the start of the list */
5215 item = l->lv_first;
5216 idx = 0;
5217 }
5218 else if (n > (l->lv_idx + l->lv_len) / 2)
5219 {
5220 /* closest to the end of the list */
5221 item = l->lv_last;
5222 idx = l->lv_len - 1;
5223 }
5224 else
5225 {
5226 /* closest to the cached index */
5227 item = l->lv_idx_item;
5228 idx = l->lv_idx;
5229 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005230 }
5231 else
5232 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00005233 if (n < l->lv_len / 2)
5234 {
5235 /* closest to the start of the list */
5236 item = l->lv_first;
5237 idx = 0;
5238 }
5239 else
5240 {
5241 /* closest to the end of the list */
5242 item = l->lv_last;
5243 idx = l->lv_len - 1;
5244 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005245 }
Bram Moolenaar758711c2005-02-02 23:11:38 +00005246
5247 while (n > idx)
5248 {
5249 /* search forward */
5250 item = item->li_next;
5251 ++idx;
5252 }
5253 while (n < idx)
5254 {
5255 /* search backward */
5256 item = item->li_prev;
5257 --idx;
5258 }
5259
5260 /* cache the used index */
5261 l->lv_idx = idx;
5262 l->lv_idx_item = item;
5263
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005264 return item;
5265}
5266
5267/*
Bram Moolenaar6cc16192005-01-08 21:49:45 +00005268 * Locate "item" list "l" and return its index.
5269 * Returns -1 when "item" is not in the list.
5270 */
5271 static long
5272list_idx_of_item(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005273 list_T *l;
5274 listitem_T *item;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00005275{
5276 long idx = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00005277 listitem_T *li;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00005278
5279 if (l == NULL)
5280 return -1;
5281 idx = 0;
5282 for (li = l->lv_first; li != NULL && li != item; li = li->li_next)
5283 ++idx;
5284 if (li == NULL)
5285 return -1;
Bram Moolenaar75c50c42005-06-04 22:06:24 +00005286 return idx;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00005287}
5288
5289/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005290 * Append item "item" to the end of list "l".
5291 */
5292 static void
5293list_append(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005294 list_T *l;
5295 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005296{
5297 if (l->lv_last == NULL)
5298 {
5299 /* empty list */
5300 l->lv_first = item;
5301 l->lv_last = item;
5302 item->li_prev = NULL;
5303 }
5304 else
5305 {
5306 l->lv_last->li_next = item;
5307 item->li_prev = l->lv_last;
5308 l->lv_last = item;
5309 }
Bram Moolenaar758711c2005-02-02 23:11:38 +00005310 ++l->lv_len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005311 item->li_next = NULL;
5312}
5313
5314/*
Bram Moolenaar33570922005-01-25 22:26:29 +00005315 * Append typval_T "tv" to the end of list "l".
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005316 * Return FAIL when out of memory.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005317 */
5318 static int
5319list_append_tv(l, tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005320 list_T *l;
5321 typval_T *tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005322{
Bram Moolenaar05159a02005-02-26 23:04:13 +00005323 listitem_T *li = listitem_alloc();
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005324
Bram Moolenaar05159a02005-02-26 23:04:13 +00005325 if (li == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005326 return FAIL;
Bram Moolenaar05159a02005-02-26 23:04:13 +00005327 copy_tv(tv, &li->li_tv);
5328 list_append(l, li);
5329 return OK;
5330}
5331
5332/*
Bram Moolenaar2641f772005-03-25 21:58:17 +00005333 * Add a dictionary to a list. Used by getqflist().
Bram Moolenaar05159a02005-02-26 23:04:13 +00005334 * Return FAIL when out of memory.
5335 */
5336 int
5337list_append_dict(list, dict)
5338 list_T *list;
5339 dict_T *dict;
5340{
5341 listitem_T *li = listitem_alloc();
5342
5343 if (li == NULL)
5344 return FAIL;
5345 li->li_tv.v_type = VAR_DICT;
5346 li->li_tv.v_lock = 0;
5347 li->li_tv.vval.v_dict = dict;
5348 list_append(list, li);
5349 ++dict->dv_refcount;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005350 return OK;
5351}
5352
5353/*
Bram Moolenaar33570922005-01-25 22:26:29 +00005354 * Insert typval_T "tv" in list "l" before "item".
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005355 * If "item" is NULL append at the end.
5356 * Return FAIL when out of memory.
5357 */
5358 static int
5359list_insert_tv(l, tv, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005360 list_T *l;
5361 typval_T *tv;
5362 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005363{
Bram Moolenaar33570922005-01-25 22:26:29 +00005364 listitem_T *ni = listitem_alloc();
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005365
5366 if (ni == NULL)
5367 return FAIL;
5368 copy_tv(tv, &ni->li_tv);
5369 if (item == NULL)
5370 /* Append new item at end of list. */
5371 list_append(l, ni);
5372 else
5373 {
5374 /* Insert new item before existing item. */
5375 ni->li_prev = item->li_prev;
5376 ni->li_next = item;
5377 if (item->li_prev == NULL)
Bram Moolenaar758711c2005-02-02 23:11:38 +00005378 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005379 l->lv_first = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005380 ++l->lv_idx;
5381 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005382 else
Bram Moolenaar758711c2005-02-02 23:11:38 +00005383 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005384 item->li_prev->li_next = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005385 l->lv_idx_item = NULL;
5386 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005387 item->li_prev = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005388 ++l->lv_len;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005389 }
5390 return OK;
5391}
5392
5393/*
5394 * Extend "l1" with "l2".
5395 * If "bef" is NULL append at the end, otherwise insert before this item.
5396 * Returns FAIL when out of memory.
5397 */
5398 static int
5399list_extend(l1, l2, bef)
Bram Moolenaar33570922005-01-25 22:26:29 +00005400 list_T *l1;
5401 list_T *l2;
5402 listitem_T *bef;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005403{
Bram Moolenaar33570922005-01-25 22:26:29 +00005404 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005405
5406 for (item = l2->lv_first; item != NULL; item = item->li_next)
5407 if (list_insert_tv(l1, &item->li_tv, bef) == FAIL)
5408 return FAIL;
5409 return OK;
5410}
5411
5412/*
5413 * Concatenate lists "l1" and "l2" into a new list, stored in "tv".
5414 * Return FAIL when out of memory.
5415 */
5416 static int
5417list_concat(l1, l2, tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005418 list_T *l1;
5419 list_T *l2;
5420 typval_T *tv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005421{
Bram Moolenaar33570922005-01-25 22:26:29 +00005422 list_T *l;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005423
5424 /* make a copy of the first list. */
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005425 l = list_copy(l1, FALSE, 0);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005426 if (l == NULL)
5427 return FAIL;
5428 tv->v_type = VAR_LIST;
5429 tv->vval.v_list = l;
5430
5431 /* append all items from the second list */
5432 return list_extend(l, l2, NULL);
5433}
5434
5435/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005436 * Make a copy of list "orig". Shallow if "deep" is FALSE.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005437 * The refcount of the new list is set to 1.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005438 * See item_copy() for "copyID".
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005439 * Returns NULL when out of memory.
5440 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005441 static list_T *
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005442list_copy(orig, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00005443 list_T *orig;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005444 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005445 int copyID;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005446{
Bram Moolenaar33570922005-01-25 22:26:29 +00005447 list_T *copy;
5448 listitem_T *item;
5449 listitem_T *ni;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005450
5451 if (orig == NULL)
5452 return NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005453
5454 copy = list_alloc();
5455 if (copy != NULL)
5456 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005457 if (copyID != 0)
5458 {
5459 /* Do this before adding the items, because one of the items may
5460 * refer back to this list. */
5461 orig->lv_copyID = copyID;
5462 orig->lv_copylist = copy;
5463 }
5464 for (item = orig->lv_first; item != NULL && !got_int;
5465 item = item->li_next)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005466 {
5467 ni = listitem_alloc();
5468 if (ni == NULL)
5469 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005470 if (deep)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005471 {
5472 if (item_copy(&item->li_tv, &ni->li_tv, deep, copyID) == FAIL)
5473 {
5474 vim_free(ni);
5475 break;
5476 }
5477 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005478 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005479 copy_tv(&item->li_tv, &ni->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005480 list_append(copy, ni);
5481 }
5482 ++copy->lv_refcount;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005483 if (item != NULL)
5484 {
5485 list_unref(copy);
5486 copy = NULL;
5487 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005488 }
5489
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005490 return copy;
5491}
5492
5493/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005494 * Remove items "item" to "item2" from list "l".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005495 * Does not free the listitem or the value!
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005496 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005497 static void
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005498list_remove(l, item, item2)
Bram Moolenaar33570922005-01-25 22:26:29 +00005499 list_T *l;
5500 listitem_T *item;
5501 listitem_T *item2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005502{
Bram Moolenaar33570922005-01-25 22:26:29 +00005503 listitem_T *ip;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005504
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005505 /* notify watchers */
5506 for (ip = item; ip != NULL; ip = ip->li_next)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005507 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00005508 --l->lv_len;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005509 list_fix_watch(l, ip);
5510 if (ip == item2)
5511 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005512 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005513
5514 if (item2->li_next == NULL)
5515 l->lv_last = item->li_prev;
5516 else
5517 item2->li_next->li_prev = item->li_prev;
5518 if (item->li_prev == NULL)
5519 l->lv_first = item2->li_next;
5520 else
5521 item->li_prev->li_next = item2->li_next;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005522 l->lv_idx_item = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005523}
5524
5525/*
5526 * Return an allocated string with the string representation of a list.
5527 * May return NULL.
5528 */
5529 static char_u *
5530list2string(tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005531 typval_T *tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005532{
5533 garray_T ga;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005534
5535 if (tv->vval.v_list == NULL)
5536 return NULL;
5537 ga_init2(&ga, (int)sizeof(char), 80);
5538 ga_append(&ga, '[');
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005539 if (list_join(&ga, tv->vval.v_list, (char_u *)", ", FALSE) == FAIL)
5540 {
5541 vim_free(ga.ga_data);
5542 return NULL;
5543 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005544 ga_append(&ga, ']');
5545 ga_append(&ga, NUL);
5546 return (char_u *)ga.ga_data;
5547}
5548
5549/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005550 * Join list "l" into a string in "*gap", using separator "sep".
5551 * When "echo" is TRUE use String as echoed, otherwise as inside a List.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005552 * Return FAIL or OK.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005553 */
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005554 static int
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005555list_join(gap, l, sep, echo)
5556 garray_T *gap;
Bram Moolenaar33570922005-01-25 22:26:29 +00005557 list_T *l;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005558 char_u *sep;
5559 int echo;
5560{
5561 int first = TRUE;
5562 char_u *tofree;
5563 char_u numbuf[NUMBUFLEN];
Bram Moolenaar33570922005-01-25 22:26:29 +00005564 listitem_T *item;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005565 char_u *s;
5566
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005567 for (item = l->lv_first; item != NULL && !got_int; item = item->li_next)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005568 {
5569 if (first)
5570 first = FALSE;
5571 else
5572 ga_concat(gap, sep);
5573
5574 if (echo)
5575 s = echo_string(&item->li_tv, &tofree, numbuf);
5576 else
5577 s = tv2string(&item->li_tv, &tofree, numbuf);
5578 if (s != NULL)
5579 ga_concat(gap, s);
5580 vim_free(tofree);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005581 if (s == NULL)
5582 return FAIL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005583 }
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005584 return OK;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005585}
5586
5587/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005588 * Garbage collection for lists and dictionaries.
5589 *
5590 * We use reference counts to be able to free most items right away when they
5591 * are no longer used. But for composite items it's possible that it becomes
5592 * unused while the reference count is > 0: When there is a recursive
5593 * reference. Example:
5594 * :let l = [1, 2, 3]
5595 * :let d = {9: l}
5596 * :let l[1] = d
5597 *
5598 * Since this is quite unusual we handle this with garbage collection: every
5599 * once in a while find out which lists and dicts are not referenced from any
5600 * variable.
5601 *
5602 * Here is a good reference text about garbage collection (refers to Python
5603 * but it applies to all reference-counting mechanisms):
5604 * http://python.ca/nas/python/gc/
Bram Moolenaard9fba312005-06-26 22:34:35 +00005605 */
Bram Moolenaard9fba312005-06-26 22:34:35 +00005606
5607/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005608 * Do garbage collection for lists and dicts.
5609 * Return TRUE if some memory was freed.
Bram Moolenaard9fba312005-06-26 22:34:35 +00005610 */
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005611 int
5612garbage_collect()
Bram Moolenaard9fba312005-06-26 22:34:35 +00005613{
5614 dict_T *dd;
5615 list_T *ll;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005616 int copyID = ++current_copyID;
5617 buf_T *buf;
5618 win_T *wp;
5619 int i;
5620 funccall_T *fc;
5621 int did_free = FALSE;
5622
5623 /*
5624 * 1. Go through all accessible variables and mark all lists and dicts
5625 * with copyID.
5626 */
5627 /* script-local variables */
5628 for (i = 1; i <= ga_scripts.ga_len; ++i)
5629 set_ref_in_ht(&SCRIPT_VARS(i), copyID);
5630
5631 /* buffer-local variables */
5632 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
5633 set_ref_in_ht(&buf->b_vars.dv_hashtab, copyID);
5634
5635 /* window-local variables */
5636 FOR_ALL_WINDOWS(wp)
5637 set_ref_in_ht(&wp->w_vars.dv_hashtab, copyID);
5638
5639 /* global variables */
5640 set_ref_in_ht(&globvarht, copyID);
5641
5642 /* function-local variables */
5643 for (fc = current_funccal; fc != NULL; fc = fc->caller)
5644 {
5645 set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID);
5646 set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID);
5647 }
5648
5649 /*
5650 * 2. Go through the list of dicts and free items without the copyID.
5651 */
5652 for (dd = first_dict; dd != NULL; )
5653 if (dd->dv_copyID != copyID)
5654 {
5655 dict_free(dd);
5656 did_free = TRUE;
5657
5658 /* restart, next dict may also have been freed */
5659 dd = first_dict;
5660 }
5661 else
5662 dd = dd->dv_used_next;
5663
5664 /*
5665 * 3. Go through the list of lists and free items without the copyID.
5666 */
5667 for (ll = first_list; ll != NULL; )
5668 if (ll->lv_copyID != copyID)
5669 {
5670 list_free(ll);
5671 did_free = TRUE;
5672
5673 /* restart, next dict may also have been freed */
5674 ll = first_list;
5675 }
5676 else
5677 ll = ll->lv_used_next;
5678
5679 return did_free;
5680}
5681
5682/*
5683 * Mark all lists and dicts referenced through hashtab "ht" with "copyID".
5684 */
5685 static void
5686set_ref_in_ht(ht, copyID)
5687 hashtab_T *ht;
5688 int copyID;
5689{
5690 int todo;
5691 hashitem_T *hi;
5692
5693 todo = ht->ht_used;
5694 for (hi = ht->ht_array; todo > 0; ++hi)
5695 if (!HASHITEM_EMPTY(hi))
5696 {
5697 --todo;
5698 set_ref_in_item(&HI2DI(hi)->di_tv, copyID);
5699 }
5700}
5701
5702/*
5703 * Mark all lists and dicts referenced through list "l" with "copyID".
5704 */
5705 static void
5706set_ref_in_list(l, copyID)
5707 list_T *l;
5708 int copyID;
5709{
5710 listitem_T *li;
5711
5712 for (li = l->lv_first; li != NULL; li = li->li_next)
5713 set_ref_in_item(&li->li_tv, copyID);
5714}
5715
5716/*
5717 * Mark all lists and dicts referenced through typval "tv" with "copyID".
5718 */
5719 static void
5720set_ref_in_item(tv, copyID)
5721 typval_T *tv;
5722 int copyID;
5723{
5724 dict_T *dd;
5725 list_T *ll;
Bram Moolenaard9fba312005-06-26 22:34:35 +00005726
5727 switch (tv->v_type)
5728 {
5729 case VAR_DICT:
5730 dd = tv->vval.v_dict;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005731 if (dd->dv_copyID != copyID)
Bram Moolenaard9fba312005-06-26 22:34:35 +00005732 {
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005733 /* Didn't see this dict yet. */
5734 dd->dv_copyID = copyID;
5735 set_ref_in_ht(&dd->dv_hashtab, copyID);
Bram Moolenaard9fba312005-06-26 22:34:35 +00005736 }
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005737 break;
Bram Moolenaard9fba312005-06-26 22:34:35 +00005738
5739 case VAR_LIST:
5740 ll = tv->vval.v_list;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005741 if (ll->lv_copyID != copyID)
Bram Moolenaard9fba312005-06-26 22:34:35 +00005742 {
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005743 /* Didn't see this list yet. */
5744 ll->lv_copyID = copyID;
5745 set_ref_in_list(ll, copyID);
Bram Moolenaard9fba312005-06-26 22:34:35 +00005746 }
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005747 break;
Bram Moolenaard9fba312005-06-26 22:34:35 +00005748 }
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005749 return;
Bram Moolenaard9fba312005-06-26 22:34:35 +00005750}
5751
5752/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005753 * Allocate an empty header for a dictionary.
5754 */
Bram Moolenaar05159a02005-02-26 23:04:13 +00005755 dict_T *
Bram Moolenaar8c711452005-01-14 21:53:12 +00005756dict_alloc()
5757{
Bram Moolenaar33570922005-01-25 22:26:29 +00005758 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005759
Bram Moolenaar33570922005-01-25 22:26:29 +00005760 d = (dict_T *)alloc(sizeof(dict_T));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005761 if (d != NULL)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005762 {
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005763 /* Add the list to the hashtable for garbage collection. */
5764 if (first_dict != NULL)
5765 first_dict->dv_used_prev = d;
5766 d->dv_used_next = first_dict;
5767 d->dv_used_prev = NULL;
5768
Bram Moolenaar33570922005-01-25 22:26:29 +00005769 hash_init(&d->dv_hashtab);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005770 d->dv_lock = 0;
5771 d->dv_refcount = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005772 d->dv_copyID = 0;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005773 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005774 return d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005775}
5776
5777/*
5778 * Unreference a Dictionary: decrement the reference count and free it when it
5779 * becomes zero.
5780 */
5781 static void
5782dict_unref(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00005783 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005784{
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005785 if (d != NULL && d->dv_refcount != DEL_REFCOUNT && --d->dv_refcount <= 0)
5786 dict_free(d);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005787}
5788
5789/*
5790 * Free a Dictionary, including all items it contains.
5791 * Ignores the reference count.
5792 */
5793 static void
5794dict_free(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00005795 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005796{
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005797 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00005798 hashitem_T *hi;
Bram Moolenaard9fba312005-06-26 22:34:35 +00005799 dictitem_T *di;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005800
Bram Moolenaard9fba312005-06-26 22:34:35 +00005801 /* Avoid that recursive reference to the dict frees us again. */
5802 d->dv_refcount = DEL_REFCOUNT;
5803
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005804 /* Remove the dict from the list of dicts for garbage collection. */
5805 if (d->dv_used_prev == NULL)
5806 first_dict = d->dv_used_next;
5807 else
5808 d->dv_used_prev->dv_used_next = d->dv_used_next;
5809 if (d->dv_used_next != NULL)
5810 d->dv_used_next->dv_used_prev = d->dv_used_prev;
5811
5812 /* Lock the hashtab, we don't want it to resize while freeing items. */
Bram Moolenaard9fba312005-06-26 22:34:35 +00005813 hash_lock(&d->dv_hashtab);
Bram Moolenaar33570922005-01-25 22:26:29 +00005814 todo = d->dv_hashtab.ht_used;
5815 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005816 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005817 if (!HASHITEM_EMPTY(hi))
5818 {
Bram Moolenaard9fba312005-06-26 22:34:35 +00005819 /* Remove the item before deleting it, just in case there is
5820 * something recursive causing trouble. */
5821 di = HI2DI(hi);
5822 hash_remove(&d->dv_hashtab, hi);
5823 dictitem_free(di);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005824 --todo;
5825 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005826 }
Bram Moolenaar33570922005-01-25 22:26:29 +00005827 hash_clear(&d->dv_hashtab);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005828 vim_free(d);
5829}
5830
5831/*
5832 * Allocate a Dictionary item.
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005833 * The "key" is copied to the new item.
5834 * Note that the value of the item "di_tv" still needs to be initialized!
5835 * Returns NULL when out of memory.
Bram Moolenaar8c711452005-01-14 21:53:12 +00005836 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005837 static dictitem_T *
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005838dictitem_alloc(key)
5839 char_u *key;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005840{
Bram Moolenaar33570922005-01-25 22:26:29 +00005841 dictitem_T *di;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005842
Bram Moolenaar33570922005-01-25 22:26:29 +00005843 di = (dictitem_T *)alloc(sizeof(dictitem_T) + STRLEN(key));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005844 if (di != NULL)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005845 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005846 STRCPY(di->di_key, key);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005847 di->di_flags = 0;
5848 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005849 return di;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005850}
5851
5852/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005853 * Make a copy of a Dictionary item.
5854 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005855 static dictitem_T *
Bram Moolenaare9a41262005-01-15 22:18:47 +00005856dictitem_copy(org)
Bram Moolenaar33570922005-01-25 22:26:29 +00005857 dictitem_T *org;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005858{
Bram Moolenaar33570922005-01-25 22:26:29 +00005859 dictitem_T *di;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005860
Bram Moolenaar33570922005-01-25 22:26:29 +00005861 di = (dictitem_T *)alloc(sizeof(dictitem_T) + STRLEN(org->di_key));
Bram Moolenaare9a41262005-01-15 22:18:47 +00005862 if (di != NULL)
5863 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005864 STRCPY(di->di_key, org->di_key);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005865 di->di_flags = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005866 copy_tv(&org->di_tv, &di->di_tv);
5867 }
5868 return di;
5869}
5870
5871/*
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005872 * Remove item "item" from Dictionary "dict" and free it.
5873 */
5874 static void
5875dictitem_remove(dict, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005876 dict_T *dict;
5877 dictitem_T *item;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005878{
Bram Moolenaar33570922005-01-25 22:26:29 +00005879 hashitem_T *hi;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005880
Bram Moolenaar33570922005-01-25 22:26:29 +00005881 hi = hash_find(&dict->dv_hashtab, item->di_key);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005882 if (HASHITEM_EMPTY(hi))
5883 EMSG2(_(e_intern2), "dictitem_remove()");
5884 else
Bram Moolenaar33570922005-01-25 22:26:29 +00005885 hash_remove(&dict->dv_hashtab, hi);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005886 dictitem_free(item);
5887}
5888
5889/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005890 * Free a dict item. Also clears the value.
5891 */
5892 static void
5893dictitem_free(item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005894 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005895{
Bram Moolenaar8c711452005-01-14 21:53:12 +00005896 clear_tv(&item->di_tv);
5897 vim_free(item);
5898}
5899
5900/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005901 * Make a copy of dict "d". Shallow if "deep" is FALSE.
5902 * The refcount of the new dict is set to 1.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005903 * See item_copy() for "copyID".
Bram Moolenaare9a41262005-01-15 22:18:47 +00005904 * Returns NULL when out of memory.
5905 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005906 static dict_T *
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005907dict_copy(orig, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00005908 dict_T *orig;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005909 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005910 int copyID;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005911{
Bram Moolenaar33570922005-01-25 22:26:29 +00005912 dict_T *copy;
5913 dictitem_T *di;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005914 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00005915 hashitem_T *hi;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005916
5917 if (orig == NULL)
5918 return NULL;
5919
5920 copy = dict_alloc();
5921 if (copy != NULL)
5922 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005923 if (copyID != 0)
5924 {
5925 orig->dv_copyID = copyID;
5926 orig->dv_copydict = copy;
5927 }
Bram Moolenaar33570922005-01-25 22:26:29 +00005928 todo = orig->dv_hashtab.ht_used;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005929 for (hi = orig->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaare9a41262005-01-15 22:18:47 +00005930 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005931 if (!HASHITEM_EMPTY(hi))
Bram Moolenaare9a41262005-01-15 22:18:47 +00005932 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005933 --todo;
5934
5935 di = dictitem_alloc(hi->hi_key);
5936 if (di == NULL)
5937 break;
5938 if (deep)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005939 {
5940 if (item_copy(&HI2DI(hi)->di_tv, &di->di_tv, deep,
5941 copyID) == FAIL)
5942 {
5943 vim_free(di);
5944 break;
5945 }
5946 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005947 else
5948 copy_tv(&HI2DI(hi)->di_tv, &di->di_tv);
5949 if (dict_add(copy, di) == FAIL)
5950 {
5951 dictitem_free(di);
5952 break;
5953 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005954 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005955 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005956
Bram Moolenaare9a41262005-01-15 22:18:47 +00005957 ++copy->dv_refcount;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005958 if (todo > 0)
5959 {
5960 dict_unref(copy);
5961 copy = NULL;
5962 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005963 }
5964
5965 return copy;
5966}
5967
5968/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005969 * Add item "item" to Dictionary "d".
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005970 * Returns FAIL when out of memory and when key already existed.
Bram Moolenaar8c711452005-01-14 21:53:12 +00005971 */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005972 static int
Bram Moolenaar8c711452005-01-14 21:53:12 +00005973dict_add(d, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005974 dict_T *d;
5975 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005976{
Bram Moolenaar33570922005-01-25 22:26:29 +00005977 return hash_add(&d->dv_hashtab, item->di_key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005978}
5979
Bram Moolenaar8c711452005-01-14 21:53:12 +00005980/*
Bram Moolenaar05159a02005-02-26 23:04:13 +00005981 * Add a number or string entry to dictionary "d".
5982 * When "str" is NULL use number "nr", otherwise use "str".
5983 * Returns FAIL when out of memory and when key already exists.
5984 */
5985 int
5986dict_add_nr_str(d, key, nr, str)
5987 dict_T *d;
5988 char *key;
5989 long nr;
5990 char_u *str;
5991{
5992 dictitem_T *item;
5993
5994 item = dictitem_alloc((char_u *)key);
5995 if (item == NULL)
5996 return FAIL;
5997 item->di_tv.v_lock = 0;
5998 if (str == NULL)
5999 {
6000 item->di_tv.v_type = VAR_NUMBER;
6001 item->di_tv.vval.v_number = nr;
6002 }
6003 else
6004 {
6005 item->di_tv.v_type = VAR_STRING;
6006 item->di_tv.vval.v_string = vim_strsave(str);
6007 }
6008 if (dict_add(d, item) == FAIL)
6009 {
6010 dictitem_free(item);
6011 return FAIL;
6012 }
6013 return OK;
6014}
6015
6016/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00006017 * Get the number of items in a Dictionary.
6018 */
6019 static long
6020dict_len(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00006021 dict_T *d;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006022{
Bram Moolenaare9a41262005-01-15 22:18:47 +00006023 if (d == NULL)
6024 return 0L;
Bram Moolenaar33570922005-01-25 22:26:29 +00006025 return d->dv_hashtab.ht_used;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006026}
6027
6028/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00006029 * Find item "key[len]" in Dictionary "d".
6030 * If "len" is negative use strlen(key).
6031 * Returns NULL when not found.
6032 */
Bram Moolenaar33570922005-01-25 22:26:29 +00006033 static dictitem_T *
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006034dict_find(d, key, len)
Bram Moolenaar33570922005-01-25 22:26:29 +00006035 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006036 char_u *key;
6037 int len;
6038{
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006039#define AKEYLEN 200
6040 char_u buf[AKEYLEN];
6041 char_u *akey;
6042 char_u *tofree = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00006043 hashitem_T *hi;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006044
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006045 if (len < 0)
6046 akey = key;
6047 else if (len >= AKEYLEN)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00006048 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006049 tofree = akey = vim_strnsave(key, len);
6050 if (akey == NULL)
6051 return NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00006052 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006053 else
6054 {
6055 /* Avoid a malloc/free by using buf[]. */
6056 STRNCPY(buf, key, len);
6057 buf[len] = NUL;
6058 akey = buf;
6059 }
6060
Bram Moolenaar33570922005-01-25 22:26:29 +00006061 hi = hash_find(&d->dv_hashtab, akey);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006062 vim_free(tofree);
6063 if (HASHITEM_EMPTY(hi))
6064 return NULL;
6065 return HI2DI(hi);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006066}
6067
6068/*
Bram Moolenaar2641f772005-03-25 21:58:17 +00006069 * Get a string item from a dictionary in allocated memory.
6070 * Returns NULL if the entry doesn't exist or out of memory.
6071 */
6072 char_u *
6073get_dict_string(d, key)
6074 dict_T *d;
6075 char_u *key;
6076{
6077 dictitem_T *di;
6078
6079 di = dict_find(d, key, -1);
6080 if (di == NULL)
6081 return NULL;
6082 return vim_strsave(get_tv_string(&di->di_tv));
6083}
6084
6085/*
6086 * Get a number item from a dictionary.
6087 * Returns 0 if the entry doesn't exist or out of memory.
6088 */
6089 long
6090get_dict_number(d, key)
6091 dict_T *d;
6092 char_u *key;
6093{
6094 dictitem_T *di;
6095
6096 di = dict_find(d, key, -1);
6097 if (di == NULL)
6098 return 0;
6099 return get_tv_number(&di->di_tv);
6100}
6101
6102/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00006103 * Return an allocated string with the string representation of a Dictionary.
6104 * May return NULL.
6105 */
6106 static char_u *
6107dict2string(tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006108 typval_T *tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006109{
6110 garray_T ga;
6111 int first = TRUE;
6112 char_u *tofree;
6113 char_u numbuf[NUMBUFLEN];
Bram Moolenaar33570922005-01-25 22:26:29 +00006114 hashitem_T *hi;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006115 char_u *s;
Bram Moolenaar33570922005-01-25 22:26:29 +00006116 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006117 int todo;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006118
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006119 if ((d = tv->vval.v_dict) == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00006120 return NULL;
6121 ga_init2(&ga, (int)sizeof(char), 80);
6122 ga_append(&ga, '{');
6123
Bram Moolenaar33570922005-01-25 22:26:29 +00006124 todo = d->dv_hashtab.ht_used;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006125 for (hi = d->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +00006126 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006127 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar8c711452005-01-14 21:53:12 +00006128 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006129 --todo;
6130
6131 if (first)
6132 first = FALSE;
6133 else
6134 ga_concat(&ga, (char_u *)", ");
6135
6136 tofree = string_quote(hi->hi_key, FALSE);
6137 if (tofree != NULL)
6138 {
6139 ga_concat(&ga, tofree);
6140 vim_free(tofree);
6141 }
6142 ga_concat(&ga, (char_u *)": ");
6143 s = tv2string(&HI2DI(hi)->di_tv, &tofree, numbuf);
6144 if (s != NULL)
6145 ga_concat(&ga, s);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006146 vim_free(tofree);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006147 if (s == NULL)
6148 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006149 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006150 }
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006151 if (todo > 0)
6152 {
6153 vim_free(ga.ga_data);
6154 return NULL;
6155 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006156
6157 ga_append(&ga, '}');
6158 ga_append(&ga, NUL);
6159 return (char_u *)ga.ga_data;
6160}
6161
6162/*
6163 * Allocate a variable for a Dictionary and fill it from "*arg".
6164 * Return OK or FAIL. Returns NOTDONE for {expr}.
6165 */
6166 static int
6167get_dict_tv(arg, rettv, evaluate)
6168 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00006169 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006170 int evaluate;
6171{
Bram Moolenaar33570922005-01-25 22:26:29 +00006172 dict_T *d = NULL;
6173 typval_T tvkey;
6174 typval_T tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006175 char_u *key;
Bram Moolenaar33570922005-01-25 22:26:29 +00006176 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006177 char_u *start = skipwhite(*arg + 1);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006178 char_u buf[NUMBUFLEN];
Bram Moolenaar8c711452005-01-14 21:53:12 +00006179
6180 /*
6181 * First check if it's not a curly-braces thing: {expr}.
6182 * Must do this without evaluating, otherwise a function may be called
6183 * twice. Unfortunately this means we need to call eval1() twice for the
6184 * first item.
Bram Moolenaare9a41262005-01-15 22:18:47 +00006185 * But {} is an empty Dictionary.
Bram Moolenaar8c711452005-01-14 21:53:12 +00006186 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00006187 if (*start != '}')
6188 {
6189 if (eval1(&start, &tv, FALSE) == FAIL) /* recursive! */
6190 return FAIL;
6191 if (*start == '}')
6192 return NOTDONE;
6193 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006194
6195 if (evaluate)
6196 {
6197 d = dict_alloc();
6198 if (d == NULL)
6199 return FAIL;
6200 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006201 tvkey.v_type = VAR_UNKNOWN;
6202 tv.v_type = VAR_UNKNOWN;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006203
6204 *arg = skipwhite(*arg + 1);
6205 while (**arg != '}' && **arg != NUL)
6206 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006207 if (eval1(arg, &tvkey, evaluate) == FAIL) /* recursive! */
Bram Moolenaar8c711452005-01-14 21:53:12 +00006208 goto failret;
6209 if (**arg != ':')
6210 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006211 EMSG2(_("E720: Missing colon in Dictionary: %s"), *arg);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006212 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006213 goto failret;
6214 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006215 key = get_tv_string_buf_chk(&tvkey, buf);
6216 if (key == NULL || *key == NUL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00006217 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006218 /* "key" is NULL when get_tv_string_buf_chk() gave an errmsg */
6219 if (key != NULL)
6220 EMSG(_(e_emptykey));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006221 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006222 goto failret;
6223 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006224
6225 *arg = skipwhite(*arg + 1);
6226 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
6227 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006228 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006229 goto failret;
6230 }
6231 if (evaluate)
6232 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006233 item = dict_find(d, key, -1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006234 if (item != NULL)
6235 {
Bram Moolenaarb982ca52005-03-28 21:02:15 +00006236 EMSG2(_("E721: Duplicate key in Dictionary: \"%s\""), key);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006237 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006238 clear_tv(&tv);
6239 goto failret;
6240 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006241 item = dictitem_alloc(key);
6242 clear_tv(&tvkey);
6243 if (item != NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00006244 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00006245 item->di_tv = tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006246 item->di_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006247 if (dict_add(d, item) == FAIL)
6248 dictitem_free(item);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006249 }
6250 }
6251
6252 if (**arg == '}')
6253 break;
6254 if (**arg != ',')
6255 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006256 EMSG2(_("E722: Missing comma in Dictionary: %s"), *arg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006257 goto failret;
6258 }
6259 *arg = skipwhite(*arg + 1);
6260 }
6261
6262 if (**arg != '}')
6263 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006264 EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006265failret:
6266 if (evaluate)
6267 dict_free(d);
6268 return FAIL;
6269 }
6270
6271 *arg = skipwhite(*arg + 1);
6272 if (evaluate)
6273 {
6274 rettv->v_type = VAR_DICT;
6275 rettv->vval.v_dict = d;
6276 ++d->dv_refcount;
6277 }
6278
6279 return OK;
6280}
6281
Bram Moolenaar8c711452005-01-14 21:53:12 +00006282/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006283 * Return a string with the string representation of a variable.
6284 * If the memory is allocated "tofree" is set to it, otherwise NULL.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006285 * "numbuf" is used for a number.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006286 * Does not put quotes around strings, as ":echo" displays values.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006287 * May return NULL;
6288 */
6289 static char_u *
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006290echo_string(tv, tofree, numbuf)
Bram Moolenaar33570922005-01-25 22:26:29 +00006291 typval_T *tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006292 char_u **tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006293 char_u *numbuf;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006294{
Bram Moolenaare9a41262005-01-15 22:18:47 +00006295 static int recurse = 0;
6296 char_u *r = NULL;
6297
Bram Moolenaar33570922005-01-25 22:26:29 +00006298 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006299 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006300 EMSG(_("E724: variable nested too deep for displaying"));
Bram Moolenaare9a41262005-01-15 22:18:47 +00006301 *tofree = NULL;
6302 return NULL;
6303 }
6304 ++recurse;
6305
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006306 switch (tv->v_type)
6307 {
6308 case VAR_FUNC:
6309 *tofree = NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006310 r = tv->vval.v_string;
6311 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006312 case VAR_LIST:
6313 *tofree = list2string(tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00006314 r = *tofree;
6315 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006316 case VAR_DICT:
6317 *tofree = dict2string(tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00006318 r = *tofree;
6319 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006320 case VAR_STRING:
6321 case VAR_NUMBER:
Bram Moolenaare9a41262005-01-15 22:18:47 +00006322 *tofree = NULL;
6323 r = get_tv_string_buf(tv, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006324 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006325 default:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006326 EMSG2(_(e_intern2), "echo_string()");
Bram Moolenaare9a41262005-01-15 22:18:47 +00006327 *tofree = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006328 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006329
6330 --recurse;
6331 return r;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006332}
6333
6334/*
6335 * Return a string with the string representation of a variable.
6336 * If the memory is allocated "tofree" is set to it, otherwise NULL.
6337 * "numbuf" is used for a number.
6338 * Puts quotes around strings, so that they can be parsed back by eval().
6339 * May return NULL;
6340 */
6341 static char_u *
6342tv2string(tv, tofree, numbuf)
Bram Moolenaar33570922005-01-25 22:26:29 +00006343 typval_T *tv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006344 char_u **tofree;
6345 char_u *numbuf;
6346{
6347 switch (tv->v_type)
6348 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006349 case VAR_FUNC:
6350 *tofree = string_quote(tv->vval.v_string, TRUE);
6351 return *tofree;
6352 case VAR_STRING:
6353 *tofree = string_quote(tv->vval.v_string, FALSE);
6354 return *tofree;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006355 case VAR_NUMBER:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006356 case VAR_LIST:
Bram Moolenaar8c711452005-01-14 21:53:12 +00006357 case VAR_DICT:
Bram Moolenaare9a41262005-01-15 22:18:47 +00006358 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006359 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006360 EMSG2(_(e_intern2), "tv2string()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006361 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006362 return echo_string(tv, tofree, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006363}
6364
6365/*
Bram Moolenaar33570922005-01-25 22:26:29 +00006366 * Return string "str" in ' quotes, doubling ' characters.
6367 * If "str" is NULL an empty string is assumed.
Bram Moolenaar8c711452005-01-14 21:53:12 +00006368 * If "function" is TRUE make it function('string').
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006369 */
6370 static char_u *
6371string_quote(str, function)
6372 char_u *str;
6373 int function;
6374{
Bram Moolenaar33570922005-01-25 22:26:29 +00006375 unsigned len;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006376 char_u *p, *r, *s;
6377
Bram Moolenaar33570922005-01-25 22:26:29 +00006378 len = (function ? 13 : 3);
6379 if (str != NULL)
6380 {
6381 len += STRLEN(str);
6382 for (p = str; *p != NUL; mb_ptr_adv(p))
6383 if (*p == '\'')
6384 ++len;
6385 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006386 s = r = alloc(len);
6387 if (r != NULL)
6388 {
6389 if (function)
6390 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00006391 STRCPY(r, "function('");
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006392 r += 10;
6393 }
6394 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00006395 *r++ = '\'';
Bram Moolenaar33570922005-01-25 22:26:29 +00006396 if (str != NULL)
6397 for (p = str; *p != NUL; )
6398 {
6399 if (*p == '\'')
6400 *r++ = '\'';
6401 MB_COPY_CHAR(p, r);
6402 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006403 *r++ = '\'';
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006404 if (function)
6405 *r++ = ')';
6406 *r++ = NUL;
6407 }
6408 return s;
6409}
6410
6411/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006412 * Get the value of an environment variable.
6413 * "arg" is pointing to the '$'. It is advanced to after the name.
6414 * If the environment variable was not set, silently assume it is empty.
6415 * Always return OK.
6416 */
6417 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006418get_env_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006419 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00006420 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006421 int evaluate;
6422{
6423 char_u *string = NULL;
6424 int len;
6425 int cc;
6426 char_u *name;
Bram Moolenaar05159a02005-02-26 23:04:13 +00006427 int mustfree = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006428
6429 ++*arg;
6430 name = *arg;
6431 len = get_env_len(arg);
6432 if (evaluate)
6433 {
6434 if (len != 0)
6435 {
6436 cc = name[len];
6437 name[len] = NUL;
Bram Moolenaar05159a02005-02-26 23:04:13 +00006438 /* first try vim_getenv(), fast for normal environment vars */
6439 string = vim_getenv(name, &mustfree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006440 if (string != NULL && *string != NUL)
Bram Moolenaar05159a02005-02-26 23:04:13 +00006441 {
6442 if (!mustfree)
6443 string = vim_strsave(string);
6444 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006445 else
6446 {
Bram Moolenaar05159a02005-02-26 23:04:13 +00006447 if (mustfree)
6448 vim_free(string);
6449
Bram Moolenaar071d4272004-06-13 20:20:40 +00006450 /* next try expanding things like $VIM and ${HOME} */
6451 string = expand_env_save(name - 1);
6452 if (string != NULL && *string == '$')
6453 {
6454 vim_free(string);
6455 string = NULL;
6456 }
6457 }
6458 name[len] = cc;
6459 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006460 rettv->v_type = VAR_STRING;
6461 rettv->vval.v_string = string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006462 }
6463
6464 return OK;
6465}
6466
6467/*
6468 * Array with names and number of arguments of all internal functions
6469 * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH!
6470 */
6471static struct fst
6472{
6473 char *f_name; /* function name */
6474 char f_min_argc; /* minimal number of arguments */
6475 char f_max_argc; /* maximal number of arguments */
Bram Moolenaar33570922005-01-25 22:26:29 +00006476 void (*f_func) __ARGS((typval_T *args, typval_T *rvar));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006477 /* implemenation of function */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006478} functions[] =
6479{
Bram Moolenaar0d660222005-01-07 21:51:51 +00006480 {"add", 2, 2, f_add},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006481 {"append", 2, 2, f_append},
6482 {"argc", 0, 0, f_argc},
6483 {"argidx", 0, 0, f_argidx},
6484 {"argv", 1, 1, f_argv},
6485 {"browse", 4, 4, f_browse},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006486 {"browsedir", 2, 2, f_browsedir},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006487 {"bufexists", 1, 1, f_bufexists},
6488 {"buffer_exists", 1, 1, f_bufexists}, /* obsolete */
6489 {"buffer_name", 1, 1, f_bufname}, /* obsolete */
6490 {"buffer_number", 1, 1, f_bufnr}, /* obsolete */
6491 {"buflisted", 1, 1, f_buflisted},
6492 {"bufloaded", 1, 1, f_bufloaded},
6493 {"bufname", 1, 1, f_bufname},
6494 {"bufnr", 1, 1, f_bufnr},
6495 {"bufwinnr", 1, 1, f_bufwinnr},
6496 {"byte2line", 1, 1, f_byte2line},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00006497 {"byteidx", 2, 2, f_byteidx},
Bram Moolenaare9a41262005-01-15 22:18:47 +00006498 {"call", 2, 3, f_call},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006499 {"char2nr", 1, 1, f_char2nr},
6500 {"cindent", 1, 1, f_cindent},
6501 {"col", 1, 1, f_col},
6502 {"confirm", 1, 4, f_confirm},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006503 {"copy", 1, 1, f_copy},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006504 {"count", 2, 4, f_count},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006505 {"cscope_connection",0,3, f_cscope_connection},
6506 {"cursor", 2, 2, f_cursor},
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006507 {"deepcopy", 1, 2, f_deepcopy},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006508 {"delete", 1, 1, f_delete},
6509 {"did_filetype", 0, 0, f_did_filetype},
Bram Moolenaar47136d72004-10-12 20:02:24 +00006510 {"diff_filler", 1, 1, f_diff_filler},
6511 {"diff_hlID", 2, 2, f_diff_hlID},
Bram Moolenaare49b69a2005-01-08 16:11:57 +00006512 {"empty", 1, 1, f_empty},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006513 {"escape", 2, 2, f_escape},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006514 {"eval", 1, 1, f_eval},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006515 {"eventhandler", 0, 0, f_eventhandler},
6516 {"executable", 1, 1, f_executable},
6517 {"exists", 1, 1, f_exists},
6518 {"expand", 1, 2, f_expand},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006519 {"extend", 2, 3, f_extend},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006520 {"file_readable", 1, 1, f_filereadable}, /* obsolete */
6521 {"filereadable", 1, 1, f_filereadable},
6522 {"filewritable", 1, 1, f_filewritable},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006523 {"filter", 2, 2, f_filter},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00006524 {"finddir", 1, 3, f_finddir},
6525 {"findfile", 1, 3, f_findfile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006526 {"fnamemodify", 2, 2, f_fnamemodify},
6527 {"foldclosed", 1, 1, f_foldclosed},
6528 {"foldclosedend", 1, 1, f_foldclosedend},
6529 {"foldlevel", 1, 1, f_foldlevel},
6530 {"foldtext", 0, 0, f_foldtext},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006531 {"foldtextresult", 1, 1, f_foldtextresult},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006532 {"foreground", 0, 0, f_foreground},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006533 {"function", 1, 1, f_function},
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006534 {"garbagecollect", 0, 0, f_garbagecollect},
Bram Moolenaar0d660222005-01-07 21:51:51 +00006535 {"get", 2, 3, f_get},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006536 {"getbufvar", 2, 2, f_getbufvar},
6537 {"getchar", 0, 1, f_getchar},
6538 {"getcharmod", 0, 0, f_getcharmod},
6539 {"getcmdline", 0, 0, f_getcmdline},
6540 {"getcmdpos", 0, 0, f_getcmdpos},
6541 {"getcwd", 0, 0, f_getcwd},
Bram Moolenaar46c9c732004-12-12 11:37:09 +00006542 {"getfontname", 0, 1, f_getfontname},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006543 {"getfperm", 1, 1, f_getfperm},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006544 {"getfsize", 1, 1, f_getfsize},
6545 {"getftime", 1, 1, f_getftime},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006546 {"getftype", 1, 1, f_getftype},
Bram Moolenaar0d660222005-01-07 21:51:51 +00006547 {"getline", 1, 2, f_getline},
Bram Moolenaar2641f772005-03-25 21:58:17 +00006548 {"getqflist", 0, 0, f_getqflist},
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00006549 {"getreg", 0, 2, f_getreg},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006550 {"getregtype", 0, 1, f_getregtype},
6551 {"getwinposx", 0, 0, f_getwinposx},
6552 {"getwinposy", 0, 0, f_getwinposy},
6553 {"getwinvar", 2, 2, f_getwinvar},
6554 {"glob", 1, 1, f_glob},
6555 {"globpath", 2, 2, f_globpath},
6556 {"has", 1, 1, f_has},
Bram Moolenaare9a41262005-01-15 22:18:47 +00006557 {"has_key", 2, 2, f_has_key},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006558 {"hasmapto", 1, 2, f_hasmapto},
6559 {"highlightID", 1, 1, f_hlID}, /* obsolete */
6560 {"highlight_exists",1, 1, f_hlexists}, /* obsolete */
6561 {"histadd", 2, 2, f_histadd},
6562 {"histdel", 1, 2, f_histdel},
6563 {"histget", 1, 2, f_histget},
6564 {"histnr", 1, 1, f_histnr},
6565 {"hlID", 1, 1, f_hlID},
6566 {"hlexists", 1, 1, f_hlexists},
6567 {"hostname", 0, 0, f_hostname},
6568 {"iconv", 3, 3, f_iconv},
6569 {"indent", 1, 1, f_indent},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006570 {"index", 2, 4, f_index},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006571 {"input", 1, 2, f_input},
6572 {"inputdialog", 1, 3, f_inputdialog},
6573 {"inputrestore", 0, 0, f_inputrestore},
6574 {"inputsave", 0, 0, f_inputsave},
6575 {"inputsecret", 1, 2, f_inputsecret},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006576 {"insert", 2, 3, f_insert},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006577 {"isdirectory", 1, 1, f_isdirectory},
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006578 {"islocked", 1, 1, f_islocked},
Bram Moolenaar8c711452005-01-14 21:53:12 +00006579 {"items", 1, 1, f_items},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006580 {"join", 1, 2, f_join},
Bram Moolenaar8c711452005-01-14 21:53:12 +00006581 {"keys", 1, 1, f_keys},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006582 {"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006583 {"len", 1, 1, f_len},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006584 {"libcall", 3, 3, f_libcall},
6585 {"libcallnr", 3, 3, f_libcallnr},
6586 {"line", 1, 1, f_line},
6587 {"line2byte", 1, 1, f_line2byte},
6588 {"lispindent", 1, 1, f_lispindent},
6589 {"localtime", 0, 0, f_localtime},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006590 {"map", 2, 2, f_map},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006591 {"maparg", 1, 2, f_maparg},
6592 {"mapcheck", 1, 2, f_mapcheck},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00006593 {"match", 2, 4, f_match},
6594 {"matchend", 2, 4, f_matchend},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006595 {"matchlist", 2, 4, f_matchlist},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00006596 {"matchstr", 2, 4, f_matchstr},
Bram Moolenaar6cc16192005-01-08 21:49:45 +00006597 {"max", 1, 1, f_max},
6598 {"min", 1, 1, f_min},
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006599#ifdef vim_mkdir
6600 {"mkdir", 1, 3, f_mkdir},
6601#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006602 {"mode", 0, 0, f_mode},
6603 {"nextnonblank", 1, 1, f_nextnonblank},
6604 {"nr2char", 1, 1, f_nr2char},
6605 {"prevnonblank", 1, 1, f_prevnonblank},
Bram Moolenaar8c711452005-01-14 21:53:12 +00006606 {"range", 1, 3, f_range},
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006607 {"readfile", 1, 3, f_readfile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006608 {"remote_expr", 2, 3, f_remote_expr},
6609 {"remote_foreground", 1, 1, f_remote_foreground},
6610 {"remote_peek", 1, 2, f_remote_peek},
6611 {"remote_read", 1, 1, f_remote_read},
6612 {"remote_send", 2, 3, f_remote_send},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006613 {"remove", 2, 3, f_remove},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006614 {"rename", 2, 2, f_rename},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00006615 {"repeat", 2, 2, f_repeat},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006616 {"resolve", 1, 1, f_resolve},
Bram Moolenaar0d660222005-01-07 21:51:51 +00006617 {"reverse", 1, 1, f_reverse},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006618 {"search", 1, 2, f_search},
6619 {"searchpair", 3, 5, f_searchpair},
6620 {"server2client", 2, 2, f_server2client},
6621 {"serverlist", 0, 0, f_serverlist},
6622 {"setbufvar", 3, 3, f_setbufvar},
6623 {"setcmdpos", 1, 1, f_setcmdpos},
6624 {"setline", 2, 2, f_setline},
Bram Moolenaarf4630b62005-05-20 21:31:17 +00006625 {"setqflist", 1, 2, f_setqflist},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006626 {"setreg", 2, 3, f_setreg},
6627 {"setwinvar", 3, 3, f_setwinvar},
6628 {"simplify", 1, 1, f_simplify},
Bram Moolenaar0d660222005-01-07 21:51:51 +00006629 {"sort", 1, 2, f_sort},
Bram Moolenaard857f0e2005-06-21 22:37:39 +00006630 {"spellbadword", 0, 0, f_spellbadword},
6631 {"spellsuggest", 1, 2, f_spellsuggest},
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00006632 {"split", 1, 3, f_split},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006633#ifdef HAVE_STRFTIME
6634 {"strftime", 1, 2, f_strftime},
6635#endif
Bram Moolenaar33570922005-01-25 22:26:29 +00006636 {"stridx", 2, 3, f_stridx},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006637 {"string", 1, 1, f_string},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006638 {"strlen", 1, 1, f_strlen},
6639 {"strpart", 2, 3, f_strpart},
Bram Moolenaar532c7802005-01-27 14:44:31 +00006640 {"strridx", 2, 3, f_strridx},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006641 {"strtrans", 1, 1, f_strtrans},
6642 {"submatch", 1, 1, f_submatch},
6643 {"substitute", 4, 4, f_substitute},
6644 {"synID", 3, 3, f_synID},
6645 {"synIDattr", 2, 3, f_synIDattr},
6646 {"synIDtrans", 1, 1, f_synIDtrans},
Bram Moolenaarc0197e22004-09-13 20:26:32 +00006647 {"system", 1, 2, f_system},
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006648 {"taglist", 1, 1, f_taglist},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006649 {"tempname", 0, 0, f_tempname},
6650 {"tolower", 1, 1, f_tolower},
6651 {"toupper", 1, 1, f_toupper},
Bram Moolenaar8299df92004-07-10 09:47:34 +00006652 {"tr", 3, 3, f_tr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006653 {"type", 1, 1, f_type},
Bram Moolenaar8c711452005-01-14 21:53:12 +00006654 {"values", 1, 1, f_values},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006655 {"virtcol", 1, 1, f_virtcol},
6656 {"visualmode", 0, 1, f_visualmode},
6657 {"winbufnr", 1, 1, f_winbufnr},
6658 {"wincol", 0, 0, f_wincol},
6659 {"winheight", 1, 1, f_winheight},
6660 {"winline", 0, 0, f_winline},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006661 {"winnr", 0, 1, f_winnr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006662 {"winrestcmd", 0, 0, f_winrestcmd},
6663 {"winwidth", 1, 1, f_winwidth},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006664 {"writefile", 2, 3, f_writefile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006665};
6666
6667#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
6668
6669/*
6670 * Function given to ExpandGeneric() to obtain the list of internal
6671 * or user defined function names.
6672 */
6673 char_u *
6674get_function_name(xp, idx)
6675 expand_T *xp;
6676 int idx;
6677{
6678 static int intidx = -1;
6679 char_u *name;
6680
6681 if (idx == 0)
6682 intidx = -1;
6683 if (intidx < 0)
6684 {
6685 name = get_user_func_name(xp, idx);
6686 if (name != NULL)
6687 return name;
6688 }
6689 if (++intidx < (int)(sizeof(functions) / sizeof(struct fst)))
6690 {
6691 STRCPY(IObuff, functions[intidx].f_name);
6692 STRCAT(IObuff, "(");
6693 if (functions[intidx].f_max_argc == 0)
6694 STRCAT(IObuff, ")");
6695 return IObuff;
6696 }
6697
6698 return NULL;
6699}
6700
6701/*
6702 * Function given to ExpandGeneric() to obtain the list of internal or
6703 * user defined variable or function names.
6704 */
6705/*ARGSUSED*/
6706 char_u *
6707get_expr_name(xp, idx)
6708 expand_T *xp;
6709 int idx;
6710{
6711 static int intidx = -1;
6712 char_u *name;
6713
6714 if (idx == 0)
6715 intidx = -1;
6716 if (intidx < 0)
6717 {
6718 name = get_function_name(xp, idx);
6719 if (name != NULL)
6720 return name;
6721 }
6722 return get_user_var_name(xp, ++intidx);
6723}
6724
6725#endif /* FEAT_CMDL_COMPL */
6726
6727/*
6728 * Find internal function in table above.
6729 * Return index, or -1 if not found
6730 */
6731 static int
6732find_internal_func(name)
6733 char_u *name; /* name of the function */
6734{
6735 int first = 0;
6736 int last = (int)(sizeof(functions) / sizeof(struct fst)) - 1;
6737 int cmp;
6738 int x;
6739
6740 /*
6741 * Find the function name in the table. Binary search.
6742 */
6743 while (first <= last)
6744 {
6745 x = first + ((unsigned)(last - first) >> 1);
6746 cmp = STRCMP(name, functions[x].f_name);
6747 if (cmp < 0)
6748 last = x - 1;
6749 else if (cmp > 0)
6750 first = x + 1;
6751 else
6752 return x;
6753 }
6754 return -1;
6755}
6756
6757/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006758 * Check if "name" is a variable of type VAR_FUNC. If so, return the function
6759 * name it contains, otherwise return "name".
6760 */
6761 static char_u *
6762deref_func_name(name, lenp)
6763 char_u *name;
6764 int *lenp;
6765{
Bram Moolenaar33570922005-01-25 22:26:29 +00006766 dictitem_T *v;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006767 int cc;
6768
6769 cc = name[*lenp];
6770 name[*lenp] = NUL;
Bram Moolenaara7043832005-01-21 11:56:39 +00006771 v = find_var(name, NULL);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006772 name[*lenp] = cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00006773 if (v != NULL && v->di_tv.v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006774 {
Bram Moolenaar33570922005-01-25 22:26:29 +00006775 if (v->di_tv.vval.v_string == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006776 {
6777 *lenp = 0;
6778 return (char_u *)""; /* just in case */
6779 }
Bram Moolenaar33570922005-01-25 22:26:29 +00006780 *lenp = STRLEN(v->di_tv.vval.v_string);
6781 return v->di_tv.vval.v_string;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006782 }
6783
6784 return name;
6785}
6786
6787/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006788 * Allocate a variable for the result of a function.
6789 * Return OK or FAIL.
6790 */
6791 static int
Bram Moolenaare9a41262005-01-15 22:18:47 +00006792get_func_tv(name, len, rettv, arg, firstline, lastline, doesrange,
6793 evaluate, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006794 char_u *name; /* name of the function */
6795 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +00006796 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006797 char_u **arg; /* argument, pointing to the '(' */
6798 linenr_T firstline; /* first line of range */
6799 linenr_T lastline; /* last line of range */
6800 int *doesrange; /* return: function handled range */
6801 int evaluate;
Bram Moolenaar33570922005-01-25 22:26:29 +00006802 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006803{
6804 char_u *argp;
6805 int ret = OK;
Bram Moolenaar33570922005-01-25 22:26:29 +00006806 typval_T argvars[MAX_FUNC_ARGS]; /* vars for arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006807 int argcount = 0; /* number of arguments found */
6808
6809 /*
6810 * Get the arguments.
6811 */
6812 argp = *arg;
6813 while (argcount < MAX_FUNC_ARGS)
6814 {
6815 argp = skipwhite(argp + 1); /* skip the '(' or ',' */
6816 if (*argp == ')' || *argp == ',' || *argp == NUL)
6817 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006818 if (eval1(&argp, &argvars[argcount], evaluate) == FAIL)
6819 {
6820 ret = FAIL;
6821 break;
6822 }
6823 ++argcount;
6824 if (*argp != ',')
6825 break;
6826 }
6827 if (*argp == ')')
6828 ++argp;
6829 else
6830 ret = FAIL;
6831
6832 if (ret == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006833 ret = call_func(name, len, rettv, argcount, argvars,
Bram Moolenaare9a41262005-01-15 22:18:47 +00006834 firstline, lastline, doesrange, evaluate, selfdict);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006835 else if (!aborting())
Bram Moolenaar33570922005-01-25 22:26:29 +00006836 {
6837 if (argcount == MAX_FUNC_ARGS)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006838 emsg_funcname("E740: Too many arguments for function %s", name);
Bram Moolenaar33570922005-01-25 22:26:29 +00006839 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006840 emsg_funcname("E116: Invalid arguments for function %s", name);
Bram Moolenaar33570922005-01-25 22:26:29 +00006841 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006842
6843 while (--argcount >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006844 clear_tv(&argvars[argcount]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006845
6846 *arg = skipwhite(argp);
6847 return ret;
6848}
6849
6850
6851/*
6852 * Call a function with its resolved parameters
6853 * Return OK or FAIL.
6854 */
6855 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006856call_func(name, len, rettv, argcount, argvars, firstline, lastline,
Bram Moolenaare9a41262005-01-15 22:18:47 +00006857 doesrange, evaluate, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006858 char_u *name; /* name of the function */
6859 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +00006860 typval_T *rettv; /* return value goes here */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006861 int argcount; /* number of "argvars" */
Bram Moolenaar33570922005-01-25 22:26:29 +00006862 typval_T *argvars; /* vars for arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006863 linenr_T firstline; /* first line of range */
6864 linenr_T lastline; /* last line of range */
6865 int *doesrange; /* return: function handled range */
6866 int evaluate;
Bram Moolenaar33570922005-01-25 22:26:29 +00006867 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006868{
6869 int ret = FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006870#define ERROR_UNKNOWN 0
6871#define ERROR_TOOMANY 1
6872#define ERROR_TOOFEW 2
6873#define ERROR_SCRIPT 3
Bram Moolenaare9a41262005-01-15 22:18:47 +00006874#define ERROR_DICT 4
6875#define ERROR_NONE 5
6876#define ERROR_OTHER 6
Bram Moolenaar071d4272004-06-13 20:20:40 +00006877 int error = ERROR_NONE;
6878 int i;
6879 int llen;
6880 ufunc_T *fp;
6881 int cc;
6882#define FLEN_FIXED 40
6883 char_u fname_buf[FLEN_FIXED + 1];
6884 char_u *fname;
6885
6886 /*
6887 * In a script change <SID>name() and s:name() to K_SNR 123_name().
6888 * Change <SNR>123_name() to K_SNR 123_name().
6889 * Use fname_buf[] when it fits, otherwise allocate memory (slow).
6890 */
6891 cc = name[len];
6892 name[len] = NUL;
6893 llen = eval_fname_script(name);
6894 if (llen > 0)
6895 {
6896 fname_buf[0] = K_SPECIAL;
6897 fname_buf[1] = KS_EXTRA;
6898 fname_buf[2] = (int)KE_SNR;
6899 i = 3;
6900 if (eval_fname_sid(name)) /* "<SID>" or "s:" */
6901 {
6902 if (current_SID <= 0)
6903 error = ERROR_SCRIPT;
6904 else
6905 {
6906 sprintf((char *)fname_buf + 3, "%ld_", (long)current_SID);
6907 i = (int)STRLEN(fname_buf);
6908 }
6909 }
6910 if (i + STRLEN(name + llen) < FLEN_FIXED)
6911 {
6912 STRCPY(fname_buf + i, name + llen);
6913 fname = fname_buf;
6914 }
6915 else
6916 {
6917 fname = alloc((unsigned)(i + STRLEN(name + llen) + 1));
6918 if (fname == NULL)
6919 error = ERROR_OTHER;
6920 else
6921 {
6922 mch_memmove(fname, fname_buf, (size_t)i);
6923 STRCPY(fname + i, name + llen);
6924 }
6925 }
6926 }
6927 else
6928 fname = name;
6929
6930 *doesrange = FALSE;
6931
6932
6933 /* execute the function if no errors detected and executing */
6934 if (evaluate && error == ERROR_NONE)
6935 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006936 rettv->v_type = VAR_NUMBER; /* default is number rettv */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006937 error = ERROR_UNKNOWN;
6938
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006939 if (!builtin_function(fname))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006940 {
6941 /*
6942 * User defined function.
6943 */
6944 fp = find_func(fname);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006945
Bram Moolenaar071d4272004-06-13 20:20:40 +00006946#ifdef FEAT_AUTOCMD
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006947 /* Trigger FuncUndefined event, may load the function. */
6948 if (fp == NULL
6949 && apply_autocmds(EVENT_FUNCUNDEFINED,
6950 fname, fname, TRUE, NULL)
6951 && !aborting())
Bram Moolenaar071d4272004-06-13 20:20:40 +00006952 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006953 /* executed an autocommand, search for the function again */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006954 fp = find_func(fname);
6955 }
6956#endif
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006957 /* Try loading a package. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006958 if (fp == NULL && script_autoload(fname) && !aborting())
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006959 {
6960 /* loaded a package, search for the function again */
6961 fp = find_func(fname);
6962 }
6963
Bram Moolenaar071d4272004-06-13 20:20:40 +00006964 if (fp != NULL)
6965 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006966 if (fp->uf_flags & FC_RANGE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006967 *doesrange = TRUE;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006968 if (argcount < fp->uf_args.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006969 error = ERROR_TOOFEW;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006970 else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006971 error = ERROR_TOOMANY;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006972 else if ((fp->uf_flags & FC_DICT) && selfdict == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006973 error = ERROR_DICT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006974 else
6975 {
6976 /*
6977 * Call the user function.
6978 * Save and restore search patterns, script variables and
6979 * redo buffer.
6980 */
6981 save_search_patterns();
6982 saveRedobuff();
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006983 ++fp->uf_calls;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006984 call_user_func(fp, argcount, argvars, rettv,
Bram Moolenaare9a41262005-01-15 22:18:47 +00006985 firstline, lastline,
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006986 (fp->uf_flags & FC_DICT) ? selfdict : NULL);
6987 if (--fp->uf_calls <= 0 && isdigit(*fp->uf_name)
6988 && fp->uf_refcount <= 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006989 /* Function was unreferenced while being used, free it
6990 * now. */
6991 func_free(fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006992 restoreRedobuff();
6993 restore_search_patterns();
6994 error = ERROR_NONE;
6995 }
6996 }
6997 }
6998 else
6999 {
7000 /*
7001 * Find the function name in the table, call its implementation.
7002 */
7003 i = find_internal_func(fname);
7004 if (i >= 0)
7005 {
7006 if (argcount < functions[i].f_min_argc)
7007 error = ERROR_TOOFEW;
7008 else if (argcount > functions[i].f_max_argc)
7009 error = ERROR_TOOMANY;
7010 else
7011 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007012 argvars[argcount].v_type = VAR_UNKNOWN;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007013 functions[i].f_func(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007014 error = ERROR_NONE;
7015 }
7016 }
7017 }
7018 /*
7019 * The function call (or "FuncUndefined" autocommand sequence) might
7020 * have been aborted by an error, an interrupt, or an explicitly thrown
7021 * exception that has not been caught so far. This situation can be
7022 * tested for by calling aborting(). For an error in an internal
7023 * function or for the "E132" error in call_user_func(), however, the
7024 * throw point at which the "force_abort" flag (temporarily reset by
7025 * emsg()) is normally updated has not been reached yet. We need to
7026 * update that flag first to make aborting() reliable.
7027 */
7028 update_force_abort();
7029 }
7030 if (error == ERROR_NONE)
7031 ret = OK;
7032
7033 /*
7034 * Report an error unless the argument evaluation or function call has been
7035 * cancelled due to an aborting error, an interrupt, or an exception.
7036 */
Bram Moolenaar8c711452005-01-14 21:53:12 +00007037 if (!aborting())
7038 {
7039 switch (error)
7040 {
7041 case ERROR_UNKNOWN:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007042 emsg_funcname("E117: Unknown function: %s", name);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007043 break;
7044 case ERROR_TOOMANY:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007045 emsg_funcname(e_toomanyarg, name);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007046 break;
7047 case ERROR_TOOFEW:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007048 emsg_funcname("E119: Not enough arguments for function: %s",
Bram Moolenaar8c711452005-01-14 21:53:12 +00007049 name);
7050 break;
7051 case ERROR_SCRIPT:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007052 emsg_funcname("E120: Using <SID> not in a script context: %s",
Bram Moolenaar8c711452005-01-14 21:53:12 +00007053 name);
7054 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007055 case ERROR_DICT:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007056 emsg_funcname("E725: Calling dict function without Dictionary: %s",
Bram Moolenaare9a41262005-01-15 22:18:47 +00007057 name);
7058 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007059 }
7060 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007061
7062 name[len] = cc;
7063 if (fname != name && fname != fname_buf)
7064 vim_free(fname);
7065
7066 return ret;
7067}
7068
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007069/*
7070 * Give an error message with a function name. Handle <SNR> things.
7071 */
7072 static void
7073emsg_funcname(msg, name)
7074 char *msg;
7075 char_u *name;
7076{
7077 char_u *p;
7078
7079 if (*name == K_SPECIAL)
7080 p = concat_str((char_u *)"<SNR>", name + 3);
7081 else
7082 p = name;
7083 EMSG2(_(msg), p);
7084 if (p != name)
7085 vim_free(p);
7086}
7087
Bram Moolenaar071d4272004-06-13 20:20:40 +00007088/*********************************************
7089 * Implementation of the built-in functions
7090 */
7091
7092/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00007093 * "add(list, item)" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00007094 */
7095 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +00007096f_add(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007097 typval_T *argvars;
7098 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007099{
Bram Moolenaar33570922005-01-25 22:26:29 +00007100 list_T *l;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007101
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007102 rettv->vval.v_number = 1; /* Default: Failed */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007103 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007104 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007105 if ((l = argvars[0].vval.v_list) != NULL
7106 && !tv_check_lock(l->lv_lock, (char_u *)"add()")
7107 && list_append_tv(l, &argvars[1]) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007108 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007109 }
7110 else
Bram Moolenaar0d660222005-01-07 21:51:51 +00007111 EMSG(_(e_listreq));
7112}
7113
7114/*
7115 * "append(lnum, string/list)" function
7116 */
7117 static void
7118f_append(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007119 typval_T *argvars;
7120 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00007121{
7122 long lnum;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007123 char_u *line;
Bram Moolenaar33570922005-01-25 22:26:29 +00007124 list_T *l = NULL;
7125 listitem_T *li = NULL;
7126 typval_T *tv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00007127 long added = 0;
7128
Bram Moolenaar0d660222005-01-07 21:51:51 +00007129 lnum = get_tv_lnum(argvars);
7130 if (lnum >= 0
7131 && lnum <= curbuf->b_ml.ml_line_count
7132 && u_save(lnum, lnum + 1) == OK)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007133 {
Bram Moolenaar0d660222005-01-07 21:51:51 +00007134 if (argvars[1].v_type == VAR_LIST)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007135 {
Bram Moolenaar0d660222005-01-07 21:51:51 +00007136 l = argvars[1].vval.v_list;
7137 if (l == NULL)
7138 return;
7139 li = l->lv_first;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007140 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007141 rettv->vval.v_number = 0; /* Default: Success */
Bram Moolenaar0d660222005-01-07 21:51:51 +00007142 for (;;)
7143 {
7144 if (l == NULL)
7145 tv = &argvars[1]; /* append a string */
7146 else if (li == NULL)
7147 break; /* end of list */
7148 else
7149 tv = &li->li_tv; /* append item from list */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007150 line = get_tv_string_chk(tv);
7151 if (line == NULL) /* type error */
7152 {
7153 rettv->vval.v_number = 1; /* Failed */
7154 break;
7155 }
7156 ml_append(lnum + added, line, (colnr_T)0, FALSE);
Bram Moolenaar0d660222005-01-07 21:51:51 +00007157 ++added;
7158 if (l == NULL)
7159 break;
7160 li = li->li_next;
7161 }
7162
7163 appended_lines_mark(lnum, added);
7164 if (curwin->w_cursor.lnum > lnum)
7165 curwin->w_cursor.lnum += added;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007166 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007167 else
7168 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007169}
7170
7171/*
7172 * "argc()" function
7173 */
7174/* ARGSUSED */
7175 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007176f_argc(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007177 typval_T *argvars;
7178 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007179{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007180 rettv->vval.v_number = ARGCOUNT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007181}
7182
7183/*
7184 * "argidx()" function
7185 */
7186/* ARGSUSED */
7187 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007188f_argidx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007189 typval_T *argvars;
7190 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007191{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007192 rettv->vval.v_number = curwin->w_arg_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007193}
7194
7195/*
7196 * "argv(nr)" function
7197 */
7198 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007199f_argv(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007200 typval_T *argvars;
7201 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007202{
7203 int idx;
7204
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007205 idx = get_tv_number_chk(&argvars[0], NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007206 if (idx >= 0 && idx < ARGCOUNT)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007207 rettv->vval.v_string = vim_strsave(alist_name(&ARGLIST[idx]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007208 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007209 rettv->vval.v_string = NULL;
7210 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007211}
7212
7213/*
7214 * "browse(save, title, initdir, default)" function
7215 */
7216/* ARGSUSED */
7217 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007218f_browse(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007219 typval_T *argvars;
7220 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007221{
7222#ifdef FEAT_BROWSE
7223 int save;
7224 char_u *title;
7225 char_u *initdir;
7226 char_u *defname;
7227 char_u buf[NUMBUFLEN];
7228 char_u buf2[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007229 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007230
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007231 save = get_tv_number_chk(&argvars[0], &error);
7232 title = get_tv_string_chk(&argvars[1]);
7233 initdir = get_tv_string_buf_chk(&argvars[2], buf);
7234 defname = get_tv_string_buf_chk(&argvars[3], buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007235
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007236 if (error || title == NULL || initdir == NULL || defname == NULL)
7237 rettv->vval.v_string = NULL;
7238 else
7239 rettv->vval.v_string =
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007240 do_browse(save ? BROWSE_SAVE : 0,
7241 title, defname, NULL, initdir, NULL, curbuf);
7242#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007243 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007244#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007245 rettv->v_type = VAR_STRING;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007246}
7247
7248/*
7249 * "browsedir(title, initdir)" function
7250 */
7251/* ARGSUSED */
7252 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007253f_browsedir(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007254 typval_T *argvars;
7255 typval_T *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007256{
7257#ifdef FEAT_BROWSE
7258 char_u *title;
7259 char_u *initdir;
7260 char_u buf[NUMBUFLEN];
7261
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007262 title = get_tv_string_chk(&argvars[0]);
7263 initdir = get_tv_string_buf_chk(&argvars[1], buf);
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007264
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007265 if (title == NULL || initdir == NULL)
7266 rettv->vval.v_string = NULL;
7267 else
7268 rettv->vval.v_string = do_browse(BROWSE_DIR,
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007269 title, NULL, NULL, initdir, NULL, curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007270#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007271 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007272#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007273 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007274}
7275
Bram Moolenaar33570922005-01-25 22:26:29 +00007276static buf_T *find_buffer __ARGS((typval_T *avar));
Bram Moolenaar0d660222005-01-07 21:51:51 +00007277
Bram Moolenaar071d4272004-06-13 20:20:40 +00007278/*
7279 * Find a buffer by number or exact name.
7280 */
7281 static buf_T *
7282find_buffer(avar)
Bram Moolenaar33570922005-01-25 22:26:29 +00007283 typval_T *avar;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007284{
7285 buf_T *buf = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007286
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007287 if (avar->v_type == VAR_NUMBER)
7288 buf = buflist_findnr((int)avar->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +00007289 else if (avar->v_type == VAR_STRING && avar->vval.v_string != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007290 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007291 buf = buflist_findname_exp(avar->vval.v_string);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00007292 if (buf == NULL)
7293 {
7294 /* No full path name match, try a match with a URL or a "nofile"
7295 * buffer, these don't use the full path. */
7296 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
7297 if (buf->b_fname != NULL
7298 && (path_with_url(buf->b_fname)
7299#ifdef FEAT_QUICKFIX
7300 || bt_nofile(buf)
7301#endif
7302 )
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007303 && STRCMP(buf->b_fname, avar->vval.v_string) == 0)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00007304 break;
7305 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007306 }
7307 return buf;
7308}
7309
7310/*
7311 * "bufexists(expr)" function
7312 */
7313 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007314f_bufexists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007315 typval_T *argvars;
7316 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007317{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007318 rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007319}
7320
7321/*
7322 * "buflisted(expr)" function
7323 */
7324 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007325f_buflisted(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007326 typval_T *argvars;
7327 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007328{
7329 buf_T *buf;
7330
7331 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007332 rettv->vval.v_number = (buf != NULL && buf->b_p_bl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007333}
7334
7335/*
7336 * "bufloaded(expr)" function
7337 */
7338 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007339f_bufloaded(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007340 typval_T *argvars;
7341 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007342{
7343 buf_T *buf;
7344
7345 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007346 rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007347}
7348
Bram Moolenaar33570922005-01-25 22:26:29 +00007349static buf_T *get_buf_tv __ARGS((typval_T *tv));
Bram Moolenaar0d660222005-01-07 21:51:51 +00007350
Bram Moolenaar071d4272004-06-13 20:20:40 +00007351/*
7352 * Get buffer by number or pattern.
7353 */
7354 static buf_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007355get_buf_tv(tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007356 typval_T *tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007357{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007358 char_u *name = tv->vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007359 int save_magic;
7360 char_u *save_cpo;
7361 buf_T *buf;
7362
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007363 if (tv->v_type == VAR_NUMBER)
7364 return buflist_findnr((int)tv->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +00007365 if (tv->v_type != VAR_STRING)
7366 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007367 if (name == NULL || *name == NUL)
7368 return curbuf;
7369 if (name[0] == '$' && name[1] == NUL)
7370 return lastbuf;
7371
7372 /* Ignore 'magic' and 'cpoptions' here to make scripts portable */
7373 save_magic = p_magic;
7374 p_magic = TRUE;
7375 save_cpo = p_cpo;
7376 p_cpo = (char_u *)"";
7377
7378 buf = buflist_findnr(buflist_findpat(name, name + STRLEN(name),
7379 TRUE, FALSE));
7380
7381 p_magic = save_magic;
7382 p_cpo = save_cpo;
7383
7384 /* If not found, try expanding the name, like done for bufexists(). */
7385 if (buf == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007386 buf = find_buffer(tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007387
7388 return buf;
7389}
7390
7391/*
7392 * "bufname(expr)" function
7393 */
7394 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007395f_bufname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007396 typval_T *argvars;
7397 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007398{
7399 buf_T *buf;
7400
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007401 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007402 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007403 buf = get_buf_tv(&argvars[0]);
7404 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007405 if (buf != NULL && buf->b_fname != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007406 rettv->vval.v_string = vim_strsave(buf->b_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007407 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007408 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007409 --emsg_off;
7410}
7411
7412/*
7413 * "bufnr(expr)" function
7414 */
7415 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007416f_bufnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007417 typval_T *argvars;
7418 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007419{
7420 buf_T *buf;
7421
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007422 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007423 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007424 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007425 if (buf != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007426 rettv->vval.v_number = buf->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007427 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007428 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007429 --emsg_off;
7430}
7431
7432/*
7433 * "bufwinnr(nr)" function
7434 */
7435 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007436f_bufwinnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007437 typval_T *argvars;
7438 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007439{
7440#ifdef FEAT_WINDOWS
7441 win_T *wp;
7442 int winnr = 0;
7443#endif
7444 buf_T *buf;
7445
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007446 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007447 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007448 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007449#ifdef FEAT_WINDOWS
7450 for (wp = firstwin; wp; wp = wp->w_next)
7451 {
7452 ++winnr;
7453 if (wp->w_buffer == buf)
7454 break;
7455 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007456 rettv->vval.v_number = (wp != NULL ? winnr : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007457#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007458 rettv->vval.v_number = (curwin->w_buffer == buf ? 1 : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007459#endif
7460 --emsg_off;
7461}
7462
7463/*
7464 * "byte2line(byte)" function
7465 */
7466/*ARGSUSED*/
7467 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007468f_byte2line(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007469 typval_T *argvars;
7470 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007471{
7472#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007473 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007474#else
7475 long boff = 0;
7476
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007477 boff = get_tv_number(&argvars[0]) - 1; /* boff gets -1 on type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007478 if (boff < 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007479 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007480 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007481 rettv->vval.v_number = ml_find_line_or_offset(curbuf,
Bram Moolenaar071d4272004-06-13 20:20:40 +00007482 (linenr_T)0, &boff);
7483#endif
7484}
7485
7486/*
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007487 * "byteidx()" function
7488 */
7489/*ARGSUSED*/
7490 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007491f_byteidx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007492 typval_T *argvars;
7493 typval_T *rettv;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007494{
7495#ifdef FEAT_MBYTE
7496 char_u *t;
7497#endif
7498 char_u *str;
7499 long idx;
7500
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007501 str = get_tv_string_chk(&argvars[0]);
7502 idx = get_tv_number_chk(&argvars[1], NULL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007503 rettv->vval.v_number = -1;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007504 if (str == NULL || idx < 0)
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007505 return;
7506
7507#ifdef FEAT_MBYTE
7508 t = str;
7509 for ( ; idx > 0; idx--)
7510 {
7511 if (*t == NUL) /* EOL reached */
7512 return;
7513 t += mb_ptr2len_check(t);
7514 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007515 rettv->vval.v_number = t - str;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007516#else
7517 if (idx <= STRLEN(str))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007518 rettv->vval.v_number = idx;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007519#endif
7520}
7521
7522/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007523 * "call(func, arglist)" function
7524 */
7525 static void
7526f_call(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007527 typval_T *argvars;
7528 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007529{
7530 char_u *func;
Bram Moolenaar33570922005-01-25 22:26:29 +00007531 typval_T argv[MAX_FUNC_ARGS];
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007532 int argc = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00007533 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007534 int dummy;
Bram Moolenaar33570922005-01-25 22:26:29 +00007535 dict_T *selfdict = NULL;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007536
7537 rettv->vval.v_number = 0;
7538 if (argvars[1].v_type != VAR_LIST)
7539 {
7540 EMSG(_(e_listreq));
7541 return;
7542 }
7543 if (argvars[1].vval.v_list == NULL)
7544 return;
7545
7546 if (argvars[0].v_type == VAR_FUNC)
7547 func = argvars[0].vval.v_string;
7548 else
7549 func = get_tv_string(&argvars[0]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007550 if (*func == NUL)
7551 return; /* type error or empty name */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007552
Bram Moolenaare9a41262005-01-15 22:18:47 +00007553 if (argvars[2].v_type != VAR_UNKNOWN)
7554 {
7555 if (argvars[2].v_type != VAR_DICT)
7556 {
7557 EMSG(_(e_dictreq));
7558 return;
7559 }
7560 selfdict = argvars[2].vval.v_dict;
7561 }
7562
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007563 for (item = argvars[1].vval.v_list->lv_first; item != NULL;
7564 item = item->li_next)
7565 {
7566 if (argc == MAX_FUNC_ARGS)
7567 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00007568 EMSG(_("E699: Too many arguments"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007569 break;
7570 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007571 /* Make a copy of each argument. This is needed to be able to set
7572 * v_lock to VAR_FIXED in the copy without changing the original list.
7573 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007574 copy_tv(&item->li_tv, &argv[argc++]);
7575 }
7576
7577 if (item == NULL)
7578 (void)call_func(func, STRLEN(func), rettv, argc, argv,
Bram Moolenaare9a41262005-01-15 22:18:47 +00007579 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
7580 &dummy, TRUE, selfdict);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007581
7582 /* Free the arguments. */
7583 while (argc > 0)
7584 clear_tv(&argv[--argc]);
7585}
7586
7587/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007588 * "char2nr(string)" function
7589 */
7590 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007591f_char2nr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007592 typval_T *argvars;
7593 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007594{
7595#ifdef FEAT_MBYTE
7596 if (has_mbyte)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007597 rettv->vval.v_number = (*mb_ptr2char)(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007598 else
7599#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007600 rettv->vval.v_number = get_tv_string(&argvars[0])[0];
Bram Moolenaar071d4272004-06-13 20:20:40 +00007601}
7602
7603/*
7604 * "cindent(lnum)" function
7605 */
7606 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007607f_cindent(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007608 typval_T *argvars;
7609 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007610{
7611#ifdef FEAT_CINDENT
7612 pos_T pos;
7613 linenr_T lnum;
7614
7615 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007616 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007617 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
7618 {
7619 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007620 rettv->vval.v_number = get_c_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +00007621 curwin->w_cursor = pos;
7622 }
7623 else
7624#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007625 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007626}
7627
7628/*
7629 * "col(string)" function
7630 */
7631 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007632f_col(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007633 typval_T *argvars;
7634 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007635{
7636 colnr_T col = 0;
7637 pos_T *fp;
7638
7639 fp = var2fpos(&argvars[0], FALSE);
7640 if (fp != NULL)
7641 {
7642 if (fp->col == MAXCOL)
7643 {
7644 /* '> can be MAXCOL, get the length of the line then */
7645 if (fp->lnum <= curbuf->b_ml.ml_line_count)
7646 col = STRLEN(ml_get(fp->lnum)) + 1;
7647 else
7648 col = MAXCOL;
7649 }
7650 else
7651 {
7652 col = fp->col + 1;
7653#ifdef FEAT_VIRTUALEDIT
7654 /* col(".") when the cursor is on the NUL at the end of the line
7655 * because of "coladd" can be seen as an extra column. */
7656 if (virtual_active() && fp == &curwin->w_cursor)
7657 {
7658 char_u *p = ml_get_cursor();
7659
7660 if (curwin->w_cursor.coladd >= (colnr_T)chartabsize(p,
7661 curwin->w_virtcol - curwin->w_cursor.coladd))
7662 {
7663# ifdef FEAT_MBYTE
7664 int l;
7665
7666 if (*p != NUL && p[(l = (*mb_ptr2len_check)(p))] == NUL)
7667 col += l;
7668# else
7669 if (*p != NUL && p[1] == NUL)
7670 ++col;
7671# endif
7672 }
7673 }
7674#endif
7675 }
7676 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007677 rettv->vval.v_number = col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007678}
7679
7680/*
7681 * "confirm(message, buttons[, default [, type]])" function
7682 */
7683/*ARGSUSED*/
7684 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007685f_confirm(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007686 typval_T *argvars;
7687 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007688{
7689#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
7690 char_u *message;
7691 char_u *buttons = NULL;
7692 char_u buf[NUMBUFLEN];
7693 char_u buf2[NUMBUFLEN];
7694 int def = 1;
7695 int type = VIM_GENERIC;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007696 char_u *typestr;
7697 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007698
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007699 message = get_tv_string_chk(&argvars[0]);
7700 if (message == NULL)
7701 error = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007702 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007703 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007704 buttons = get_tv_string_buf_chk(&argvars[1], buf);
7705 if (buttons == NULL)
7706 error = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007707 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007708 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007709 def = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007710 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007711 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007712 typestr = get_tv_string_buf_chk(&argvars[3], buf2);
7713 if (typestr == NULL)
7714 error = TRUE;
7715 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00007716 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007717 switch (TOUPPER_ASC(*typestr))
7718 {
7719 case 'E': type = VIM_ERROR; break;
7720 case 'Q': type = VIM_QUESTION; break;
7721 case 'I': type = VIM_INFO; break;
7722 case 'W': type = VIM_WARNING; break;
7723 case 'G': type = VIM_GENERIC; break;
7724 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007725 }
7726 }
7727 }
7728 }
7729
7730 if (buttons == NULL || *buttons == NUL)
7731 buttons = (char_u *)_("&Ok");
7732
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007733 if (error)
7734 rettv->vval.v_number = 0;
7735 else
7736 rettv->vval.v_number = do_dialog(type, NULL, message, buttons,
Bram Moolenaar071d4272004-06-13 20:20:40 +00007737 def, NULL);
7738#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007739 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007740#endif
7741}
7742
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007743/*
7744 * "copy()" function
7745 */
7746 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007747f_copy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007748 typval_T *argvars;
7749 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007750{
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007751 item_copy(&argvars[0], rettv, FALSE, 0);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007752}
Bram Moolenaar071d4272004-06-13 20:20:40 +00007753
7754/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007755 * "count()" function
7756 */
7757 static void
7758f_count(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007759 typval_T *argvars;
7760 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007761{
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007762 long n = 0;
7763 int ic = FALSE;
7764
Bram Moolenaare9a41262005-01-15 22:18:47 +00007765 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007766 {
Bram Moolenaar33570922005-01-25 22:26:29 +00007767 listitem_T *li;
7768 list_T *l;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007769 long idx;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007770
Bram Moolenaare9a41262005-01-15 22:18:47 +00007771 if ((l = argvars[0].vval.v_list) != NULL)
7772 {
7773 li = l->lv_first;
7774 if (argvars[2].v_type != VAR_UNKNOWN)
7775 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007776 int error = FALSE;
7777
7778 ic = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaare9a41262005-01-15 22:18:47 +00007779 if (argvars[3].v_type != VAR_UNKNOWN)
7780 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007781 idx = get_tv_number_chk(&argvars[3], &error);
7782 if (!error)
7783 {
7784 li = list_find(l, idx);
7785 if (li == NULL)
7786 EMSGN(_(e_listidx), idx);
7787 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007788 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007789 if (error)
7790 li = NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007791 }
7792
7793 for ( ; li != NULL; li = li->li_next)
7794 if (tv_equal(&li->li_tv, &argvars[1], ic))
7795 ++n;
7796 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007797 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007798 else if (argvars[0].v_type == VAR_DICT)
7799 {
Bram Moolenaar33570922005-01-25 22:26:29 +00007800 int todo;
7801 dict_T *d;
7802 hashitem_T *hi;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007803
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007804 if ((d = argvars[0].vval.v_dict) != NULL)
7805 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007806 int error = FALSE;
7807
Bram Moolenaare9a41262005-01-15 22:18:47 +00007808 if (argvars[2].v_type != VAR_UNKNOWN)
7809 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007810 ic = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaare9a41262005-01-15 22:18:47 +00007811 if (argvars[3].v_type != VAR_UNKNOWN)
7812 EMSG(_(e_invarg));
7813 }
7814
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007815 todo = error ? 0 : d->dv_hashtab.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00007816 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007817 {
7818 if (!HASHITEM_EMPTY(hi))
7819 {
7820 --todo;
7821 if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic))
7822 ++n;
7823 }
7824 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007825 }
7826 }
7827 else
7828 EMSG2(_(e_listdictarg), "count()");
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007829 rettv->vval.v_number = n;
7830}
7831
7832/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007833 * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
7834 *
7835 * Checks the existence of a cscope connection.
7836 */
7837/*ARGSUSED*/
7838 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007839f_cscope_connection(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007840 typval_T *argvars;
7841 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007842{
7843#ifdef FEAT_CSCOPE
7844 int num = 0;
7845 char_u *dbpath = NULL;
7846 char_u *prepend = NULL;
7847 char_u buf[NUMBUFLEN];
7848
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007849 if (argvars[0].v_type != VAR_UNKNOWN
7850 && argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007851 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007852 num = (int)get_tv_number(&argvars[0]);
7853 dbpath = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007854 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007855 prepend = get_tv_string_buf(&argvars[2], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007856 }
7857
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007858 rettv->vval.v_number = cs_connection(num, dbpath, prepend);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007859#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007860 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007861#endif
7862}
7863
7864/*
7865 * "cursor(lnum, col)" function
7866 *
7867 * Moves the cursor to the specified line and column
7868 */
7869/*ARGSUSED*/
7870 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007871f_cursor(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007872 typval_T *argvars;
7873 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007874{
7875 long line, col;
7876
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007877 line = get_tv_lnum(argvars);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007878 col = get_tv_number_chk(&argvars[1], NULL);
7879 if (line < 0 || col < 0)
7880 return; /* type error; errmsg already given */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007881 if (line > 0)
7882 curwin->w_cursor.lnum = line;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007883 if (col > 0)
7884 curwin->w_cursor.col = col - 1;
7885#ifdef FEAT_VIRTUALEDIT
7886 curwin->w_cursor.coladd = 0;
7887#endif
7888
7889 /* Make sure the cursor is in a valid position. */
7890 check_cursor();
7891#ifdef FEAT_MBYTE
7892 /* Correct cursor for multi-byte character. */
7893 if (has_mbyte)
7894 mb_adjust_cursor();
7895#endif
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00007896
7897 curwin->w_set_curswant = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007898}
7899
7900/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007901 * "deepcopy()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00007902 */
7903 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007904f_deepcopy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007905 typval_T *argvars;
7906 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007907{
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007908 int noref = 0;
7909
7910 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007911 noref = get_tv_number_chk(&argvars[1], NULL);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007912 if (noref < 0 || noref > 1)
7913 EMSG(_(e_invarg));
7914 else
Bram Moolenaard9fba312005-06-26 22:34:35 +00007915 item_copy(&argvars[0], rettv, TRUE, noref == 0 ? ++current_copyID : 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007916}
7917
7918/*
7919 * "delete()" function
7920 */
7921 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007922f_delete(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007923 typval_T *argvars;
7924 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007925{
7926 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007927 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007928 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007929 rettv->vval.v_number = mch_remove(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007930}
7931
7932/*
7933 * "did_filetype()" function
7934 */
7935/*ARGSUSED*/
7936 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007937f_did_filetype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007938 typval_T *argvars;
7939 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007940{
7941#ifdef FEAT_AUTOCMD
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007942 rettv->vval.v_number = did_filetype;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007943#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007944 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007945#endif
7946}
7947
7948/*
Bram Moolenaar47136d72004-10-12 20:02:24 +00007949 * "diff_filler()" function
7950 */
7951/*ARGSUSED*/
7952 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007953f_diff_filler(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007954 typval_T *argvars;
7955 typval_T *rettv;
Bram Moolenaar47136d72004-10-12 20:02:24 +00007956{
7957#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007958 rettv->vval.v_number = diff_check_fill(curwin, get_tv_lnum(argvars));
Bram Moolenaar47136d72004-10-12 20:02:24 +00007959#endif
7960}
7961
7962/*
7963 * "diff_hlID()" function
7964 */
7965/*ARGSUSED*/
7966 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007967f_diff_hlID(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007968 typval_T *argvars;
7969 typval_T *rettv;
Bram Moolenaar47136d72004-10-12 20:02:24 +00007970{
7971#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007972 linenr_T lnum = get_tv_lnum(argvars);
Bram Moolenaar47136d72004-10-12 20:02:24 +00007973 static linenr_T prev_lnum = 0;
7974 static int changedtick = 0;
7975 static int fnum = 0;
7976 static int change_start = 0;
7977 static int change_end = 0;
7978 static enum hlf_value hlID = 0;
7979 int filler_lines;
7980 int col;
7981
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007982 if (lnum < 0) /* ignore type error in {lnum} arg */
7983 lnum = 0;
Bram Moolenaar47136d72004-10-12 20:02:24 +00007984 if (lnum != prev_lnum
7985 || changedtick != curbuf->b_changedtick
7986 || fnum != curbuf->b_fnum)
7987 {
7988 /* New line, buffer, change: need to get the values. */
7989 filler_lines = diff_check(curwin, lnum);
7990 if (filler_lines < 0)
7991 {
7992 if (filler_lines == -1)
7993 {
7994 change_start = MAXCOL;
7995 change_end = -1;
7996 if (diff_find_change(curwin, lnum, &change_start, &change_end))
7997 hlID = HLF_ADD; /* added line */
7998 else
7999 hlID = HLF_CHD; /* changed line */
8000 }
8001 else
8002 hlID = HLF_ADD; /* added line */
8003 }
8004 else
8005 hlID = (enum hlf_value)0;
8006 prev_lnum = lnum;
8007 changedtick = curbuf->b_changedtick;
8008 fnum = curbuf->b_fnum;
8009 }
8010
8011 if (hlID == HLF_CHD || hlID == HLF_TXD)
8012 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008013 col = get_tv_number(&argvars[1]) - 1; /* ignore type error in {col} */
Bram Moolenaar47136d72004-10-12 20:02:24 +00008014 if (col >= change_start && col <= change_end)
8015 hlID = HLF_TXD; /* changed text */
8016 else
8017 hlID = HLF_CHD; /* changed line */
8018 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008019 rettv->vval.v_number = hlID == (enum hlf_value)0 ? 0 : (int)hlID;
Bram Moolenaar47136d72004-10-12 20:02:24 +00008020#endif
8021}
8022
8023/*
Bram Moolenaare49b69a2005-01-08 16:11:57 +00008024 * "empty({expr})" function
8025 */
8026 static void
8027f_empty(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008028 typval_T *argvars;
8029 typval_T *rettv;
Bram Moolenaare49b69a2005-01-08 16:11:57 +00008030{
8031 int n;
8032
8033 switch (argvars[0].v_type)
8034 {
8035 case VAR_STRING:
8036 case VAR_FUNC:
8037 n = argvars[0].vval.v_string == NULL
8038 || *argvars[0].vval.v_string == NUL;
8039 break;
8040 case VAR_NUMBER:
8041 n = argvars[0].vval.v_number == 0;
8042 break;
8043 case VAR_LIST:
8044 n = argvars[0].vval.v_list == NULL
8045 || argvars[0].vval.v_list->lv_first == NULL;
8046 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008047 case VAR_DICT:
8048 n = argvars[0].vval.v_dict == NULL
Bram Moolenaar33570922005-01-25 22:26:29 +00008049 || argvars[0].vval.v_dict->dv_hashtab.ht_used == 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008050 break;
Bram Moolenaare49b69a2005-01-08 16:11:57 +00008051 default:
8052 EMSG2(_(e_intern2), "f_empty()");
8053 n = 0;
8054 }
8055
8056 rettv->vval.v_number = n;
8057}
8058
8059/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008060 * "escape({string}, {chars})" function
8061 */
8062 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008063f_escape(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008064 typval_T *argvars;
8065 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008066{
8067 char_u buf[NUMBUFLEN];
8068
Bram Moolenaar758711c2005-02-02 23:11:38 +00008069 rettv->vval.v_string = vim_strsave_escaped(get_tv_string(&argvars[0]),
8070 get_tv_string_buf(&argvars[1], buf));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008071 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008072}
8073
8074/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008075 * "eval()" function
8076 */
8077/*ARGSUSED*/
8078 static void
8079f_eval(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008080 typval_T *argvars;
8081 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008082{
8083 char_u *s;
8084
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008085 s = get_tv_string_chk(&argvars[0]);
8086 if (s != NULL)
8087 s = skipwhite(s);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008088
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008089 if (s == NULL || eval1(&s, rettv, TRUE) == FAIL)
8090 {
8091 rettv->v_type = VAR_NUMBER;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008092 rettv->vval.v_number = 0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008093 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008094 else if (*s != NUL)
8095 EMSG(_(e_trailing));
8096}
8097
8098/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008099 * "eventhandler()" function
8100 */
8101/*ARGSUSED*/
8102 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008103f_eventhandler(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008104 typval_T *argvars;
8105 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008106{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008107 rettv->vval.v_number = vgetc_busy;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008108}
8109
8110/*
8111 * "executable()" function
8112 */
8113 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008114f_executable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008115 typval_T *argvars;
8116 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008117{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008118 rettv->vval.v_number = mch_can_exe(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008119}
8120
8121/*
8122 * "exists()" function
8123 */
8124 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008125f_exists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008126 typval_T *argvars;
8127 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008128{
8129 char_u *p;
8130 char_u *name;
8131 int n = FALSE;
8132 int len = 0;
8133
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008134 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008135 if (*p == '$') /* environment variable */
8136 {
8137 /* first try "normal" environment variables (fast) */
8138 if (mch_getenv(p + 1) != NULL)
8139 n = TRUE;
8140 else
8141 {
8142 /* try expanding things like $VIM and ${HOME} */
8143 p = expand_env_save(p);
8144 if (p != NULL && *p != '$')
8145 n = TRUE;
8146 vim_free(p);
8147 }
8148 }
8149 else if (*p == '&' || *p == '+') /* option */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008150 n = (get_option_tv(&p, NULL, TRUE) == OK);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008151 else if (*p == '*') /* internal or user defined function */
8152 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008153 n = function_exists(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008154 }
8155 else if (*p == ':')
8156 {
8157 n = cmd_exists(p + 1);
8158 }
8159 else if (*p == '#')
8160 {
8161#ifdef FEAT_AUTOCMD
8162 name = p + 1;
8163 p = vim_strchr(name, '#');
8164 if (p != NULL)
8165 n = au_exists(name, p, p + 1);
8166 else
8167 n = au_exists(name, name + STRLEN(name), NULL);
8168#endif
8169 }
8170 else /* internal variable */
8171 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008172 char_u *tofree;
8173 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008174
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008175 /* get_name_len() takes care of expanding curly braces */
8176 name = p;
8177 len = get_name_len(&p, &tofree, TRUE, FALSE);
8178 if (len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008179 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008180 if (tofree != NULL)
8181 name = tofree;
8182 n = (get_var_tv(name, len, &tv, FALSE) == OK);
8183 if (n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008184 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008185 /* handle d.key, l[idx], f(expr) */
8186 n = (handle_subscript(&p, &tv, TRUE, FALSE) == OK);
8187 if (n)
8188 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008189 }
8190 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008191
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008192 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008193 }
8194
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008195 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008196}
8197
8198/*
8199 * "expand()" function
8200 */
8201 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008202f_expand(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008203 typval_T *argvars;
8204 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008205{
8206 char_u *s;
8207 int len;
8208 char_u *errormsg;
8209 int flags = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND;
8210 expand_T xpc;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008211 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008212
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008213 rettv->v_type = VAR_STRING;
8214 s = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008215 if (*s == '%' || *s == '#' || *s == '<')
8216 {
8217 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008218 rettv->vval.v_string = eval_vars(s, &len, NULL, &errormsg, s);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008219 --emsg_off;
8220 }
8221 else
8222 {
8223 /* When the optional second argument is non-zero, don't remove matches
8224 * for 'suffixes' and 'wildignore' */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008225 if (argvars[1].v_type != VAR_UNKNOWN
8226 && get_tv_number_chk(&argvars[1], &error))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008227 flags |= WILD_KEEP_ALL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008228 if (!error)
8229 {
8230 ExpandInit(&xpc);
8231 xpc.xp_context = EXPAND_FILES;
8232 rettv->vval.v_string = ExpandOne(&xpc, s, NULL, flags, WILD_ALL);
8233 ExpandCleanup(&xpc);
8234 }
8235 else
8236 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008237 }
8238}
8239
8240/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008241 * "extend(list, list [, idx])" function
Bram Moolenaare9a41262005-01-15 22:18:47 +00008242 * "extend(dict, dict [, action])" function
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008243 */
8244 static void
8245f_extend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008246 typval_T *argvars;
8247 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008248{
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008249 rettv->vval.v_number = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008250 if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008251 {
Bram Moolenaar33570922005-01-25 22:26:29 +00008252 list_T *l1, *l2;
8253 listitem_T *item;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008254 long before;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008255 int error = FALSE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008256
Bram Moolenaare9a41262005-01-15 22:18:47 +00008257 l1 = argvars[0].vval.v_list;
8258 l2 = argvars[1].vval.v_list;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008259 if (l1 != NULL && !tv_check_lock(l1->lv_lock, (char_u *)"extend()")
8260 && l2 != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008261 {
8262 if (argvars[2].v_type != VAR_UNKNOWN)
8263 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008264 before = get_tv_number_chk(&argvars[2], &error);
8265 if (error)
8266 return; /* type error; errmsg already given */
8267
Bram Moolenaar758711c2005-02-02 23:11:38 +00008268 if (before == l1->lv_len)
8269 item = NULL;
8270 else
Bram Moolenaare9a41262005-01-15 22:18:47 +00008271 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00008272 item = list_find(l1, before);
8273 if (item == NULL)
8274 {
8275 EMSGN(_(e_listidx), before);
8276 return;
8277 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008278 }
8279 }
8280 else
8281 item = NULL;
8282 list_extend(l1, l2, item);
8283
Bram Moolenaare9a41262005-01-15 22:18:47 +00008284 copy_tv(&argvars[0], rettv);
8285 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008286 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008287 else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT)
8288 {
Bram Moolenaar33570922005-01-25 22:26:29 +00008289 dict_T *d1, *d2;
8290 dictitem_T *di1;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008291 char_u *action;
8292 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00008293 hashitem_T *hi2;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008294 int todo;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008295
8296 d1 = argvars[0].vval.v_dict;
8297 d2 = argvars[1].vval.v_dict;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008298 if (d1 != NULL && !tv_check_lock(d1->dv_lock, (char_u *)"extend()")
8299 && d2 != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008300 {
8301 /* Check the third argument. */
8302 if (argvars[2].v_type != VAR_UNKNOWN)
8303 {
8304 static char *(av[]) = {"keep", "force", "error"};
8305
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008306 action = get_tv_string_chk(&argvars[2]);
8307 if (action == NULL)
8308 return; /* type error; errmsg already given */
Bram Moolenaare9a41262005-01-15 22:18:47 +00008309 for (i = 0; i < 3; ++i)
8310 if (STRCMP(action, av[i]) == 0)
8311 break;
8312 if (i == 3)
8313 {
8314 EMSGN(_(e_invarg2), action);
8315 return;
8316 }
8317 }
8318 else
8319 action = (char_u *)"force";
8320
8321 /* Go over all entries in the second dict and add them to the
8322 * first dict. */
Bram Moolenaar33570922005-01-25 22:26:29 +00008323 todo = d2->dv_hashtab.ht_used;
8324 for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008325 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008326 if (!HASHITEM_EMPTY(hi2))
Bram Moolenaare9a41262005-01-15 22:18:47 +00008327 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008328 --todo;
8329 di1 = dict_find(d1, hi2->hi_key, -1);
8330 if (di1 == NULL)
8331 {
8332 di1 = dictitem_copy(HI2DI(hi2));
8333 if (di1 != NULL && dict_add(d1, di1) == FAIL)
8334 dictitem_free(di1);
8335 }
8336 else if (*action == 'e')
8337 {
8338 EMSG2(_("E737: Key already exists: %s"), hi2->hi_key);
8339 break;
8340 }
8341 else if (*action == 'f')
8342 {
8343 clear_tv(&di1->di_tv);
8344 copy_tv(&HI2DI(hi2)->di_tv, &di1->di_tv);
8345 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008346 }
8347 }
8348
Bram Moolenaare9a41262005-01-15 22:18:47 +00008349 copy_tv(&argvars[0], rettv);
8350 }
8351 }
8352 else
8353 EMSG2(_(e_listdictarg), "extend()");
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008354}
8355
8356/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008357 * "filereadable()" function
8358 */
8359 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008360f_filereadable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008361 typval_T *argvars;
8362 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008363{
8364 FILE *fd;
8365 char_u *p;
8366 int n;
8367
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008368 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008369 if (*p && !mch_isdir(p) && (fd = mch_fopen((char *)p, "r")) != NULL)
8370 {
8371 n = TRUE;
8372 fclose(fd);
8373 }
8374 else
8375 n = FALSE;
8376
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008377 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008378}
8379
8380/*
Bram Moolenaar0e4d8772005-06-07 21:12:49 +00008381 * Return 0 for not writable, 1 for writable file, 2 for a dir which we have
Bram Moolenaar071d4272004-06-13 20:20:40 +00008382 * rights to write into.
8383 */
8384 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008385f_filewritable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008386 typval_T *argvars;
8387 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008388{
Bram Moolenaar0e4d8772005-06-07 21:12:49 +00008389 rettv->vval.v_number = filewritable(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008390}
8391
Bram Moolenaar33570922005-01-25 22:26:29 +00008392static void findfilendir __ARGS((typval_T *argvars, typval_T *rettv, int dir));
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008393
8394 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +00008395findfilendir(argvars, rettv, dir)
Bram Moolenaar33570922005-01-25 22:26:29 +00008396 typval_T *argvars;
8397 typval_T *rettv;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008398 int dir;
8399{
8400#ifdef FEAT_SEARCHPATH
8401 char_u *fname;
8402 char_u *fresult = NULL;
8403 char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
8404 char_u *p;
8405 char_u pathbuf[NUMBUFLEN];
8406 int count = 1;
8407 int first = TRUE;
8408
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008409 fname = get_tv_string(&argvars[0]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008410
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008411 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008412 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008413 p = get_tv_string_buf_chk(&argvars[1], pathbuf);
8414 if (p == NULL)
8415 count = -1; /* error */
8416 else
8417 {
8418 if (*p != NUL)
8419 path = p;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008420
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008421 if (argvars[2].v_type != VAR_UNKNOWN)
8422 count = get_tv_number_chk(&argvars[2], NULL); /* -1: error */
8423 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008424 }
8425
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008426 if (*fname != NUL && count >= 0)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008427 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008428 do
8429 {
8430 vim_free(fresult);
8431 fresult = find_file_in_path_option(first ? fname : NULL,
8432 first ? (int)STRLEN(fname) : 0,
8433 0, first, path, dir, NULL);
8434 first = FALSE;
8435 } while (--count > 0 && fresult != NULL);
8436 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008437
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008438 rettv->vval.v_string = fresult;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008439#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008440 rettv->vval.v_string = NULL;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008441#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008442 rettv->v_type = VAR_STRING;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008443}
8444
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008445static void prepare_vimvar __ARGS((int idx, typval_T *save_tv));
8446static void restore_vimvar __ARGS((int idx, typval_T *save_tv));
Bram Moolenaar33570922005-01-25 22:26:29 +00008447static void filter_map __ARGS((typval_T *argvars, typval_T *rettv, int map));
8448static int filter_map_one __ARGS((typval_T *tv, char_u *expr, int map, int *remp));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008449
8450/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008451 * Prepare v: variable "idx" to be used.
8452 * Save the current typeval in "save_tv".
8453 * When not used yet add the variable to the v: hashtable.
8454 */
8455 static void
8456prepare_vimvar(idx, save_tv)
8457 int idx;
8458 typval_T *save_tv;
8459{
8460 *save_tv = vimvars[idx].vv_tv;
8461 if (vimvars[idx].vv_type == VAR_UNKNOWN)
8462 hash_add(&vimvarht, vimvars[idx].vv_di.di_key);
8463}
8464
8465/*
8466 * Restore v: variable "idx" to typeval "save_tv".
8467 * When no longer defined, remove the variable from the v: hashtable.
8468 */
8469 static void
8470restore_vimvar(idx, save_tv)
8471 int idx;
8472 typval_T *save_tv;
8473{
8474 hashitem_T *hi;
8475
8476 clear_tv(&vimvars[idx].vv_tv);
8477 vimvars[idx].vv_tv = *save_tv;
8478 if (vimvars[idx].vv_type == VAR_UNKNOWN)
8479 {
8480 hi = hash_find(&vimvarht, vimvars[idx].vv_di.di_key);
8481 if (HASHITEM_EMPTY(hi))
8482 EMSG2(_(e_intern2), "restore_vimvar()");
8483 else
8484 hash_remove(&vimvarht, hi);
8485 }
8486}
8487
8488/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008489 * Implementation of map() and filter().
8490 */
8491 static void
8492filter_map(argvars, rettv, map)
Bram Moolenaar33570922005-01-25 22:26:29 +00008493 typval_T *argvars;
8494 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008495 int map;
8496{
8497 char_u buf[NUMBUFLEN];
Bram Moolenaare9a41262005-01-15 22:18:47 +00008498 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +00008499 listitem_T *li, *nli;
8500 list_T *l = NULL;
8501 dictitem_T *di;
8502 hashtab_T *ht;
8503 hashitem_T *hi;
8504 dict_T *d = NULL;
8505 typval_T save_val;
8506 typval_T save_key;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008507 int rem;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008508 int todo;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008509 char_u *msg = map ? (char_u *)"map()" : (char_u *)"filter()";
8510
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008511
8512 rettv->vval.v_number = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008513 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008514 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008515 if ((l = argvars[0].vval.v_list) == NULL
8516 || (map && tv_check_lock(l->lv_lock, msg)))
Bram Moolenaare9a41262005-01-15 22:18:47 +00008517 return;
8518 }
8519 else if (argvars[0].v_type == VAR_DICT)
8520 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008521 if ((d = argvars[0].vval.v_dict) == NULL
8522 || (map && tv_check_lock(d->dv_lock, msg)))
Bram Moolenaare9a41262005-01-15 22:18:47 +00008523 return;
8524 }
8525 else
8526 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008527 EMSG2(_(e_listdictarg), msg);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008528 return;
8529 }
8530
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008531 expr = get_tv_string_buf_chk(&argvars[1], buf);
8532 /* On type errors, the preceding call has already displayed an error
8533 * message. Avoid a misleading error message for an empty string that
8534 * was not passed as argument. */
8535 if (expr != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008536 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008537 prepare_vimvar(VV_VAL, &save_val);
8538 expr = skipwhite(expr);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008539
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008540 if (argvars[0].v_type == VAR_DICT)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008541 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008542 prepare_vimvar(VV_KEY, &save_key);
8543 vimvars[VV_KEY].vv_type = VAR_STRING;
8544
8545 ht = &d->dv_hashtab;
8546 hash_lock(ht);
8547 todo = ht->ht_used;
8548 for (hi = ht->ht_array; todo > 0; ++hi)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008549 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008550 if (!HASHITEM_EMPTY(hi))
8551 {
8552 --todo;
8553 di = HI2DI(hi);
8554 if (tv_check_lock(di->di_tv.v_lock, msg))
8555 break;
8556 vimvars[VV_KEY].vv_str = vim_strsave(di->di_key);
8557 if (filter_map_one(&di->di_tv, expr, map, &rem) == FAIL)
8558 break;
8559 if (!map && rem)
8560 dictitem_remove(d, di);
8561 clear_tv(&vimvars[VV_KEY].vv_tv);
8562 }
8563 }
8564 hash_unlock(ht);
8565
8566 restore_vimvar(VV_KEY, &save_key);
8567 }
8568 else
8569 {
8570 for (li = l->lv_first; li != NULL; li = nli)
8571 {
8572 if (tv_check_lock(li->li_tv.v_lock, msg))
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008573 break;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008574 nli = li->li_next;
8575 if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008576 break;
8577 if (!map && rem)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008578 listitem_remove(l, li);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008579 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008580 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008581
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008582 restore_vimvar(VV_VAL, &save_val);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008583 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008584
8585 copy_tv(&argvars[0], rettv);
8586}
8587
8588 static int
8589filter_map_one(tv, expr, map, remp)
Bram Moolenaar33570922005-01-25 22:26:29 +00008590 typval_T *tv;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008591 char_u *expr;
8592 int map;
8593 int *remp;
8594{
Bram Moolenaar33570922005-01-25 22:26:29 +00008595 typval_T rettv;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008596 char_u *s;
8597
Bram Moolenaar33570922005-01-25 22:26:29 +00008598 copy_tv(tv, &vimvars[VV_VAL].vv_tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008599 s = expr;
8600 if (eval1(&s, &rettv, TRUE) == FAIL)
8601 return FAIL;
8602 if (*s != NUL) /* check for trailing chars after expr */
8603 {
8604 EMSG2(_(e_invexpr2), s);
8605 return FAIL;
8606 }
8607 if (map)
8608 {
8609 /* map(): replace the list item value */
8610 clear_tv(tv);
8611 *tv = rettv;
8612 }
8613 else
8614 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008615 int error = FALSE;
8616
Bram Moolenaare9a41262005-01-15 22:18:47 +00008617 /* filter(): when expr is zero remove the item */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008618 *remp = (get_tv_number_chk(&rettv, &error) == 0);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008619 clear_tv(&rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008620 /* On type error, nothing has been removed; return FAIL to stop the
8621 * loop. The error message was given by get_tv_number_chk(). */
8622 if (error)
8623 return FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008624 }
Bram Moolenaar33570922005-01-25 22:26:29 +00008625 clear_tv(&vimvars[VV_VAL].vv_tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008626 return OK;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008627}
8628
8629/*
8630 * "filter()" function
8631 */
8632 static void
8633f_filter(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008634 typval_T *argvars;
8635 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008636{
8637 filter_map(argvars, rettv, FALSE);
8638}
8639
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008640/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00008641 * "finddir({fname}[, {path}[, {count}]])" function
8642 */
8643 static void
8644f_finddir(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008645 typval_T *argvars;
8646 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008647{
8648 findfilendir(argvars, rettv, TRUE);
8649}
8650
8651/*
8652 * "findfile({fname}[, {path}[, {count}]])" function
8653 */
8654 static void
8655f_findfile(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008656 typval_T *argvars;
8657 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008658{
8659 findfilendir(argvars, rettv, FALSE);
8660}
8661
8662/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008663 * "fnamemodify({fname}, {mods})" function
8664 */
8665 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008666f_fnamemodify(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008667 typval_T *argvars;
8668 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008669{
8670 char_u *fname;
8671 char_u *mods;
8672 int usedlen = 0;
8673 int len;
8674 char_u *fbuf = NULL;
8675 char_u buf[NUMBUFLEN];
8676
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008677 fname = get_tv_string_chk(&argvars[0]);
8678 mods = get_tv_string_buf_chk(&argvars[1], buf);
8679 if (fname == NULL || mods == NULL)
8680 fname = NULL;
8681 else
8682 {
8683 len = (int)STRLEN(fname);
8684 (void)modify_fname(mods, &usedlen, &fname, &fbuf, &len);
8685 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008686
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008687 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008688 if (fname == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008689 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008690 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008691 rettv->vval.v_string = vim_strnsave(fname, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008692 vim_free(fbuf);
8693}
8694
Bram Moolenaar33570922005-01-25 22:26:29 +00008695static void foldclosed_both __ARGS((typval_T *argvars, typval_T *rettv, int end));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008696
8697/*
8698 * "foldclosed()" function
8699 */
8700 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008701foldclosed_both(argvars, rettv, end)
Bram Moolenaar33570922005-01-25 22:26:29 +00008702 typval_T *argvars;
8703 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008704 int end;
8705{
8706#ifdef FEAT_FOLDING
8707 linenr_T lnum;
8708 linenr_T first, last;
8709
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008710 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008711 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
8712 {
8713 if (hasFoldingWin(curwin, lnum, &first, &last, FALSE, NULL))
8714 {
8715 if (end)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008716 rettv->vval.v_number = (varnumber_T)last;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008717 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008718 rettv->vval.v_number = (varnumber_T)first;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008719 return;
8720 }
8721 }
8722#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008723 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008724}
8725
8726/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00008727 * "foldclosed()" function
8728 */
8729 static void
8730f_foldclosed(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008731 typval_T *argvars;
8732 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008733{
8734 foldclosed_both(argvars, rettv, FALSE);
8735}
8736
8737/*
8738 * "foldclosedend()" function
8739 */
8740 static void
8741f_foldclosedend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008742 typval_T *argvars;
8743 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008744{
8745 foldclosed_both(argvars, rettv, TRUE);
8746}
8747
8748/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008749 * "foldlevel()" function
8750 */
8751 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008752f_foldlevel(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008753 typval_T *argvars;
8754 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008755{
8756#ifdef FEAT_FOLDING
8757 linenr_T lnum;
8758
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008759 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008760 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008761 rettv->vval.v_number = foldLevel(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008762 else
8763#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008764 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008765}
8766
8767/*
8768 * "foldtext()" function
8769 */
8770/*ARGSUSED*/
8771 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008772f_foldtext(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008773 typval_T *argvars;
8774 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008775{
8776#ifdef FEAT_FOLDING
8777 linenr_T lnum;
8778 char_u *s;
8779 char_u *r;
8780 int len;
8781 char *txt;
8782#endif
8783
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008784 rettv->v_type = VAR_STRING;
8785 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008786#ifdef FEAT_FOLDING
Bram Moolenaare9a41262005-01-15 22:18:47 +00008787 if ((linenr_T)vimvars[VV_FOLDSTART].vv_nr > 0
8788 && (linenr_T)vimvars[VV_FOLDEND].vv_nr
8789 <= curbuf->b_ml.ml_line_count
8790 && vimvars[VV_FOLDDASHES].vv_str != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008791 {
8792 /* Find first non-empty line in the fold. */
Bram Moolenaare9a41262005-01-15 22:18:47 +00008793 lnum = (linenr_T)vimvars[VV_FOLDSTART].vv_nr;
8794 while (lnum < (linenr_T)vimvars[VV_FOLDEND].vv_nr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008795 {
8796 if (!linewhite(lnum))
8797 break;
8798 ++lnum;
8799 }
8800
8801 /* Find interesting text in this line. */
8802 s = skipwhite(ml_get(lnum));
8803 /* skip C comment-start */
8804 if (s[0] == '/' && (s[1] == '*' || s[1] == '/'))
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00008805 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00008806 s = skipwhite(s + 2);
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00008807 if (*skipwhite(s) == NUL
Bram Moolenaare9a41262005-01-15 22:18:47 +00008808 && lnum + 1 < (linenr_T)vimvars[VV_FOLDEND].vv_nr)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00008809 {
8810 s = skipwhite(ml_get(lnum + 1));
8811 if (*s == '*')
8812 s = skipwhite(s + 1);
8813 }
8814 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008815 txt = _("+-%s%3ld lines: ");
8816 r = alloc((unsigned)(STRLEN(txt)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008817 + STRLEN(vimvars[VV_FOLDDASHES].vv_str) /* for %s */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008818 + 20 /* for %3ld */
8819 + STRLEN(s))); /* concatenated */
8820 if (r != NULL)
8821 {
Bram Moolenaare9a41262005-01-15 22:18:47 +00008822 sprintf((char *)r, txt, vimvars[VV_FOLDDASHES].vv_str,
8823 (long)((linenr_T)vimvars[VV_FOLDEND].vv_nr
8824 - (linenr_T)vimvars[VV_FOLDSTART].vv_nr + 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008825 len = (int)STRLEN(r);
8826 STRCAT(r, s);
8827 /* remove 'foldmarker' and 'commentstring' */
8828 foldtext_cleanup(r + len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008829 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008830 }
8831 }
8832#endif
8833}
8834
8835/*
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008836 * "foldtextresult(lnum)" function
8837 */
8838/*ARGSUSED*/
8839 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008840f_foldtextresult(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008841 typval_T *argvars;
8842 typval_T *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008843{
8844#ifdef FEAT_FOLDING
8845 linenr_T lnum;
8846 char_u *text;
8847 char_u buf[51];
8848 foldinfo_T foldinfo;
8849 int fold_count;
8850#endif
8851
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008852 rettv->v_type = VAR_STRING;
8853 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008854#ifdef FEAT_FOLDING
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008855 lnum = get_tv_lnum(argvars);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008856 /* treat illegal types and illegal string values for {lnum} the same */
8857 if (lnum < 0)
8858 lnum = 0;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008859 fold_count = foldedCount(curwin, lnum, &foldinfo);
8860 if (fold_count > 0)
8861 {
8862 text = get_foldtext(curwin, lnum, lnum + fold_count - 1,
8863 &foldinfo, buf);
8864 if (text == buf)
8865 text = vim_strsave(text);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008866 rettv->vval.v_string = text;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008867 }
8868#endif
8869}
8870
8871/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008872 * "foreground()" function
8873 */
8874/*ARGSUSED*/
8875 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008876f_foreground(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008877 typval_T *argvars;
8878 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008879{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008880 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008881#ifdef FEAT_GUI
8882 if (gui.in_use)
8883 gui_mch_set_foreground();
8884#else
8885# ifdef WIN32
8886 win32_set_foreground();
8887# endif
8888#endif
8889}
8890
8891/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008892 * "function()" function
8893 */
8894/*ARGSUSED*/
8895 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008896f_function(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008897 typval_T *argvars;
8898 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008899{
8900 char_u *s;
8901
Bram Moolenaara7043832005-01-21 11:56:39 +00008902 rettv->vval.v_number = 0;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008903 s = get_tv_string(&argvars[0]);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008904 if (s == NULL || *s == NUL || VIM_ISDIGIT(*s))
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008905 EMSG2(_(e_invarg2), s);
8906 else if (!function_exists(s))
Bram Moolenaare49b69a2005-01-08 16:11:57 +00008907 EMSG2(_("E700: Unknown function: %s"), s);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008908 else
8909 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008910 rettv->vval.v_string = vim_strsave(s);
8911 rettv->v_type = VAR_FUNC;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008912 }
8913}
8914
8915/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00008916 * "garbagecollect()" function
8917 */
8918/*ARGSUSED*/
8919 static void
8920f_garbagecollect(argvars, rettv)
8921 typval_T *argvars;
8922 typval_T *rettv;
8923{
8924 garbage_collect();
8925}
8926
8927/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00008928 * "get()" function
8929 */
8930 static void
8931f_get(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008932 typval_T *argvars;
8933 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008934{
Bram Moolenaar33570922005-01-25 22:26:29 +00008935 listitem_T *li;
8936 list_T *l;
8937 dictitem_T *di;
8938 dict_T *d;
8939 typval_T *tv = NULL;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008940
Bram Moolenaare9a41262005-01-15 22:18:47 +00008941 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar0d660222005-01-07 21:51:51 +00008942 {
Bram Moolenaare9a41262005-01-15 22:18:47 +00008943 if ((l = argvars[0].vval.v_list) != NULL)
Bram Moolenaar0d660222005-01-07 21:51:51 +00008944 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008945 int error = FALSE;
8946
8947 li = list_find(l, get_tv_number_chk(&argvars[1], &error));
8948 if (!error && li != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008949 tv = &li->li_tv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008950 }
Bram Moolenaar0d660222005-01-07 21:51:51 +00008951 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008952 else if (argvars[0].v_type == VAR_DICT)
8953 {
8954 if ((d = argvars[0].vval.v_dict) != NULL)
8955 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008956 di = dict_find(d, get_tv_string(&argvars[1]), -1);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008957 if (di != NULL)
8958 tv = &di->di_tv;
8959 }
8960 }
8961 else
8962 EMSG2(_(e_listdictarg), "get()");
8963
8964 if (tv == NULL)
8965 {
8966 if (argvars[2].v_type == VAR_UNKNOWN)
8967 rettv->vval.v_number = 0;
8968 else
8969 copy_tv(&argvars[2], rettv);
8970 }
8971 else
8972 copy_tv(tv, rettv);
Bram Moolenaar0d660222005-01-07 21:51:51 +00008973}
8974
8975/*
8976 * "getbufvar()" function
8977 */
8978 static void
8979f_getbufvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008980 typval_T *argvars;
8981 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008982{
8983 buf_T *buf;
8984 buf_T *save_curbuf;
8985 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +00008986 dictitem_T *v;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008987
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008988 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
8989 varname = get_tv_string_chk(&argvars[1]);
Bram Moolenaar0d660222005-01-07 21:51:51 +00008990 ++emsg_off;
8991 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar0d660222005-01-07 21:51:51 +00008992
8993 rettv->v_type = VAR_STRING;
8994 rettv->vval.v_string = NULL;
8995
8996 if (buf != NULL && varname != NULL)
8997 {
8998 if (*varname == '&') /* buffer-local-option */
8999 {
9000 /* set curbuf to be our buf, temporarily */
9001 save_curbuf = curbuf;
9002 curbuf = buf;
9003
9004 get_option_tv(&varname, rettv, TRUE);
9005
9006 /* restore previous notion of curbuf */
9007 curbuf = save_curbuf;
9008 }
9009 else
9010 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009011 if (*varname == NUL)
9012 /* let getbufvar({nr}, "") return the "b:" dictionary. The
9013 * scope prefix before the NUL byte is required by
9014 * find_var_in_ht(). */
9015 varname = (char_u *)"b:" + 2;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009016 /* look up the variable */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00009017 v = find_var_in_ht(&buf->b_vars.dv_hashtab, varname, FALSE);
Bram Moolenaar0d660222005-01-07 21:51:51 +00009018 if (v != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +00009019 copy_tv(&v->di_tv, rettv);
Bram Moolenaar0d660222005-01-07 21:51:51 +00009020 }
9021 }
9022
9023 --emsg_off;
9024}
9025
9026/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009027 * "getchar()" function
9028 */
9029 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009030f_getchar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009031 typval_T *argvars;
9032 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009033{
9034 varnumber_T n;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009035 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009036
9037 ++no_mapping;
9038 ++allow_keys;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009039 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009040 /* getchar(): blocking wait. */
9041 n = safe_vgetc();
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009042 else if (get_tv_number_chk(&argvars[0], &error) == 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009043 /* getchar(1): only check if char avail */
9044 n = vpeekc();
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009045 else if (error || vpeekc() == NUL)
9046 /* illegal argument or getchar(0) and no char avail: return zero */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009047 n = 0;
9048 else
9049 /* getchar(0) and char avail: return char */
9050 n = safe_vgetc();
9051 --no_mapping;
9052 --allow_keys;
9053
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009054 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009055 if (IS_SPECIAL(n) || mod_mask != 0)
9056 {
9057 char_u temp[10]; /* modifier: 3, mbyte-char: 6, NUL: 1 */
9058 int i = 0;
9059
9060 /* Turn a special key into three bytes, plus modifier. */
9061 if (mod_mask != 0)
9062 {
9063 temp[i++] = K_SPECIAL;
9064 temp[i++] = KS_MODIFIER;
9065 temp[i++] = mod_mask;
9066 }
9067 if (IS_SPECIAL(n))
9068 {
9069 temp[i++] = K_SPECIAL;
9070 temp[i++] = K_SECOND(n);
9071 temp[i++] = K_THIRD(n);
9072 }
9073#ifdef FEAT_MBYTE
9074 else if (has_mbyte)
9075 i += (*mb_char2bytes)(n, temp + i);
9076#endif
9077 else
9078 temp[i++] = n;
9079 temp[i++] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009080 rettv->v_type = VAR_STRING;
9081 rettv->vval.v_string = vim_strsave(temp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009082 }
9083}
9084
9085/*
9086 * "getcharmod()" function
9087 */
9088/*ARGSUSED*/
9089 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009090f_getcharmod(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009091 typval_T *argvars;
9092 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009093{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009094 rettv->vval.v_number = mod_mask;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009095}
9096
9097/*
9098 * "getcmdline()" function
9099 */
9100/*ARGSUSED*/
9101 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009102f_getcmdline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009103 typval_T *argvars;
9104 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009105{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009106 rettv->v_type = VAR_STRING;
9107 rettv->vval.v_string = get_cmdline_str();
Bram Moolenaar071d4272004-06-13 20:20:40 +00009108}
9109
9110/*
9111 * "getcmdpos()" function
9112 */
9113/*ARGSUSED*/
9114 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009115f_getcmdpos(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009116 typval_T *argvars;
9117 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009118{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009119 rettv->vval.v_number = get_cmdline_pos() + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009120}
9121
9122/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009123 * "getcwd()" function
9124 */
9125/*ARGSUSED*/
9126 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009127f_getcwd(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009128 typval_T *argvars;
9129 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009130{
9131 char_u cwd[MAXPATHL];
9132
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009133 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009134 if (mch_dirname(cwd, MAXPATHL) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009135 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009136 else
9137 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009138 rettv->vval.v_string = vim_strsave(cwd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009139#ifdef BACKSLASH_IN_FILENAME
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009140 slash_adjust(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009141#endif
9142 }
9143}
9144
9145/*
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009146 * "getfontname()" function
9147 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00009148/*ARGSUSED*/
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009149 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009150f_getfontname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009151 typval_T *argvars;
9152 typval_T *rettv;
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009153{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009154 rettv->v_type = VAR_STRING;
9155 rettv->vval.v_string = NULL;
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009156#ifdef FEAT_GUI
9157 if (gui.in_use)
9158 {
9159 GuiFont font;
9160 char_u *name = NULL;
9161
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009162 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009163 {
9164 /* Get the "Normal" font. Either the name saved by
9165 * hl_set_font_name() or from the font ID. */
9166 font = gui.norm_font;
9167 name = hl_get_font_name();
9168 }
9169 else
9170 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009171 name = get_tv_string(&argvars[0]);
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009172 if (STRCMP(name, "*") == 0) /* don't use font dialog */
9173 return;
9174 font = gui_mch_get_font(name, FALSE);
9175 if (font == NOFONT)
9176 return; /* Invalid font name, return empty string. */
9177 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009178 rettv->vval.v_string = gui_mch_get_fontname(font, name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009179 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009180 gui_mch_free_font(font);
9181 }
9182#endif
9183}
9184
9185/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009186 * "getfperm({fname})" function
9187 */
9188 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009189f_getfperm(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009190 typval_T *argvars;
9191 typval_T *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009192{
9193 char_u *fname;
9194 struct stat st;
9195 char_u *perm = NULL;
9196 char_u flags[] = "rwx";
9197 int i;
9198
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009199 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009200
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009201 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009202 if (mch_stat((char *)fname, &st) >= 0)
9203 {
9204 perm = vim_strsave((char_u *)"---------");
9205 if (perm != NULL)
9206 {
9207 for (i = 0; i < 9; i++)
9208 {
9209 if (st.st_mode & (1 << (8 - i)))
9210 perm[i] = flags[i % 3];
9211 }
9212 }
9213 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009214 rettv->vval.v_string = perm;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009215}
9216
9217/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009218 * "getfsize({fname})" function
9219 */
9220 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009221f_getfsize(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009222 typval_T *argvars;
9223 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009224{
9225 char_u *fname;
9226 struct stat st;
9227
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009228 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009229
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009230 rettv->v_type = VAR_NUMBER;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009231
9232 if (mch_stat((char *)fname, &st) >= 0)
9233 {
9234 if (mch_isdir(fname))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009235 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009236 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009237 rettv->vval.v_number = (varnumber_T)st.st_size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009238 }
9239 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009240 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009241}
9242
9243/*
9244 * "getftime({fname})" function
9245 */
9246 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009247f_getftime(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009248 typval_T *argvars;
9249 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009250{
9251 char_u *fname;
9252 struct stat st;
9253
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009254 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009255
9256 if (mch_stat((char *)fname, &st) >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009257 rettv->vval.v_number = (varnumber_T)st.st_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009258 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009259 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009260}
9261
9262/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009263 * "getftype({fname})" function
9264 */
9265 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009266f_getftype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009267 typval_T *argvars;
9268 typval_T *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009269{
9270 char_u *fname;
9271 struct stat st;
9272 char_u *type = NULL;
9273 char *t;
9274
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009275 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009276
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009277 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009278 if (mch_lstat((char *)fname, &st) >= 0)
9279 {
9280#ifdef S_ISREG
9281 if (S_ISREG(st.st_mode))
9282 t = "file";
9283 else if (S_ISDIR(st.st_mode))
9284 t = "dir";
9285# ifdef S_ISLNK
9286 else if (S_ISLNK(st.st_mode))
9287 t = "link";
9288# endif
9289# ifdef S_ISBLK
9290 else if (S_ISBLK(st.st_mode))
9291 t = "bdev";
9292# endif
9293# ifdef S_ISCHR
9294 else if (S_ISCHR(st.st_mode))
9295 t = "cdev";
9296# endif
9297# ifdef S_ISFIFO
9298 else if (S_ISFIFO(st.st_mode))
9299 t = "fifo";
9300# endif
9301# ifdef S_ISSOCK
9302 else if (S_ISSOCK(st.st_mode))
9303 t = "fifo";
9304# endif
9305 else
9306 t = "other";
9307#else
9308# ifdef S_IFMT
9309 switch (st.st_mode & S_IFMT)
9310 {
9311 case S_IFREG: t = "file"; break;
9312 case S_IFDIR: t = "dir"; break;
9313# ifdef S_IFLNK
9314 case S_IFLNK: t = "link"; break;
9315# endif
9316# ifdef S_IFBLK
9317 case S_IFBLK: t = "bdev"; break;
9318# endif
9319# ifdef S_IFCHR
9320 case S_IFCHR: t = "cdev"; break;
9321# endif
9322# ifdef S_IFIFO
9323 case S_IFIFO: t = "fifo"; break;
9324# endif
9325# ifdef S_IFSOCK
9326 case S_IFSOCK: t = "socket"; break;
9327# endif
9328 default: t = "other";
9329 }
9330# else
9331 if (mch_isdir(fname))
9332 t = "dir";
9333 else
9334 t = "file";
9335# endif
9336#endif
9337 type = vim_strsave((char_u *)t);
9338 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009339 rettv->vval.v_string = type;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009340}
9341
9342/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00009343 * "getline(lnum)" function
9344 */
9345 static void
9346f_getline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009347 typval_T *argvars;
9348 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009349{
9350 linenr_T lnum;
9351 linenr_T end;
9352 char_u *p;
Bram Moolenaar33570922005-01-25 22:26:29 +00009353 list_T *l;
9354 listitem_T *li;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009355
9356 lnum = get_tv_lnum(argvars);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009357 if (lnum < 0)
9358 rettv->vval.v_number = 0; /* failure; error message already given */
9359 else if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar0d660222005-01-07 21:51:51 +00009360 {
9361 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
9362 p = ml_get(lnum);
9363 else
9364 p = (char_u *)"";
9365
9366 rettv->v_type = VAR_STRING;
9367 rettv->vval.v_string = vim_strsave(p);
9368 }
9369 else
9370 {
9371 end = get_tv_lnum(&argvars[1]);
9372 if (end < lnum)
9373 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009374 if (end >= 0) /* else: error message already given */
9375 EMSG(_(e_invrange));
Bram Moolenaar0d660222005-01-07 21:51:51 +00009376 rettv->vval.v_number = 0;
9377 }
9378 else
9379 {
9380 l = list_alloc();
9381 if (l != NULL)
9382 {
9383 if (lnum < 1)
9384 lnum = 1;
9385 if (end > curbuf->b_ml.ml_line_count)
9386 end = curbuf->b_ml.ml_line_count;
9387 while (lnum <= end)
9388 {
9389 li = listitem_alloc();
9390 if (li == NULL)
9391 break;
9392 list_append(l, li);
9393 li->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00009394 li->li_tv.v_lock = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009395 li->li_tv.vval.v_string = vim_strsave(ml_get(lnum++));
9396 }
9397 rettv->vval.v_list = l;
9398 rettv->v_type = VAR_LIST;
9399 ++l->lv_refcount;
9400 }
9401 }
9402 }
9403}
9404
9405/*
Bram Moolenaar2641f772005-03-25 21:58:17 +00009406 * "getqflist()" function
9407 */
9408/*ARGSUSED*/
9409 static void
9410f_getqflist(argvars, rettv)
9411 typval_T *argvars;
9412 typval_T *rettv;
9413{
9414#ifdef FEAT_QUICKFIX
9415 list_T *l;
9416#endif
9417
9418 rettv->vval.v_number = FALSE;
9419#ifdef FEAT_QUICKFIX
9420 l = list_alloc();
9421 if (l != NULL)
9422 {
9423 if (get_errorlist(l) != FAIL)
9424 {
9425 rettv->vval.v_list = l;
9426 rettv->v_type = VAR_LIST;
9427 ++l->lv_refcount;
9428 }
9429 else
9430 list_free(l);
9431 }
9432#endif
9433}
9434
9435/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009436 * "getreg()" function
9437 */
9438 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009439f_getreg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009440 typval_T *argvars;
9441 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009442{
9443 char_u *strregname;
9444 int regname;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00009445 int arg2 = FALSE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009446 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009447
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009448 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00009449 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009450 strregname = get_tv_string_chk(&argvars[0]);
9451 error = strregname == NULL;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00009452 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009453 arg2 = get_tv_number_chk(&argvars[1], &error);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00009454 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009455 else
Bram Moolenaare9a41262005-01-15 22:18:47 +00009456 strregname = vimvars[VV_REG].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009457 regname = (strregname == NULL ? '"' : *strregname);
9458 if (regname == 0)
9459 regname = '"';
9460
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009461 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009462 rettv->vval.v_string = error ? NULL :
9463 get_reg_contents(regname, TRUE, arg2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009464}
9465
9466/*
9467 * "getregtype()" function
9468 */
9469 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009470f_getregtype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009471 typval_T *argvars;
9472 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009473{
9474 char_u *strregname;
9475 int regname;
9476 char_u buf[NUMBUFLEN + 2];
9477 long reglen = 0;
9478
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009479 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009480 {
9481 strregname = get_tv_string_chk(&argvars[0]);
9482 if (strregname == NULL) /* type error; errmsg already given */
9483 {
9484 rettv->v_type = VAR_STRING;
9485 rettv->vval.v_string = NULL;
9486 return;
9487 }
9488 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009489 else
9490 /* Default to v:register */
Bram Moolenaare9a41262005-01-15 22:18:47 +00009491 strregname = vimvars[VV_REG].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009492
9493 regname = (strregname == NULL ? '"' : *strregname);
9494 if (regname == 0)
9495 regname = '"';
9496
9497 buf[0] = NUL;
9498 buf[1] = NUL;
9499 switch (get_reg_type(regname, &reglen))
9500 {
9501 case MLINE: buf[0] = 'V'; break;
9502 case MCHAR: buf[0] = 'v'; break;
9503#ifdef FEAT_VISUAL
9504 case MBLOCK:
9505 buf[0] = Ctrl_V;
9506 sprintf((char *)buf + 1, "%ld", reglen + 1);
9507 break;
9508#endif
9509 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009510 rettv->v_type = VAR_STRING;
9511 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009512}
9513
9514/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009515 * "getwinposx()" function
9516 */
9517/*ARGSUSED*/
9518 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009519f_getwinposx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009520 typval_T *argvars;
9521 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009522{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009523 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009524#ifdef FEAT_GUI
9525 if (gui.in_use)
9526 {
9527 int x, y;
9528
9529 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009530 rettv->vval.v_number = x;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009531 }
9532#endif
9533}
9534
9535/*
9536 * "getwinposy()" function
9537 */
9538/*ARGSUSED*/
9539 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009540f_getwinposy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009541 typval_T *argvars;
9542 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009543{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009544 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009545#ifdef FEAT_GUI
9546 if (gui.in_use)
9547 {
9548 int x, y;
9549
9550 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009551 rettv->vval.v_number = y;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009552 }
9553#endif
9554}
9555
9556/*
9557 * "getwinvar()" function
9558 */
9559 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009560f_getwinvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009561 typval_T *argvars;
9562 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009563{
9564 win_T *win, *oldcurwin;
9565 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +00009566 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009567
Bram Moolenaar071d4272004-06-13 20:20:40 +00009568 win = find_win_by_nr(&argvars[0]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009569 varname = get_tv_string_chk(&argvars[1]);
9570 ++emsg_off;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009571
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009572 rettv->v_type = VAR_STRING;
9573 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009574
9575 if (win != NULL && varname != NULL)
9576 {
9577 if (*varname == '&') /* window-local-option */
9578 {
Bram Moolenaarc0761132005-03-18 20:30:32 +00009579 /* Set curwin to be our win, temporarily. Also set curbuf, so
9580 * that we can get buffer-local options. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009581 oldcurwin = curwin;
9582 curwin = win;
Bram Moolenaarc0761132005-03-18 20:30:32 +00009583 curbuf = win->w_buffer;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009584
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009585 get_option_tv(&varname, rettv, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009586
9587 /* restore previous notion of curwin */
9588 curwin = oldcurwin;
Bram Moolenaarc0761132005-03-18 20:30:32 +00009589 curbuf = curwin->w_buffer;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009590 }
9591 else
9592 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009593 if (*varname == NUL)
9594 /* let getwinvar({nr}, "") return the "w:" dictionary. The
9595 * scope prefix before the NUL byte is required by
9596 * find_var_in_ht(). */
9597 varname = (char_u *)"w:" + 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009598 /* look up the variable */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00009599 v = find_var_in_ht(&win->w_vars.dv_hashtab, varname, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009600 if (v != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +00009601 copy_tv(&v->di_tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009602 }
9603 }
9604
9605 --emsg_off;
9606}
9607
9608/*
9609 * "glob()" function
9610 */
9611 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009612f_glob(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009613 typval_T *argvars;
9614 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009615{
9616 expand_T xpc;
9617
9618 ExpandInit(&xpc);
9619 xpc.xp_context = EXPAND_FILES;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009620 rettv->v_type = VAR_STRING;
9621 rettv->vval.v_string = ExpandOne(&xpc, get_tv_string(&argvars[0]),
Bram Moolenaar071d4272004-06-13 20:20:40 +00009622 NULL, WILD_USE_NL|WILD_SILENT, WILD_ALL);
9623 ExpandCleanup(&xpc);
9624}
9625
9626/*
9627 * "globpath()" function
9628 */
9629 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009630f_globpath(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009631 typval_T *argvars;
9632 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009633{
9634 char_u buf1[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009635 char_u *file = get_tv_string_buf_chk(&argvars[1], buf1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009636
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009637 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009638 if (file == NULL)
9639 rettv->vval.v_string = NULL;
9640 else
9641 rettv->vval.v_string = globpath(get_tv_string(&argvars[0]), file);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009642}
9643
9644/*
9645 * "has()" function
9646 */
9647 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009648f_has(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009649 typval_T *argvars;
9650 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009651{
9652 int i;
9653 char_u *name;
9654 int n = FALSE;
9655 static char *(has_list[]) =
9656 {
9657#ifdef AMIGA
9658 "amiga",
9659# ifdef FEAT_ARP
9660 "arp",
9661# endif
9662#endif
9663#ifdef __BEOS__
9664 "beos",
9665#endif
9666#ifdef MSDOS
9667# ifdef DJGPP
9668 "dos32",
9669# else
9670 "dos16",
9671# endif
9672#endif
9673#ifdef MACOS /* TODO: Should we add MACOS_CLASSIC, MACOS_X? (Dany) */
9674 "mac",
9675#endif
9676#if defined(MACOS_X_UNIX)
9677 "macunix",
9678#endif
9679#ifdef OS2
9680 "os2",
9681#endif
9682#ifdef __QNX__
9683 "qnx",
9684#endif
9685#ifdef RISCOS
9686 "riscos",
9687#endif
9688#ifdef UNIX
9689 "unix",
9690#endif
9691#ifdef VMS
9692 "vms",
9693#endif
9694#ifdef WIN16
9695 "win16",
9696#endif
9697#ifdef WIN32
9698 "win32",
9699#endif
9700#if defined(UNIX) && (defined(__CYGWIN32__) || defined(__CYGWIN__))
9701 "win32unix",
9702#endif
9703#ifdef WIN64
9704 "win64",
9705#endif
9706#ifdef EBCDIC
9707 "ebcdic",
9708#endif
9709#ifndef CASE_INSENSITIVE_FILENAME
9710 "fname_case",
9711#endif
9712#ifdef FEAT_ARABIC
9713 "arabic",
9714#endif
9715#ifdef FEAT_AUTOCMD
9716 "autocmd",
9717#endif
9718#ifdef FEAT_BEVAL
9719 "balloon_eval",
9720#endif
9721#if defined(SOME_BUILTIN_TCAPS) || defined(ALL_BUILTIN_TCAPS)
9722 "builtin_terms",
9723# ifdef ALL_BUILTIN_TCAPS
9724 "all_builtin_terms",
9725# endif
9726#endif
9727#ifdef FEAT_BYTEOFF
9728 "byte_offset",
9729#endif
9730#ifdef FEAT_CINDENT
9731 "cindent",
9732#endif
9733#ifdef FEAT_CLIENTSERVER
9734 "clientserver",
9735#endif
9736#ifdef FEAT_CLIPBOARD
9737 "clipboard",
9738#endif
9739#ifdef FEAT_CMDL_COMPL
9740 "cmdline_compl",
9741#endif
9742#ifdef FEAT_CMDHIST
9743 "cmdline_hist",
9744#endif
9745#ifdef FEAT_COMMENTS
9746 "comments",
9747#endif
9748#ifdef FEAT_CRYPT
9749 "cryptv",
9750#endif
9751#ifdef FEAT_CSCOPE
9752 "cscope",
9753#endif
9754#ifdef DEBUG
9755 "debug",
9756#endif
9757#ifdef FEAT_CON_DIALOG
9758 "dialog_con",
9759#endif
9760#ifdef FEAT_GUI_DIALOG
9761 "dialog_gui",
9762#endif
9763#ifdef FEAT_DIFF
9764 "diff",
9765#endif
9766#ifdef FEAT_DIGRAPHS
9767 "digraphs",
9768#endif
9769#ifdef FEAT_DND
9770 "dnd",
9771#endif
9772#ifdef FEAT_EMACS_TAGS
9773 "emacs_tags",
9774#endif
9775 "eval", /* always present, of course! */
9776#ifdef FEAT_EX_EXTRA
9777 "ex_extra",
9778#endif
9779#ifdef FEAT_SEARCH_EXTRA
9780 "extra_search",
9781#endif
9782#ifdef FEAT_FKMAP
9783 "farsi",
9784#endif
9785#ifdef FEAT_SEARCHPATH
9786 "file_in_path",
9787#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00009788#if defined(UNIX) && !defined(USE_SYSTEM)
9789 "filterpipe",
9790#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009791#ifdef FEAT_FIND_ID
9792 "find_in_path",
9793#endif
9794#ifdef FEAT_FOLDING
9795 "folding",
9796#endif
9797#ifdef FEAT_FOOTER
9798 "footer",
9799#endif
9800#if !defined(USE_SYSTEM) && defined(UNIX)
9801 "fork",
9802#endif
9803#ifdef FEAT_GETTEXT
9804 "gettext",
9805#endif
9806#ifdef FEAT_GUI
9807 "gui",
9808#endif
9809#ifdef FEAT_GUI_ATHENA
9810# ifdef FEAT_GUI_NEXTAW
9811 "gui_neXtaw",
9812# else
9813 "gui_athena",
9814# endif
9815#endif
Bram Moolenaar843ee412004-06-30 16:16:41 +00009816#ifdef FEAT_GUI_KDE
9817 "gui_kde",
9818#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009819#ifdef FEAT_GUI_GTK
9820 "gui_gtk",
9821# ifdef HAVE_GTK2
9822 "gui_gtk2",
9823# endif
9824#endif
9825#ifdef FEAT_GUI_MAC
9826 "gui_mac",
9827#endif
9828#ifdef FEAT_GUI_MOTIF
9829 "gui_motif",
9830#endif
9831#ifdef FEAT_GUI_PHOTON
9832 "gui_photon",
9833#endif
9834#ifdef FEAT_GUI_W16
9835 "gui_win16",
9836#endif
9837#ifdef FEAT_GUI_W32
9838 "gui_win32",
9839#endif
9840#ifdef FEAT_HANGULIN
9841 "hangul_input",
9842#endif
9843#if defined(HAVE_ICONV_H) && defined(USE_ICONV)
9844 "iconv",
9845#endif
9846#ifdef FEAT_INS_EXPAND
9847 "insert_expand",
9848#endif
9849#ifdef FEAT_JUMPLIST
9850 "jumplist",
9851#endif
9852#ifdef FEAT_KEYMAP
9853 "keymap",
9854#endif
9855#ifdef FEAT_LANGMAP
9856 "langmap",
9857#endif
9858#ifdef FEAT_LIBCALL
9859 "libcall",
9860#endif
9861#ifdef FEAT_LINEBREAK
9862 "linebreak",
9863#endif
9864#ifdef FEAT_LISP
9865 "lispindent",
9866#endif
9867#ifdef FEAT_LISTCMDS
9868 "listcmds",
9869#endif
9870#ifdef FEAT_LOCALMAP
9871 "localmap",
9872#endif
9873#ifdef FEAT_MENU
9874 "menu",
9875#endif
9876#ifdef FEAT_SESSION
9877 "mksession",
9878#endif
9879#ifdef FEAT_MODIFY_FNAME
9880 "modify_fname",
9881#endif
9882#ifdef FEAT_MOUSE
9883 "mouse",
9884#endif
9885#ifdef FEAT_MOUSESHAPE
9886 "mouseshape",
9887#endif
9888#if defined(UNIX) || defined(VMS)
9889# ifdef FEAT_MOUSE_DEC
9890 "mouse_dec",
9891# endif
9892# ifdef FEAT_MOUSE_GPM
9893 "mouse_gpm",
9894# endif
9895# ifdef FEAT_MOUSE_JSB
9896 "mouse_jsbterm",
9897# endif
9898# ifdef FEAT_MOUSE_NET
9899 "mouse_netterm",
9900# endif
9901# ifdef FEAT_MOUSE_PTERM
9902 "mouse_pterm",
9903# endif
9904# ifdef FEAT_MOUSE_XTERM
9905 "mouse_xterm",
9906# endif
9907#endif
9908#ifdef FEAT_MBYTE
9909 "multi_byte",
9910#endif
9911#ifdef FEAT_MBYTE_IME
9912 "multi_byte_ime",
9913#endif
9914#ifdef FEAT_MULTI_LANG
9915 "multi_lang",
9916#endif
Bram Moolenaar325b7a22004-07-05 15:58:32 +00009917#ifdef FEAT_MZSCHEME
Bram Moolenaar33570922005-01-25 22:26:29 +00009918#ifndef DYNAMIC_MZSCHEME
Bram Moolenaar325b7a22004-07-05 15:58:32 +00009919 "mzscheme",
9920#endif
Bram Moolenaar33570922005-01-25 22:26:29 +00009921#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009922#ifdef FEAT_OLE
9923 "ole",
9924#endif
9925#ifdef FEAT_OSFILETYPE
9926 "osfiletype",
9927#endif
9928#ifdef FEAT_PATH_EXTRA
9929 "path_extra",
9930#endif
9931#ifdef FEAT_PERL
9932#ifndef DYNAMIC_PERL
9933 "perl",
9934#endif
9935#endif
9936#ifdef FEAT_PYTHON
9937#ifndef DYNAMIC_PYTHON
9938 "python",
9939#endif
9940#endif
9941#ifdef FEAT_POSTSCRIPT
9942 "postscript",
9943#endif
9944#ifdef FEAT_PRINTER
9945 "printer",
9946#endif
Bram Moolenaar05159a02005-02-26 23:04:13 +00009947#ifdef FEAT_PROFILE
9948 "profile",
9949#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009950#ifdef FEAT_QUICKFIX
9951 "quickfix",
9952#endif
9953#ifdef FEAT_RIGHTLEFT
9954 "rightleft",
9955#endif
9956#if defined(FEAT_RUBY) && !defined(DYNAMIC_RUBY)
9957 "ruby",
9958#endif
9959#ifdef FEAT_SCROLLBIND
9960 "scrollbind",
9961#endif
9962#ifdef FEAT_CMDL_INFO
9963 "showcmd",
9964 "cmdline_info",
9965#endif
9966#ifdef FEAT_SIGNS
9967 "signs",
9968#endif
9969#ifdef FEAT_SMARTINDENT
9970 "smartindent",
9971#endif
9972#ifdef FEAT_SNIFF
9973 "sniff",
9974#endif
9975#ifdef FEAT_STL_OPT
9976 "statusline",
9977#endif
9978#ifdef FEAT_SUN_WORKSHOP
9979 "sun_workshop",
9980#endif
9981#ifdef FEAT_NETBEANS_INTG
9982 "netbeans_intg",
9983#endif
9984#ifdef FEAT_SYN_HL
Bram Moolenaar0e4d8772005-06-07 21:12:49 +00009985 "spell",
9986#endif
9987#ifdef FEAT_SYN_HL
Bram Moolenaar071d4272004-06-13 20:20:40 +00009988 "syntax",
9989#endif
9990#if defined(USE_SYSTEM) || !defined(UNIX)
9991 "system",
9992#endif
9993#ifdef FEAT_TAG_BINS
9994 "tag_binary",
9995#endif
9996#ifdef FEAT_TAG_OLDSTATIC
9997 "tag_old_static",
9998#endif
9999#ifdef FEAT_TAG_ANYWHITE
10000 "tag_any_white",
10001#endif
10002#ifdef FEAT_TCL
10003# ifndef DYNAMIC_TCL
10004 "tcl",
10005# endif
10006#endif
10007#ifdef TERMINFO
10008 "terminfo",
10009#endif
10010#ifdef FEAT_TERMRESPONSE
10011 "termresponse",
10012#endif
10013#ifdef FEAT_TEXTOBJ
10014 "textobjects",
10015#endif
10016#ifdef HAVE_TGETENT
10017 "tgetent",
10018#endif
10019#ifdef FEAT_TITLE
10020 "title",
10021#endif
10022#ifdef FEAT_TOOLBAR
10023 "toolbar",
10024#endif
10025#ifdef FEAT_USR_CMDS
10026 "user-commands", /* was accidentally included in 5.4 */
10027 "user_commands",
10028#endif
10029#ifdef FEAT_VIMINFO
10030 "viminfo",
10031#endif
10032#ifdef FEAT_VERTSPLIT
10033 "vertsplit",
10034#endif
10035#ifdef FEAT_VIRTUALEDIT
10036 "virtualedit",
10037#endif
10038#ifdef FEAT_VISUAL
10039 "visual",
10040#endif
10041#ifdef FEAT_VISUALEXTRA
10042 "visualextra",
10043#endif
10044#ifdef FEAT_VREPLACE
10045 "vreplace",
10046#endif
10047#ifdef FEAT_WILDIGN
10048 "wildignore",
10049#endif
10050#ifdef FEAT_WILDMENU
10051 "wildmenu",
10052#endif
10053#ifdef FEAT_WINDOWS
10054 "windows",
10055#endif
10056#ifdef FEAT_WAK
10057 "winaltkeys",
10058#endif
10059#ifdef FEAT_WRITEBACKUP
10060 "writebackup",
10061#endif
10062#ifdef FEAT_XIM
10063 "xim",
10064#endif
10065#ifdef FEAT_XFONTSET
10066 "xfontset",
10067#endif
10068#ifdef USE_XSMP
10069 "xsmp",
10070#endif
10071#ifdef USE_XSMP_INTERACT
10072 "xsmp_interact",
10073#endif
10074#ifdef FEAT_XCLIPBOARD
10075 "xterm_clipboard",
10076#endif
10077#ifdef FEAT_XTERM_SAVE
10078 "xterm_save",
10079#endif
10080#if defined(UNIX) && defined(FEAT_X11)
10081 "X11",
10082#endif
10083 NULL
10084 };
10085
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010086 name = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010087 for (i = 0; has_list[i] != NULL; ++i)
10088 if (STRICMP(name, has_list[i]) == 0)
10089 {
10090 n = TRUE;
10091 break;
10092 }
10093
10094 if (n == FALSE)
10095 {
10096 if (STRNICMP(name, "patch", 5) == 0)
10097 n = has_patch(atoi((char *)name + 5));
10098 else if (STRICMP(name, "vim_starting") == 0)
10099 n = (starting != 0);
10100#ifdef DYNAMIC_TCL
10101 else if (STRICMP(name, "tcl") == 0)
10102 n = tcl_enabled(FALSE);
10103#endif
10104#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
10105 else if (STRICMP(name, "iconv") == 0)
10106 n = iconv_enabled(FALSE);
10107#endif
Bram Moolenaar33570922005-01-25 22:26:29 +000010108#ifdef DYNAMIC_MZSCHEME
10109 else if (STRICMP(name, "mzscheme") == 0)
10110 n = mzscheme_enabled(FALSE);
10111#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010112#ifdef DYNAMIC_RUBY
10113 else if (STRICMP(name, "ruby") == 0)
10114 n = ruby_enabled(FALSE);
10115#endif
10116#ifdef DYNAMIC_PYTHON
10117 else if (STRICMP(name, "python") == 0)
10118 n = python_enabled(FALSE);
10119#endif
10120#ifdef DYNAMIC_PERL
10121 else if (STRICMP(name, "perl") == 0)
10122 n = perl_enabled(FALSE);
10123#endif
10124#ifdef FEAT_GUI
10125 else if (STRICMP(name, "gui_running") == 0)
10126 n = (gui.in_use || gui.starting);
10127# ifdef FEAT_GUI_W32
10128 else if (STRICMP(name, "gui_win32s") == 0)
10129 n = gui_is_win32s();
10130# endif
10131# ifdef FEAT_BROWSE
10132 else if (STRICMP(name, "browse") == 0)
10133 n = gui.in_use; /* gui_mch_browse() works when GUI is running */
10134# endif
10135#endif
10136#ifdef FEAT_SYN_HL
10137 else if (STRICMP(name, "syntax_items") == 0)
10138 n = syntax_present(curbuf);
10139#endif
10140#if defined(WIN3264)
10141 else if (STRICMP(name, "win95") == 0)
10142 n = mch_windows95();
10143#endif
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +000010144#ifdef FEAT_NETBEANS_INTG
10145 else if (STRICMP(name, "netbeans_enabled") == 0)
10146 n = usingNetbeans;
10147#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010148 }
10149
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010150 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010151}
10152
10153/*
Bram Moolenaare9a41262005-01-15 22:18:47 +000010154 * "has_key()" function
10155 */
10156 static void
10157f_has_key(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010158 typval_T *argvars;
10159 typval_T *rettv;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010160{
10161 rettv->vval.v_number = 0;
10162 if (argvars[0].v_type != VAR_DICT)
10163 {
10164 EMSG(_(e_dictreq));
10165 return;
10166 }
10167 if (argvars[0].vval.v_dict == NULL)
10168 return;
10169
10170 rettv->vval.v_number = dict_find(argvars[0].vval.v_dict,
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010171 get_tv_string(&argvars[1]), -1) != NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010172}
10173
10174/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010175 * "hasmapto()" function
10176 */
10177 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010178f_hasmapto(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010179 typval_T *argvars;
10180 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010181{
10182 char_u *name;
10183 char_u *mode;
10184 char_u buf[NUMBUFLEN];
10185
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010186 name = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010187 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010188 mode = (char_u *)"nvo";
10189 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010190 mode = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010191
10192 if (map_to_exists(name, mode))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010193 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010194 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010195 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010196}
10197
10198/*
10199 * "histadd()" function
10200 */
10201/*ARGSUSED*/
10202 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010203f_histadd(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010204 typval_T *argvars;
10205 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010206{
10207#ifdef FEAT_CMDHIST
10208 int histype;
10209 char_u *str;
10210 char_u buf[NUMBUFLEN];
10211#endif
10212
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010213 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010214 if (check_restricted() || check_secure())
10215 return;
10216#ifdef FEAT_CMDHIST
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010217 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
10218 histype = str != NULL ? get_histtype(str) : -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010219 if (histype >= 0)
10220 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010221 str = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010222 if (*str != NUL)
10223 {
10224 add_to_history(histype, str, FALSE, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010225 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010226 return;
10227 }
10228 }
10229#endif
10230}
10231
10232/*
10233 * "histdel()" function
10234 */
10235/*ARGSUSED*/
10236 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010237f_histdel(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010238 typval_T *argvars;
10239 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010240{
10241#ifdef FEAT_CMDHIST
10242 int n;
10243 char_u buf[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010244 char_u *str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010245
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010246 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
10247 if (str == NULL)
10248 n = 0;
10249 else if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010250 /* only one argument: clear entire history */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010251 n = clr_history(get_histtype(str));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010252 else if (argvars[1].v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010253 /* index given: remove that entry */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010254 n = del_history_idx(get_histtype(str),
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010255 (int)get_tv_number(&argvars[1]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010256 else
10257 /* string given: remove all matching entries */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010258 n = del_history_entry(get_histtype(str),
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010259 get_tv_string_buf(&argvars[1], buf));
10260 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010261#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010262 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010263#endif
10264}
10265
10266/*
10267 * "histget()" function
10268 */
10269/*ARGSUSED*/
10270 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010271f_histget(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010272 typval_T *argvars;
10273 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010274{
10275#ifdef FEAT_CMDHIST
10276 int type;
10277 int idx;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010278 char_u *str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010279
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010280 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
10281 if (str == NULL)
10282 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010283 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010284 {
10285 type = get_histtype(str);
10286 if (argvars[1].v_type == VAR_UNKNOWN)
10287 idx = get_history_idx(type);
10288 else
10289 idx = (int)get_tv_number_chk(&argvars[1], NULL);
10290 /* -1 on type error */
10291 rettv->vval.v_string = vim_strsave(get_history_entry(type, idx));
10292 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010293#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010294 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010295#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010296 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010297}
10298
10299/*
10300 * "histnr()" function
10301 */
10302/*ARGSUSED*/
10303 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010304f_histnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010305 typval_T *argvars;
10306 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010307{
10308 int i;
10309
10310#ifdef FEAT_CMDHIST
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010311 char_u *history = get_tv_string_chk(&argvars[0]);
10312
10313 i = history == NULL ? HIST_CMD - 1 : get_histtype(history);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010314 if (i >= HIST_CMD && i < HIST_COUNT)
10315 i = get_history_idx(i);
10316 else
10317#endif
10318 i = -1;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010319 rettv->vval.v_number = i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010320}
10321
10322/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010323 * "highlightID(name)" function
10324 */
10325 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010326f_hlID(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010327 typval_T *argvars;
10328 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010329{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010330 rettv->vval.v_number = syn_name2id(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010331}
10332
10333/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010334 * "highlight_exists()" function
10335 */
10336 static void
10337f_hlexists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010338 typval_T *argvars;
10339 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010340{
10341 rettv->vval.v_number = highlight_exists(get_tv_string(&argvars[0]));
10342}
10343
10344/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010345 * "hostname()" function
10346 */
10347/*ARGSUSED*/
10348 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010349f_hostname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010350 typval_T *argvars;
10351 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010352{
10353 char_u hostname[256];
10354
10355 mch_get_host_name(hostname, 256);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010356 rettv->v_type = VAR_STRING;
10357 rettv->vval.v_string = vim_strsave(hostname);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010358}
10359
10360/*
10361 * iconv() function
10362 */
10363/*ARGSUSED*/
10364 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010365f_iconv(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010366 typval_T *argvars;
10367 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010368{
10369#ifdef FEAT_MBYTE
10370 char_u buf1[NUMBUFLEN];
10371 char_u buf2[NUMBUFLEN];
10372 char_u *from, *to, *str;
10373 vimconv_T vimconv;
10374#endif
10375
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010376 rettv->v_type = VAR_STRING;
10377 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010378
10379#ifdef FEAT_MBYTE
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010380 str = get_tv_string(&argvars[0]);
10381 from = enc_canonize(enc_skip(get_tv_string_buf(&argvars[1], buf1)));
10382 to = enc_canonize(enc_skip(get_tv_string_buf(&argvars[2], buf2)));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010383 vimconv.vc_type = CONV_NONE;
10384 convert_setup(&vimconv, from, to);
10385
10386 /* If the encodings are equal, no conversion needed. */
10387 if (vimconv.vc_type == CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010388 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010389 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010390 rettv->vval.v_string = string_convert(&vimconv, str, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010391
10392 convert_setup(&vimconv, NULL, NULL);
10393 vim_free(from);
10394 vim_free(to);
10395#endif
10396}
10397
10398/*
10399 * "indent()" function
10400 */
10401 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010402f_indent(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010403 typval_T *argvars;
10404 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010405{
10406 linenr_T lnum;
10407
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010408 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010409 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010410 rettv->vval.v_number = get_indent_lnum(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010411 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010412 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010413}
10414
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010415/*
10416 * "index()" function
10417 */
10418 static void
10419f_index(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010420 typval_T *argvars;
10421 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010422{
Bram Moolenaar33570922005-01-25 22:26:29 +000010423 list_T *l;
10424 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010425 long idx = 0;
10426 int ic = FALSE;
10427
10428 rettv->vval.v_number = -1;
10429 if (argvars[0].v_type != VAR_LIST)
10430 {
10431 EMSG(_(e_listreq));
10432 return;
10433 }
10434 l = argvars[0].vval.v_list;
10435 if (l != NULL)
10436 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000010437 item = l->lv_first;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010438 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010439 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010440 int error = FALSE;
10441
Bram Moolenaar758711c2005-02-02 23:11:38 +000010442 /* Start at specified item. Use the cached index that list_find()
10443 * sets, so that a negative number also works. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010444 item = list_find(l, get_tv_number_chk(&argvars[2], &error));
Bram Moolenaar758711c2005-02-02 23:11:38 +000010445 idx = l->lv_idx;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010446 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010447 ic = get_tv_number_chk(&argvars[3], &error);
10448 if (error)
10449 item = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010450 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010451
Bram Moolenaar758711c2005-02-02 23:11:38 +000010452 for ( ; item != NULL; item = item->li_next, ++idx)
10453 if (tv_equal(&item->li_tv, &argvars[1], ic))
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010454 {
10455 rettv->vval.v_number = idx;
10456 break;
10457 }
10458 }
10459}
10460
Bram Moolenaar071d4272004-06-13 20:20:40 +000010461static int inputsecret_flag = 0;
10462
10463/*
10464 * "input()" function
10465 * Also handles inputsecret() when inputsecret is set.
10466 */
10467 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010468f_input(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010469 typval_T *argvars;
10470 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010471{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010472 char_u *prompt = get_tv_string_chk(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010473 char_u *p = NULL;
10474 int c;
10475 char_u buf[NUMBUFLEN];
10476 int cmd_silent_save = cmd_silent;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010477 char_u *defstr = (char_u *)"";
Bram Moolenaar071d4272004-06-13 20:20:40 +000010478
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010479 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010480
10481#ifdef NO_CONSOLE_INPUT
10482 /* While starting up, there is no place to enter text. */
10483 if (no_console_input())
10484 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010485 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010486 return;
10487 }
10488#endif
10489
10490 cmd_silent = FALSE; /* Want to see the prompt. */
10491 if (prompt != NULL)
10492 {
10493 /* Only the part of the message after the last NL is considered as
10494 * prompt for the command line */
10495 p = vim_strrchr(prompt, '\n');
10496 if (p == NULL)
10497 p = prompt;
10498 else
10499 {
10500 ++p;
10501 c = *p;
10502 *p = NUL;
10503 msg_start();
10504 msg_clr_eos();
10505 msg_puts_attr(prompt, echo_attr);
10506 msg_didout = FALSE;
10507 msg_starthere();
10508 *p = c;
10509 }
10510 cmdline_row = msg_row;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010511
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010512 if (argvars[1].v_type != VAR_UNKNOWN)
10513 {
10514 defstr = get_tv_string_buf_chk(&argvars[1], buf);
10515 if (defstr != NULL)
10516 stuffReadbuffSpec(defstr);
10517 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010518
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010519 if (defstr != NULL)
10520 rettv->vval.v_string =
Bram Moolenaar071d4272004-06-13 20:20:40 +000010521 getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr);
10522
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010523 /* since the user typed this, no need to wait for return */
10524 need_wait_return = FALSE;
10525 msg_didout = FALSE;
10526 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010527 cmd_silent = cmd_silent_save;
10528}
10529
10530/*
10531 * "inputdialog()" function
10532 */
10533 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010534f_inputdialog(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010535 typval_T *argvars;
10536 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010537{
10538#if defined(FEAT_GUI_TEXTDIALOG)
10539 /* Use a GUI dialog if the GUI is running and 'c' is not in 'guioptions' */
10540 if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
10541 {
10542 char_u *message;
10543 char_u buf[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010544 char_u *defstr = (char_u *)"";
Bram Moolenaar071d4272004-06-13 20:20:40 +000010545
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010546 message = get_tv_string_chk(&argvars[0]);
10547 if (argvars[1].v_type != VAR_UNKNOWN
10548 && (defstr = get_tv_string_buf_chk(&argvars[1], buf)) != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010549 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010550 STRNCPY(IObuff, defstr, IOSIZE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010551 IObuff[IOSIZE - 1] = NUL;
10552 }
10553 else
10554 IObuff[0] = NUL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010555 if (message != NULL && defstr != NULL
10556 && do_dialog(VIM_QUESTION, NULL, message,
10557 (char_u *)_("&OK\n&Cancel"), 1, IObuff) == 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010558 rettv->vval.v_string = vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010559 else
10560 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010561 if (message != NULL && defstr != NULL
10562 && argvars[1].v_type != VAR_UNKNOWN
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010563 && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010564 rettv->vval.v_string = vim_strsave(
10565 get_tv_string_buf(&argvars[2], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010566 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010567 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010568 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010569 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010570 }
10571 else
10572#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010573 f_input(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010574}
10575
10576static garray_T ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL};
10577
10578/*
10579 * "inputrestore()" function
10580 */
10581/*ARGSUSED*/
10582 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010583f_inputrestore(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010584 typval_T *argvars;
10585 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010586{
10587 if (ga_userinput.ga_len > 0)
10588 {
10589 --ga_userinput.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010590 restore_typeahead((tasave_T *)(ga_userinput.ga_data)
10591 + ga_userinput.ga_len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010592 rettv->vval.v_number = 0; /* OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010593 }
10594 else if (p_verbose > 1)
10595 {
Bram Moolenaar54ee7752005-05-31 22:22:17 +000010596 verb_msg((char_u *)_("called inputrestore() more often than inputsave()"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010597 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010598 }
10599}
10600
10601/*
10602 * "inputsave()" function
10603 */
10604/*ARGSUSED*/
10605 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010606f_inputsave(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010607 typval_T *argvars;
10608 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010609{
10610 /* Add an entry to the stack of typehead storage. */
10611 if (ga_grow(&ga_userinput, 1) == OK)
10612 {
10613 save_typeahead((tasave_T *)(ga_userinput.ga_data)
10614 + ga_userinput.ga_len);
10615 ++ga_userinput.ga_len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010616 rettv->vval.v_number = 0; /* OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010617 }
10618 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010619 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010620}
10621
10622/*
10623 * "inputsecret()" function
10624 */
10625 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010626f_inputsecret(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010627 typval_T *argvars;
10628 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010629{
10630 ++cmdline_star;
10631 ++inputsecret_flag;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010632 f_input(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010633 --cmdline_star;
10634 --inputsecret_flag;
10635}
10636
10637/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010638 * "insert()" function
10639 */
10640 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010641f_insert(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010642 typval_T *argvars;
10643 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010644{
10645 long before = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000010646 listitem_T *item;
10647 list_T *l;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010648 int error = FALSE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010649
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010650 rettv->vval.v_number = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010651 if (argvars[0].v_type != VAR_LIST)
Bram Moolenaar0d660222005-01-07 21:51:51 +000010652 EMSG2(_(e_listarg), "insert()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010653 else if ((l = argvars[0].vval.v_list) != NULL
10654 && !tv_check_lock(l->lv_lock, (char_u *)"insert()"))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010655 {
10656 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010657 before = get_tv_number_chk(&argvars[2], &error);
10658 if (error)
10659 return; /* type error; errmsg already given */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010660
Bram Moolenaar758711c2005-02-02 23:11:38 +000010661 if (before == l->lv_len)
10662 item = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010663 else
10664 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000010665 item = list_find(l, before);
10666 if (item == NULL)
10667 {
10668 EMSGN(_(e_listidx), before);
10669 l = NULL;
10670 }
10671 }
10672 if (l != NULL)
10673 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010674 list_insert_tv(l, &argvars[1], item);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010675 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010676 }
10677 }
10678}
10679
10680/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010681 * "isdirectory()" function
10682 */
10683 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010684f_isdirectory(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010685 typval_T *argvars;
10686 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010687{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010688 rettv->vval.v_number = mch_isdir(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010689}
10690
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010691/*
10692 * Return TRUE if typeval "tv" is locked: Either tha value is locked itself or
10693 * it refers to a List or Dictionary that is locked.
10694 */
10695 static int
10696tv_islocked(tv)
10697 typval_T *tv;
10698{
10699 return (tv->v_lock & VAR_LOCKED)
10700 || (tv->v_type == VAR_LIST
10701 && tv->vval.v_list != NULL
10702 && (tv->vval.v_list->lv_lock & VAR_LOCKED))
10703 || (tv->v_type == VAR_DICT
10704 && tv->vval.v_dict != NULL
10705 && (tv->vval.v_dict->dv_lock & VAR_LOCKED));
10706}
10707
10708/*
10709 * "islocked()" function
10710 */
10711 static void
10712f_islocked(argvars, rettv)
10713 typval_T *argvars;
10714 typval_T *rettv;
10715{
10716 lval_T lv;
10717 char_u *end;
10718 dictitem_T *di;
10719
10720 rettv->vval.v_number = -1;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000010721 end = get_lval(get_tv_string(&argvars[0]), NULL, &lv, FALSE, FALSE, FALSE,
10722 FNE_CHECK_START);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010723 if (end != NULL && lv.ll_name != NULL)
10724 {
10725 if (*end != NUL)
10726 EMSG(_(e_trailing));
10727 else
10728 {
10729 if (lv.ll_tv == NULL)
10730 {
10731 if (check_changedtick(lv.ll_name))
10732 rettv->vval.v_number = 1; /* always locked */
10733 else
10734 {
10735 di = find_var(lv.ll_name, NULL);
10736 if (di != NULL)
10737 {
10738 /* Consider a variable locked when:
10739 * 1. the variable itself is locked
10740 * 2. the value of the variable is locked.
10741 * 3. the List or Dict value is locked.
10742 */
10743 rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK)
10744 || tv_islocked(&di->di_tv));
10745 }
10746 }
10747 }
10748 else if (lv.ll_range)
10749 EMSG(_("E745: Range not allowed"));
10750 else if (lv.ll_newkey != NULL)
10751 EMSG2(_(e_dictkey), lv.ll_newkey);
10752 else if (lv.ll_list != NULL)
10753 /* List item. */
10754 rettv->vval.v_number = tv_islocked(&lv.ll_li->li_tv);
10755 else
10756 /* Dictionary item. */
10757 rettv->vval.v_number = tv_islocked(&lv.ll_di->di_tv);
10758 }
10759 }
10760
10761 clear_lval(&lv);
10762}
10763
Bram Moolenaar33570922005-01-25 22:26:29 +000010764static void dict_list __ARGS((typval_T *argvars, typval_T *rettv, int what));
Bram Moolenaar8c711452005-01-14 21:53:12 +000010765
10766/*
10767 * Turn a dict into a list:
10768 * "what" == 0: list of keys
10769 * "what" == 1: list of values
10770 * "what" == 2: list of items
10771 */
10772 static void
10773dict_list(argvars, rettv, what)
Bram Moolenaar33570922005-01-25 22:26:29 +000010774 typval_T *argvars;
10775 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000010776 int what;
10777{
Bram Moolenaar33570922005-01-25 22:26:29 +000010778 list_T *l;
10779 list_T *l2;
10780 dictitem_T *di;
10781 hashitem_T *hi;
10782 listitem_T *li;
10783 listitem_T *li2;
10784 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010785 int todo;
Bram Moolenaar8c711452005-01-14 21:53:12 +000010786
10787 rettv->vval.v_number = 0;
10788 if (argvars[0].v_type != VAR_DICT)
10789 {
10790 EMSG(_(e_dictreq));
10791 return;
10792 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010793 if ((d = argvars[0].vval.v_dict) == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000010794 return;
10795
10796 l = list_alloc();
10797 if (l == NULL)
10798 return;
10799 rettv->v_type = VAR_LIST;
10800 rettv->vval.v_list = l;
10801 ++l->lv_refcount;
10802
Bram Moolenaar33570922005-01-25 22:26:29 +000010803 todo = d->dv_hashtab.ht_used;
10804 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +000010805 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010806 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar8c711452005-01-14 21:53:12 +000010807 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010808 --todo;
10809 di = HI2DI(hi);
Bram Moolenaar8c711452005-01-14 21:53:12 +000010810
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010811 li = listitem_alloc();
10812 if (li == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000010813 break;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010814 list_append(l, li);
Bram Moolenaar8c711452005-01-14 21:53:12 +000010815
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010816 if (what == 0)
10817 {
10818 /* keys() */
10819 li->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010820 li->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010821 li->li_tv.vval.v_string = vim_strsave(di->di_key);
10822 }
10823 else if (what == 1)
10824 {
10825 /* values() */
10826 copy_tv(&di->di_tv, &li->li_tv);
10827 }
10828 else
10829 {
10830 /* items() */
10831 l2 = list_alloc();
10832 li->li_tv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010833 li->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010834 li->li_tv.vval.v_list = l2;
10835 if (l2 == NULL)
10836 break;
10837 ++l2->lv_refcount;
10838
10839 li2 = listitem_alloc();
10840 if (li2 == NULL)
10841 break;
10842 list_append(l2, li2);
10843 li2->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010844 li2->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010845 li2->li_tv.vval.v_string = vim_strsave(di->di_key);
10846
10847 li2 = listitem_alloc();
10848 if (li2 == NULL)
10849 break;
10850 list_append(l2, li2);
10851 copy_tv(&di->di_tv, &li2->li_tv);
10852 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000010853 }
10854 }
10855}
10856
10857/*
10858 * "items(dict)" function
10859 */
10860 static void
10861f_items(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010862 typval_T *argvars;
10863 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000010864{
10865 dict_list(argvars, rettv, 2);
10866}
10867
Bram Moolenaar071d4272004-06-13 20:20:40 +000010868/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010869 * "join()" function
10870 */
10871 static void
10872f_join(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010873 typval_T *argvars;
10874 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010875{
10876 garray_T ga;
10877 char_u *sep;
10878
10879 rettv->vval.v_number = 0;
10880 if (argvars[0].v_type != VAR_LIST)
10881 {
10882 EMSG(_(e_listreq));
10883 return;
10884 }
10885 if (argvars[0].vval.v_list == NULL)
10886 return;
10887 if (argvars[1].v_type == VAR_UNKNOWN)
10888 sep = (char_u *)" ";
10889 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010890 sep = get_tv_string_chk(&argvars[1]);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010891
10892 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010893
10894 if (sep != NULL)
10895 {
10896 ga_init2(&ga, (int)sizeof(char), 80);
10897 list_join(&ga, argvars[0].vval.v_list, sep, TRUE);
10898 ga_append(&ga, NUL);
10899 rettv->vval.v_string = (char_u *)ga.ga_data;
10900 }
10901 else
10902 rettv->vval.v_string = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010903}
10904
10905/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000010906 * "keys()" function
10907 */
10908 static void
10909f_keys(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010910 typval_T *argvars;
10911 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000010912{
10913 dict_list(argvars, rettv, 0);
10914}
10915
10916/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010917 * "last_buffer_nr()" function.
10918 */
10919/*ARGSUSED*/
10920 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010921f_last_buffer_nr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010922 typval_T *argvars;
10923 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010924{
10925 int n = 0;
10926 buf_T *buf;
10927
10928 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
10929 if (n < buf->b_fnum)
10930 n = buf->b_fnum;
10931
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010932 rettv->vval.v_number = n;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010933}
10934
10935/*
10936 * "len()" function
10937 */
10938 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010939f_len(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010940 typval_T *argvars;
10941 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010942{
10943 switch (argvars[0].v_type)
10944 {
10945 case VAR_STRING:
10946 case VAR_NUMBER:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010947 rettv->vval.v_number = (varnumber_T)STRLEN(
10948 get_tv_string(&argvars[0]));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010949 break;
10950 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010951 rettv->vval.v_number = list_len(argvars[0].vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010952 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010953 case VAR_DICT:
10954 rettv->vval.v_number = dict_len(argvars[0].vval.v_dict);
10955 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010956 default:
Bram Moolenaare49b69a2005-01-08 16:11:57 +000010957 EMSG(_("E701: Invalid type for len()"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010958 break;
10959 }
10960}
10961
Bram Moolenaar33570922005-01-25 22:26:29 +000010962static void libcall_common __ARGS((typval_T *argvars, typval_T *rettv, int type));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010963
10964 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010965libcall_common(argvars, rettv, type)
Bram Moolenaar33570922005-01-25 22:26:29 +000010966 typval_T *argvars;
10967 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010968 int type;
10969{
10970#ifdef FEAT_LIBCALL
10971 char_u *string_in;
10972 char_u **string_result;
10973 int nr_result;
10974#endif
10975
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010976 rettv->v_type = type;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010977 if (type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010978 rettv->vval.v_number = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010979 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010980 rettv->vval.v_string = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010981
10982 if (check_restricted() || check_secure())
10983 return;
10984
10985#ifdef FEAT_LIBCALL
10986 /* The first two args must be strings, otherwise its meaningless */
10987 if (argvars[0].v_type == VAR_STRING && argvars[1].v_type == VAR_STRING)
10988 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000010989 string_in = NULL;
10990 if (argvars[2].v_type == VAR_STRING)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010991 string_in = argvars[2].vval.v_string;
10992 if (type == VAR_NUMBER)
10993 string_result = NULL;
10994 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010995 string_result = &rettv->vval.v_string;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010996 if (mch_libcall(argvars[0].vval.v_string,
10997 argvars[1].vval.v_string,
10998 string_in,
10999 argvars[2].vval.v_number,
11000 string_result,
11001 &nr_result) == OK
11002 && type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011003 rettv->vval.v_number = nr_result;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011004 }
11005#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000011006}
11007
11008/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011009 * "libcall()" function
11010 */
11011 static void
11012f_libcall(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011013 typval_T *argvars;
11014 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011015{
11016 libcall_common(argvars, rettv, VAR_STRING);
11017}
11018
11019/*
11020 * "libcallnr()" function
11021 */
11022 static void
11023f_libcallnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011024 typval_T *argvars;
11025 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011026{
11027 libcall_common(argvars, rettv, VAR_NUMBER);
11028}
11029
11030/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011031 * "line(string)" function
11032 */
11033 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011034f_line(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011035 typval_T *argvars;
11036 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011037{
11038 linenr_T lnum = 0;
11039 pos_T *fp;
11040
11041 fp = var2fpos(&argvars[0], TRUE);
11042 if (fp != NULL)
11043 lnum = fp->lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011044 rettv->vval.v_number = lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011045}
11046
11047/*
11048 * "line2byte(lnum)" function
11049 */
11050/*ARGSUSED*/
11051 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011052f_line2byte(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011053 typval_T *argvars;
11054 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011055{
11056#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011057 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011058#else
11059 linenr_T lnum;
11060
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011061 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011062 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011063 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011064 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011065 rettv->vval.v_number = ml_find_line_or_offset(curbuf, lnum, NULL);
11066 if (rettv->vval.v_number >= 0)
11067 ++rettv->vval.v_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011068#endif
11069}
11070
11071/*
11072 * "lispindent(lnum)" function
11073 */
11074 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011075f_lispindent(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011076 typval_T *argvars;
11077 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011078{
11079#ifdef FEAT_LISP
11080 pos_T pos;
11081 linenr_T lnum;
11082
11083 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011084 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011085 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
11086 {
11087 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011088 rettv->vval.v_number = get_lisp_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +000011089 curwin->w_cursor = pos;
11090 }
11091 else
11092#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011093 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011094}
11095
11096/*
11097 * "localtime()" function
11098 */
11099/*ARGSUSED*/
11100 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011101f_localtime(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011102 typval_T *argvars;
11103 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011104{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011105 rettv->vval.v_number = (varnumber_T)time(NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011106}
11107
Bram Moolenaar33570922005-01-25 22:26:29 +000011108static void get_maparg __ARGS((typval_T *argvars, typval_T *rettv, int exact));
Bram Moolenaar071d4272004-06-13 20:20:40 +000011109
11110 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011111get_maparg(argvars, rettv, exact)
Bram Moolenaar33570922005-01-25 22:26:29 +000011112 typval_T *argvars;
11113 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011114 int exact;
11115{
11116 char_u *keys;
11117 char_u *which;
11118 char_u buf[NUMBUFLEN];
11119 char_u *keys_buf = NULL;
11120 char_u *rhs;
11121 int mode;
11122 garray_T ga;
11123
11124 /* return empty string for failure */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011125 rettv->v_type = VAR_STRING;
11126 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011127
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011128 keys = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011129 if (*keys == NUL)
11130 return;
11131
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011132 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011133 which = get_tv_string_buf_chk(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011134 else
11135 which = (char_u *)"";
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011136 if (which == NULL)
11137 return;
11138
Bram Moolenaar071d4272004-06-13 20:20:40 +000011139 mode = get_map_mode(&which, 0);
11140
11141 keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE);
Bram Moolenaarf4630b62005-05-20 21:31:17 +000011142 rhs = check_map(keys, mode, exact, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011143 vim_free(keys_buf);
11144 if (rhs != NULL)
11145 {
11146 ga_init(&ga);
11147 ga.ga_itemsize = 1;
11148 ga.ga_growsize = 40;
11149
11150 while (*rhs != NUL)
11151 ga_concat(&ga, str2special(&rhs, FALSE));
11152
11153 ga_append(&ga, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011154 rettv->vval.v_string = (char_u *)ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011155 }
11156}
11157
11158/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011159 * "map()" function
11160 */
11161 static void
11162f_map(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011163 typval_T *argvars;
11164 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011165{
11166 filter_map(argvars, rettv, TRUE);
11167}
11168
11169/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011170 * "maparg()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000011171 */
11172 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000011173f_maparg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011174 typval_T *argvars;
11175 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011176{
Bram Moolenaar0d660222005-01-07 21:51:51 +000011177 get_maparg(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011178}
11179
11180/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011181 * "mapcheck()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000011182 */
11183 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000011184f_mapcheck(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011185 typval_T *argvars;
11186 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011187{
Bram Moolenaar0d660222005-01-07 21:51:51 +000011188 get_maparg(argvars, rettv, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011189}
11190
Bram Moolenaar33570922005-01-25 22:26:29 +000011191static void find_some_match __ARGS((typval_T *argvars, typval_T *rettv, int start));
Bram Moolenaar071d4272004-06-13 20:20:40 +000011192
11193 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011194find_some_match(argvars, rettv, type)
Bram Moolenaar33570922005-01-25 22:26:29 +000011195 typval_T *argvars;
11196 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011197 int type;
11198{
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011199 char_u *str = NULL;
11200 char_u *expr = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011201 char_u *pat;
11202 regmatch_T regmatch;
11203 char_u patbuf[NUMBUFLEN];
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011204 char_u strbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000011205 char_u *save_cpo;
11206 long start = 0;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011207 long nth = 1;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000011208 int match = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000011209 list_T *l = NULL;
11210 listitem_T *li = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011211 long idx = 0;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011212 char_u *tofree = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011213
11214 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
11215 save_cpo = p_cpo;
11216 p_cpo = (char_u *)"";
11217
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011218 rettv->vval.v_number = -1;
11219 if (type == 3)
11220 {
11221 /* return empty list when there are no matches */
11222 if ((rettv->vval.v_list = list_alloc()) == NULL)
11223 goto theend;
11224 rettv->v_type = VAR_LIST;
11225 ++rettv->vval.v_list->lv_refcount;
11226 }
11227 else if (type == 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011228 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011229 rettv->v_type = VAR_STRING;
11230 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011231 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011232
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011233 if (argvars[0].v_type == VAR_LIST)
11234 {
11235 if ((l = argvars[0].vval.v_list) == NULL)
11236 goto theend;
11237 li = l->lv_first;
11238 }
11239 else
11240 expr = str = get_tv_string(&argvars[0]);
11241
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011242 pat = get_tv_string_buf_chk(&argvars[1], patbuf);
11243 if (pat == NULL)
11244 goto theend;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011245
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011246 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011247 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011248 int error = FALSE;
11249
11250 start = get_tv_number_chk(&argvars[2], &error);
11251 if (error)
11252 goto theend;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011253 if (l != NULL)
11254 {
11255 li = list_find(l, start);
11256 if (li == NULL)
11257 goto theend;
Bram Moolenaar758711c2005-02-02 23:11:38 +000011258 idx = l->lv_idx; /* use the cached index */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011259 }
11260 else
11261 {
11262 if (start < 0)
11263 start = 0;
11264 if (start > (long)STRLEN(str))
11265 goto theend;
11266 str += start;
11267 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011268
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011269 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011270 nth = get_tv_number_chk(&argvars[3], &error);
11271 if (error)
11272 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011273 }
11274
11275 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
11276 if (regmatch.regprog != NULL)
11277 {
11278 regmatch.rm_ic = p_ic;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011279
11280 while (1)
11281 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011282 if (l != NULL)
11283 {
11284 if (li == NULL)
11285 {
11286 match = FALSE;
11287 break;
11288 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011289 vim_free(tofree);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011290 str = echo_string(&li->li_tv, &tofree, strbuf);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000011291 if (str == NULL)
11292 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011293 }
11294
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011295 match = vim_regexec_nl(&regmatch, str, (colnr_T)0);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011296
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011297 if (match && --nth <= 0)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011298 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011299 if (l == NULL && !match)
11300 break;
11301
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011302 /* Advance to just after the match. */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011303 if (l != NULL)
11304 {
11305 li = li->li_next;
11306 ++idx;
11307 }
11308 else
11309 {
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011310#ifdef FEAT_MBYTE
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011311 str = regmatch.startp[0] + mb_ptr2len_check(regmatch.startp[0]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011312#else
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011313 str = regmatch.startp[0] + 1;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011314#endif
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011315 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011316 }
11317
11318 if (match)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011319 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011320 if (type == 3)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011321 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011322 int i;
11323
11324 /* return list with matched string and submatches */
11325 for (i = 0; i < NSUBEXP; ++i)
11326 {
11327 if (regmatch.endp[i] == NULL)
11328 break;
11329 li = listitem_alloc();
11330 if (li == NULL)
11331 break;
11332 li->li_tv.v_type = VAR_STRING;
11333 li->li_tv.v_lock = 0;
11334 li->li_tv.vval.v_string = vim_strnsave(regmatch.startp[i],
11335 (int)(regmatch.endp[i] - regmatch.startp[i]));
11336 list_append(rettv->vval.v_list, li);
11337 }
11338 }
11339 else if (type == 2)
11340 {
11341 /* return matched string */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011342 if (l != NULL)
11343 copy_tv(&li->li_tv, rettv);
11344 else
11345 rettv->vval.v_string = vim_strnsave(regmatch.startp[0],
Bram Moolenaar071d4272004-06-13 20:20:40 +000011346 (int)(regmatch.endp[0] - regmatch.startp[0]));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011347 }
11348 else if (l != NULL)
11349 rettv->vval.v_number = idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011350 else
11351 {
11352 if (type != 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011353 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +000011354 (varnumber_T)(regmatch.startp[0] - str);
11355 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011356 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +000011357 (varnumber_T)(regmatch.endp[0] - str);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011358 rettv->vval.v_number += str - expr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011359 }
11360 }
11361 vim_free(regmatch.regprog);
11362 }
11363
11364theend:
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011365 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011366 p_cpo = save_cpo;
11367}
11368
11369/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011370 * "match()" function
11371 */
11372 static void
11373f_match(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011374 typval_T *argvars;
11375 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011376{
11377 find_some_match(argvars, rettv, 1);
11378}
11379
11380/*
11381 * "matchend()" function
11382 */
11383 static void
11384f_matchend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011385 typval_T *argvars;
11386 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011387{
11388 find_some_match(argvars, rettv, 0);
11389}
11390
11391/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011392 * "matchlist()" function
11393 */
11394 static void
11395f_matchlist(argvars, rettv)
11396 typval_T *argvars;
11397 typval_T *rettv;
11398{
11399 find_some_match(argvars, rettv, 3);
11400}
11401
11402/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011403 * "matchstr()" function
11404 */
11405 static void
11406f_matchstr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011407 typval_T *argvars;
11408 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011409{
11410 find_some_match(argvars, rettv, 2);
11411}
11412
Bram Moolenaar33570922005-01-25 22:26:29 +000011413static void max_min __ARGS((typval_T *argvars, typval_T *rettv, int domax));
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011414
11415 static void
11416max_min(argvars, rettv, domax)
Bram Moolenaar33570922005-01-25 22:26:29 +000011417 typval_T *argvars;
11418 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011419 int domax;
11420{
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011421 long n = 0;
11422 long i;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011423 int error = FALSE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011424
11425 if (argvars[0].v_type == VAR_LIST)
11426 {
Bram Moolenaar33570922005-01-25 22:26:29 +000011427 list_T *l;
11428 listitem_T *li;
Bram Moolenaare9a41262005-01-15 22:18:47 +000011429
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011430 l = argvars[0].vval.v_list;
11431 if (l != NULL)
11432 {
11433 li = l->lv_first;
11434 if (li != NULL)
11435 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011436 n = get_tv_number_chk(&li->li_tv, &error);
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011437 while (1)
11438 {
11439 li = li->li_next;
11440 if (li == NULL)
11441 break;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011442 i = get_tv_number_chk(&li->li_tv, &error);
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011443 if (domax ? i > n : i < n)
11444 n = i;
11445 }
11446 }
11447 }
11448 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000011449 else if (argvars[0].v_type == VAR_DICT)
11450 {
Bram Moolenaar33570922005-01-25 22:26:29 +000011451 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011452 int first = TRUE;
Bram Moolenaar33570922005-01-25 22:26:29 +000011453 hashitem_T *hi;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011454 int todo;
Bram Moolenaare9a41262005-01-15 22:18:47 +000011455
11456 d = argvars[0].vval.v_dict;
11457 if (d != NULL)
11458 {
Bram Moolenaar33570922005-01-25 22:26:29 +000011459 todo = d->dv_hashtab.ht_used;
11460 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaare9a41262005-01-15 22:18:47 +000011461 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011462 if (!HASHITEM_EMPTY(hi))
Bram Moolenaare9a41262005-01-15 22:18:47 +000011463 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011464 --todo;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011465 i = get_tv_number_chk(&HI2DI(hi)->di_tv, &error);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011466 if (first)
11467 {
11468 n = i;
11469 first = FALSE;
11470 }
11471 else if (domax ? i > n : i < n)
Bram Moolenaare9a41262005-01-15 22:18:47 +000011472 n = i;
11473 }
11474 }
11475 }
11476 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011477 else
Bram Moolenaar758711c2005-02-02 23:11:38 +000011478 EMSG(_(e_listdictarg));
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011479 rettv->vval.v_number = error ? 0 : n;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011480}
11481
11482/*
11483 * "max()" function
11484 */
11485 static void
11486f_max(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011487 typval_T *argvars;
11488 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011489{
11490 max_min(argvars, rettv, TRUE);
11491}
11492
11493/*
11494 * "min()" function
11495 */
11496 static void
11497f_min(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011498 typval_T *argvars;
11499 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011500{
11501 max_min(argvars, rettv, FALSE);
11502}
11503
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011504static int mkdir_recurse __ARGS((char_u *dir, int prot));
11505
11506/*
11507 * Create the directory in which "dir" is located, and higher levels when
11508 * needed.
11509 */
11510 static int
11511mkdir_recurse(dir, prot)
11512 char_u *dir;
11513 int prot;
11514{
11515 char_u *p;
11516 char_u *updir;
11517 int r = FAIL;
11518
11519 /* Get end of directory name in "dir".
11520 * We're done when it's "/" or "c:/". */
11521 p = gettail_sep(dir);
11522 if (p <= get_past_head(dir))
11523 return OK;
11524
11525 /* If the directory exists we're done. Otherwise: create it.*/
11526 updir = vim_strnsave(dir, (int)(p - dir));
11527 if (updir == NULL)
11528 return FAIL;
11529 if (mch_isdir(updir))
11530 r = OK;
11531 else if (mkdir_recurse(updir, prot) == OK)
11532 r = vim_mkdir_emsg(updir, prot);
11533 vim_free(updir);
11534 return r;
11535}
11536
11537#ifdef vim_mkdir
11538/*
11539 * "mkdir()" function
11540 */
11541 static void
11542f_mkdir(argvars, rettv)
11543 typval_T *argvars;
11544 typval_T *rettv;
11545{
11546 char_u *dir;
11547 char_u buf[NUMBUFLEN];
11548 int prot = 0755;
11549
11550 rettv->vval.v_number = FAIL;
11551 if (check_restricted() || check_secure())
11552 return;
11553
11554 dir = get_tv_string_buf(&argvars[0], buf);
11555 if (argvars[1].v_type != VAR_UNKNOWN)
11556 {
11557 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011558 prot = get_tv_number_chk(&argvars[2], NULL);
11559 if (prot != -1 && STRCMP(get_tv_string(&argvars[1]), "p") == 0)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011560 mkdir_recurse(dir, prot);
11561 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011562 rettv->vval.v_number = prot != -1 ? vim_mkdir_emsg(dir, prot) : 0;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011563}
11564#endif
11565
Bram Moolenaar0d660222005-01-07 21:51:51 +000011566/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011567 * "mode()" function
11568 */
11569/*ARGSUSED*/
11570 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011571f_mode(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011572 typval_T *argvars;
11573 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011574{
11575 char_u buf[2];
11576
11577#ifdef FEAT_VISUAL
11578 if (VIsual_active)
11579 {
11580 if (VIsual_select)
11581 buf[0] = VIsual_mode + 's' - 'v';
11582 else
11583 buf[0] = VIsual_mode;
11584 }
11585 else
11586#endif
11587 if (State == HITRETURN || State == ASKMORE || State == SETWSIZE)
11588 buf[0] = 'r';
11589 else if (State & INSERT)
11590 {
11591 if (State & REPLACE_FLAG)
11592 buf[0] = 'R';
11593 else
11594 buf[0] = 'i';
11595 }
11596 else if (State & CMDLINE)
11597 buf[0] = 'c';
11598 else
11599 buf[0] = 'n';
11600
11601 buf[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011602 rettv->vval.v_string = vim_strsave(buf);
11603 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011604}
11605
11606/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011607 * "nextnonblank()" function
11608 */
11609 static void
11610f_nextnonblank(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011611 typval_T *argvars;
11612 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011613{
11614 linenr_T lnum;
11615
11616 for (lnum = get_tv_lnum(argvars); ; ++lnum)
11617 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011618 if (lnum < 0 || lnum > curbuf->b_ml.ml_line_count)
Bram Moolenaar0d660222005-01-07 21:51:51 +000011619 {
11620 lnum = 0;
11621 break;
11622 }
11623 if (*skipwhite(ml_get(lnum)) != NUL)
11624 break;
11625 }
11626 rettv->vval.v_number = lnum;
11627}
11628
11629/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011630 * "nr2char()" function
11631 */
11632 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011633f_nr2char(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011634 typval_T *argvars;
11635 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011636{
11637 char_u buf[NUMBUFLEN];
11638
11639#ifdef FEAT_MBYTE
11640 if (has_mbyte)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011641 buf[(*mb_char2bytes)((int)get_tv_number(&argvars[0]), buf)] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011642 else
11643#endif
11644 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011645 buf[0] = (char_u)get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011646 buf[1] = NUL;
11647 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011648 rettv->v_type = VAR_STRING;
11649 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011650}
11651
11652/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011653 * "prevnonblank()" function
11654 */
11655 static void
11656f_prevnonblank(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011657 typval_T *argvars;
11658 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011659{
11660 linenr_T lnum;
11661
11662 lnum = get_tv_lnum(argvars);
11663 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
11664 lnum = 0;
11665 else
11666 while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL)
11667 --lnum;
11668 rettv->vval.v_number = lnum;
11669}
11670
Bram Moolenaar8c711452005-01-14 21:53:12 +000011671/*
11672 * "range()" function
11673 */
11674 static void
11675f_range(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011676 typval_T *argvars;
11677 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011678{
11679 long start;
11680 long end;
11681 long stride = 1;
11682 long i;
Bram Moolenaar33570922005-01-25 22:26:29 +000011683 list_T *l;
11684 listitem_T *li;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011685 int error = FALSE;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011686
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011687 start = get_tv_number_chk(&argvars[0], &error);
Bram Moolenaar8c711452005-01-14 21:53:12 +000011688 if (argvars[1].v_type == VAR_UNKNOWN)
11689 {
11690 end = start - 1;
11691 start = 0;
11692 }
11693 else
11694 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011695 end = get_tv_number_chk(&argvars[1], &error);
Bram Moolenaar8c711452005-01-14 21:53:12 +000011696 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011697 stride = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaar8c711452005-01-14 21:53:12 +000011698 }
11699
11700 rettv->vval.v_number = 0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011701 if (error)
11702 return; /* type error; errmsg already given */
Bram Moolenaar8c711452005-01-14 21:53:12 +000011703 if (stride == 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000011704 EMSG(_("E726: Stride is zero"));
Bram Moolenaar92124a32005-06-17 22:03:40 +000011705 else if (stride > 0 ? end + 1 < start : end - 1 > start)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000011706 EMSG(_("E727: Start past end"));
Bram Moolenaar8c711452005-01-14 21:53:12 +000011707 else
11708 {
11709 l = list_alloc();
11710 if (l != NULL)
11711 {
11712 rettv->v_type = VAR_LIST;
11713 rettv->vval.v_list = l;
11714 ++l->lv_refcount;
11715
11716 for (i = start; stride > 0 ? i <= end : i >= end; i += stride)
11717 {
11718 li = listitem_alloc();
11719 if (li == NULL)
11720 break;
11721 li->li_tv.v_type = VAR_NUMBER;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011722 li->li_tv.v_lock = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011723 li->li_tv.vval.v_number = i;
11724 list_append(l, li);
11725 }
11726 }
11727 }
11728}
11729
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011730/*
11731 * "readfile()" function
11732 */
11733 static void
11734f_readfile(argvars, rettv)
11735 typval_T *argvars;
11736 typval_T *rettv;
11737{
11738 int binary = FALSE;
11739 char_u *fname;
11740 FILE *fd;
11741 list_T *l;
11742 listitem_T *li;
11743#define FREAD_SIZE 200 /* optimized for text lines */
11744 char_u buf[FREAD_SIZE];
11745 int readlen; /* size of last fread() */
11746 int buflen; /* nr of valid chars in buf[] */
11747 int filtd; /* how much in buf[] was NUL -> '\n' filtered */
11748 int tolist; /* first byte in buf[] still to be put in list */
11749 int chop; /* how many CR to chop off */
11750 char_u *prev = NULL; /* previously read bytes, if any */
11751 int prevlen = 0; /* length of "prev" if not NULL */
11752 char_u *s;
11753 int len;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011754 long maxline = MAXLNUM;
11755 long cnt = 0;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011756
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011757 if (argvars[1].v_type != VAR_UNKNOWN)
11758 {
11759 if (STRCMP(get_tv_string(&argvars[1]), "b") == 0)
11760 binary = TRUE;
11761 if (argvars[2].v_type != VAR_UNKNOWN)
11762 maxline = get_tv_number(&argvars[2]);
11763 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011764
11765 l = list_alloc();
11766 if (l == NULL)
11767 return;
11768 rettv->v_type = VAR_LIST;
11769 rettv->vval.v_list = l;
11770 l->lv_refcount = 1;
11771
11772 /* Always open the file in binary mode, library functions have a mind of
11773 * their own about CR-LF conversion. */
11774 fname = get_tv_string(&argvars[0]);
11775 if (*fname == NUL || (fd = mch_fopen((char *)fname, READBIN)) == NULL)
11776 {
11777 EMSG2(_(e_notopen), *fname == NUL ? (char_u *)_("<empty>") : fname);
11778 return;
11779 }
11780
11781 filtd = 0;
Bram Moolenaarb982ca52005-03-28 21:02:15 +000011782 while (cnt < maxline || maxline < 0)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011783 {
11784 readlen = fread(buf + filtd, 1, FREAD_SIZE - filtd, fd);
11785 buflen = filtd + readlen;
11786 tolist = 0;
11787 for ( ; filtd < buflen || readlen <= 0; ++filtd)
11788 {
11789 if (buf[filtd] == '\n' || readlen <= 0)
11790 {
11791 /* Only when in binary mode add an empty list item when the
11792 * last line ends in a '\n'. */
11793 if (!binary && readlen == 0 && filtd == 0)
11794 break;
11795
11796 /* Found end-of-line or end-of-file: add a text line to the
11797 * list. */
11798 chop = 0;
11799 if (!binary)
11800 while (filtd - chop - 1 >= tolist
11801 && buf[filtd - chop - 1] == '\r')
11802 ++chop;
11803 len = filtd - tolist - chop;
11804 if (prev == NULL)
11805 s = vim_strnsave(buf + tolist, len);
11806 else
11807 {
11808 s = alloc((unsigned)(prevlen + len + 1));
11809 if (s != NULL)
11810 {
11811 mch_memmove(s, prev, prevlen);
11812 vim_free(prev);
11813 prev = NULL;
11814 mch_memmove(s + prevlen, buf + tolist, len);
11815 s[prevlen + len] = NUL;
11816 }
11817 }
11818 tolist = filtd + 1;
11819
11820 li = listitem_alloc();
11821 if (li == NULL)
11822 {
11823 vim_free(s);
11824 break;
11825 }
11826 li->li_tv.v_type = VAR_STRING;
11827 li->li_tv.v_lock = 0;
11828 li->li_tv.vval.v_string = s;
11829 list_append(l, li);
11830
Bram Moolenaarb982ca52005-03-28 21:02:15 +000011831 if (++cnt >= maxline && maxline >= 0)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011832 break;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011833 if (readlen <= 0)
11834 break;
11835 }
11836 else if (buf[filtd] == NUL)
11837 buf[filtd] = '\n';
11838 }
11839 if (readlen <= 0)
11840 break;
11841
11842 if (tolist == 0)
11843 {
11844 /* "buf" is full, need to move text to an allocated buffer */
11845 if (prev == NULL)
11846 {
11847 prev = vim_strnsave(buf, buflen);
11848 prevlen = buflen;
11849 }
11850 else
11851 {
11852 s = alloc((unsigned)(prevlen + buflen));
11853 if (s != NULL)
11854 {
11855 mch_memmove(s, prev, prevlen);
11856 mch_memmove(s + prevlen, buf, buflen);
11857 vim_free(prev);
11858 prev = s;
11859 prevlen += buflen;
11860 }
11861 }
11862 filtd = 0;
11863 }
11864 else
11865 {
11866 mch_memmove(buf, buf + tolist, buflen - tolist);
11867 filtd -= tolist;
11868 }
11869 }
11870
Bram Moolenaarb982ca52005-03-28 21:02:15 +000011871 /*
11872 * For a negative line count use only the lines at the end of the file,
11873 * free the rest.
11874 */
11875 if (maxline < 0)
11876 while (cnt > -maxline)
11877 {
11878 listitem_remove(l, l->lv_first);
11879 --cnt;
11880 }
11881
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011882 vim_free(prev);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011883 fclose(fd);
11884}
11885
11886
Bram Moolenaar0d660222005-01-07 21:51:51 +000011887#if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
11888static void make_connection __ARGS((void));
11889static int check_connection __ARGS((void));
11890
11891 static void
11892make_connection()
11893{
11894 if (X_DISPLAY == NULL
11895# ifdef FEAT_GUI
11896 && !gui.in_use
11897# endif
11898 )
11899 {
11900 x_force_connect = TRUE;
11901 setup_term_clip();
11902 x_force_connect = FALSE;
11903 }
11904}
11905
11906 static int
11907check_connection()
11908{
11909 make_connection();
11910 if (X_DISPLAY == NULL)
11911 {
11912 EMSG(_("E240: No connection to Vim server"));
11913 return FAIL;
11914 }
11915 return OK;
11916}
11917#endif
11918
11919#ifdef FEAT_CLIENTSERVER
Bram Moolenaar33570922005-01-25 22:26:29 +000011920static void remote_common __ARGS((typval_T *argvars, typval_T *rettv, int expr));
Bram Moolenaar0d660222005-01-07 21:51:51 +000011921
11922 static void
11923remote_common(argvars, rettv, expr)
Bram Moolenaar33570922005-01-25 22:26:29 +000011924 typval_T *argvars;
11925 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011926 int expr;
11927{
11928 char_u *server_name;
11929 char_u *keys;
11930 char_u *r = NULL;
11931 char_u buf[NUMBUFLEN];
11932# ifdef WIN32
11933 HWND w;
11934# else
11935 Window w;
11936# endif
11937
11938 if (check_restricted() || check_secure())
11939 return;
11940
11941# ifdef FEAT_X11
11942 if (check_connection() == FAIL)
11943 return;
11944# endif
11945
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011946 server_name = get_tv_string_chk(&argvars[0]);
11947 if (server_name == NULL)
11948 return; /* type error; errmsg already given */
Bram Moolenaar0d660222005-01-07 21:51:51 +000011949 keys = get_tv_string_buf(&argvars[1], buf);
11950# ifdef WIN32
11951 if (serverSendToVim(server_name, keys, &r, &w, expr, TRUE) < 0)
11952# else
11953 if (serverSendToVim(X_DISPLAY, server_name, keys, &r, &w, expr, 0, TRUE)
11954 < 0)
11955# endif
11956 {
11957 if (r != NULL)
11958 EMSG(r); /* sending worked but evaluation failed */
11959 else
11960 EMSG2(_("E241: Unable to send to %s"), server_name);
11961 return;
11962 }
11963
11964 rettv->vval.v_string = r;
11965
11966 if (argvars[2].v_type != VAR_UNKNOWN)
11967 {
Bram Moolenaar33570922005-01-25 22:26:29 +000011968 dictitem_T v;
Bram Moolenaar555b2802005-05-19 21:08:39 +000011969 char_u str[30];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011970 char_u *idvar;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011971
11972 sprintf((char *)str, "0x%x", (unsigned int)w);
Bram Moolenaar33570922005-01-25 22:26:29 +000011973 v.di_tv.v_type = VAR_STRING;
11974 v.di_tv.vval.v_string = vim_strsave(str);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011975 idvar = get_tv_string_chk(&argvars[2]);
11976 if (idvar != NULL)
11977 set_var(idvar, &v.di_tv, FALSE);
Bram Moolenaar33570922005-01-25 22:26:29 +000011978 vim_free(v.di_tv.vval.v_string);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011979 }
11980}
11981#endif
11982
11983/*
11984 * "remote_expr()" function
11985 */
11986/*ARGSUSED*/
11987 static void
11988f_remote_expr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011989 typval_T *argvars;
11990 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011991{
11992 rettv->v_type = VAR_STRING;
11993 rettv->vval.v_string = NULL;
11994#ifdef FEAT_CLIENTSERVER
11995 remote_common(argvars, rettv, TRUE);
11996#endif
11997}
11998
11999/*
12000 * "remote_foreground()" function
12001 */
12002/*ARGSUSED*/
12003 static void
12004f_remote_foreground(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012005 typval_T *argvars;
12006 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012007{
12008 rettv->vval.v_number = 0;
12009#ifdef FEAT_CLIENTSERVER
12010# ifdef WIN32
12011 /* On Win32 it's done in this application. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012012 {
12013 char_u *server_name = get_tv_string_chk(&argvars[0]);
12014
12015 if (server_name != NULL)
12016 serverForeground(server_name);
12017 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000012018# else
12019 /* Send a foreground() expression to the server. */
12020 argvars[1].v_type = VAR_STRING;
12021 argvars[1].vval.v_string = vim_strsave((char_u *)"foreground()");
12022 argvars[2].v_type = VAR_UNKNOWN;
12023 remote_common(argvars, rettv, TRUE);
12024 vim_free(argvars[1].vval.v_string);
12025# endif
12026#endif
12027}
12028
12029/*ARGSUSED*/
12030 static void
12031f_remote_peek(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012032 typval_T *argvars;
12033 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012034{
12035#ifdef FEAT_CLIENTSERVER
Bram Moolenaar33570922005-01-25 22:26:29 +000012036 dictitem_T v;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012037 char_u *s = NULL;
12038# ifdef WIN32
12039 int n = 0;
12040# endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012041 char_u *serverid;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012042
12043 if (check_restricted() || check_secure())
12044 {
12045 rettv->vval.v_number = -1;
12046 return;
12047 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012048 serverid = get_tv_string_chk(&argvars[0]);
12049 if (serverid == NULL)
12050 {
12051 rettv->vval.v_number = -1;
12052 return; /* type error; errmsg already given */
12053 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000012054# ifdef WIN32
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012055 sscanf(serverid, "%x", &n);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012056 if (n == 0)
12057 rettv->vval.v_number = -1;
12058 else
12059 {
12060 s = serverGetReply((HWND)n, FALSE, FALSE, FALSE);
12061 rettv->vval.v_number = (s != NULL);
12062 }
12063# else
12064 rettv->vval.v_number = 0;
12065 if (check_connection() == FAIL)
12066 return;
12067
12068 rettv->vval.v_number = serverPeekReply(X_DISPLAY,
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012069 serverStrToWin(serverid), &s);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012070# endif
12071
12072 if (argvars[1].v_type != VAR_UNKNOWN && rettv->vval.v_number > 0)
12073 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012074 char_u *retvar;
12075
Bram Moolenaar33570922005-01-25 22:26:29 +000012076 v.di_tv.v_type = VAR_STRING;
12077 v.di_tv.vval.v_string = vim_strsave(s);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012078 retvar = get_tv_string_chk(&argvars[1]);
12079 if (retvar != NULL)
12080 set_var(retvar, &v.di_tv, FALSE);
Bram Moolenaar33570922005-01-25 22:26:29 +000012081 vim_free(v.di_tv.vval.v_string);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012082 }
12083#else
12084 rettv->vval.v_number = -1;
12085#endif
12086}
12087
12088/*ARGSUSED*/
12089 static void
12090f_remote_read(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012091 typval_T *argvars;
12092 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012093{
12094 char_u *r = NULL;
12095
12096#ifdef FEAT_CLIENTSERVER
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012097 char_u *serverid = get_tv_string_chk(&argvars[0]);
12098
12099 if (serverid != NULL && !check_restricted() && !check_secure())
Bram Moolenaar0d660222005-01-07 21:51:51 +000012100 {
12101# ifdef WIN32
12102 /* The server's HWND is encoded in the 'id' parameter */
12103 int n = 0;
12104
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012105 sscanf(serverid, "%x", &n);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012106 if (n != 0)
12107 r = serverGetReply((HWND)n, FALSE, TRUE, TRUE);
12108 if (r == NULL)
12109# else
12110 if (check_connection() == FAIL || serverReadReply(X_DISPLAY,
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012111 serverStrToWin(serverid), &r, FALSE) < 0)
Bram Moolenaar0d660222005-01-07 21:51:51 +000012112# endif
12113 EMSG(_("E277: Unable to read a server reply"));
12114 }
12115#endif
12116 rettv->v_type = VAR_STRING;
12117 rettv->vval.v_string = r;
12118}
12119
12120/*
12121 * "remote_send()" function
12122 */
12123/*ARGSUSED*/
12124 static void
12125f_remote_send(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012126 typval_T *argvars;
12127 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012128{
12129 rettv->v_type = VAR_STRING;
12130 rettv->vval.v_string = NULL;
12131#ifdef FEAT_CLIENTSERVER
12132 remote_common(argvars, rettv, FALSE);
12133#endif
12134}
12135
12136/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000012137 * "remove()" function
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012138 */
12139 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012140f_remove(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012141 typval_T *argvars;
12142 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012143{
Bram Moolenaar33570922005-01-25 22:26:29 +000012144 list_T *l;
12145 listitem_T *item, *item2;
12146 listitem_T *li;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012147 long idx;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012148 long end;
Bram Moolenaar8c711452005-01-14 21:53:12 +000012149 char_u *key;
Bram Moolenaar33570922005-01-25 22:26:29 +000012150 dict_T *d;
12151 dictitem_T *di;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012152
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012153 rettv->vval.v_number = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +000012154 if (argvars[0].v_type == VAR_DICT)
12155 {
12156 if (argvars[2].v_type != VAR_UNKNOWN)
12157 EMSG2(_(e_toomanyarg), "remove()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000012158 else if ((d = argvars[0].vval.v_dict) != NULL
Bram Moolenaar758711c2005-02-02 23:11:38 +000012159 && !tv_check_lock(d->dv_lock, (char_u *)"remove()"))
Bram Moolenaar8c711452005-01-14 21:53:12 +000012160 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012161 key = get_tv_string_chk(&argvars[1]);
12162 if (key != NULL)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000012163 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012164 di = dict_find(d, key, -1);
12165 if (di == NULL)
12166 EMSG2(_(e_dictkey), key);
12167 else
12168 {
12169 *rettv = di->di_tv;
12170 init_tv(&di->di_tv);
12171 dictitem_remove(d, di);
12172 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000012173 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000012174 }
12175 }
12176 else if (argvars[0].v_type != VAR_LIST)
12177 EMSG2(_(e_listdictarg), "remove()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000012178 else if ((l = argvars[0].vval.v_list) != NULL
12179 && !tv_check_lock(l->lv_lock, (char_u *)"remove()"))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012180 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012181 int error = FALSE;
12182
12183 idx = get_tv_number_chk(&argvars[1], &error);
12184 if (error)
12185 ; /* type error: do nothing, errmsg already given */
12186 else if ((item = list_find(l, idx)) == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012187 EMSGN(_(e_listidx), idx);
12188 else
12189 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012190 if (argvars[2].v_type == VAR_UNKNOWN)
12191 {
12192 /* Remove one item, return its value. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000012193 list_remove(l, item, item);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012194 *rettv = item->li_tv;
12195 vim_free(item);
12196 }
12197 else
12198 {
12199 /* Remove range of items, return list with values. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012200 end = get_tv_number_chk(&argvars[2], &error);
12201 if (error)
12202 ; /* type error: do nothing */
12203 else if ((item2 = list_find(l, end)) == NULL)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012204 EMSGN(_(e_listidx), end);
12205 else
12206 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000012207 int cnt = 0;
12208
12209 for (li = item; li != NULL; li = li->li_next)
12210 {
12211 ++cnt;
12212 if (li == item2)
12213 break;
12214 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012215 if (li == NULL) /* didn't find "item2" after "item" */
12216 EMSG(_(e_invrange));
12217 else
12218 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000012219 list_remove(l, item, item2);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012220 l = list_alloc();
12221 if (l != NULL)
12222 {
12223 rettv->v_type = VAR_LIST;
12224 rettv->vval.v_list = l;
12225 l->lv_first = item;
12226 l->lv_last = item2;
12227 l->lv_refcount = 1;
12228 item->li_prev = NULL;
12229 item2->li_next = NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +000012230 l->lv_len = cnt;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012231 }
12232 }
12233 }
12234 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012235 }
12236 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012237}
12238
12239/*
12240 * "rename({from}, {to})" function
12241 */
12242 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012243f_rename(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012244 typval_T *argvars;
12245 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012246{
12247 char_u buf[NUMBUFLEN];
12248
12249 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012250 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012251 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012252 rettv->vval.v_number = vim_rename(get_tv_string(&argvars[0]),
12253 get_tv_string_buf(&argvars[1], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +000012254}
12255
12256/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012257 * "repeat()" function
12258 */
12259/*ARGSUSED*/
12260 static void
12261f_repeat(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012262 typval_T *argvars;
12263 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012264{
12265 char_u *p;
12266 int n;
12267 int slen;
12268 int len;
12269 char_u *r;
12270 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +000012271 list_T *l;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012272
12273 n = get_tv_number(&argvars[1]);
12274 if (argvars[0].v_type == VAR_LIST)
12275 {
12276 l = list_alloc();
12277 if (l != NULL && argvars[0].vval.v_list != NULL)
12278 {
12279 l->lv_refcount = 1;
12280 while (n-- > 0)
12281 if (list_extend(l, argvars[0].vval.v_list, NULL) == FAIL)
12282 break;
12283 }
12284 rettv->v_type = VAR_LIST;
12285 rettv->vval.v_list = l;
12286 }
12287 else
12288 {
12289 p = get_tv_string(&argvars[0]);
12290 rettv->v_type = VAR_STRING;
12291 rettv->vval.v_string = NULL;
12292
12293 slen = (int)STRLEN(p);
12294 len = slen * n;
12295 if (len <= 0)
12296 return;
12297
12298 r = alloc(len + 1);
12299 if (r != NULL)
12300 {
12301 for (i = 0; i < n; i++)
12302 mch_memmove(r + i * slen, p, (size_t)slen);
12303 r[len] = NUL;
12304 }
12305
12306 rettv->vval.v_string = r;
12307 }
12308}
12309
12310/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012311 * "resolve()" function
12312 */
12313 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012314f_resolve(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012315 typval_T *argvars;
12316 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012317{
12318 char_u *p;
12319
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012320 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012321#ifdef FEAT_SHORTCUT
12322 {
12323 char_u *v = NULL;
12324
12325 v = mch_resolve_shortcut(p);
12326 if (v != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012327 rettv->vval.v_string = v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012328 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012329 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012330 }
12331#else
12332# ifdef HAVE_READLINK
12333 {
12334 char_u buf[MAXPATHL + 1];
12335 char_u *cpy;
12336 int len;
12337 char_u *remain = NULL;
12338 char_u *q;
12339 int is_relative_to_current = FALSE;
12340 int has_trailing_pathsep = FALSE;
12341 int limit = 100;
12342
12343 p = vim_strsave(p);
12344
12345 if (p[0] == '.' && (vim_ispathsep(p[1])
12346 || (p[1] == '.' && (vim_ispathsep(p[2])))))
12347 is_relative_to_current = TRUE;
12348
12349 len = STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012350 if (len > 0 && after_pathsep(p, p + len))
Bram Moolenaar071d4272004-06-13 20:20:40 +000012351 has_trailing_pathsep = TRUE;
12352
12353 q = getnextcomp(p);
12354 if (*q != NUL)
12355 {
12356 /* Separate the first path component in "p", and keep the
12357 * remainder (beginning with the path separator). */
12358 remain = vim_strsave(q - 1);
12359 q[-1] = NUL;
12360 }
12361
12362 for (;;)
12363 {
12364 for (;;)
12365 {
12366 len = readlink((char *)p, (char *)buf, MAXPATHL);
12367 if (len <= 0)
12368 break;
12369 buf[len] = NUL;
12370
12371 if (limit-- == 0)
12372 {
12373 vim_free(p);
12374 vim_free(remain);
12375 EMSG(_("E655: Too many symbolic links (cycle?)"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012376 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012377 goto fail;
12378 }
12379
12380 /* Ensure that the result will have a trailing path separator
12381 * if the argument has one. */
12382 if (remain == NULL && has_trailing_pathsep)
12383 add_pathsep(buf);
12384
12385 /* Separate the first path component in the link value and
12386 * concatenate the remainders. */
12387 q = getnextcomp(vim_ispathsep(*buf) ? buf + 1 : buf);
12388 if (*q != NUL)
12389 {
12390 if (remain == NULL)
12391 remain = vim_strsave(q - 1);
12392 else
12393 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000012394 cpy = vim_strnsave(q-1, STRLEN(q-1) + STRLEN(remain));
Bram Moolenaar071d4272004-06-13 20:20:40 +000012395 if (cpy != NULL)
12396 {
12397 STRCAT(cpy, remain);
12398 vim_free(remain);
12399 remain = cpy;
12400 }
12401 }
12402 q[-1] = NUL;
12403 }
12404
12405 q = gettail(p);
12406 if (q > p && *q == NUL)
12407 {
12408 /* Ignore trailing path separator. */
12409 q[-1] = NUL;
12410 q = gettail(p);
12411 }
12412 if (q > p && !mch_isFullName(buf))
12413 {
12414 /* symlink is relative to directory of argument */
12415 cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1));
12416 if (cpy != NULL)
12417 {
12418 STRCPY(cpy, p);
12419 STRCPY(gettail(cpy), buf);
12420 vim_free(p);
12421 p = cpy;
12422 }
12423 }
12424 else
12425 {
12426 vim_free(p);
12427 p = vim_strsave(buf);
12428 }
12429 }
12430
12431 if (remain == NULL)
12432 break;
12433
12434 /* Append the first path component of "remain" to "p". */
12435 q = getnextcomp(remain + 1);
12436 len = q - remain - (*q != NUL);
12437 cpy = vim_strnsave(p, STRLEN(p) + len);
12438 if (cpy != NULL)
12439 {
12440 STRNCAT(cpy, remain, len);
12441 vim_free(p);
12442 p = cpy;
12443 }
12444 /* Shorten "remain". */
12445 if (*q != NUL)
12446 STRCPY(remain, q - 1);
12447 else
12448 {
12449 vim_free(remain);
12450 remain = NULL;
12451 }
12452 }
12453
12454 /* If the result is a relative path name, make it explicitly relative to
12455 * the current directory if and only if the argument had this form. */
12456 if (!vim_ispathsep(*p))
12457 {
12458 if (is_relative_to_current
12459 && *p != NUL
12460 && !(p[0] == '.'
12461 && (p[1] == NUL
12462 || vim_ispathsep(p[1])
12463 || (p[1] == '.'
12464 && (p[2] == NUL
12465 || vim_ispathsep(p[2]))))))
12466 {
12467 /* Prepend "./". */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000012468 cpy = concat_str((char_u *)"./", p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012469 if (cpy != NULL)
12470 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000012471 vim_free(p);
12472 p = cpy;
12473 }
12474 }
12475 else if (!is_relative_to_current)
12476 {
12477 /* Strip leading "./". */
12478 q = p;
12479 while (q[0] == '.' && vim_ispathsep(q[1]))
12480 q += 2;
12481 if (q > p)
12482 mch_memmove(p, p + 2, STRLEN(p + 2) + (size_t)1);
12483 }
12484 }
12485
12486 /* Ensure that the result will have no trailing path separator
12487 * if the argument had none. But keep "/" or "//". */
12488 if (!has_trailing_pathsep)
12489 {
12490 q = p + STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012491 if (after_pathsep(p, q))
12492 *gettail_sep(p) = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012493 }
12494
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012495 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012496 }
12497# else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012498 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012499# endif
12500#endif
12501
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012502 simplify_filename(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012503
12504#ifdef HAVE_READLINK
12505fail:
12506#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012507 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012508}
12509
12510/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012511 * "reverse({list})" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000012512 */
12513 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000012514f_reverse(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012515 typval_T *argvars;
12516 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012517{
Bram Moolenaar33570922005-01-25 22:26:29 +000012518 list_T *l;
12519 listitem_T *li, *ni;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012520
Bram Moolenaar0d660222005-01-07 21:51:51 +000012521 rettv->vval.v_number = 0;
12522 if (argvars[0].v_type != VAR_LIST)
12523 EMSG2(_(e_listarg), "reverse()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000012524 else if ((l = argvars[0].vval.v_list) != NULL
12525 && !tv_check_lock(l->lv_lock, (char_u *)"reverse()"))
Bram Moolenaar0d660222005-01-07 21:51:51 +000012526 {
12527 li = l->lv_last;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000012528 l->lv_first = l->lv_last = NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +000012529 l->lv_len = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012530 while (li != NULL)
12531 {
12532 ni = li->li_prev;
12533 list_append(l, li);
12534 li = ni;
12535 }
12536 rettv->vval.v_list = l;
12537 rettv->v_type = VAR_LIST;
12538 ++l->lv_refcount;
12539 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012540}
12541
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012542#define SP_NOMOVE 1 /* don't move cursor */
12543#define SP_REPEAT 2 /* repeat to find outer pair */
12544#define SP_RETCOUNT 4 /* return matchcount */
12545
Bram Moolenaar33570922005-01-25 22:26:29 +000012546static int get_search_arg __ARGS((typval_T *varp, int *flagsp));
Bram Moolenaar0d660222005-01-07 21:51:51 +000012547
12548/*
12549 * Get flags for a search function.
12550 * Possibly sets "p_ws".
12551 * Returns BACKWARD, FORWARD or zero (for an error).
12552 */
12553 static int
12554get_search_arg(varp, flagsp)
Bram Moolenaar33570922005-01-25 22:26:29 +000012555 typval_T *varp;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012556 int *flagsp;
12557{
12558 int dir = FORWARD;
12559 char_u *flags;
12560 char_u nbuf[NUMBUFLEN];
12561 int mask;
12562
12563 if (varp->v_type != VAR_UNKNOWN)
12564 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012565 flags = get_tv_string_buf_chk(varp, nbuf);
12566 if (flags == NULL)
12567 return 0; /* type error; errmsg already given */
Bram Moolenaar0d660222005-01-07 21:51:51 +000012568 while (*flags != NUL)
12569 {
12570 switch (*flags)
12571 {
12572 case 'b': dir = BACKWARD; break;
12573 case 'w': p_ws = TRUE; break;
12574 case 'W': p_ws = FALSE; break;
12575 default: mask = 0;
12576 if (flagsp != NULL)
12577 switch (*flags)
12578 {
12579 case 'n': mask = SP_NOMOVE; break;
12580 case 'r': mask = SP_REPEAT; break;
12581 case 'm': mask = SP_RETCOUNT; break;
12582 }
12583 if (mask == 0)
12584 {
12585 EMSG2(_(e_invarg2), flags);
12586 dir = 0;
12587 }
12588 else
12589 *flagsp |= mask;
12590 }
12591 if (dir == 0)
12592 break;
12593 ++flags;
12594 }
12595 }
12596 return dir;
12597}
12598
Bram Moolenaar071d4272004-06-13 20:20:40 +000012599/*
12600 * "search()" function
12601 */
12602 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012603f_search(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012604 typval_T *argvars;
12605 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012606{
12607 char_u *pat;
12608 pos_T pos;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012609 pos_T save_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012610 int save_p_ws = p_ws;
12611 int dir;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012612 int flags = 0;
12613
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012614 rettv->vval.v_number = 0; /* default: FAIL */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012615
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012616 pat = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012617 dir = get_search_arg(&argvars[1], &flags); /* may set p_ws */
12618 if (dir == 0)
12619 goto theend;
12620 if ((flags & ~SP_NOMOVE) != 0)
12621 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012622 EMSG2(_(e_invarg2), get_tv_string(&argvars[1]));
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012623 goto theend;
12624 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012625
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012626 pos = save_cursor = curwin->w_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012627 if (searchit(curwin, curbuf, &pos, dir, pat, 1L,
12628 SEARCH_KEEP, RE_SEARCH) != FAIL)
12629 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012630 rettv->vval.v_number = pos.lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012631 curwin->w_cursor = pos;
12632 /* "/$" will put the cursor after the end of the line, may need to
12633 * correct that here */
12634 check_cursor();
12635 }
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012636
12637 /* If 'n' flag is used: restore cursor position. */
12638 if (flags & SP_NOMOVE)
12639 curwin->w_cursor = save_cursor;
12640theend:
Bram Moolenaar071d4272004-06-13 20:20:40 +000012641 p_ws = save_p_ws;
12642}
12643
Bram Moolenaar071d4272004-06-13 20:20:40 +000012644/*
12645 * "searchpair()" function
12646 */
12647 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012648f_searchpair(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012649 typval_T *argvars;
12650 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012651{
12652 char_u *spat, *mpat, *epat;
12653 char_u *skip;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012654 char_u *pat, *pat2 = NULL, *pat3 = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012655 pos_T pos;
12656 pos_T firstpos;
Bram Moolenaarc9a2d2e2005-04-24 22:09:56 +000012657 pos_T foundpos;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012658 pos_T save_cursor;
12659 pos_T save_pos;
12660 int save_p_ws = p_ws;
12661 char_u *save_cpo;
12662 int dir;
12663 int flags = 0;
12664 char_u nbuf1[NUMBUFLEN];
12665 char_u nbuf2[NUMBUFLEN];
12666 char_u nbuf3[NUMBUFLEN];
12667 int n;
12668 int r;
12669 int nest = 1;
12670 int err;
12671
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012672 rettv->vval.v_number = 0; /* default: FAIL */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012673
12674 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
12675 save_cpo = p_cpo;
12676 p_cpo = (char_u *)"";
12677
12678 /* Get the three pattern arguments: start, middle, end. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012679 spat = get_tv_string_chk(&argvars[0]);
12680 mpat = get_tv_string_buf_chk(&argvars[1], nbuf1);
12681 epat = get_tv_string_buf_chk(&argvars[2], nbuf2);
12682 if (spat == NULL || mpat == NULL || epat == NULL)
12683 goto theend; /* type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012684
12685 /* Make two search patterns: start/end (pat2, for in nested pairs) and
12686 * start/middle/end (pat3, for the top pair). */
12687 pat2 = alloc((unsigned)(STRLEN(spat) + STRLEN(epat) + 15));
12688 pat3 = alloc((unsigned)(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 23));
12689 if (pat2 == NULL || pat3 == NULL)
12690 goto theend;
12691 sprintf((char *)pat2, "\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat);
12692 if (*mpat == NUL)
12693 STRCPY(pat3, pat2);
12694 else
12695 sprintf((char *)pat3, "\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)",
12696 spat, epat, mpat);
12697
12698 /* Handle the optional fourth argument: flags */
12699 dir = get_search_arg(&argvars[3], &flags); /* may set p_ws */
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012700 if (dir == 0)
12701 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012702
12703 /* Optional fifth argument: skip expresion */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012704 if (argvars[3].v_type == VAR_UNKNOWN
12705 || argvars[4].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012706 skip = (char_u *)"";
12707 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012708 skip = get_tv_string_buf_chk(&argvars[4], nbuf3);
12709 if (skip == NULL)
12710 goto theend; /* type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012711
12712 save_cursor = curwin->w_cursor;
12713 pos = curwin->w_cursor;
12714 firstpos.lnum = 0;
Bram Moolenaarc9a2d2e2005-04-24 22:09:56 +000012715 foundpos.lnum = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012716 pat = pat3;
12717 for (;;)
12718 {
12719 n = searchit(curwin, curbuf, &pos, dir, pat, 1L,
12720 SEARCH_KEEP, RE_SEARCH);
12721 if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos)))
12722 /* didn't find it or found the first match again: FAIL */
12723 break;
12724
12725 if (firstpos.lnum == 0)
12726 firstpos = pos;
Bram Moolenaarc9a2d2e2005-04-24 22:09:56 +000012727 if (equalpos(pos, foundpos))
12728 {
12729 /* Found the same position again. Can happen with a pattern that
12730 * has "\zs" at the end and searching backwards. Advance one
12731 * character and try again. */
12732 if (dir == BACKWARD)
12733 decl(&pos);
12734 else
12735 incl(&pos);
12736 }
12737 foundpos = pos;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012738
12739 /* If the skip pattern matches, ignore this match. */
12740 if (*skip != NUL)
12741 {
12742 save_pos = curwin->w_cursor;
12743 curwin->w_cursor = pos;
12744 r = eval_to_bool(skip, &err, NULL, FALSE);
12745 curwin->w_cursor = save_pos;
12746 if (err)
12747 {
12748 /* Evaluating {skip} caused an error, break here. */
12749 curwin->w_cursor = save_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012750 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012751 break;
12752 }
12753 if (r)
12754 continue;
12755 }
12756
12757 if ((dir == BACKWARD && n == 3) || (dir == FORWARD && n == 2))
12758 {
12759 /* Found end when searching backwards or start when searching
12760 * forward: nested pair. */
12761 ++nest;
12762 pat = pat2; /* nested, don't search for middle */
12763 }
12764 else
12765 {
12766 /* Found end when searching forward or start when searching
12767 * backward: end of (nested) pair; or found middle in outer pair. */
12768 if (--nest == 1)
12769 pat = pat3; /* outer level, search for middle */
12770 }
12771
12772 if (nest == 0)
12773 {
12774 /* Found the match: return matchcount or line number. */
12775 if (flags & SP_RETCOUNT)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012776 ++rettv->vval.v_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012777 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012778 rettv->vval.v_number = pos.lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012779 curwin->w_cursor = pos;
12780 if (!(flags & SP_REPEAT))
12781 break;
12782 nest = 1; /* search for next unmatched */
12783 }
12784 }
12785
12786 /* If 'n' flag is used or search failed: restore cursor position. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012787 if ((flags & SP_NOMOVE) || rettv->vval.v_number == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012788 curwin->w_cursor = save_cursor;
12789
12790theend:
12791 vim_free(pat2);
12792 vim_free(pat3);
12793 p_ws = save_p_ws;
12794 p_cpo = save_cpo;
12795}
12796
Bram Moolenaar0d660222005-01-07 21:51:51 +000012797/*ARGSUSED*/
12798 static void
12799f_server2client(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012800 typval_T *argvars;
12801 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012802{
Bram Moolenaar0d660222005-01-07 21:51:51 +000012803#ifdef FEAT_CLIENTSERVER
12804 char_u buf[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012805 char_u *server = get_tv_string_chk(&argvars[0]);
12806 char_u *reply = get_tv_string_buf_chk(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012807
Bram Moolenaar0d660222005-01-07 21:51:51 +000012808 rettv->vval.v_number = -1;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012809 if (server == NULL || reply == NULL)
12810 return;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012811 if (check_restricted() || check_secure())
12812 return;
12813# ifdef FEAT_X11
12814 if (check_connection() == FAIL)
12815 return;
12816# endif
12817
12818 if (serverSendReply(server, reply) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012819 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000012820 EMSG(_("E258: Unable to send to client"));
12821 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012822 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000012823 rettv->vval.v_number = 0;
12824#else
12825 rettv->vval.v_number = -1;
12826#endif
12827}
12828
12829/*ARGSUSED*/
12830 static void
12831f_serverlist(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012832 typval_T *argvars;
12833 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012834{
12835 char_u *r = NULL;
12836
12837#ifdef FEAT_CLIENTSERVER
12838# ifdef WIN32
12839 r = serverGetVimNames();
12840# else
12841 make_connection();
12842 if (X_DISPLAY != NULL)
12843 r = serverGetVimNames(X_DISPLAY);
12844# endif
12845#endif
12846 rettv->v_type = VAR_STRING;
12847 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012848}
12849
12850/*
12851 * "setbufvar()" function
12852 */
12853/*ARGSUSED*/
12854 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012855f_setbufvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012856 typval_T *argvars;
12857 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012858{
12859 buf_T *buf;
12860#ifdef FEAT_AUTOCMD
12861 aco_save_T aco;
12862#else
12863 buf_T *save_curbuf;
12864#endif
12865 char_u *varname, *bufvarname;
Bram Moolenaar33570922005-01-25 22:26:29 +000012866 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012867 char_u nbuf[NUMBUFLEN];
12868
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012869 rettv->vval.v_number = 0;
12870
Bram Moolenaar071d4272004-06-13 20:20:40 +000012871 if (check_restricted() || check_secure())
12872 return;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012873 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
12874 varname = get_tv_string_chk(&argvars[1]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012875 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012876 varp = &argvars[2];
12877
12878 if (buf != NULL && varname != NULL && varp != NULL)
12879 {
12880 /* set curbuf to be our buf, temporarily */
12881#ifdef FEAT_AUTOCMD
12882 aucmd_prepbuf(&aco, buf);
12883#else
12884 save_curbuf = curbuf;
12885 curbuf = buf;
12886#endif
12887
12888 if (*varname == '&')
12889 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012890 long numval;
12891 char_u *strval;
12892 int error = FALSE;
12893
Bram Moolenaar071d4272004-06-13 20:20:40 +000012894 ++varname;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012895 numval = get_tv_number_chk(varp, &error);
12896 strval = get_tv_string_buf_chk(varp, nbuf);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012897 if (!error && strval != NULL)
12898 set_option_value(varname, numval, strval, OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012899 }
12900 else
12901 {
12902 bufvarname = alloc((unsigned)STRLEN(varname) + 3);
12903 if (bufvarname != NULL)
12904 {
12905 STRCPY(bufvarname, "b:");
12906 STRCPY(bufvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000012907 set_var(bufvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012908 vim_free(bufvarname);
12909 }
12910 }
12911
12912 /* reset notion of buffer */
12913#ifdef FEAT_AUTOCMD
12914 aucmd_restbuf(&aco);
12915#else
12916 curbuf = save_curbuf;
12917#endif
12918 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012919}
12920
12921/*
12922 * "setcmdpos()" function
12923 */
12924 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012925f_setcmdpos(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012926 typval_T *argvars;
12927 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012928{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012929 int pos = (int)get_tv_number(&argvars[0]) - 1;
12930
12931 if (pos >= 0)
12932 rettv->vval.v_number = set_cmdline_pos(pos);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012933}
12934
12935/*
12936 * "setline()" function
12937 */
12938 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012939f_setline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012940 typval_T *argvars;
12941 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012942{
12943 linenr_T lnum;
Bram Moolenaar0e6830e2005-05-27 20:23:44 +000012944 char_u *line = NULL;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000012945 list_T *l = NULL;
12946 listitem_T *li = NULL;
12947 long added = 0;
12948 linenr_T lcount = curbuf->b_ml.ml_line_count;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012949
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000012950 lnum = get_tv_lnum(&argvars[0]);
12951 if (argvars[1].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012952 {
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000012953 l = argvars[1].vval.v_list;
12954 li = l->lv_first;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012955 }
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000012956 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012957 line = get_tv_string_chk(&argvars[1]);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000012958
12959 rettv->vval.v_number = 0; /* OK */
12960 for (;;)
12961 {
12962 if (l != NULL)
12963 {
12964 /* list argument, get next string */
12965 if (li == NULL)
12966 break;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012967 line = get_tv_string_chk(&li->li_tv);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000012968 li = li->li_next;
12969 }
12970
12971 rettv->vval.v_number = 1; /* FAIL */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012972 if (line == NULL || lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000012973 break;
12974 if (lnum <= curbuf->b_ml.ml_line_count)
12975 {
12976 /* existing line, replace it */
12977 if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK)
12978 {
12979 changed_bytes(lnum, 0);
12980 check_cursor_col();
12981 rettv->vval.v_number = 0; /* OK */
12982 }
12983 }
12984 else if (added > 0 || u_save(lnum - 1, lnum) == OK)
12985 {
12986 /* lnum is one past the last line, append the line */
12987 ++added;
12988 if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK)
12989 rettv->vval.v_number = 0; /* OK */
12990 }
12991
12992 if (l == NULL) /* only one string argument */
12993 break;
12994 ++lnum;
12995 }
12996
12997 if (added > 0)
12998 appended_lines_mark(lcount, added);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012999}
13000
13001/*
Bram Moolenaar2641f772005-03-25 21:58:17 +000013002 * "setqflist()" function
13003 */
13004/*ARGSUSED*/
13005 static void
13006f_setqflist(argvars, rettv)
13007 typval_T *argvars;
13008 typval_T *rettv;
13009{
Bram Moolenaarf4630b62005-05-20 21:31:17 +000013010 char_u *act;
13011 int action = ' ';
13012
Bram Moolenaar2641f772005-03-25 21:58:17 +000013013 rettv->vval.v_number = -1;
13014
13015#ifdef FEAT_QUICKFIX
13016 if (argvars[0].v_type != VAR_LIST)
13017 EMSG(_(e_listreq));
13018 else
13019 {
13020 list_T *l = argvars[0].vval.v_list;
13021
Bram Moolenaarf4630b62005-05-20 21:31:17 +000013022 if (argvars[1].v_type == VAR_STRING)
13023 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013024 act = get_tv_string_chk(&argvars[1]);
13025 if (act == NULL)
13026 return; /* type error; errmsg already given */
Bram Moolenaarf4630b62005-05-20 21:31:17 +000013027 if (*act == 'a' || *act == 'r')
13028 action = *act;
13029 }
13030
13031 if (l != NULL && set_errorlist(l, action) == OK)
Bram Moolenaar2641f772005-03-25 21:58:17 +000013032 rettv->vval.v_number = 0;
13033 }
13034#endif
13035}
13036
13037/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013038 * "setreg()" function
13039 */
13040 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013041f_setreg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013042 typval_T *argvars;
13043 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013044{
13045 int regname;
13046 char_u *strregname;
13047 char_u *stropt;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013048 char_u *strval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013049 int append;
13050 char_u yank_type;
13051 long block_len;
13052
13053 block_len = -1;
13054 yank_type = MAUTO;
13055 append = FALSE;
13056
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013057 strregname = get_tv_string_chk(argvars);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013058 rettv->vval.v_number = 1; /* FAIL is default */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013059
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013060 if (strregname == NULL)
13061 return; /* type error; errmsg already given */
13062 regname = *strregname;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013063 if (regname == 0 || regname == '@')
13064 regname = '"';
13065 else if (regname == '=')
13066 return;
13067
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013068 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013069 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013070 stropt = get_tv_string_chk(&argvars[2]);
13071 if (stropt == NULL)
13072 return; /* type error */
13073 for (; *stropt != NUL; ++stropt)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013074 switch (*stropt)
13075 {
13076 case 'a': case 'A': /* append */
13077 append = TRUE;
13078 break;
13079 case 'v': case 'c': /* character-wise selection */
13080 yank_type = MCHAR;
13081 break;
13082 case 'V': case 'l': /* line-wise selection */
13083 yank_type = MLINE;
13084 break;
13085#ifdef FEAT_VISUAL
13086 case 'b': case Ctrl_V: /* block-wise selection */
13087 yank_type = MBLOCK;
13088 if (VIM_ISDIGIT(stropt[1]))
13089 {
13090 ++stropt;
13091 block_len = getdigits(&stropt) - 1;
13092 --stropt;
13093 }
13094 break;
13095#endif
13096 }
13097 }
13098
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013099 strval = get_tv_string_chk(&argvars[1]);
13100 if (strval != NULL)
13101 write_reg_contents_ex(regname, strval, -1,
Bram Moolenaar071d4272004-06-13 20:20:40 +000013102 append, yank_type, block_len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013103 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013104}
13105
13106
13107/*
13108 * "setwinvar(expr)" function
13109 */
13110/*ARGSUSED*/
13111 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013112f_setwinvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013113 typval_T *argvars;
13114 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013115{
13116 win_T *win;
13117#ifdef FEAT_WINDOWS
13118 win_T *save_curwin;
13119#endif
13120 char_u *varname, *winvarname;
Bram Moolenaar33570922005-01-25 22:26:29 +000013121 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013122 char_u nbuf[NUMBUFLEN];
13123
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013124 rettv->vval.v_number = 0;
13125
Bram Moolenaar071d4272004-06-13 20:20:40 +000013126 if (check_restricted() || check_secure())
13127 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013128 win = find_win_by_nr(&argvars[0]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013129 varname = get_tv_string_chk(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013130 varp = &argvars[2];
13131
13132 if (win != NULL && varname != NULL && varp != NULL)
13133 {
13134#ifdef FEAT_WINDOWS
13135 /* set curwin to be our win, temporarily */
13136 save_curwin = curwin;
13137 curwin = win;
13138 curbuf = curwin->w_buffer;
13139#endif
13140
13141 if (*varname == '&')
13142 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013143 long numval;
13144 char_u *strval;
13145 int error = FALSE;
13146
Bram Moolenaar071d4272004-06-13 20:20:40 +000013147 ++varname;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013148 numval = get_tv_number_chk(varp, &error);
13149 strval = get_tv_string_buf_chk(varp, nbuf);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013150 if (!error && strval != NULL)
13151 set_option_value(varname, numval, strval, OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013152 }
13153 else
13154 {
13155 winvarname = alloc((unsigned)STRLEN(varname) + 3);
13156 if (winvarname != NULL)
13157 {
13158 STRCPY(winvarname, "w:");
13159 STRCPY(winvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000013160 set_var(winvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013161 vim_free(winvarname);
13162 }
13163 }
13164
13165#ifdef FEAT_WINDOWS
13166 /* Restore current window, if it's still valid (autocomands can make
13167 * it invalid). */
13168 if (win_valid(save_curwin))
13169 {
13170 curwin = save_curwin;
13171 curbuf = curwin->w_buffer;
13172 }
13173#endif
13174 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013175}
13176
13177/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000013178 * "simplify()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000013179 */
13180 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000013181f_simplify(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013182 typval_T *argvars;
13183 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013184{
Bram Moolenaar0d660222005-01-07 21:51:51 +000013185 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013186
Bram Moolenaar0d660222005-01-07 21:51:51 +000013187 p = get_tv_string(&argvars[0]);
13188 rettv->vval.v_string = vim_strsave(p);
13189 simplify_filename(rettv->vval.v_string); /* simplify in place */
13190 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013191}
13192
Bram Moolenaar0d660222005-01-07 21:51:51 +000013193static int
13194#ifdef __BORLANDC__
13195 _RTLENTRYF
13196#endif
13197 item_compare __ARGS((const void *s1, const void *s2));
13198static int
13199#ifdef __BORLANDC__
13200 _RTLENTRYF
13201#endif
13202 item_compare2 __ARGS((const void *s1, const void *s2));
13203
13204static int item_compare_ic;
13205static char_u *item_compare_func;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013206static int item_compare_func_err;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013207#define ITEM_COMPARE_FAIL 999
13208
Bram Moolenaar071d4272004-06-13 20:20:40 +000013209/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000013210 * Compare functions for f_sort() below.
Bram Moolenaar071d4272004-06-13 20:20:40 +000013211 */
Bram Moolenaar0d660222005-01-07 21:51:51 +000013212 static int
13213#ifdef __BORLANDC__
13214_RTLENTRYF
13215#endif
13216item_compare(s1, s2)
13217 const void *s1;
13218 const void *s2;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013219{
Bram Moolenaar0d660222005-01-07 21:51:51 +000013220 char_u *p1, *p2;
13221 char_u *tofree1, *tofree2;
13222 int res;
13223 char_u numbuf1[NUMBUFLEN];
13224 char_u numbuf2[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000013225
Bram Moolenaar33570922005-01-25 22:26:29 +000013226 p1 = tv2string(&(*(listitem_T **)s1)->li_tv, &tofree1, numbuf1);
13227 p2 = tv2string(&(*(listitem_T **)s2)->li_tv, &tofree2, numbuf2);
Bram Moolenaar0d660222005-01-07 21:51:51 +000013228 if (item_compare_ic)
13229 res = STRICMP(p1, p2);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013230 else
Bram Moolenaar0d660222005-01-07 21:51:51 +000013231 res = STRCMP(p1, p2);
13232 vim_free(tofree1);
13233 vim_free(tofree2);
13234 return res;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013235}
13236
13237 static int
Bram Moolenaar0d660222005-01-07 21:51:51 +000013238#ifdef __BORLANDC__
13239_RTLENTRYF
Bram Moolenaar071d4272004-06-13 20:20:40 +000013240#endif
Bram Moolenaar0d660222005-01-07 21:51:51 +000013241item_compare2(s1, s2)
13242 const void *s1;
13243 const void *s2;
13244{
13245 int res;
Bram Moolenaar33570922005-01-25 22:26:29 +000013246 typval_T rettv;
13247 typval_T argv[2];
Bram Moolenaar0d660222005-01-07 21:51:51 +000013248 int dummy;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013249
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013250 /* shortcut after failure in previous call; compare all items equal */
13251 if (item_compare_func_err)
13252 return 0;
13253
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000013254 /* copy the values. This is needed to be able to set v_lock to VAR_FIXED
13255 * in the copy without changing the original list items. */
Bram Moolenaar33570922005-01-25 22:26:29 +000013256 copy_tv(&(*(listitem_T **)s1)->li_tv, &argv[0]);
13257 copy_tv(&(*(listitem_T **)s2)->li_tv, &argv[1]);
Bram Moolenaar0d660222005-01-07 21:51:51 +000013258
13259 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
13260 res = call_func(item_compare_func, STRLEN(item_compare_func),
Bram Moolenaare9a41262005-01-15 22:18:47 +000013261 &rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL);
Bram Moolenaar0d660222005-01-07 21:51:51 +000013262 clear_tv(&argv[0]);
13263 clear_tv(&argv[1]);
13264
13265 if (res == FAIL)
13266 res = ITEM_COMPARE_FAIL;
13267 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013268 /* return value has wrong type */
13269 res = get_tv_number_chk(&rettv, &item_compare_func_err);
13270 if (item_compare_func_err)
13271 res = ITEM_COMPARE_FAIL;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013272 clear_tv(&rettv);
13273 return res;
13274}
13275
13276/*
13277 * "sort({list})" function
13278 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013279 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000013280f_sort(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013281 typval_T *argvars;
13282 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013283{
Bram Moolenaar33570922005-01-25 22:26:29 +000013284 list_T *l;
13285 listitem_T *li;
13286 listitem_T **ptrs;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013287 long len;
13288 long i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013289
Bram Moolenaar0d660222005-01-07 21:51:51 +000013290 rettv->vval.v_number = 0;
13291 if (argvars[0].v_type != VAR_LIST)
13292 EMSG2(_(e_listarg), "sort()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000013293 else
13294 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000013295 l = argvars[0].vval.v_list;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000013296 if (l == NULL || tv_check_lock(l->lv_lock, (char_u *)"sort()"))
Bram Moolenaar0d660222005-01-07 21:51:51 +000013297 return;
13298 rettv->vval.v_list = l;
13299 rettv->v_type = VAR_LIST;
13300 ++l->lv_refcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013301
Bram Moolenaar0d660222005-01-07 21:51:51 +000013302 len = list_len(l);
13303 if (len <= 1)
13304 return; /* short list sorts pretty quickly */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013305
Bram Moolenaar0d660222005-01-07 21:51:51 +000013306 item_compare_ic = FALSE;
13307 item_compare_func = NULL;
13308 if (argvars[1].v_type != VAR_UNKNOWN)
13309 {
13310 if (argvars[1].v_type == VAR_FUNC)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013311 item_compare_func = argvars[1].vval.v_string;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013312 else
13313 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013314 int error = FALSE;
13315
13316 i = get_tv_number_chk(&argvars[1], &error);
13317 if (error)
13318 return; /* type error; errmsg already given */
Bram Moolenaar0d660222005-01-07 21:51:51 +000013319 if (i == 1)
13320 item_compare_ic = TRUE;
13321 else
13322 item_compare_func = get_tv_string(&argvars[1]);
13323 }
13324 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013325
Bram Moolenaar0d660222005-01-07 21:51:51 +000013326 /* Make an array with each entry pointing to an item in the List. */
Bram Moolenaar33570922005-01-25 22:26:29 +000013327 ptrs = (listitem_T **)alloc((int)(len * sizeof(listitem_T *)));
Bram Moolenaar0d660222005-01-07 21:51:51 +000013328 if (ptrs == NULL)
13329 return;
13330 i = 0;
13331 for (li = l->lv_first; li != NULL; li = li->li_next)
13332 ptrs[i++] = li;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013333
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013334 item_compare_func_err = FALSE;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013335 /* test the compare function */
13336 if (item_compare_func != NULL
13337 && item_compare2((void *)&ptrs[0], (void *)&ptrs[1])
13338 == ITEM_COMPARE_FAIL)
Bram Moolenaare49b69a2005-01-08 16:11:57 +000013339 EMSG(_("E702: Sort compare function failed"));
Bram Moolenaar071d4272004-06-13 20:20:40 +000013340 else
Bram Moolenaar0d660222005-01-07 21:51:51 +000013341 {
13342 /* Sort the array with item pointers. */
Bram Moolenaar33570922005-01-25 22:26:29 +000013343 qsort((void *)ptrs, (size_t)len, sizeof(listitem_T *),
Bram Moolenaar0d660222005-01-07 21:51:51 +000013344 item_compare_func == NULL ? item_compare : item_compare2);
13345
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013346 if (!item_compare_func_err)
13347 {
13348 /* Clear the List and append the items in the sorted order. */
13349 l->lv_first = l->lv_last = NULL;
13350 l->lv_len = 0;
13351 for (i = 0; i < len; ++i)
13352 list_append(l, ptrs[i]);
13353 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000013354 }
13355
13356 vim_free(ptrs);
13357 }
13358}
13359
Bram Moolenaard857f0e2005-06-21 22:37:39 +000013360/*
13361 * "spellbadword()" function
13362 */
13363/* ARGSUSED */
13364 static void
13365f_spellbadword(argvars, rettv)
13366 typval_T *argvars;
13367 typval_T *rettv;
13368{
13369 int attr;
13370 char_u *ptr;
13371 int len;
13372
13373 rettv->vval.v_string = NULL;
13374 rettv->v_type = VAR_STRING;
13375
13376#ifdef FEAT_SYN_HL
13377 /* Find the start of the badly spelled word. */
13378 if (spell_move_to(FORWARD, TRUE, TRUE) == FAIL)
13379 return;
13380
13381 /* Get the length of the word and copy it. */
13382 ptr = ml_get_cursor();
13383 len = spell_check(curwin, ptr, &attr);
13384 rettv->vval.v_string = vim_strnsave(ptr, len);
13385#endif
13386}
13387
13388/*
13389 * "spellsuggest()" function
13390 */
13391 static void
13392f_spellsuggest(argvars, rettv)
13393 typval_T *argvars;
13394 typval_T *rettv;
13395{
13396 char_u *str;
13397 int maxcount;
13398 garray_T ga;
13399 list_T *l;
13400 listitem_T *li;
13401 int i;
13402
13403 l = list_alloc();
13404 if (l == NULL)
13405 return;
13406 rettv->v_type = VAR_LIST;
13407 rettv->vval.v_list = l;
13408 ++l->lv_refcount;
13409
13410#ifdef FEAT_SYN_HL
13411 if (curwin->w_p_spell && *curbuf->b_p_spl != NUL)
13412 {
13413 str = get_tv_string(&argvars[0]);
13414 if (argvars[1].v_type != VAR_UNKNOWN)
13415 {
13416 maxcount = get_tv_number(&argvars[1]);
13417 if (maxcount <= 0)
13418 return;
13419 }
13420 else
13421 maxcount = 25;
13422
13423 spell_suggest_list(&ga, str, maxcount);
13424
13425 for (i = 0; i < ga.ga_len; ++i)
13426 {
13427 str = ((char_u **)ga.ga_data)[i];
13428
13429 li = listitem_alloc();
13430 if (li == NULL)
13431 vim_free(str);
13432 else
13433 {
13434 li->li_tv.v_type = VAR_STRING;
13435 li->li_tv.v_lock = 0;
13436 li->li_tv.vval.v_string = str;
13437 list_append(l, li);
13438 }
13439 }
13440 ga_clear(&ga);
13441 }
13442#endif
13443}
13444
Bram Moolenaar0d660222005-01-07 21:51:51 +000013445 static void
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000013446f_split(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013447 typval_T *argvars;
13448 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013449{
13450 char_u *str;
13451 char_u *end;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013452 char_u *pat = NULL;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013453 regmatch_T regmatch;
13454 char_u patbuf[NUMBUFLEN];
13455 char_u *save_cpo;
13456 int match;
Bram Moolenaar33570922005-01-25 22:26:29 +000013457 listitem_T *ni;
13458 list_T *l;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013459 colnr_T col = 0;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013460 int keepempty = FALSE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013461 int typeerr = FALSE;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013462
13463 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
13464 save_cpo = p_cpo;
13465 p_cpo = (char_u *)"";
13466
13467 str = get_tv_string(&argvars[0]);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013468 if (argvars[1].v_type != VAR_UNKNOWN)
13469 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013470 pat = get_tv_string_buf_chk(&argvars[1], patbuf);
13471 if (pat == NULL)
13472 typeerr = TRUE;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013473 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013474 keepempty = get_tv_number_chk(&argvars[2], &typeerr);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013475 }
13476 if (pat == NULL || *pat == NUL)
13477 pat = (char_u *)"[\\x01- ]\\+";
Bram Moolenaar0d660222005-01-07 21:51:51 +000013478
13479 l = list_alloc();
13480 if (l == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013481 return;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013482 rettv->v_type = VAR_LIST;
13483 rettv->vval.v_list = l;
13484 ++l->lv_refcount;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013485 if (typeerr)
13486 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013487
Bram Moolenaar0d660222005-01-07 21:51:51 +000013488 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
13489 if (regmatch.regprog != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013490 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000013491 regmatch.rm_ic = FALSE;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013492 while (*str != NUL || keepempty)
Bram Moolenaar0d660222005-01-07 21:51:51 +000013493 {
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013494 if (*str == NUL)
13495 match = FALSE; /* empty item at the end */
13496 else
13497 match = vim_regexec_nl(&regmatch, str, col);
Bram Moolenaar0d660222005-01-07 21:51:51 +000013498 if (match)
13499 end = regmatch.startp[0];
13500 else
13501 end = str + STRLEN(str);
Bram Moolenaar54ee7752005-05-31 22:22:17 +000013502 if (keepempty || end > str || (l->lv_len > 0 && *str != NUL
13503 && match && end < regmatch.endp[0]))
Bram Moolenaar0d660222005-01-07 21:51:51 +000013504 {
13505 ni = listitem_alloc();
13506 if (ni == NULL)
13507 break;
13508 ni->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000013509 ni->li_tv.v_lock = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013510 ni->li_tv.vval.v_string = vim_strnsave(str, end - str);
13511 list_append(l, ni);
13512 }
13513 if (!match)
13514 break;
13515 /* Advance to just after the match. */
13516 if (regmatch.endp[0] > str)
13517 col = 0;
13518 else
13519 {
13520 /* Don't get stuck at the same match. */
13521#ifdef FEAT_MBYTE
13522 col = mb_ptr2len_check(regmatch.endp[0]);
13523#else
13524 col = 1;
13525#endif
13526 }
13527 str = regmatch.endp[0];
13528 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013529
Bram Moolenaar0d660222005-01-07 21:51:51 +000013530 vim_free(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013531 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013532
Bram Moolenaar0d660222005-01-07 21:51:51 +000013533 p_cpo = save_cpo;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013534}
13535
13536#ifdef HAVE_STRFTIME
13537/*
13538 * "strftime({format}[, {time}])" function
13539 */
13540 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013541f_strftime(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013542 typval_T *argvars;
13543 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013544{
13545 char_u result_buf[256];
13546 struct tm *curtime;
13547 time_t seconds;
13548 char_u *p;
13549
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013550 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013551
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013552 p = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013553 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013554 seconds = time(NULL);
13555 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013556 seconds = (time_t)get_tv_number(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013557 curtime = localtime(&seconds);
13558 /* MSVC returns NULL for an invalid value of seconds. */
13559 if (curtime == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013560 rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
Bram Moolenaar071d4272004-06-13 20:20:40 +000013561 else
13562 {
13563# ifdef FEAT_MBYTE
13564 vimconv_T conv;
13565 char_u *enc;
13566
13567 conv.vc_type = CONV_NONE;
13568 enc = enc_locale();
13569 convert_setup(&conv, p_enc, enc);
13570 if (conv.vc_type != CONV_NONE)
13571 p = string_convert(&conv, p, NULL);
13572# endif
13573 if (p != NULL)
13574 (void)strftime((char *)result_buf, sizeof(result_buf),
13575 (char *)p, curtime);
13576 else
13577 result_buf[0] = NUL;
13578
13579# ifdef FEAT_MBYTE
13580 if (conv.vc_type != CONV_NONE)
13581 vim_free(p);
13582 convert_setup(&conv, enc, p_enc);
13583 if (conv.vc_type != CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013584 rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013585 else
13586# endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013587 rettv->vval.v_string = vim_strsave(result_buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013588
13589# ifdef FEAT_MBYTE
13590 /* Release conversion descriptors */
13591 convert_setup(&conv, NULL, NULL);
13592 vim_free(enc);
13593# endif
13594 }
13595}
13596#endif
13597
13598/*
13599 * "stridx()" function
13600 */
13601 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013602f_stridx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013603 typval_T *argvars;
13604 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013605{
13606 char_u buf[NUMBUFLEN];
13607 char_u *needle;
13608 char_u *haystack;
Bram Moolenaar33570922005-01-25 22:26:29 +000013609 char_u *save_haystack;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013610 char_u *pos;
Bram Moolenaar33570922005-01-25 22:26:29 +000013611 int start_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013612
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013613 needle = get_tv_string_chk(&argvars[1]);
13614 save_haystack = haystack = get_tv_string_buf_chk(&argvars[0], buf);
Bram Moolenaar33570922005-01-25 22:26:29 +000013615 rettv->vval.v_number = -1;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013616 if (needle == NULL || haystack == NULL)
13617 return; /* type error; errmsg already given */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013618
Bram Moolenaar33570922005-01-25 22:26:29 +000013619 if (argvars[2].v_type != VAR_UNKNOWN)
13620 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013621 int error = FALSE;
13622
13623 start_idx = get_tv_number_chk(&argvars[2], &error);
13624 if (error || start_idx >= (int)STRLEN(haystack))
Bram Moolenaar33570922005-01-25 22:26:29 +000013625 return;
Bram Moolenaar532c7802005-01-27 14:44:31 +000013626 if (start_idx >= 0)
13627 haystack += start_idx;
Bram Moolenaar33570922005-01-25 22:26:29 +000013628 }
13629
13630 pos = (char_u *)strstr((char *)haystack, (char *)needle);
13631 if (pos != NULL)
13632 rettv->vval.v_number = (varnumber_T)(pos - save_haystack);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013633}
13634
13635/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013636 * "string()" function
13637 */
13638 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013639f_string(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013640 typval_T *argvars;
13641 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013642{
13643 char_u *tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013644 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013645
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013646 rettv->v_type = VAR_STRING;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013647 rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013648 if (tofree == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013649 rettv->vval.v_string = vim_strsave(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013650}
13651
13652/*
13653 * "strlen()" function
13654 */
13655 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013656f_strlen(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013657 typval_T *argvars;
13658 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013659{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013660 rettv->vval.v_number = (varnumber_T)(STRLEN(
13661 get_tv_string(&argvars[0])));
Bram Moolenaar071d4272004-06-13 20:20:40 +000013662}
13663
13664/*
13665 * "strpart()" function
13666 */
13667 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013668f_strpart(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013669 typval_T *argvars;
13670 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013671{
13672 char_u *p;
13673 int n;
13674 int len;
13675 int slen;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013676 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013677
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013678 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013679 slen = (int)STRLEN(p);
13680
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013681 n = get_tv_number_chk(&argvars[1], &error);
13682 if (error)
13683 len = 0;
13684 else if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013685 len = get_tv_number(&argvars[2]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013686 else
13687 len = slen - n; /* default len: all bytes that are available. */
13688
13689 /*
13690 * Only return the overlap between the specified part and the actual
13691 * string.
13692 */
13693 if (n < 0)
13694 {
13695 len += n;
13696 n = 0;
13697 }
13698 else if (n > slen)
13699 n = slen;
13700 if (len < 0)
13701 len = 0;
13702 else if (n + len > slen)
13703 len = slen - n;
13704
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013705 rettv->v_type = VAR_STRING;
13706 rettv->vval.v_string = vim_strnsave(p + n, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013707}
13708
13709/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000013710 * "strridx()" function
13711 */
13712 static void
13713f_strridx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013714 typval_T *argvars;
13715 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013716{
13717 char_u buf[NUMBUFLEN];
13718 char_u *needle;
13719 char_u *haystack;
13720 char_u *rest;
13721 char_u *lastmatch = NULL;
Bram Moolenaar532c7802005-01-27 14:44:31 +000013722 int haystack_len, end_idx;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013723
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013724 needle = get_tv_string_chk(&argvars[1]);
13725 haystack = get_tv_string_buf_chk(&argvars[0], buf);
Bram Moolenaar532c7802005-01-27 14:44:31 +000013726 haystack_len = STRLEN(haystack);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013727
13728 rettv->vval.v_number = -1;
13729 if (needle == NULL || haystack == NULL)
13730 return; /* type error; errmsg already given */
Bram Moolenaar05159a02005-02-26 23:04:13 +000013731 if (argvars[2].v_type != VAR_UNKNOWN)
13732 {
13733 /* Third argument: upper limit for index */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013734 end_idx = get_tv_number_chk(&argvars[2], NULL);
Bram Moolenaar05159a02005-02-26 23:04:13 +000013735 if (end_idx < 0)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013736 return; /* can never find a match */
Bram Moolenaar05159a02005-02-26 23:04:13 +000013737 }
13738 else
13739 end_idx = haystack_len;
13740
Bram Moolenaar0d660222005-01-07 21:51:51 +000013741 if (*needle == NUL)
Bram Moolenaar05159a02005-02-26 23:04:13 +000013742 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000013743 /* Empty string matches past the end. */
Bram Moolenaar05159a02005-02-26 23:04:13 +000013744 lastmatch = haystack + end_idx;
13745 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000013746 else
Bram Moolenaar532c7802005-01-27 14:44:31 +000013747 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000013748 for (rest = haystack; *rest != '\0'; ++rest)
13749 {
13750 rest = (char_u *)strstr((char *)rest, (char *)needle);
Bram Moolenaar532c7802005-01-27 14:44:31 +000013751 if (rest == NULL || rest > haystack + end_idx)
Bram Moolenaar0d660222005-01-07 21:51:51 +000013752 break;
13753 lastmatch = rest;
13754 }
Bram Moolenaar532c7802005-01-27 14:44:31 +000013755 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000013756
13757 if (lastmatch == NULL)
13758 rettv->vval.v_number = -1;
13759 else
13760 rettv->vval.v_number = (varnumber_T)(lastmatch - haystack);
13761}
13762
13763/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013764 * "strtrans()" function
13765 */
13766 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013767f_strtrans(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013768 typval_T *argvars;
13769 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013770{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013771 rettv->v_type = VAR_STRING;
13772 rettv->vval.v_string = transstr(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000013773}
13774
13775/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000013776 * "submatch()" function
13777 */
13778 static void
13779f_submatch(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013780 typval_T *argvars;
13781 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013782{
13783 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013784 rettv->vval.v_string =
13785 reg_submatch((int)get_tv_number_chk(&argvars[0], NULL));
Bram Moolenaar0d660222005-01-07 21:51:51 +000013786}
13787
13788/*
13789 * "substitute()" function
13790 */
13791 static void
13792f_substitute(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013793 typval_T *argvars;
13794 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013795{
13796 char_u patbuf[NUMBUFLEN];
13797 char_u subbuf[NUMBUFLEN];
13798 char_u flagsbuf[NUMBUFLEN];
13799
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013800 char_u *str = get_tv_string_chk(&argvars[0]);
13801 char_u *pat = get_tv_string_buf_chk(&argvars[1], patbuf);
13802 char_u *sub = get_tv_string_buf_chk(&argvars[2], subbuf);
13803 char_u *flg = get_tv_string_buf_chk(&argvars[3], flagsbuf);
13804
Bram Moolenaar0d660222005-01-07 21:51:51 +000013805 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013806 if (str == NULL || pat == NULL || sub == NULL || flg == NULL)
13807 rettv->vval.v_string = NULL;
13808 else
13809 rettv->vval.v_string = do_string_sub(str, pat, sub, flg);
Bram Moolenaar0d660222005-01-07 21:51:51 +000013810}
13811
13812/*
Bram Moolenaar54ff3412005-04-20 19:48:33 +000013813 * "synID(lnum, col, trans)" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000013814 */
13815/*ARGSUSED*/
13816 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013817f_synID(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013818 typval_T *argvars;
13819 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013820{
13821 int id = 0;
13822#ifdef FEAT_SYN_HL
Bram Moolenaar54ff3412005-04-20 19:48:33 +000013823 long lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013824 long col;
13825 int trans;
Bram Moolenaar92124a32005-06-17 22:03:40 +000013826 int transerr = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013827
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013828 lnum = get_tv_lnum(argvars); /* -1 on type error */
13829 col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */
13830 trans = get_tv_number_chk(&argvars[2], &transerr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013831
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013832 if (!transerr && lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
Bram Moolenaar54ff3412005-04-20 19:48:33 +000013833 && col >= 0 && col < (long)STRLEN(ml_get(lnum)))
13834 id = syn_get_id(lnum, (colnr_T)col, trans, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013835#endif
13836
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013837 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013838}
13839
13840/*
13841 * "synIDattr(id, what [, mode])" function
13842 */
13843/*ARGSUSED*/
13844 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013845f_synIDattr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013846 typval_T *argvars;
13847 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013848{
13849 char_u *p = NULL;
13850#ifdef FEAT_SYN_HL
13851 int id;
13852 char_u *what;
13853 char_u *mode;
13854 char_u modebuf[NUMBUFLEN];
13855 int modec;
13856
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013857 id = get_tv_number(&argvars[0]);
13858 what = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013859 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013860 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013861 mode = get_tv_string_buf(&argvars[2], modebuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013862 modec = TOLOWER_ASC(mode[0]);
13863 if (modec != 't' && modec != 'c'
13864#ifdef FEAT_GUI
13865 && modec != 'g'
13866#endif
13867 )
13868 modec = 0; /* replace invalid with current */
13869 }
13870 else
13871 {
13872#ifdef FEAT_GUI
13873 if (gui.in_use)
13874 modec = 'g';
13875 else
13876#endif
13877 if (t_colors > 1)
13878 modec = 'c';
13879 else
13880 modec = 't';
13881 }
13882
13883
13884 switch (TOLOWER_ASC(what[0]))
13885 {
13886 case 'b':
13887 if (TOLOWER_ASC(what[1]) == 'g') /* bg[#] */
13888 p = highlight_color(id, what, modec);
13889 else /* bold */
13890 p = highlight_has_attr(id, HL_BOLD, modec);
13891 break;
13892
13893 case 'f': /* fg[#] */
13894 p = highlight_color(id, what, modec);
13895 break;
13896
13897 case 'i':
13898 if (TOLOWER_ASC(what[1]) == 'n') /* inverse */
13899 p = highlight_has_attr(id, HL_INVERSE, modec);
13900 else /* italic */
13901 p = highlight_has_attr(id, HL_ITALIC, modec);
13902 break;
13903
13904 case 'n': /* name */
13905 p = get_highlight_name(NULL, id - 1);
13906 break;
13907
13908 case 'r': /* reverse */
13909 p = highlight_has_attr(id, HL_INVERSE, modec);
13910 break;
13911
13912 case 's': /* standout */
13913 p = highlight_has_attr(id, HL_STANDOUT, modec);
13914 break;
13915
Bram Moolenaar5b743bf2005-03-15 22:50:43 +000013916 case 'u':
13917 if (STRLEN(what) <= 5 || TOLOWER_ASC(what[5]) != 'c')
13918 /* underline */
13919 p = highlight_has_attr(id, HL_UNDERLINE, modec);
13920 else
13921 /* undercurl */
13922 p = highlight_has_attr(id, HL_UNDERCURL, modec);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013923 break;
13924 }
13925
13926 if (p != NULL)
13927 p = vim_strsave(p);
13928#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013929 rettv->v_type = VAR_STRING;
13930 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013931}
13932
13933/*
13934 * "synIDtrans(id)" function
13935 */
13936/*ARGSUSED*/
13937 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013938f_synIDtrans(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013939 typval_T *argvars;
13940 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013941{
13942 int id;
13943
13944#ifdef FEAT_SYN_HL
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013945 id = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013946
13947 if (id > 0)
13948 id = syn_get_final_id(id);
13949 else
13950#endif
13951 id = 0;
13952
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013953 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013954}
13955
13956/*
13957 * "system()" function
13958 */
13959 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013960f_system(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013961 typval_T *argvars;
13962 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013963{
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013964 char_u *res = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013965 char_u *p;
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013966 char_u *infile = NULL;
13967 char_u buf[NUMBUFLEN];
13968 int err = FALSE;
13969 FILE *fd;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013970
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013971 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013972 {
13973 /*
13974 * Write the string to a temp file, to be used for input of the shell
13975 * command.
13976 */
13977 if ((infile = vim_tempname('i')) == NULL)
13978 {
13979 EMSG(_(e_notmp));
13980 return;
13981 }
13982
13983 fd = mch_fopen((char *)infile, WRITEBIN);
13984 if (fd == NULL)
13985 {
13986 EMSG2(_(e_notopen), infile);
13987 goto done;
13988 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013989 p = get_tv_string_buf_chk(&argvars[1], buf);
13990 if (p == NULL)
13991 goto done; /* type error; errmsg already given */
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013992 if (fwrite(p, STRLEN(p), 1, fd) != 1)
13993 err = TRUE;
13994 if (fclose(fd) != 0)
13995 err = TRUE;
13996 if (err)
13997 {
13998 EMSG(_("E677: Error writing temp file"));
13999 goto done;
14000 }
14001 }
14002
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014003 res = get_cmd_output(get_tv_string(&argvars[0]), infile, SHELL_SILENT);
Bram Moolenaarc0197e22004-09-13 20:26:32 +000014004
Bram Moolenaar071d4272004-06-13 20:20:40 +000014005#ifdef USE_CR
14006 /* translate <CR> into <NL> */
Bram Moolenaarc0197e22004-09-13 20:26:32 +000014007 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014008 {
14009 char_u *s;
14010
Bram Moolenaarc0197e22004-09-13 20:26:32 +000014011 for (s = res; *s; ++s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014012 {
14013 if (*s == CAR)
14014 *s = NL;
14015 }
14016 }
14017#else
14018# ifdef USE_CRNL
14019 /* translate <CR><NL> into <NL> */
Bram Moolenaarc0197e22004-09-13 20:26:32 +000014020 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014021 {
14022 char_u *s, *d;
14023
Bram Moolenaarc0197e22004-09-13 20:26:32 +000014024 d = res;
14025 for (s = res; *s; ++s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014026 {
14027 if (s[0] == CAR && s[1] == NL)
14028 ++s;
14029 *d++ = *s;
14030 }
14031 *d = NUL;
14032 }
14033# endif
14034#endif
Bram Moolenaarc0197e22004-09-13 20:26:32 +000014035
14036done:
14037 if (infile != NULL)
14038 {
14039 mch_remove(infile);
14040 vim_free(infile);
14041 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014042 rettv->v_type = VAR_STRING;
14043 rettv->vval.v_string = res;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014044}
14045
14046/*
Bram Moolenaare2ac10d2005-03-07 23:26:06 +000014047 * "taglist()" function
Bram Moolenaar19a09a12005-03-04 23:39:37 +000014048 */
14049 static void
14050f_taglist(argvars, rettv)
14051 typval_T *argvars;
14052 typval_T *rettv;
14053{
14054 char_u *tag_pattern;
14055 list_T *l;
14056
14057 tag_pattern = get_tv_string(&argvars[0]);
14058
14059 rettv->vval.v_number = FALSE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014060 if (*tag_pattern == NUL)
14061 return;
Bram Moolenaar19a09a12005-03-04 23:39:37 +000014062
14063 l = list_alloc();
14064 if (l != NULL)
14065 {
14066 if (get_tags(l, tag_pattern) != FAIL)
14067 {
14068 rettv->vval.v_list = l;
14069 rettv->v_type = VAR_LIST;
14070 ++l->lv_refcount;
14071 }
14072 else
14073 list_free(l);
14074 }
14075}
14076
14077/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014078 * "tempname()" function
14079 */
14080/*ARGSUSED*/
14081 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014082f_tempname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014083 typval_T *argvars;
14084 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014085{
14086 static int x = 'A';
14087
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014088 rettv->v_type = VAR_STRING;
14089 rettv->vval.v_string = vim_tempname(x);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014090
14091 /* Advance 'x' to use A-Z and 0-9, so that there are at least 34 different
14092 * names. Skip 'I' and 'O', they are used for shell redirection. */
14093 do
14094 {
14095 if (x == 'Z')
14096 x = '0';
14097 else if (x == '9')
14098 x = 'A';
14099 else
14100 {
14101#ifdef EBCDIC
14102 if (x == 'I')
14103 x = 'J';
14104 else if (x == 'R')
14105 x = 'S';
14106 else
14107#endif
14108 ++x;
14109 }
14110 } while (x == 'I' || x == 'O');
14111}
14112
14113/*
14114 * "tolower(string)" function
14115 */
14116 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014117f_tolower(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014118 typval_T *argvars;
14119 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014120{
14121 char_u *p;
14122
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014123 p = vim_strsave(get_tv_string(&argvars[0]));
14124 rettv->v_type = VAR_STRING;
14125 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014126
14127 if (p != NULL)
14128 while (*p != NUL)
14129 {
14130#ifdef FEAT_MBYTE
14131 int l;
14132
14133 if (enc_utf8)
14134 {
14135 int c, lc;
14136
14137 c = utf_ptr2char(p);
14138 lc = utf_tolower(c);
14139 l = utf_ptr2len_check(p);
14140 /* TODO: reallocate string when byte count changes. */
14141 if (utf_char2len(lc) == l)
14142 utf_char2bytes(lc, p);
14143 p += l;
14144 }
14145 else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
14146 p += l; /* skip multi-byte character */
14147 else
14148#endif
14149 {
14150 *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */
14151 ++p;
14152 }
14153 }
14154}
14155
14156/*
14157 * "toupper(string)" function
14158 */
14159 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014160f_toupper(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014161 typval_T *argvars;
14162 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014163{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014164 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014165 rettv->vval.v_string = strup_save(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000014166}
14167
14168/*
Bram Moolenaar8299df92004-07-10 09:47:34 +000014169 * "tr(string, fromstr, tostr)" function
14170 */
14171 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014172f_tr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014173 typval_T *argvars;
14174 typval_T *rettv;
Bram Moolenaar8299df92004-07-10 09:47:34 +000014175{
14176 char_u *instr;
14177 char_u *fromstr;
14178 char_u *tostr;
14179 char_u *p;
14180#ifdef FEAT_MBYTE
14181 int inlen;
14182 int fromlen;
14183 int tolen;
14184 int idx;
14185 char_u *cpstr;
14186 int cplen;
14187 int first = TRUE;
14188#endif
14189 char_u buf[NUMBUFLEN];
14190 char_u buf2[NUMBUFLEN];
14191 garray_T ga;
14192
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014193 instr = get_tv_string(&argvars[0]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014194 fromstr = get_tv_string_buf_chk(&argvars[1], buf);
14195 tostr = get_tv_string_buf_chk(&argvars[2], buf2);
Bram Moolenaar8299df92004-07-10 09:47:34 +000014196
14197 /* Default return value: empty string. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014198 rettv->v_type = VAR_STRING;
14199 rettv->vval.v_string = NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014200 if (fromstr == NULL || tostr == NULL)
14201 return; /* type error; errmsg already given */
Bram Moolenaar8299df92004-07-10 09:47:34 +000014202 ga_init2(&ga, (int)sizeof(char), 80);
14203
14204#ifdef FEAT_MBYTE
14205 if (!has_mbyte)
14206#endif
14207 /* not multi-byte: fromstr and tostr must be the same length */
14208 if (STRLEN(fromstr) != STRLEN(tostr))
14209 {
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000014210#ifdef FEAT_MBYTE
Bram Moolenaar8299df92004-07-10 09:47:34 +000014211error:
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000014212#endif
Bram Moolenaar8299df92004-07-10 09:47:34 +000014213 EMSG2(_(e_invarg2), fromstr);
14214 ga_clear(&ga);
14215 return;
14216 }
14217
14218 /* fromstr and tostr have to contain the same number of chars */
14219 while (*instr != NUL)
14220 {
14221#ifdef FEAT_MBYTE
14222 if (has_mbyte)
14223 {
14224 inlen = mb_ptr2len_check(instr);
14225 cpstr = instr;
14226 cplen = inlen;
14227 idx = 0;
14228 for (p = fromstr; *p != NUL; p += fromlen)
14229 {
14230 fromlen = mb_ptr2len_check(p);
14231 if (fromlen == inlen && STRNCMP(instr, p, inlen) == 0)
14232 {
14233 for (p = tostr; *p != NUL; p += tolen)
14234 {
14235 tolen = mb_ptr2len_check(p);
14236 if (idx-- == 0)
14237 {
14238 cplen = tolen;
14239 cpstr = p;
14240 break;
14241 }
14242 }
14243 if (*p == NUL) /* tostr is shorter than fromstr */
14244 goto error;
14245 break;
14246 }
14247 ++idx;
14248 }
14249
14250 if (first && cpstr == instr)
14251 {
14252 /* Check that fromstr and tostr have the same number of
14253 * (multi-byte) characters. Done only once when a character
14254 * of instr doesn't appear in fromstr. */
14255 first = FALSE;
14256 for (p = tostr; *p != NUL; p += tolen)
14257 {
14258 tolen = mb_ptr2len_check(p);
14259 --idx;
14260 }
14261 if (idx != 0)
14262 goto error;
14263 }
14264
14265 ga_grow(&ga, cplen);
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +000014266 mch_memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen);
Bram Moolenaar8299df92004-07-10 09:47:34 +000014267 ga.ga_len += cplen;
Bram Moolenaar8299df92004-07-10 09:47:34 +000014268
14269 instr += inlen;
14270 }
14271 else
14272#endif
14273 {
14274 /* When not using multi-byte chars we can do it faster. */
14275 p = vim_strchr(fromstr, *instr);
14276 if (p != NULL)
14277 ga_append(&ga, tostr[p - fromstr]);
14278 else
14279 ga_append(&ga, *instr);
14280 ++instr;
14281 }
14282 }
14283
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014284 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar8299df92004-07-10 09:47:34 +000014285}
14286
14287/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014288 * "type(expr)" function
14289 */
14290 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014291f_type(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{
Bram Moolenaar6cc16192005-01-08 21:49:45 +000014295 int n;
14296
14297 switch (argvars[0].v_type)
14298 {
14299 case VAR_NUMBER: n = 0; break;
14300 case VAR_STRING: n = 1; break;
14301 case VAR_FUNC: n = 2; break;
14302 case VAR_LIST: n = 3; break;
Bram Moolenaar758711c2005-02-02 23:11:38 +000014303 case VAR_DICT: n = 4; break;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000014304 default: EMSG2(_(e_intern2), "f_type()"); n = 0; break;
14305 }
14306 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014307}
14308
14309/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000014310 * "values(dict)" function
14311 */
14312 static void
14313f_values(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014314 typval_T *argvars;
14315 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000014316{
14317 dict_list(argvars, rettv, 1);
14318}
14319
14320/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014321 * "virtcol(string)" function
14322 */
14323 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014324f_virtcol(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014325 typval_T *argvars;
14326 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014327{
14328 colnr_T vcol = 0;
14329 pos_T *fp;
14330
14331 fp = var2fpos(&argvars[0], FALSE);
14332 if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count)
14333 {
14334 getvvcol(curwin, fp, NULL, NULL, &vcol);
14335 ++vcol;
14336 }
14337
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014338 rettv->vval.v_number = vcol;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014339}
14340
14341/*
14342 * "visualmode()" function
14343 */
14344/*ARGSUSED*/
14345 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014346f_visualmode(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014347 typval_T *argvars;
14348 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014349{
14350#ifdef FEAT_VISUAL
14351 char_u str[2];
14352
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014353 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014354 str[0] = curbuf->b_visual_mode_eval;
14355 str[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014356 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014357
14358 /* A non-zero number or non-empty string argument: reset mode. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014359 if ((argvars[0].v_type == VAR_NUMBER
14360 && argvars[0].vval.v_number != 0)
14361 || (argvars[0].v_type == VAR_STRING
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014362 && *get_tv_string(&argvars[0]) != NUL))
Bram Moolenaar071d4272004-06-13 20:20:40 +000014363 curbuf->b_visual_mode_eval = NUL;
14364#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014365 rettv->vval.v_number = 0; /* return anything, it won't work anyway */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014366#endif
14367}
14368
14369/*
14370 * "winbufnr(nr)" function
14371 */
14372 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014373f_winbufnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014374 typval_T *argvars;
14375 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014376{
14377 win_T *wp;
14378
14379 wp = find_win_by_nr(&argvars[0]);
14380 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014381 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014382 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014383 rettv->vval.v_number = wp->w_buffer->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014384}
14385
14386/*
14387 * "wincol()" function
14388 */
14389/*ARGSUSED*/
14390 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014391f_wincol(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014392 typval_T *argvars;
14393 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014394{
14395 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014396 rettv->vval.v_number = curwin->w_wcol + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014397}
14398
14399/*
14400 * "winheight(nr)" function
14401 */
14402 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014403f_winheight(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014404 typval_T *argvars;
14405 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014406{
14407 win_T *wp;
14408
14409 wp = find_win_by_nr(&argvars[0]);
14410 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014411 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014412 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014413 rettv->vval.v_number = wp->w_height;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014414}
14415
14416/*
14417 * "winline()" function
14418 */
14419/*ARGSUSED*/
14420 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014421f_winline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014422 typval_T *argvars;
14423 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014424{
14425 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014426 rettv->vval.v_number = curwin->w_wrow + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014427}
14428
14429/*
14430 * "winnr()" function
14431 */
14432/* ARGSUSED */
14433 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014434f_winnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014435 typval_T *argvars;
14436 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014437{
14438 int nr = 1;
14439#ifdef FEAT_WINDOWS
14440 win_T *wp;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000014441 win_T *twin = curwin;
14442 char_u *arg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014443
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014444 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000014445 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014446 arg = get_tv_string_chk(&argvars[0]);
14447 if (arg == NULL)
14448 nr = 0; /* type error; errmsg already given */
14449 else if (STRCMP(arg, "$") == 0)
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000014450 twin = lastwin;
14451 else if (STRCMP(arg, "#") == 0)
14452 {
14453 twin = prevwin;
14454 if (prevwin == NULL)
14455 nr = 0;
14456 }
14457 else
14458 {
14459 EMSG2(_(e_invexpr2), arg);
14460 nr = 0;
14461 }
14462 }
14463
14464 if (nr > 0)
14465 for (wp = firstwin; wp != twin; wp = wp->w_next)
14466 ++nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014467#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014468 rettv->vval.v_number = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014469}
14470
14471/*
14472 * "winrestcmd()" function
14473 */
14474/* ARGSUSED */
14475 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014476f_winrestcmd(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014477 typval_T *argvars;
14478 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014479{
14480#ifdef FEAT_WINDOWS
14481 win_T *wp;
14482 int winnr = 1;
14483 garray_T ga;
14484 char_u buf[50];
14485
14486 ga_init2(&ga, (int)sizeof(char), 70);
14487 for (wp = firstwin; wp != NULL; wp = wp->w_next)
14488 {
14489 sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height);
14490 ga_concat(&ga, buf);
14491# ifdef FEAT_VERTSPLIT
14492 sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width);
14493 ga_concat(&ga, buf);
14494# endif
14495 ++winnr;
14496 }
Bram Moolenaar269ec652004-07-29 08:43:53 +000014497 ga_append(&ga, NUL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014498
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014499 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014500#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014501 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014502#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014503 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014504}
14505
14506/*
14507 * "winwidth(nr)" function
14508 */
14509 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014510f_winwidth(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014511 typval_T *argvars;
14512 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014513{
14514 win_T *wp;
14515
14516 wp = find_win_by_nr(&argvars[0]);
14517 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014518 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014519 else
14520#ifdef FEAT_VERTSPLIT
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014521 rettv->vval.v_number = wp->w_width;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014522#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014523 rettv->vval.v_number = Columns;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014524#endif
14525}
14526
14527 static win_T *
14528find_win_by_nr(vp)
Bram Moolenaar33570922005-01-25 22:26:29 +000014529 typval_T *vp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014530{
14531#ifdef FEAT_WINDOWS
14532 win_T *wp;
14533#endif
14534 int nr;
14535
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014536 nr = get_tv_number_chk(vp, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014537
14538#ifdef FEAT_WINDOWS
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014539 if (nr < 0)
14540 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014541 if (nr == 0)
14542 return curwin;
14543
14544 for (wp = firstwin; wp != NULL; wp = wp->w_next)
14545 if (--nr <= 0)
14546 break;
14547 return wp;
14548#else
14549 if (nr == 0 || nr == 1)
14550 return curwin;
14551 return NULL;
14552#endif
14553}
14554
14555/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014556 * "writefile()" function
14557 */
14558 static void
14559f_writefile(argvars, rettv)
14560 typval_T *argvars;
14561 typval_T *rettv;
14562{
14563 int binary = FALSE;
14564 char_u *fname;
14565 FILE *fd;
14566 listitem_T *li;
14567 char_u *s;
14568 int ret = 0;
14569 int c;
14570
14571 if (argvars[0].v_type != VAR_LIST)
14572 {
14573 EMSG2(_(e_listarg), "writefile()");
14574 return;
14575 }
14576 if (argvars[0].vval.v_list == NULL)
14577 return;
14578
14579 if (argvars[2].v_type != VAR_UNKNOWN
14580 && STRCMP(get_tv_string(&argvars[2]), "b") == 0)
14581 binary = TRUE;
14582
14583 /* Always open the file in binary mode, library functions have a mind of
14584 * their own about CR-LF conversion. */
14585 fname = get_tv_string(&argvars[1]);
14586 if (*fname == NUL || (fd = mch_fopen((char *)fname, WRITEBIN)) == NULL)
14587 {
14588 EMSG2(_(e_notcreate), *fname == NUL ? (char_u *)_("<empty>") : fname);
14589 ret = -1;
14590 }
14591 else
14592 {
14593 for (li = argvars[0].vval.v_list->lv_first; li != NULL;
14594 li = li->li_next)
14595 {
14596 for (s = get_tv_string(&li->li_tv); *s != NUL; ++s)
14597 {
14598 if (*s == '\n')
14599 c = putc(NUL, fd);
14600 else
14601 c = putc(*s, fd);
14602 if (c == EOF)
14603 {
14604 ret = -1;
14605 break;
14606 }
14607 }
14608 if (!binary || li->li_next != NULL)
14609 if (putc('\n', fd) == EOF)
14610 {
14611 ret = -1;
14612 break;
14613 }
14614 if (ret < 0)
14615 {
14616 EMSG(_(e_write));
14617 break;
14618 }
14619 }
14620 fclose(fd);
14621 }
14622
14623 rettv->vval.v_number = ret;
14624}
14625
14626/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014627 * Translate a String variable into a position.
14628 */
14629 static pos_T *
14630var2fpos(varp, lnum)
Bram Moolenaar33570922005-01-25 22:26:29 +000014631 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014632 int lnum; /* TRUE when $ is last line */
14633{
14634 char_u *name;
14635 static pos_T pos;
14636 pos_T *pp;
14637
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014638 name = get_tv_string_chk(varp);
14639 if (name == NULL)
14640 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014641 if (name[0] == '.') /* cursor */
14642 return &curwin->w_cursor;
14643 if (name[0] == '\'') /* mark */
14644 {
14645 pp = getmark(name[1], FALSE);
14646 if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
14647 return NULL;
14648 return pp;
14649 }
14650 if (name[0] == '$') /* last column or line */
14651 {
14652 if (lnum)
14653 {
14654 pos.lnum = curbuf->b_ml.ml_line_count;
14655 pos.col = 0;
14656 }
14657 else
14658 {
14659 pos.lnum = curwin->w_cursor.lnum;
14660 pos.col = (colnr_T)STRLEN(ml_get_curline());
14661 }
14662 return &pos;
14663 }
14664 return NULL;
14665}
14666
14667/*
14668 * Get the length of an environment variable name.
14669 * Advance "arg" to the first character after the name.
14670 * Return 0 for error.
14671 */
14672 static int
14673get_env_len(arg)
14674 char_u **arg;
14675{
14676 char_u *p;
14677 int len;
14678
14679 for (p = *arg; vim_isIDc(*p); ++p)
14680 ;
14681 if (p == *arg) /* no name found */
14682 return 0;
14683
14684 len = (int)(p - *arg);
14685 *arg = p;
14686 return len;
14687}
14688
14689/*
14690 * Get the length of the name of a function or internal variable.
14691 * "arg" is advanced to the first non-white character after the name.
14692 * Return 0 if something is wrong.
14693 */
14694 static int
14695get_id_len(arg)
14696 char_u **arg;
14697{
14698 char_u *p;
14699 int len;
14700
14701 /* Find the end of the name. */
14702 for (p = *arg; eval_isnamec(*p); ++p)
14703 ;
14704 if (p == *arg) /* no name found */
14705 return 0;
14706
14707 len = (int)(p - *arg);
14708 *arg = skipwhite(p);
14709
14710 return len;
14711}
14712
14713/*
Bram Moolenaara7043832005-01-21 11:56:39 +000014714 * Get the length of the name of a variable or function.
14715 * Only the name is recognized, does not handle ".key" or "[idx]".
Bram Moolenaar071d4272004-06-13 20:20:40 +000014716 * "arg" is advanced to the first non-white character after the name.
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014717 * Return -1 if curly braces expansion failed.
14718 * Return 0 if something else is wrong.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014719 * If the name contains 'magic' {}'s, expand them and return the
14720 * expanded name in an allocated string via 'alias' - caller must free.
14721 */
14722 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014723get_name_len(arg, alias, evaluate, verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014724 char_u **arg;
14725 char_u **alias;
14726 int evaluate;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014727 int verbose;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014728{
14729 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014730 char_u *p;
14731 char_u *expr_start;
14732 char_u *expr_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014733
14734 *alias = NULL; /* default to no alias */
14735
14736 if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
14737 && (*arg)[2] == (int)KE_SNR)
14738 {
14739 /* hard coded <SNR>, already translated */
14740 *arg += 3;
14741 return get_id_len(arg) + 3;
14742 }
14743 len = eval_fname_script(*arg);
14744 if (len > 0)
14745 {
14746 /* literal "<SID>", "s:" or "<SNR>" */
14747 *arg += len;
14748 }
14749
Bram Moolenaar071d4272004-06-13 20:20:40 +000014750 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014751 * Find the end of the name; check for {} construction.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014752 */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000014753 p = find_name_end(*arg, &expr_start, &expr_end,
14754 len > 0 ? 0 : FNE_CHECK_START);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014755 if (expr_start != NULL)
14756 {
14757 char_u *temp_string;
14758
14759 if (!evaluate)
14760 {
14761 len += (int)(p - *arg);
14762 *arg = skipwhite(p);
14763 return len;
14764 }
14765
14766 /*
14767 * Include any <SID> etc in the expanded string:
14768 * Thus the -len here.
14769 */
14770 temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
14771 if (temp_string == NULL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014772 return -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014773 *alias = temp_string;
14774 *arg = skipwhite(p);
14775 return (int)STRLEN(temp_string);
14776 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014777
14778 len += get_id_len(arg);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014779 if (len == 0 && verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014780 EMSG2(_(e_invexpr2), *arg);
14781
14782 return len;
14783}
14784
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014785/*
14786 * Find the end of a variable or function name, taking care of magic braces.
14787 * If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the
14788 * start and end of the first magic braces item.
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000014789 * "flags" can have FNE_INCL_BR and FNE_CHECK_START.
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014790 * Return a pointer to just after the name. Equal to "arg" if there is no
14791 * valid name.
14792 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014793 static char_u *
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000014794find_name_end(arg, expr_start, expr_end, flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014795 char_u *arg;
14796 char_u **expr_start;
14797 char_u **expr_end;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000014798 int flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014799{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014800 int mb_nest = 0;
14801 int br_nest = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014802 char_u *p;
14803
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014804 if (expr_start != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014805 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014806 *expr_start = NULL;
14807 *expr_end = NULL;
14808 }
14809
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000014810 /* Quick check for valid starting character. */
14811 if ((flags & FNE_CHECK_START) && !eval_isnamec1(*arg) && *arg != '{')
14812 return arg;
14813
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014814 for (p = arg; *p != NUL
14815 && (eval_isnamec(*p)
Bram Moolenaare9a41262005-01-15 22:18:47 +000014816 || *p == '{'
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000014817 || ((flags & FNE_INCL_BR) && (*p == '[' || *p == '.'))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014818 || mb_nest != 0
14819 || br_nest != 0); ++p)
14820 {
14821 if (mb_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014822 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014823 if (*p == '[')
14824 ++br_nest;
14825 else if (*p == ']')
14826 --br_nest;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014827 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014828 if (br_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014829 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014830 if (*p == '{')
14831 {
14832 mb_nest++;
14833 if (expr_start != NULL && *expr_start == NULL)
14834 *expr_start = p;
14835 }
14836 else if (*p == '}')
14837 {
14838 mb_nest--;
14839 if (expr_start != NULL && mb_nest == 0 && *expr_end == NULL)
14840 *expr_end = p;
14841 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014842 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014843 }
14844
14845 return p;
14846}
14847
14848/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014849 * Expands out the 'magic' {}'s in a variable/function name.
14850 * Note that this can call itself recursively, to deal with
14851 * constructs like foo{bar}{baz}{bam}
14852 * The four pointer arguments point to "foo{expre}ss{ion}bar"
14853 * "in_start" ^
14854 * "expr_start" ^
14855 * "expr_end" ^
14856 * "in_end" ^
14857 *
14858 * Returns a new allocated string, which the caller must free.
14859 * Returns NULL for failure.
14860 */
14861 static char_u *
14862make_expanded_name(in_start, expr_start, expr_end, in_end)
14863 char_u *in_start;
14864 char_u *expr_start;
14865 char_u *expr_end;
14866 char_u *in_end;
14867{
14868 char_u c1;
14869 char_u *retval = NULL;
14870 char_u *temp_result;
14871 char_u *nextcmd = NULL;
14872
14873 if (expr_end == NULL || in_end == NULL)
14874 return NULL;
14875 *expr_start = NUL;
14876 *expr_end = NUL;
14877 c1 = *in_end;
14878 *in_end = NUL;
14879
14880 temp_result = eval_to_string(expr_start + 1, &nextcmd);
14881 if (temp_result != NULL && nextcmd == NULL)
14882 {
14883 retval = alloc((unsigned)(STRLEN(temp_result) + (expr_start - in_start)
14884 + (in_end - expr_end) + 1));
14885 if (retval != NULL)
14886 {
14887 STRCPY(retval, in_start);
14888 STRCAT(retval, temp_result);
14889 STRCAT(retval, expr_end + 1);
14890 }
14891 }
14892 vim_free(temp_result);
14893
14894 *in_end = c1; /* put char back for error messages */
14895 *expr_start = '{';
14896 *expr_end = '}';
14897
14898 if (retval != NULL)
14899 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000014900 temp_result = find_name_end(retval, &expr_start, &expr_end, 0);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014901 if (expr_start != NULL)
14902 {
14903 /* Further expansion! */
14904 temp_result = make_expanded_name(retval, expr_start,
14905 expr_end, temp_result);
14906 vim_free(retval);
14907 retval = temp_result;
14908 }
14909 }
14910
14911 return retval;
14912}
14913
14914/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014915 * Return TRUE if character "c" can be used in a variable or function name.
Bram Moolenaare9a41262005-01-15 22:18:47 +000014916 * Does not include '{' or '}' for magic braces.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014917 */
14918 static int
14919eval_isnamec(c)
14920 int c;
14921{
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000014922 return (ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR);
14923}
14924
14925/*
14926 * Return TRUE if character "c" can be used as the first character in a
14927 * variable or function name (excluding '{' and '}').
14928 */
14929 static int
14930eval_isnamec1(c)
14931 int c;
14932{
14933 return (ASCII_ISALPHA(c) || c == '_');
Bram Moolenaar071d4272004-06-13 20:20:40 +000014934}
14935
14936/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014937 * Set number v: variable to "val".
14938 */
14939 void
14940set_vim_var_nr(idx, val)
14941 int idx;
14942 long val;
14943{
Bram Moolenaare9a41262005-01-15 22:18:47 +000014944 vimvars[idx].vv_nr = val;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014945}
14946
14947/*
Bram Moolenaar19a09a12005-03-04 23:39:37 +000014948 * Get number v: variable value.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014949 */
14950 long
14951get_vim_var_nr(idx)
14952 int idx;
14953{
Bram Moolenaare9a41262005-01-15 22:18:47 +000014954 return vimvars[idx].vv_nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014955}
14956
Bram Moolenaar19a09a12005-03-04 23:39:37 +000014957#if defined(FEAT_AUTOCMD) || defined(PROTO)
14958/*
14959 * Get string v: variable value. Uses a static buffer, can only be used once.
14960 */
14961 char_u *
14962get_vim_var_str(idx)
14963 int idx;
14964{
14965 return get_tv_string(&vimvars[idx].vv_tv);
14966}
14967#endif
14968
Bram Moolenaar071d4272004-06-13 20:20:40 +000014969/*
14970 * Set v:count, v:count1 and v:prevcount.
14971 */
14972 void
14973set_vcount(count, count1)
14974 long count;
14975 long count1;
14976{
Bram Moolenaare9a41262005-01-15 22:18:47 +000014977 vimvars[VV_PREVCOUNT].vv_nr = vimvars[VV_COUNT].vv_nr;
14978 vimvars[VV_COUNT].vv_nr = count;
14979 vimvars[VV_COUNT1].vv_nr = count1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014980}
14981
14982/*
14983 * Set string v: variable to a copy of "val".
14984 */
14985 void
14986set_vim_var_string(idx, val, len)
14987 int idx;
14988 char_u *val;
14989 int len; /* length of "val" to use or -1 (whole string) */
14990{
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014991 /* Need to do this (at least) once, since we can't initialize a union.
14992 * Will always be invoked when "v:progname" is set. */
14993 vimvars[VV_VERSION].vv_nr = VIM_VERSION_100;
14994
Bram Moolenaare9a41262005-01-15 22:18:47 +000014995 vim_free(vimvars[idx].vv_str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014996 if (val == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000014997 vimvars[idx].vv_str = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014998 else if (len == -1)
Bram Moolenaare9a41262005-01-15 22:18:47 +000014999 vimvars[idx].vv_str = vim_strsave(val);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015000 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000015001 vimvars[idx].vv_str = vim_strnsave(val, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015002}
15003
15004/*
15005 * Set v:register if needed.
15006 */
15007 void
15008set_reg_var(c)
15009 int c;
15010{
15011 char_u regname;
15012
15013 if (c == 0 || c == ' ')
15014 regname = '"';
15015 else
15016 regname = c;
15017 /* Avoid free/alloc when the value is already right. */
Bram Moolenaare9a41262005-01-15 22:18:47 +000015018 if (vimvars[VV_REG].vv_str == NULL || vimvars[VV_REG].vv_str[0] != c)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015019 set_vim_var_string(VV_REG, &regname, 1);
15020}
15021
15022/*
15023 * Get or set v:exception. If "oldval" == NULL, return the current value.
15024 * Otherwise, restore the value to "oldval" and return NULL.
15025 * Must always be called in pairs to save and restore v:exception! Does not
15026 * take care of memory allocations.
15027 */
15028 char_u *
15029v_exception(oldval)
15030 char_u *oldval;
15031{
15032 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000015033 return vimvars[VV_EXCEPTION].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015034
Bram Moolenaare9a41262005-01-15 22:18:47 +000015035 vimvars[VV_EXCEPTION].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015036 return NULL;
15037}
15038
15039/*
15040 * Get or set v:throwpoint. If "oldval" == NULL, return the current value.
15041 * Otherwise, restore the value to "oldval" and return NULL.
15042 * Must always be called in pairs to save and restore v:throwpoint! Does not
15043 * take care of memory allocations.
15044 */
15045 char_u *
15046v_throwpoint(oldval)
15047 char_u *oldval;
15048{
15049 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000015050 return vimvars[VV_THROWPOINT].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015051
Bram Moolenaare9a41262005-01-15 22:18:47 +000015052 vimvars[VV_THROWPOINT].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015053 return NULL;
15054}
15055
15056#if defined(FEAT_AUTOCMD) || defined(PROTO)
15057/*
15058 * Set v:cmdarg.
15059 * If "eap" != NULL, use "eap" to generate the value and return the old value.
15060 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
15061 * Must always be called in pairs!
15062 */
15063 char_u *
15064set_cmdarg(eap, oldarg)
15065 exarg_T *eap;
15066 char_u *oldarg;
15067{
15068 char_u *oldval;
15069 char_u *newval;
15070 unsigned len;
15071
Bram Moolenaare9a41262005-01-15 22:18:47 +000015072 oldval = vimvars[VV_CMDARG].vv_str;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000015073 if (eap == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015074 {
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000015075 vim_free(oldval);
Bram Moolenaare9a41262005-01-15 22:18:47 +000015076 vimvars[VV_CMDARG].vv_str = oldarg;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000015077 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015078 }
15079
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000015080 if (eap->force_bin == FORCE_BIN)
15081 len = 6;
15082 else if (eap->force_bin == FORCE_NOBIN)
15083 len = 8;
15084 else
15085 len = 0;
15086 if (eap->force_ff != 0)
15087 len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6;
15088# ifdef FEAT_MBYTE
15089 if (eap->force_enc != 0)
15090 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
15091# endif
15092
15093 newval = alloc(len + 1);
15094 if (newval == NULL)
15095 return NULL;
15096
15097 if (eap->force_bin == FORCE_BIN)
15098 sprintf((char *)newval, " ++bin");
15099 else if (eap->force_bin == FORCE_NOBIN)
15100 sprintf((char *)newval, " ++nobin");
15101 else
15102 *newval = NUL;
15103 if (eap->force_ff != 0)
15104 sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
15105 eap->cmd + eap->force_ff);
15106# ifdef FEAT_MBYTE
15107 if (eap->force_enc != 0)
15108 sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
15109 eap->cmd + eap->force_enc);
15110# endif
Bram Moolenaare9a41262005-01-15 22:18:47 +000015111 vimvars[VV_CMDARG].vv_str = newval;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000015112 return oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015113}
15114#endif
15115
15116/*
15117 * Get the value of internal variable "name".
15118 * Return OK or FAIL.
15119 */
15120 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015121get_var_tv(name, len, rettv, verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015122 char_u *name;
15123 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +000015124 typval_T *rettv; /* NULL when only checking existence */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015125 int verbose; /* may give error message */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015126{
15127 int ret = OK;
Bram Moolenaar33570922005-01-25 22:26:29 +000015128 typval_T *tv = NULL;
15129 typval_T atv;
15130 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015131 int cc;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015132
15133 /* truncate the name, so that we can use strcmp() */
15134 cc = name[len];
15135 name[len] = NUL;
15136
15137 /*
15138 * Check for "b:changedtick".
15139 */
15140 if (STRCMP(name, "b:changedtick") == 0)
15141 {
Bram Moolenaare9a41262005-01-15 22:18:47 +000015142 atv.v_type = VAR_NUMBER;
15143 atv.vval.v_number = curbuf->b_changedtick;
15144 tv = &atv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015145 }
15146
15147 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +000015148 * Check for user-defined variables.
15149 */
15150 else
15151 {
Bram Moolenaara7043832005-01-21 11:56:39 +000015152 v = find_var(name, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015153 if (v != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000015154 tv = &v->di_tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015155 }
15156
Bram Moolenaare9a41262005-01-15 22:18:47 +000015157 if (tv == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015158 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015159 if (rettv != NULL && verbose)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015160 EMSG2(_(e_undefvar), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015161 ret = FAIL;
15162 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015163 else if (rettv != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000015164 copy_tv(tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015165
15166 name[len] = cc;
15167
15168 return ret;
15169}
15170
15171/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015172 * Handle expr[expr], expr[expr:expr] subscript and .name lookup.
15173 * Also handle function call with Funcref variable: func(expr)
15174 * Can all be combined: dict.func(expr)[idx]['func'](expr)
15175 */
15176 static int
15177handle_subscript(arg, rettv, evaluate, verbose)
15178 char_u **arg;
15179 typval_T *rettv;
15180 int evaluate; /* do more than finding the end */
15181 int verbose; /* give error messages */
15182{
15183 int ret = OK;
15184 dict_T *selfdict = NULL;
15185 char_u *s;
15186 int len;
Bram Moolenaard9fba312005-06-26 22:34:35 +000015187 typval_T functv;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015188
15189 while (ret == OK
15190 && (**arg == '['
15191 || (**arg == '.' && rettv->v_type == VAR_DICT)
15192 || (**arg == '(' && rettv->v_type == VAR_FUNC))
15193 && !vim_iswhite(*(*arg - 1)))
15194 {
15195 if (**arg == '(')
15196 {
Bram Moolenaard9fba312005-06-26 22:34:35 +000015197 /* need to copy the funcref so that we can clear rettv */
15198 functv = *rettv;
15199 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015200
15201 /* Invoke the function. Recursive! */
Bram Moolenaard9fba312005-06-26 22:34:35 +000015202 s = functv.vval.v_string;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015203 ret = get_func_tv(s, STRLEN(s), rettv, arg,
Bram Moolenaard9fba312005-06-26 22:34:35 +000015204 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
15205 &len, evaluate, selfdict);
15206
15207 /* Clear the funcref afterwards, so that deleting it while
15208 * evaluating the arguments is possible (see test55). */
15209 clear_tv(&functv);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015210
15211 /* Stop the expression evaluation when immediately aborting on
15212 * error, or when an interrupt occurred or an exception was thrown
15213 * but not caught. */
15214 if (aborting())
15215 {
15216 if (ret == OK)
15217 clear_tv(rettv);
15218 ret = FAIL;
15219 }
15220 dict_unref(selfdict);
15221 selfdict = NULL;
15222 }
15223 else /* **arg == '[' || **arg == '.' */
15224 {
15225 dict_unref(selfdict);
15226 if (rettv->v_type == VAR_DICT)
15227 {
15228 selfdict = rettv->vval.v_dict;
15229 if (selfdict != NULL)
15230 ++selfdict->dv_refcount;
15231 }
15232 else
15233 selfdict = NULL;
15234 if (eval_index(arg, rettv, evaluate, verbose) == FAIL)
15235 {
15236 clear_tv(rettv);
15237 ret = FAIL;
15238 }
15239 }
15240 }
15241 dict_unref(selfdict);
15242 return ret;
15243}
15244
15245/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015246 * Allocate memory for a variable type-value, and make it emtpy (0 or NULL
15247 * value).
15248 */
Bram Moolenaar33570922005-01-25 22:26:29 +000015249 static typval_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015250alloc_tv()
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015251{
Bram Moolenaar33570922005-01-25 22:26:29 +000015252 return (typval_T *)alloc_clear((unsigned)sizeof(typval_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015253}
15254
15255/*
15256 * Allocate memory for a variable type-value, and assign a string to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015257 * The string "s" must have been allocated, it is consumed.
15258 * Return NULL for out of memory, the variable otherwise.
15259 */
Bram Moolenaar33570922005-01-25 22:26:29 +000015260 static typval_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015261alloc_string_tv(s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015262 char_u *s;
15263{
Bram Moolenaar33570922005-01-25 22:26:29 +000015264 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015265
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015266 rettv = alloc_tv();
15267 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015268 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015269 rettv->v_type = VAR_STRING;
15270 rettv->vval.v_string = s;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015271 }
15272 else
15273 vim_free(s);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015274 return rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015275}
15276
15277/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015278 * Free the memory for a variable type-value.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015279 */
15280 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015281free_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000015282 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015283{
15284 if (varp != NULL)
15285 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015286 switch (varp->v_type)
15287 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015288 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015289 func_unref(varp->vval.v_string);
15290 /*FALLTHROUGH*/
15291 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015292 vim_free(varp->vval.v_string);
15293 break;
15294 case VAR_LIST:
15295 list_unref(varp->vval.v_list);
15296 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015297 case VAR_DICT:
15298 dict_unref(varp->vval.v_dict);
15299 break;
Bram Moolenaar758711c2005-02-02 23:11:38 +000015300 case VAR_NUMBER:
15301 case VAR_UNKNOWN:
15302 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015303 default:
Bram Moolenaar758711c2005-02-02 23:11:38 +000015304 EMSG2(_(e_intern2), "free_tv()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015305 break;
15306 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015307 vim_free(varp);
15308 }
15309}
15310
15311/*
15312 * Free the memory for a variable value and set the value to NULL or 0.
15313 */
15314 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015315clear_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000015316 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015317{
15318 if (varp != NULL)
15319 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015320 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015321 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015322 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015323 func_unref(varp->vval.v_string);
15324 /*FALLTHROUGH*/
15325 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015326 vim_free(varp->vval.v_string);
15327 varp->vval.v_string = NULL;
15328 break;
15329 case VAR_LIST:
15330 list_unref(varp->vval.v_list);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015331 varp->vval.v_list = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015332 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000015333 case VAR_DICT:
15334 dict_unref(varp->vval.v_dict);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015335 varp->vval.v_dict = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +000015336 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015337 case VAR_NUMBER:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015338 varp->vval.v_number = 0;
15339 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015340 case VAR_UNKNOWN:
15341 break;
15342 default:
15343 EMSG2(_(e_intern2), "clear_tv()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000015344 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015345 varp->v_lock = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015346 }
15347}
15348
15349/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015350 * Set the value of a variable to NULL without freeing items.
15351 */
15352 static void
15353init_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000015354 typval_T *varp;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015355{
15356 if (varp != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000015357 vim_memset(varp, 0, sizeof(typval_T));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015358}
15359
15360/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000015361 * Get the number value of a variable.
15362 * If it is a String variable, uses vim_str2nr().
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015363 * For incompatible types, return 0.
15364 * get_tv_number_chk() is similar to get_tv_number(), but informs the
15365 * caller of incompatible types: it sets *denote to TRUE if "denote"
15366 * is not NULL or returns -1 otherwise.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015367 */
15368 static long
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015369get_tv_number(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000015370 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015371{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015372 int error = FALSE;
15373
15374 return get_tv_number_chk(varp, &error); /* return 0L on error */
15375}
15376
15377 static long
15378get_tv_number_chk(varp, denote)
15379 typval_T *varp;
15380 int *denote;
15381{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015382 long n = 0L;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015383
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015384 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015385 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015386 case VAR_NUMBER:
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015387 return (long)(varp->vval.v_number);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015388 case VAR_FUNC:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015389 EMSG(_("E703: Using a Funcref as a number"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015390 break;
15391 case VAR_STRING:
15392 if (varp->vval.v_string != NULL)
15393 vim_str2nr(varp->vval.v_string, NULL, NULL,
15394 TRUE, TRUE, &n, NULL);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015395 return n;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015396 case VAR_LIST:
Bram Moolenaar758711c2005-02-02 23:11:38 +000015397 EMSG(_("E745: Using a List as a number"));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015398 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015399 case VAR_DICT:
15400 EMSG(_("E728: Using a Dictionary as a number"));
15401 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015402 default:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015403 EMSG2(_(e_intern2), "get_tv_number()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015404 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015405 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015406 if (denote == NULL) /* useful for values that must be unsigned */
15407 n = -1;
15408 else
15409 *denote = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015410 return n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015411}
15412
15413/*
15414 * Get the lnum from the first argument. Also accepts ".", "$", etc.
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015415 * Returns -1 on error.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015416 */
15417 static linenr_T
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015418get_tv_lnum(argvars)
Bram Moolenaar33570922005-01-25 22:26:29 +000015419 typval_T *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015420{
Bram Moolenaar33570922005-01-25 22:26:29 +000015421 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015422 linenr_T lnum;
15423
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015424 lnum = get_tv_number_chk(&argvars[0], NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015425 if (lnum == 0) /* no valid number, try using line() */
15426 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015427 rettv.v_type = VAR_NUMBER;
15428 f_line(argvars, &rettv);
15429 lnum = rettv.vval.v_number;
15430 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015431 }
15432 return lnum;
15433}
15434
15435/*
15436 * Get the string value of a variable.
15437 * If it is a Number variable, the number is converted into a string.
Bram Moolenaara7043832005-01-21 11:56:39 +000015438 * get_tv_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
15439 * get_tv_string_buf() uses a given buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015440 * If the String variable has never been set, return an empty string.
15441 * Never returns NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015442 * get_tv_string_chk() and get_tv_string_buf_chk() are similar, but return
15443 * NULL on error.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015444 */
15445 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015446get_tv_string(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000015447 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015448{
15449 static char_u mybuf[NUMBUFLEN];
15450
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015451 return get_tv_string_buf(varp, mybuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015452}
15453
15454 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015455get_tv_string_buf(varp, buf)
Bram Moolenaar33570922005-01-25 22:26:29 +000015456 typval_T *varp;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015457 char_u *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015458{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015459 char_u *res = get_tv_string_buf_chk(varp, buf);
15460
15461 return res != NULL ? res : (char_u *)"";
15462}
15463
15464 static char_u *
15465get_tv_string_chk(varp)
15466 typval_T *varp;
15467{
15468 static char_u mybuf[NUMBUFLEN];
15469
15470 return get_tv_string_buf_chk(varp, mybuf);
15471}
15472
15473 static char_u *
15474get_tv_string_buf_chk(varp, buf)
15475 typval_T *varp;
15476 char_u *buf;
15477{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015478 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015479 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015480 case VAR_NUMBER:
15481 sprintf((char *)buf, "%ld", (long)varp->vval.v_number);
15482 return buf;
15483 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015484 EMSG(_("E729: using Funcref as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015485 break;
15486 case VAR_LIST:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015487 EMSG(_("E730: using List as a String"));
Bram Moolenaar8c711452005-01-14 21:53:12 +000015488 break;
15489 case VAR_DICT:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015490 EMSG(_("E731: using Dictionary as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015491 break;
15492 case VAR_STRING:
15493 if (varp->vval.v_string != NULL)
15494 return varp->vval.v_string;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015495 return (char_u *)"";
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015496 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015497 EMSG2(_(e_intern2), "get_tv_string_buf()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015498 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015499 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015500 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015501}
15502
15503/*
15504 * Find variable "name" in the list of variables.
15505 * Return a pointer to it if found, NULL if not found.
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015506 * Careful: "a:0" variables don't have a name.
Bram Moolenaara7043832005-01-21 11:56:39 +000015507 * When "htp" is not NULL we are writing to the variable, set "htp" to the
Bram Moolenaar33570922005-01-25 22:26:29 +000015508 * hashtab_T used.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015509 */
Bram Moolenaar33570922005-01-25 22:26:29 +000015510 static dictitem_T *
Bram Moolenaara7043832005-01-21 11:56:39 +000015511find_var(name, htp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015512 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000015513 hashtab_T **htp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015514{
Bram Moolenaar071d4272004-06-13 20:20:40 +000015515 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000015516 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015517
Bram Moolenaara7043832005-01-21 11:56:39 +000015518 ht = find_var_ht(name, &varname);
15519 if (htp != NULL)
15520 *htp = ht;
15521 if (ht == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015522 return NULL;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015523 return find_var_in_ht(ht, varname, htp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015524}
15525
15526/*
Bram Moolenaar33570922005-01-25 22:26:29 +000015527 * Find variable "varname" in hashtab "ht".
Bram Moolenaara7043832005-01-21 11:56:39 +000015528 * Returns NULL if not found.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015529 */
Bram Moolenaar33570922005-01-25 22:26:29 +000015530 static dictitem_T *
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015531find_var_in_ht(ht, varname, writing)
Bram Moolenaar33570922005-01-25 22:26:29 +000015532 hashtab_T *ht;
Bram Moolenaara7043832005-01-21 11:56:39 +000015533 char_u *varname;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015534 int writing;
Bram Moolenaara7043832005-01-21 11:56:39 +000015535{
Bram Moolenaar33570922005-01-25 22:26:29 +000015536 hashitem_T *hi;
15537
15538 if (*varname == NUL)
15539 {
15540 /* Must be something like "s:", otherwise "ht" would be NULL. */
15541 switch (varname[-2])
15542 {
15543 case 's': return &SCRIPT_SV(current_SID).sv_var;
15544 case 'g': return &globvars_var;
15545 case 'v': return &vimvars_var;
15546 case 'b': return &curbuf->b_bufvar;
15547 case 'w': return &curwin->w_winvar;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000015548 case 'l': return current_funccal == NULL
15549 ? NULL : &current_funccal->l_vars_var;
15550 case 'a': return current_funccal == NULL
15551 ? NULL : &current_funccal->l_avars_var;
Bram Moolenaar33570922005-01-25 22:26:29 +000015552 }
15553 return NULL;
15554 }
Bram Moolenaara7043832005-01-21 11:56:39 +000015555
15556 hi = hash_find(ht, varname);
15557 if (HASHITEM_EMPTY(hi))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015558 {
15559 /* For global variables we may try auto-loading the script. If it
15560 * worked find the variable again. */
15561 if (ht == &globvarht && !writing
15562 && script_autoload(varname) && !aborting())
15563 hi = hash_find(ht, varname);
15564 if (HASHITEM_EMPTY(hi))
15565 return NULL;
15566 }
Bram Moolenaar33570922005-01-25 22:26:29 +000015567 return HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +000015568}
15569
15570/*
Bram Moolenaar33570922005-01-25 22:26:29 +000015571 * Find the hashtab used for a variable name.
Bram Moolenaara7043832005-01-21 11:56:39 +000015572 * Set "varname" to the start of name without ':'.
15573 */
Bram Moolenaar33570922005-01-25 22:26:29 +000015574 static hashtab_T *
Bram Moolenaara7043832005-01-21 11:56:39 +000015575find_var_ht(name, varname)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015576 char_u *name;
15577 char_u **varname;
15578{
Bram Moolenaar75c50c42005-06-04 22:06:24 +000015579 hashitem_T *hi;
15580
Bram Moolenaar071d4272004-06-13 20:20:40 +000015581 if (name[1] != ':')
15582 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000015583 /* The name must not start with a colon or #. */
15584 if (name[0] == ':' || name[0] == AUTOLOAD_CHAR)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015585 return NULL;
15586 *varname = name;
Bram Moolenaar532c7802005-01-27 14:44:31 +000015587
15588 /* "version" is "v:version" in all scopes */
Bram Moolenaar75c50c42005-06-04 22:06:24 +000015589 hi = hash_find(&compat_hashtab, name);
15590 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar532c7802005-01-27 14:44:31 +000015591 return &compat_hashtab;
15592
Bram Moolenaar071d4272004-06-13 20:20:40 +000015593 if (current_funccal == NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000015594 return &globvarht; /* global variable */
15595 return &current_funccal->l_vars.dv_hashtab; /* l: variable */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015596 }
15597 *varname = name + 2;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015598 if (*name == 'g') /* global variable */
15599 return &globvarht;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000015600 /* There must be no ':' or '#' in the rest of the name, unless g: is used
15601 */
15602 if (vim_strchr(name + 2, ':') != NULL
15603 || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015604 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015605 if (*name == 'b') /* buffer variable */
Bram Moolenaar33570922005-01-25 22:26:29 +000015606 return &curbuf->b_vars.dv_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015607 if (*name == 'w') /* window variable */
Bram Moolenaar33570922005-01-25 22:26:29 +000015608 return &curwin->w_vars.dv_hashtab;
Bram Moolenaar33570922005-01-25 22:26:29 +000015609 if (*name == 'v') /* v: variable */
15610 return &vimvarht;
15611 if (*name == 'a' && current_funccal != NULL) /* function argument */
15612 return &current_funccal->l_avars.dv_hashtab;
15613 if (*name == 'l' && current_funccal != NULL) /* local function variable */
15614 return &current_funccal->l_vars.dv_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015615 if (*name == 's' /* script variable */
15616 && current_SID > 0 && current_SID <= ga_scripts.ga_len)
15617 return &SCRIPT_VARS(current_SID);
15618 return NULL;
15619}
15620
15621/*
15622 * Get the string value of a (global/local) variable.
15623 * Returns NULL when it doesn't exist.
15624 */
15625 char_u *
15626get_var_value(name)
15627 char_u *name;
15628{
Bram Moolenaar33570922005-01-25 22:26:29 +000015629 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015630
Bram Moolenaara7043832005-01-21 11:56:39 +000015631 v = find_var(name, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015632 if (v == NULL)
15633 return NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +000015634 return get_tv_string(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015635}
15636
15637/*
Bram Moolenaar33570922005-01-25 22:26:29 +000015638 * Allocate a new hashtab for a sourced script. It will be used while
Bram Moolenaar071d4272004-06-13 20:20:40 +000015639 * sourcing this script and when executing functions defined in the script.
15640 */
15641 void
15642new_script_vars(id)
15643 scid_T id;
15644{
Bram Moolenaara7043832005-01-21 11:56:39 +000015645 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +000015646 hashtab_T *ht;
15647 scriptvar_T *sv;
Bram Moolenaara7043832005-01-21 11:56:39 +000015648
Bram Moolenaar071d4272004-06-13 20:20:40 +000015649 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
15650 {
Bram Moolenaara7043832005-01-21 11:56:39 +000015651 /* Re-allocating ga_data means that an ht_array pointing to
15652 * ht_smallarray becomes invalid. We can recognize this: ht_mask is
Bram Moolenaar33570922005-01-25 22:26:29 +000015653 * at its init value. Also reset "v_dict", it's always the same. */
Bram Moolenaara7043832005-01-21 11:56:39 +000015654 for (i = 1; i <= ga_scripts.ga_len; ++i)
15655 {
15656 ht = &SCRIPT_VARS(i);
15657 if (ht->ht_mask == HT_INIT_SIZE - 1)
15658 ht->ht_array = ht->ht_smallarray;
Bram Moolenaar33570922005-01-25 22:26:29 +000015659 sv = &SCRIPT_SV(i);
15660 sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict;
Bram Moolenaara7043832005-01-21 11:56:39 +000015661 }
15662
Bram Moolenaar071d4272004-06-13 20:20:40 +000015663 while (ga_scripts.ga_len < id)
15664 {
Bram Moolenaar33570922005-01-25 22:26:29 +000015665 sv = &SCRIPT_SV(ga_scripts.ga_len + 1);
15666 init_var_dict(&sv->sv_dict, &sv->sv_var);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015667 ++ga_scripts.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015668 }
15669 }
15670}
15671
15672/*
Bram Moolenaar33570922005-01-25 22:26:29 +000015673 * Initialize dictionary "dict" as a scope and set variable "dict_var" to
15674 * point to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015675 */
15676 void
Bram Moolenaar33570922005-01-25 22:26:29 +000015677init_var_dict(dict, dict_var)
15678 dict_T *dict;
15679 dictitem_T *dict_var;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015680{
Bram Moolenaar33570922005-01-25 22:26:29 +000015681 hash_init(&dict->dv_hashtab);
15682 dict->dv_refcount = 99999;
15683 dict_var->di_tv.vval.v_dict = dict;
15684 dict_var->di_tv.v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015685 dict_var->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000015686 dict_var->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
15687 dict_var->di_key[0] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015688}
15689
15690/*
15691 * Clean up a list of internal variables.
Bram Moolenaar33570922005-01-25 22:26:29 +000015692 * Frees all allocated variables and the value they contain.
15693 * Clears hashtab "ht", does not free it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015694 */
15695 void
Bram Moolenaara7043832005-01-21 11:56:39 +000015696vars_clear(ht)
Bram Moolenaar33570922005-01-25 22:26:29 +000015697 hashtab_T *ht;
15698{
15699 vars_clear_ext(ht, TRUE);
15700}
15701
15702/*
15703 * Like vars_clear(), but only free the value if "free_val" is TRUE.
15704 */
15705 static void
15706vars_clear_ext(ht, free_val)
15707 hashtab_T *ht;
15708 int free_val;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015709{
Bram Moolenaara7043832005-01-21 11:56:39 +000015710 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000015711 hashitem_T *hi;
15712 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015713
Bram Moolenaar33570922005-01-25 22:26:29 +000015714 hash_lock(ht);
Bram Moolenaara7043832005-01-21 11:56:39 +000015715 todo = ht->ht_used;
15716 for (hi = ht->ht_array; todo > 0; ++hi)
15717 {
15718 if (!HASHITEM_EMPTY(hi))
15719 {
15720 --todo;
15721
Bram Moolenaar33570922005-01-25 22:26:29 +000015722 /* Free the variable. Don't remove it from the hashtab,
Bram Moolenaara7043832005-01-21 11:56:39 +000015723 * ht_array might change then. hash_clear() takes care of it
15724 * later. */
Bram Moolenaar33570922005-01-25 22:26:29 +000015725 v = HI2DI(hi);
15726 if (free_val)
15727 clear_tv(&v->di_tv);
15728 if ((v->di_flags & DI_FLAGS_FIX) == 0)
15729 vim_free(v);
Bram Moolenaara7043832005-01-21 11:56:39 +000015730 }
15731 }
15732 hash_clear(ht);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000015733 ht->ht_used = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015734}
15735
Bram Moolenaara7043832005-01-21 11:56:39 +000015736/*
Bram Moolenaar33570922005-01-25 22:26:29 +000015737 * Delete a variable from hashtab "ht" at item "hi".
15738 * Clear the variable value and free the dictitem.
Bram Moolenaara7043832005-01-21 11:56:39 +000015739 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015740 static void
Bram Moolenaara7043832005-01-21 11:56:39 +000015741delete_var(ht, hi)
Bram Moolenaar33570922005-01-25 22:26:29 +000015742 hashtab_T *ht;
15743 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015744{
Bram Moolenaar33570922005-01-25 22:26:29 +000015745 dictitem_T *di = HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +000015746
15747 hash_remove(ht, hi);
Bram Moolenaar33570922005-01-25 22:26:29 +000015748 clear_tv(&di->di_tv);
15749 vim_free(di);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015750}
15751
15752/*
15753 * List the value of one internal variable.
15754 */
15755 static void
15756list_one_var(v, prefix)
Bram Moolenaar33570922005-01-25 22:26:29 +000015757 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015758 char_u *prefix;
15759{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015760 char_u *tofree;
15761 char_u *s;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015762 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015763
Bram Moolenaar33570922005-01-25 22:26:29 +000015764 s = echo_string(&v->di_tv, &tofree, numbuf);
15765 list_one_var_a(prefix, v->di_key, v->di_tv.v_type,
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015766 s == NULL ? (char_u *)"" : s);
15767 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015768}
15769
Bram Moolenaar071d4272004-06-13 20:20:40 +000015770 static void
15771list_one_var_a(prefix, name, type, string)
15772 char_u *prefix;
15773 char_u *name;
15774 int type;
15775 char_u *string;
15776{
15777 msg_attr(prefix, 0); /* don't use msg(), it overwrites "v:statusmsg" */
15778 if (name != NULL) /* "a:" vars don't have a name stored */
15779 msg_puts(name);
15780 msg_putchar(' ');
15781 msg_advance(22);
15782 if (type == VAR_NUMBER)
15783 msg_putchar('#');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015784 else if (type == VAR_FUNC)
15785 msg_putchar('*');
15786 else if (type == VAR_LIST)
15787 {
15788 msg_putchar('[');
15789 if (*string == '[')
15790 ++string;
15791 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000015792 else if (type == VAR_DICT)
15793 {
15794 msg_putchar('{');
15795 if (*string == '{')
15796 ++string;
15797 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015798 else
15799 msg_putchar(' ');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015800
Bram Moolenaar071d4272004-06-13 20:20:40 +000015801 msg_outtrans(string);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015802
15803 if (type == VAR_FUNC)
15804 msg_puts((char_u *)"()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000015805}
15806
15807/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015808 * Set variable "name" to value in "tv".
Bram Moolenaar071d4272004-06-13 20:20:40 +000015809 * If the variable already exists, the value is updated.
15810 * Otherwise the variable is created.
15811 */
15812 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015813set_var(name, tv, copy)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015814 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000015815 typval_T *tv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015816 int copy; /* make copy of value in "tv" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015817{
Bram Moolenaar33570922005-01-25 22:26:29 +000015818 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015819 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000015820 hashtab_T *ht;
Bram Moolenaar92124a32005-06-17 22:03:40 +000015821 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015822
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015823 if (tv->v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015824 {
15825 if (!(vim_strchr((char_u *)"wbs", name[0]) != NULL && name[1] == ':')
15826 && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
15827 ? name[2] : name[0]))
15828 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +000015829 EMSG2(_("E704: Funcref variable name must start with a capital: %s"), name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015830 return;
15831 }
15832 if (function_exists(name))
15833 {
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000015834 EMSG2(_("E705: Variable name conflicts with existing function: %s"),
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015835 name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015836 return;
15837 }
15838 }
15839
Bram Moolenaara7043832005-01-21 11:56:39 +000015840 ht = find_var_ht(name, &varname);
Bram Moolenaar33570922005-01-25 22:26:29 +000015841 if (ht == NULL || *varname == NUL)
Bram Moolenaara7043832005-01-21 11:56:39 +000015842 {
Bram Moolenaar92124a32005-06-17 22:03:40 +000015843 EMSG2(_(e_illvar), name);
Bram Moolenaara7043832005-01-21 11:56:39 +000015844 return;
15845 }
15846
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015847 v = find_var_in_ht(ht, varname, TRUE);
Bram Moolenaar33570922005-01-25 22:26:29 +000015848 if (v != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015849 {
Bram Moolenaar33570922005-01-25 22:26:29 +000015850 /* existing variable, need to clear the value */
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015851 if (var_check_ro(v->di_flags, name)
15852 || tv_check_lock(v->di_tv.v_lock, name))
Bram Moolenaar33570922005-01-25 22:26:29 +000015853 return;
15854 if (v->di_tv.v_type != tv->v_type
15855 && !((v->di_tv.v_type == VAR_STRING
15856 || v->di_tv.v_type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015857 && (tv->v_type == VAR_STRING
15858 || tv->v_type == VAR_NUMBER)))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015859 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +000015860 EMSG2(_("E706: Variable type mismatch for: %s"), name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015861 return;
15862 }
Bram Moolenaar33570922005-01-25 22:26:29 +000015863
15864 /*
Bram Moolenaar758711c2005-02-02 23:11:38 +000015865 * Handle setting internal v: variables separately: we don't change
15866 * the type.
Bram Moolenaar33570922005-01-25 22:26:29 +000015867 */
15868 if (ht == &vimvarht)
15869 {
15870 if (v->di_tv.v_type == VAR_STRING)
15871 {
15872 vim_free(v->di_tv.vval.v_string);
15873 if (copy || tv->v_type != VAR_STRING)
15874 v->di_tv.vval.v_string = vim_strsave(get_tv_string(tv));
15875 else
15876 {
15877 /* Take over the string to avoid an extra alloc/free. */
15878 v->di_tv.vval.v_string = tv->vval.v_string;
15879 tv->vval.v_string = NULL;
15880 }
15881 }
15882 else if (v->di_tv.v_type != VAR_NUMBER)
15883 EMSG2(_(e_intern2), "set_var()");
15884 else
15885 v->di_tv.vval.v_number = get_tv_number(tv);
15886 return;
15887 }
15888
15889 clear_tv(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015890 }
15891 else /* add a new variable */
15892 {
Bram Moolenaar92124a32005-06-17 22:03:40 +000015893 /* Make sure the variable name is valid. */
15894 for (p = varname; *p != NUL; ++p)
15895 if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p)))
15896 {
15897 EMSG2(_(e_illvar), varname);
15898 return;
15899 }
15900
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015901 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
15902 + STRLEN(varname)));
Bram Moolenaara7043832005-01-21 11:56:39 +000015903 if (v == NULL)
15904 return;
Bram Moolenaar33570922005-01-25 22:26:29 +000015905 STRCPY(v->di_key, varname);
Bram Moolenaar33570922005-01-25 22:26:29 +000015906 if (hash_add(ht, DI2HIKEY(v)) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015907 {
Bram Moolenaara7043832005-01-21 11:56:39 +000015908 vim_free(v);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015909 return;
15910 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015911 v->di_flags = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015912 }
Bram Moolenaara7043832005-01-21 11:56:39 +000015913
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015914 if (copy || tv->v_type == VAR_NUMBER)
Bram Moolenaar33570922005-01-25 22:26:29 +000015915 copy_tv(tv, &v->di_tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000015916 else
15917 {
Bram Moolenaar33570922005-01-25 22:26:29 +000015918 v->di_tv = *tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015919 v->di_tv.v_lock = 0;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015920 init_tv(tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000015921 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015922}
15923
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015924/*
Bram Moolenaar33570922005-01-25 22:26:29 +000015925 * Return TRUE if di_flags "flags" indicate read-only variable "name".
15926 * Also give an error message.
15927 */
15928 static int
15929var_check_ro(flags, name)
15930 int flags;
15931 char_u *name;
15932{
15933 if (flags & DI_FLAGS_RO)
15934 {
15935 EMSG2(_(e_readonlyvar), name);
15936 return TRUE;
15937 }
15938 if ((flags & DI_FLAGS_RO_SBX) && sandbox)
15939 {
15940 EMSG2(_(e_readonlysbx), name);
15941 return TRUE;
15942 }
15943 return FALSE;
15944}
15945
15946/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015947 * Return TRUE if typeval "tv" is set to be locked (immutable).
15948 * Also give an error message, using "name".
15949 */
15950 static int
15951tv_check_lock(lock, name)
15952 int lock;
15953 char_u *name;
15954{
15955 if (lock & VAR_LOCKED)
15956 {
15957 EMSG2(_("E741: Value is locked: %s"),
15958 name == NULL ? (char_u *)_("Unknown") : name);
15959 return TRUE;
15960 }
15961 if (lock & VAR_FIXED)
15962 {
15963 EMSG2(_("E742: Cannot change value of %s"),
15964 name == NULL ? (char_u *)_("Unknown") : name);
15965 return TRUE;
15966 }
15967 return FALSE;
15968}
15969
15970/*
Bram Moolenaar33570922005-01-25 22:26:29 +000015971 * Copy the values from typval_T "from" to typval_T "to".
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015972 * When needed allocates string or increases reference count.
Bram Moolenaare9a41262005-01-15 22:18:47 +000015973 * Does not make a copy of a list or dict but copies the reference!
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015974 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015975 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015976copy_tv(from, to)
Bram Moolenaar33570922005-01-25 22:26:29 +000015977 typval_T *from;
15978 typval_T *to;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015979{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015980 to->v_type = from->v_type;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015981 to->v_lock = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015982 switch (from->v_type)
15983 {
15984 case VAR_NUMBER:
15985 to->vval.v_number = from->vval.v_number;
15986 break;
15987 case VAR_STRING:
15988 case VAR_FUNC:
15989 if (from->vval.v_string == NULL)
15990 to->vval.v_string = NULL;
15991 else
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015992 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015993 to->vval.v_string = vim_strsave(from->vval.v_string);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015994 if (from->v_type == VAR_FUNC)
15995 func_ref(to->vval.v_string);
15996 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015997 break;
15998 case VAR_LIST:
15999 if (from->vval.v_list == NULL)
16000 to->vval.v_list = NULL;
16001 else
16002 {
16003 to->vval.v_list = from->vval.v_list;
16004 ++to->vval.v_list->lv_refcount;
16005 }
16006 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000016007 case VAR_DICT:
16008 if (from->vval.v_dict == NULL)
16009 to->vval.v_dict = NULL;
16010 else
16011 {
16012 to->vval.v_dict = from->vval.v_dict;
16013 ++to->vval.v_dict->dv_refcount;
16014 }
16015 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016016 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016017 EMSG2(_(e_intern2), "copy_tv()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016018 break;
16019 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016020}
16021
16022/*
Bram Moolenaare9a41262005-01-15 22:18:47 +000016023 * Make a copy of an item.
16024 * Lists and Dictionaries are also copied. A deep copy if "deep" is set.
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016025 * For deepcopy() "copyID" is zero for a full copy or the ID for when a
16026 * reference to an already copied list/dict can be used.
16027 * Returns FAIL or OK.
Bram Moolenaare9a41262005-01-15 22:18:47 +000016028 */
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016029 static int
16030item_copy(from, to, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +000016031 typval_T *from;
16032 typval_T *to;
Bram Moolenaare9a41262005-01-15 22:18:47 +000016033 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016034 int copyID;
Bram Moolenaare9a41262005-01-15 22:18:47 +000016035{
16036 static int recurse = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016037 int ret = OK;
Bram Moolenaare9a41262005-01-15 22:18:47 +000016038
Bram Moolenaar33570922005-01-25 22:26:29 +000016039 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +000016040 {
16041 EMSG(_("E698: variable nested too deep for making a copy"));
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016042 return FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000016043 }
16044 ++recurse;
16045
16046 switch (from->v_type)
16047 {
16048 case VAR_NUMBER:
16049 case VAR_STRING:
16050 case VAR_FUNC:
16051 copy_tv(from, to);
16052 break;
16053 case VAR_LIST:
16054 to->v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016055 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016056 if (from->vval.v_list == NULL)
16057 to->vval.v_list = NULL;
16058 else if (copyID != 0 && from->vval.v_list->lv_copyID == copyID)
16059 {
16060 /* use the copy made earlier */
16061 to->vval.v_list = from->vval.v_list->lv_copylist;
16062 ++to->vval.v_list->lv_refcount;
16063 }
16064 else
16065 to->vval.v_list = list_copy(from->vval.v_list, deep, copyID);
16066 if (to->vval.v_list == NULL)
16067 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000016068 break;
16069 case VAR_DICT:
16070 to->v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016071 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016072 if (from->vval.v_dict == NULL)
16073 to->vval.v_dict = NULL;
16074 else if (copyID != 0 && from->vval.v_dict->dv_copyID == copyID)
16075 {
16076 /* use the copy made earlier */
16077 to->vval.v_dict = from->vval.v_dict->dv_copydict;
16078 ++to->vval.v_dict->dv_refcount;
16079 }
16080 else
16081 to->vval.v_dict = dict_copy(from->vval.v_dict, deep, copyID);
16082 if (to->vval.v_dict == NULL)
16083 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000016084 break;
16085 default:
16086 EMSG2(_(e_intern2), "item_copy()");
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016087 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000016088 }
16089 --recurse;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016090 return ret;
Bram Moolenaare9a41262005-01-15 22:18:47 +000016091}
16092
16093/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000016094 * ":echo expr1 ..." print each argument separated with a space, add a
16095 * newline at the end.
16096 * ":echon expr1 ..." print each argument plain.
16097 */
16098 void
16099ex_echo(eap)
16100 exarg_T *eap;
16101{
16102 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000016103 typval_T rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016104 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016105 char_u *p;
16106 int needclr = TRUE;
16107 int atstart = TRUE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016108 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000016109
16110 if (eap->skip)
16111 ++emsg_skip;
16112 while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int)
16113 {
16114 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016115 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016116 {
16117 /*
16118 * Report the invalid expression unless the expression evaluation
16119 * has been cancelled due to an aborting error, an interrupt, or an
16120 * exception.
16121 */
16122 if (!aborting())
16123 EMSG2(_(e_invexpr2), p);
16124 break;
16125 }
16126 if (!eap->skip)
16127 {
16128 if (atstart)
16129 {
16130 atstart = FALSE;
16131 /* Call msg_start() after eval1(), evaluating the expression
16132 * may cause a message to appear. */
16133 if (eap->cmdidx == CMD_echo)
16134 msg_start();
16135 }
16136 else if (eap->cmdidx == CMD_echo)
16137 msg_puts_attr((char_u *)" ", echo_attr);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016138 p = echo_string(&rettv, &tofree, numbuf);
16139 if (p != NULL)
16140 for ( ; *p != NUL && !got_int; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016141 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016142 if (*p == '\n' || *p == '\r' || *p == TAB)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016143 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016144 if (*p != TAB && needclr)
16145 {
16146 /* remove any text still there from the command */
16147 msg_clr_eos();
16148 needclr = FALSE;
16149 }
16150 msg_putchar_attr(*p, echo_attr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016151 }
16152 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016153 {
16154#ifdef FEAT_MBYTE
16155 if (has_mbyte)
16156 {
16157 int i = (*mb_ptr2len_check)(p);
16158
16159 (void)msg_outtrans_len_attr(p, i, echo_attr);
16160 p += i - 1;
16161 }
16162 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000016163#endif
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016164 (void)msg_outtrans_len_attr(p, 1, echo_attr);
16165 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016166 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016167 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016168 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016169 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016170 arg = skipwhite(arg);
16171 }
16172 eap->nextcmd = check_nextcmd(arg);
16173
16174 if (eap->skip)
16175 --emsg_skip;
16176 else
16177 {
16178 /* remove text that may still be there from the command */
16179 if (needclr)
16180 msg_clr_eos();
16181 if (eap->cmdidx == CMD_echo)
16182 msg_end();
16183 }
16184}
16185
16186/*
16187 * ":echohl {name}".
16188 */
16189 void
16190ex_echohl(eap)
16191 exarg_T *eap;
16192{
16193 int id;
16194
16195 id = syn_name2id(eap->arg);
16196 if (id == 0)
16197 echo_attr = 0;
16198 else
16199 echo_attr = syn_id2attr(id);
16200}
16201
16202/*
16203 * ":execute expr1 ..." execute the result of an expression.
16204 * ":echomsg expr1 ..." Print a message
16205 * ":echoerr expr1 ..." Print an error
16206 * Each gets spaces around each argument and a newline at the end for
16207 * echo commands
16208 */
16209 void
16210ex_execute(eap)
16211 exarg_T *eap;
16212{
16213 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000016214 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016215 int ret = OK;
16216 char_u *p;
16217 garray_T ga;
16218 int len;
16219 int save_did_emsg;
16220
16221 ga_init2(&ga, 1, 80);
16222
16223 if (eap->skip)
16224 ++emsg_skip;
16225 while (*arg != NUL && *arg != '|' && *arg != '\n')
16226 {
16227 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016228 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016229 {
16230 /*
16231 * Report the invalid expression unless the expression evaluation
16232 * has been cancelled due to an aborting error, an interrupt, or an
16233 * exception.
16234 */
16235 if (!aborting())
16236 EMSG2(_(e_invexpr2), p);
16237 ret = FAIL;
16238 break;
16239 }
16240
16241 if (!eap->skip)
16242 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016243 p = get_tv_string(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016244 len = (int)STRLEN(p);
16245 if (ga_grow(&ga, len + 2) == FAIL)
16246 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016247 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016248 ret = FAIL;
16249 break;
16250 }
16251 if (ga.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016252 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
Bram Moolenaar071d4272004-06-13 20:20:40 +000016253 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016254 ga.ga_len += len;
16255 }
16256
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016257 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016258 arg = skipwhite(arg);
16259 }
16260
16261 if (ret != FAIL && ga.ga_data != NULL)
16262 {
16263 if (eap->cmdidx == CMD_echomsg)
16264 MSG_ATTR(ga.ga_data, echo_attr);
16265 else if (eap->cmdidx == CMD_echoerr)
16266 {
16267 /* We don't want to abort following commands, restore did_emsg. */
16268 save_did_emsg = did_emsg;
16269 EMSG((char_u *)ga.ga_data);
16270 if (!force_abort)
16271 did_emsg = save_did_emsg;
16272 }
16273 else if (eap->cmdidx == CMD_execute)
16274 do_cmdline((char_u *)ga.ga_data,
16275 eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE);
16276 }
16277
16278 ga_clear(&ga);
16279
16280 if (eap->skip)
16281 --emsg_skip;
16282
16283 eap->nextcmd = check_nextcmd(arg);
16284}
16285
16286/*
16287 * Skip over the name of an option: "&option", "&g:option" or "&l:option".
16288 * "arg" points to the "&" or '+' when called, to "option" when returning.
16289 * Returns NULL when no option name found. Otherwise pointer to the char
16290 * after the option name.
16291 */
16292 static char_u *
16293find_option_end(arg, opt_flags)
16294 char_u **arg;
16295 int *opt_flags;
16296{
16297 char_u *p = *arg;
16298
16299 ++p;
16300 if (*p == 'g' && p[1] == ':')
16301 {
16302 *opt_flags = OPT_GLOBAL;
16303 p += 2;
16304 }
16305 else if (*p == 'l' && p[1] == ':')
16306 {
16307 *opt_flags = OPT_LOCAL;
16308 p += 2;
16309 }
16310 else
16311 *opt_flags = 0;
16312
16313 if (!ASCII_ISALPHA(*p))
16314 return NULL;
16315 *arg = p;
16316
16317 if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL)
16318 p += 4; /* termcap option */
16319 else
16320 while (ASCII_ISALPHA(*p))
16321 ++p;
16322 return p;
16323}
16324
16325/*
16326 * ":function"
16327 */
16328 void
16329ex_function(eap)
16330 exarg_T *eap;
16331{
16332 char_u *theline;
16333 int j;
16334 int c;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016335 int saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016336 char_u *name = NULL;
16337 char_u *p;
16338 char_u *arg;
16339 garray_T newargs;
16340 garray_T newlines;
16341 int varargs = FALSE;
16342 int mustend = FALSE;
16343 int flags = 0;
16344 ufunc_T *fp;
16345 int indent;
16346 int nesting;
16347 char_u *skip_until = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +000016348 dictitem_T *v;
16349 funcdict_T fudi;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016350 static int func_nr = 0; /* number for nameless function */
16351 int paren;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016352 hashtab_T *ht;
16353 int todo;
16354 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016355
16356 /*
16357 * ":function" without argument: list functions.
16358 */
16359 if (ends_excmd(*eap->arg))
16360 {
16361 if (!eap->skip)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016362 {
Bram Moolenaar038eb0e2005-02-27 22:43:26 +000016363 todo = func_hashtab.ht_used;
16364 for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016365 {
16366 if (!HASHITEM_EMPTY(hi))
16367 {
16368 --todo;
16369 fp = HI2UF(hi);
16370 if (!isdigit(*fp->uf_name))
16371 list_func_head(fp, FALSE);
16372 }
16373 }
16374 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016375 eap->nextcmd = check_nextcmd(eap->arg);
16376 return;
16377 }
16378
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016379 /*
16380 * Get the function name. There are these situations:
16381 * func normal function name
16382 * "name" == func, "fudi.fd_dict" == NULL
16383 * dict.func new dictionary entry
16384 * "name" == NULL, "fudi.fd_dict" set,
16385 * "fudi.fd_di" == NULL, "fudi.fd_newkey" == func
16386 * dict.func existing dict entry with a Funcref
Bram Moolenaard857f0e2005-06-21 22:37:39 +000016387 * "name" == func, "fudi.fd_dict" set,
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016388 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL
16389 * dict.func existing dict entry that's not a Funcref
16390 * "name" == NULL, "fudi.fd_dict" set,
16391 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL
16392 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016393 p = eap->arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016394 name = trans_function_name(&p, eap->skip, 0, &fudi);
16395 paren = (vim_strchr(p, '(') != NULL);
16396 if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016397 {
16398 /*
16399 * Return on an invalid expression in braces, unless the expression
16400 * evaluation has been cancelled due to an aborting error, an
16401 * interrupt, or an exception.
16402 */
16403 if (!aborting())
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016404 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000016405 if (!eap->skip && fudi.fd_newkey != NULL)
16406 EMSG2(_(e_dictkey), fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016407 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016408 return;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016409 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016410 else
16411 eap->skip = TRUE;
16412 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016413 /* An error in a function call during evaluation of an expression in magic
16414 * braces should not cause the function not to be defined. */
16415 saved_did_emsg = did_emsg;
16416 did_emsg = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016417
16418 /*
16419 * ":function func" with only function name: list function.
16420 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016421 if (!paren)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016422 {
16423 if (!ends_excmd(*skipwhite(p)))
16424 {
16425 EMSG(_(e_trailing));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016426 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016427 }
16428 eap->nextcmd = check_nextcmd(p);
16429 if (eap->nextcmd != NULL)
16430 *p = NUL;
16431 if (!eap->skip && !got_int)
16432 {
16433 fp = find_func(name);
16434 if (fp != NULL)
16435 {
16436 list_func_head(fp, TRUE);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016437 for (j = 0; j < fp->uf_lines.ga_len && !got_int; ++j)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016438 {
16439 msg_putchar('\n');
16440 msg_outnum((long)(j + 1));
16441 if (j < 9)
16442 msg_putchar(' ');
16443 if (j < 99)
16444 msg_putchar(' ');
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016445 msg_prt_line(FUNCLINE(fp, j), FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016446 out_flush(); /* show a line at a time */
16447 ui_breakcheck();
16448 }
16449 if (!got_int)
16450 {
16451 msg_putchar('\n');
16452 msg_puts((char_u *)" endfunction");
16453 }
16454 }
16455 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016456 emsg_funcname("E123: Undefined function: %s", name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016457 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016458 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016459 }
16460
16461 /*
16462 * ":function name(arg1, arg2)" Define function.
16463 */
16464 p = skipwhite(p);
16465 if (*p != '(')
16466 {
16467 if (!eap->skip)
16468 {
16469 EMSG2(_("E124: Missing '(': %s"), eap->arg);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016470 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016471 }
16472 /* attempt to continue by skipping some text */
16473 if (vim_strchr(p, '(') != NULL)
16474 p = vim_strchr(p, '(');
16475 }
16476 p = skipwhite(p + 1);
16477
16478 ga_init2(&newargs, (int)sizeof(char_u *), 3);
16479 ga_init2(&newlines, (int)sizeof(char_u *), 3);
16480
Bram Moolenaard857f0e2005-06-21 22:37:39 +000016481 if (!eap->skip)
16482 {
16483 /* Check the name of the function. */
16484 if (name != NULL)
16485 arg = name;
16486 else
16487 arg = fudi.fd_newkey;
16488 if (arg != NULL)
16489 {
16490 if (*arg == K_SPECIAL)
16491 j = 3;
16492 else
16493 j = 0;
16494 while (arg[j] != NUL && (j == 0 ? eval_isnamec1(arg[j])
16495 : eval_isnamec(arg[j])))
16496 ++j;
16497 if (arg[j] != NUL)
16498 emsg_funcname(_(e_invarg2), arg);
16499 }
16500 }
16501
Bram Moolenaar071d4272004-06-13 20:20:40 +000016502 /*
16503 * Isolate the arguments: "arg1, arg2, ...)"
16504 */
16505 while (*p != ')')
16506 {
16507 if (p[0] == '.' && p[1] == '.' && p[2] == '.')
16508 {
16509 varargs = TRUE;
16510 p += 3;
16511 mustend = TRUE;
16512 }
16513 else
16514 {
16515 arg = p;
16516 while (ASCII_ISALNUM(*p) || *p == '_')
16517 ++p;
16518 if (arg == p || isdigit(*arg)
16519 || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0)
16520 || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0))
16521 {
16522 if (!eap->skip)
16523 EMSG2(_("E125: Illegal argument: %s"), arg);
16524 break;
16525 }
16526 if (ga_grow(&newargs, 1) == FAIL)
16527 goto erret;
16528 c = *p;
16529 *p = NUL;
16530 arg = vim_strsave(arg);
16531 if (arg == NULL)
16532 goto erret;
16533 ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg;
16534 *p = c;
16535 newargs.ga_len++;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016536 if (*p == ',')
16537 ++p;
16538 else
16539 mustend = TRUE;
16540 }
16541 p = skipwhite(p);
16542 if (mustend && *p != ')')
16543 {
16544 if (!eap->skip)
16545 EMSG2(_(e_invarg2), eap->arg);
16546 break;
16547 }
16548 }
16549 ++p; /* skip the ')' */
16550
Bram Moolenaare9a41262005-01-15 22:18:47 +000016551 /* find extra arguments "range", "dict" and "abort" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016552 for (;;)
16553 {
16554 p = skipwhite(p);
16555 if (STRNCMP(p, "range", 5) == 0)
16556 {
16557 flags |= FC_RANGE;
16558 p += 5;
16559 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000016560 else if (STRNCMP(p, "dict", 4) == 0)
16561 {
16562 flags |= FC_DICT;
16563 p += 4;
16564 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016565 else if (STRNCMP(p, "abort", 5) == 0)
16566 {
16567 flags |= FC_ABORT;
16568 p += 5;
16569 }
16570 else
16571 break;
16572 }
16573
16574 if (*p != NUL && *p != '"' && *p != '\n' && !eap->skip && !did_emsg)
16575 EMSG(_(e_trailing));
16576
16577 /*
16578 * Read the body of the function, until ":endfunction" is found.
16579 */
16580 if (KeyTyped)
16581 {
16582 /* Check if the function already exists, don't let the user type the
16583 * whole function before telling him it doesn't work! For a script we
16584 * need to skip the body to be able to find what follows. */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016585 if (!eap->skip && !eap->forceit)
16586 {
16587 if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL)
16588 EMSG(_(e_funcdict));
16589 else if (name != NULL && find_func(name) != NULL)
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016590 emsg_funcname(e_funcexts, name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016591 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016592
Bram Moolenaard857f0e2005-06-21 22:37:39 +000016593 if (!eap->skip && did_emsg)
16594 goto erret;
16595
Bram Moolenaar071d4272004-06-13 20:20:40 +000016596 msg_putchar('\n'); /* don't overwrite the function name */
16597 cmdline_row = msg_row;
16598 }
16599
16600 indent = 2;
16601 nesting = 0;
16602 for (;;)
16603 {
16604 msg_scroll = TRUE;
16605 need_wait_return = FALSE;
16606 if (eap->getline == NULL)
16607 theline = getcmdline(':', 0L, indent);
16608 else
16609 theline = eap->getline(':', eap->cookie, indent);
16610 if (KeyTyped)
16611 lines_left = Rows - 1;
16612 if (theline == NULL)
16613 {
16614 EMSG(_("E126: Missing :endfunction"));
16615 goto erret;
16616 }
16617
16618 if (skip_until != NULL)
16619 {
16620 /* between ":append" and "." and between ":python <<EOF" and "EOF"
16621 * don't check for ":endfunc". */
16622 if (STRCMP(theline, skip_until) == 0)
16623 {
16624 vim_free(skip_until);
16625 skip_until = NULL;
16626 }
16627 }
16628 else
16629 {
16630 /* skip ':' and blanks*/
16631 for (p = theline; vim_iswhite(*p) || *p == ':'; ++p)
16632 ;
16633
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000016634 /* Check for "endfunction". */
16635 if (checkforcmd(&p, "endfunction", 4) && nesting-- == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016636 {
16637 vim_free(theline);
16638 break;
16639 }
16640
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000016641 /* Increase indent inside "if", "while", "for" and "try", decrease
Bram Moolenaar071d4272004-06-13 20:20:40 +000016642 * at "end". */
16643 if (indent > 2 && STRNCMP(p, "end", 3) == 0)
16644 indent -= 2;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000016645 else if (STRNCMP(p, "if", 2) == 0
16646 || STRNCMP(p, "wh", 2) == 0
16647 || STRNCMP(p, "for", 3) == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +000016648 || STRNCMP(p, "try", 3) == 0)
16649 indent += 2;
16650
16651 /* Check for defining a function inside this function. */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000016652 if (checkforcmd(&p, "function", 2))
Bram Moolenaar071d4272004-06-13 20:20:40 +000016653 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000016654 if (*p == '!')
16655 p = skipwhite(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016656 p += eval_fname_script(p);
16657 if (ASCII_ISALPHA(*p))
16658 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016659 vim_free(trans_function_name(&p, TRUE, 0, NULL));
Bram Moolenaar071d4272004-06-13 20:20:40 +000016660 if (*skipwhite(p) == '(')
16661 {
16662 ++nesting;
16663 indent += 2;
16664 }
16665 }
16666 }
16667
16668 /* Check for ":append" or ":insert". */
16669 p = skip_range(p, NULL);
16670 if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
16671 || (p[0] == 'i'
16672 && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
16673 && (!ASCII_ISALPHA(p[2]) || (p[2] == 's'))))))
16674 skip_until = vim_strsave((char_u *)".");
16675
16676 /* Check for ":python <<EOF", ":tcl <<EOF", etc. */
16677 arg = skipwhite(skiptowhite(p));
16678 if (arg[0] == '<' && arg[1] =='<'
16679 && ((p[0] == 'p' && p[1] == 'y'
16680 && (!ASCII_ISALPHA(p[2]) || p[2] == 't'))
16681 || (p[0] == 'p' && p[1] == 'e'
16682 && (!ASCII_ISALPHA(p[2]) || p[2] == 'r'))
16683 || (p[0] == 't' && p[1] == 'c'
16684 && (!ASCII_ISALPHA(p[2]) || p[2] == 'l'))
16685 || (p[0] == 'r' && p[1] == 'u' && p[2] == 'b'
16686 && (!ASCII_ISALPHA(p[3]) || p[3] == 'y'))
Bram Moolenaar325b7a22004-07-05 15:58:32 +000016687 || (p[0] == 'm' && p[1] == 'z'
16688 && (!ASCII_ISALPHA(p[2]) || p[2] == 's'))
Bram Moolenaar071d4272004-06-13 20:20:40 +000016689 ))
16690 {
16691 /* ":python <<" continues until a dot, like ":append" */
16692 p = skipwhite(arg + 2);
16693 if (*p == NUL)
16694 skip_until = vim_strsave((char_u *)".");
16695 else
16696 skip_until = vim_strsave(p);
16697 }
16698 }
16699
16700 /* Add the line to the function. */
16701 if (ga_grow(&newlines, 1) == FAIL)
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000016702 {
16703 vim_free(theline);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016704 goto erret;
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000016705 }
16706
16707 /* Copy the line to newly allocated memory. get_one_sourceline()
16708 * allocates 250 bytes per line, this saves 80% on average. The cost
16709 * is an extra alloc/free. */
16710 p = vim_strsave(theline);
16711 if (p != NULL)
16712 {
16713 vim_free(theline);
16714 theline = p;
16715 }
16716
Bram Moolenaar071d4272004-06-13 20:20:40 +000016717 ((char_u **)(newlines.ga_data))[newlines.ga_len] = theline;
16718 newlines.ga_len++;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016719 }
16720
16721 /* Don't define the function when skipping commands or when an error was
16722 * detected. */
16723 if (eap->skip || did_emsg)
16724 goto erret;
16725
16726 /*
16727 * If there are no errors, add the function
16728 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016729 if (fudi.fd_dict == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016730 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016731 v = find_var(name, &ht);
Bram Moolenaar33570922005-01-25 22:26:29 +000016732 if (v != NULL && v->di_tv.v_type == VAR_FUNC)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016733 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016734 emsg_funcname("E707: Function name conflicts with variable: %s",
16735 name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016736 goto erret;
16737 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016738
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016739 fp = find_func(name);
16740 if (fp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016741 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016742 if (!eap->forceit)
16743 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016744 emsg_funcname(e_funcexts, name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016745 goto erret;
16746 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016747 if (fp->uf_calls > 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016748 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016749 emsg_funcname("E127: Cannot redefine function %s: It is in use",
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016750 name);
16751 goto erret;
16752 }
16753 /* redefine existing function */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016754 ga_clear_strings(&(fp->uf_args));
16755 ga_clear_strings(&(fp->uf_lines));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016756 vim_free(name);
16757 name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016758 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016759 }
16760 else
16761 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016762 char numbuf[20];
16763
16764 fp = NULL;
16765 if (fudi.fd_newkey == NULL && !eap->forceit)
16766 {
16767 EMSG(_(e_funcdict));
16768 goto erret;
16769 }
Bram Moolenaar758711c2005-02-02 23:11:38 +000016770 if (fudi.fd_di == NULL)
16771 {
16772 /* Can't add a function to a locked dictionary */
16773 if (tv_check_lock(fudi.fd_dict->dv_lock, eap->arg))
16774 goto erret;
16775 }
16776 /* Can't change an existing function if it is locked */
16777 else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg))
16778 goto erret;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016779
16780 /* Give the function a sequential number. Can only be used with a
16781 * Funcref! */
16782 vim_free(name);
16783 sprintf(numbuf, "%d", ++func_nr);
16784 name = vim_strsave((char_u *)numbuf);
16785 if (name == NULL)
16786 goto erret;
16787 }
16788
16789 if (fp == NULL)
16790 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000016791 if (fudi.fd_dict == NULL && vim_strchr(name, AUTOLOAD_CHAR) != NULL)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016792 {
16793 int slen, plen;
16794 char_u *scriptname;
16795
16796 /* Check that the autoload name matches the script name. */
16797 j = FAIL;
16798 if (sourcing_name != NULL)
16799 {
16800 scriptname = autoload_name(name);
16801 if (scriptname != NULL)
16802 {
16803 p = vim_strchr(scriptname, '/');
16804 plen = STRLEN(p);
16805 slen = STRLEN(sourcing_name);
16806 if (slen > plen && fnamecmp(p,
16807 sourcing_name + slen - plen) == 0)
16808 j = OK;
16809 vim_free(scriptname);
16810 }
16811 }
16812 if (j == FAIL)
16813 {
16814 EMSG2(_("E746: Function name does not match script file name: %s"), name);
16815 goto erret;
16816 }
16817 }
16818
16819 fp = (ufunc_T *)alloc((unsigned)(sizeof(ufunc_T) + STRLEN(name)));
Bram Moolenaar071d4272004-06-13 20:20:40 +000016820 if (fp == NULL)
16821 goto erret;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016822
16823 if (fudi.fd_dict != NULL)
16824 {
16825 if (fudi.fd_di == NULL)
16826 {
16827 /* add new dict entry */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000016828 fudi.fd_di = dictitem_alloc(fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016829 if (fudi.fd_di == NULL)
16830 {
16831 vim_free(fp);
16832 goto erret;
16833 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000016834 if (dict_add(fudi.fd_dict, fudi.fd_di) == FAIL)
16835 {
16836 vim_free(fudi.fd_di);
16837 goto erret;
16838 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016839 }
16840 else
16841 /* overwrite existing dict entry */
16842 clear_tv(&fudi.fd_di->di_tv);
16843 fudi.fd_di->di_tv.v_type = VAR_FUNC;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016844 fudi.fd_di->di_tv.v_lock = 0;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016845 fudi.fd_di->di_tv.vval.v_string = vim_strsave(name);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016846 fp->uf_refcount = 1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016847 }
16848
Bram Moolenaar071d4272004-06-13 20:20:40 +000016849 /* insert the new function in the function list */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016850 STRCPY(fp->uf_name, name);
16851 hash_add(&func_hashtab, UF2HIKEY(fp));
Bram Moolenaar071d4272004-06-13 20:20:40 +000016852 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016853 fp->uf_args = newargs;
16854 fp->uf_lines = newlines;
Bram Moolenaar05159a02005-02-26 23:04:13 +000016855#ifdef FEAT_PROFILE
16856 fp->uf_tml_count = NULL;
16857 fp->uf_tml_total = NULL;
16858 fp->uf_tml_self = NULL;
16859 fp->uf_profiling = FALSE;
16860 if (prof_def_func())
16861 func_do_profile(fp);
16862#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016863 fp->uf_varargs = varargs;
16864 fp->uf_flags = flags;
16865 fp->uf_calls = 0;
16866 fp->uf_script_ID = current_SID;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016867 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016868
16869erret:
Bram Moolenaar071d4272004-06-13 20:20:40 +000016870 ga_clear_strings(&newargs);
16871 ga_clear_strings(&newlines);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016872ret_free:
16873 vim_free(skip_until);
16874 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016875 vim_free(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016876 did_emsg |= saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016877}
16878
16879/*
16880 * Get a function name, translating "<SID>" and "<SNR>".
Bram Moolenaara7043832005-01-21 11:56:39 +000016881 * Also handles a Funcref in a List or Dictionary.
Bram Moolenaar071d4272004-06-13 20:20:40 +000016882 * Returns the function name in allocated memory, or NULL for failure.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016883 * flags:
16884 * TFN_INT: internal function name OK
16885 * TFN_QUIET: be quiet
Bram Moolenaar071d4272004-06-13 20:20:40 +000016886 * Advances "pp" to just after the function name (if no error).
16887 */
16888 static char_u *
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016889trans_function_name(pp, skip, flags, fdp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016890 char_u **pp;
16891 int skip; /* only find the end, don't evaluate */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016892 int flags;
Bram Moolenaar33570922005-01-25 22:26:29 +000016893 funcdict_T *fdp; /* return: info about dictionary used */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016894{
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000016895 char_u *name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016896 char_u *start;
16897 char_u *end;
16898 int lead;
16899 char_u sid_buf[20];
Bram Moolenaar071d4272004-06-13 20:20:40 +000016900 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +000016901 lval_T lv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016902
16903 if (fdp != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000016904 vim_memset(fdp, 0, sizeof(funcdict_T));
Bram Moolenaar071d4272004-06-13 20:20:40 +000016905 start = *pp;
Bram Moolenaara7043832005-01-21 11:56:39 +000016906
16907 /* Check for hard coded <SNR>: already translated function ID (from a user
16908 * command). */
16909 if ((*pp)[0] == K_SPECIAL && (*pp)[1] == KS_EXTRA
16910 && (*pp)[2] == (int)KE_SNR)
16911 {
16912 *pp += 3;
16913 len = get_id_len(pp) + 3;
16914 return vim_strnsave(start, len);
16915 }
16916
16917 /* A name starting with "<SID>" or "<SNR>" is local to a script. But
16918 * don't skip over "s:", get_lval() needs it for "s:dict.func". */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016919 lead = eval_fname_script(start);
Bram Moolenaara7043832005-01-21 11:56:39 +000016920 if (lead > 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016921 start += lead;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000016922
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000016923 end = get_lval(start, NULL, &lv, FALSE, skip, flags & TFN_QUIET,
16924 lead > 2 ? 0 : FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000016925 if (end == start)
16926 {
16927 if (!skip)
16928 EMSG(_("E129: Function name required"));
16929 goto theend;
16930 }
Bram Moolenaara7043832005-01-21 11:56:39 +000016931 if (end == NULL || (lv.ll_tv != NULL && (lead > 2 || lv.ll_range)))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000016932 {
16933 /*
16934 * Report an invalid expression in braces, unless the expression
16935 * evaluation has been cancelled due to an aborting error, an
16936 * interrupt, or an exception.
16937 */
16938 if (!aborting())
16939 {
16940 if (end != NULL)
16941 EMSG2(_(e_invarg2), start);
16942 }
16943 else
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000016944 *pp = find_name_end(start, NULL, NULL, FNE_INCL_BR);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000016945 goto theend;
16946 }
16947
16948 if (lv.ll_tv != NULL)
16949 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016950 if (fdp != NULL)
16951 {
16952 fdp->fd_dict = lv.ll_dict;
16953 fdp->fd_newkey = lv.ll_newkey;
16954 lv.ll_newkey = NULL;
16955 fdp->fd_di = lv.ll_di;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016956 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000016957 if (lv.ll_tv->v_type == VAR_FUNC && lv.ll_tv->vval.v_string != NULL)
16958 {
16959 name = vim_strsave(lv.ll_tv->vval.v_string);
16960 *pp = end;
16961 }
16962 else
16963 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000016964 if (!skip && !(flags & TFN_QUIET) && (fdp == NULL
16965 || lv.ll_dict == NULL || fdp->fd_newkey == NULL))
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016966 EMSG(_(e_funcref));
16967 else
16968 *pp = end;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000016969 name = NULL;
16970 }
16971 goto theend;
16972 }
16973
16974 if (lv.ll_name == NULL)
16975 {
16976 /* Error found, but continue after the function name. */
16977 *pp = end;
16978 goto theend;
16979 }
16980
16981 if (lv.ll_exp_name != NULL)
16982 len = STRLEN(lv.ll_exp_name);
16983 else
Bram Moolenaara7043832005-01-21 11:56:39 +000016984 {
16985 if (lead == 2) /* skip over "s:" */
16986 lv.ll_name += 2;
16987 len = (int)(end - lv.ll_name);
16988 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000016989
16990 /*
16991 * Copy the function name to allocated memory.
16992 * Accept <SID>name() inside a script, translate into <SNR>123_name().
16993 * Accept <SNR>123_name() outside a script.
16994 */
16995 if (skip)
16996 lead = 0; /* do nothing */
16997 else if (lead > 0)
16998 {
16999 lead = 3;
17000 if (eval_fname_sid(*pp)) /* If it's "<SID>" */
17001 {
17002 if (current_SID <= 0)
17003 {
17004 EMSG(_(e_usingsid));
17005 goto theend;
17006 }
17007 sprintf((char *)sid_buf, "%ld_", (long)current_SID);
17008 lead += (int)STRLEN(sid_buf);
17009 }
17010 }
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017011 else if (!(flags & TFN_INT) && builtin_function(lv.ll_name))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000017012 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017013 EMSG2(_("E128: Function name must start with a capital or contain a colon: %s"), lv.ll_name);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000017014 goto theend;
17015 }
17016 name = alloc((unsigned)(len + lead + 1));
17017 if (name != NULL)
17018 {
17019 if (lead > 0)
17020 {
17021 name[0] = K_SPECIAL;
17022 name[1] = KS_EXTRA;
17023 name[2] = (int)KE_SNR;
Bram Moolenaara7043832005-01-21 11:56:39 +000017024 if (lead > 3) /* If it's "<SID>" */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000017025 STRCPY(name + 3, sid_buf);
17026 }
17027 mch_memmove(name + lead, lv.ll_name, (size_t)len);
17028 name[len + lead] = NUL;
17029 }
17030 *pp = end;
17031
17032theend:
17033 clear_lval(&lv);
17034 return name;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017035}
17036
17037/*
17038 * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case).
17039 * Return 2 if "p" starts with "s:".
17040 * Return 0 otherwise.
17041 */
17042 static int
17043eval_fname_script(p)
17044 char_u *p;
17045{
17046 if (p[0] == '<' && (STRNICMP(p + 1, "SID>", 4) == 0
17047 || STRNICMP(p + 1, "SNR>", 4) == 0))
17048 return 5;
17049 if (p[0] == 's' && p[1] == ':')
17050 return 2;
17051 return 0;
17052}
17053
17054/*
17055 * Return TRUE if "p" starts with "<SID>" or "s:".
17056 * Only works if eval_fname_script() returned non-zero for "p"!
17057 */
17058 static int
17059eval_fname_sid(p)
17060 char_u *p;
17061{
17062 return (*p == 's' || TOUPPER_ASC(p[2]) == 'I');
17063}
17064
17065/*
17066 * List the head of the function: "name(arg1, arg2)".
17067 */
17068 static void
17069list_func_head(fp, indent)
17070 ufunc_T *fp;
17071 int indent;
17072{
17073 int j;
17074
17075 msg_start();
17076 if (indent)
17077 MSG_PUTS(" ");
17078 MSG_PUTS("function ");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017079 if (fp->uf_name[0] == K_SPECIAL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017080 {
17081 MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017082 msg_puts(fp->uf_name + 3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017083 }
17084 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017085 msg_puts(fp->uf_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017086 msg_putchar('(');
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017087 for (j = 0; j < fp->uf_args.ga_len; ++j)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017088 {
17089 if (j)
17090 MSG_PUTS(", ");
17091 msg_puts(FUNCARG(fp, j));
17092 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017093 if (fp->uf_varargs)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017094 {
17095 if (j)
17096 MSG_PUTS(", ");
17097 MSG_PUTS("...");
17098 }
17099 msg_putchar(')');
17100}
17101
17102/*
17103 * Find a function by name, return pointer to it in ufuncs.
17104 * Return NULL for unknown function.
17105 */
17106 static ufunc_T *
17107find_func(name)
17108 char_u *name;
17109{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017110 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017111
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017112 hi = hash_find(&func_hashtab, name);
17113 if (!HASHITEM_EMPTY(hi))
17114 return HI2UF(hi);
17115 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017116}
17117
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000017118#if defined(EXITFREE) || defined(PROTO)
17119 void
17120free_all_functions()
17121{
17122 hashitem_T *hi;
17123
17124 /* Need to start all over every time, because func_free() may change the
17125 * hash table. */
17126 while (func_hashtab.ht_used > 0)
17127 for (hi = func_hashtab.ht_array; ; ++hi)
17128 if (!HASHITEM_EMPTY(hi))
17129 {
17130 func_free(HI2UF(hi));
17131 break;
17132 }
17133}
17134#endif
17135
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017136/*
17137 * Return TRUE if a function "name" exists.
17138 */
17139 static int
17140function_exists(name)
17141 char_u *name;
17142{
17143 char_u *p = name;
17144 int n = FALSE;
17145
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017146 p = trans_function_name(&p, FALSE, TFN_INT|TFN_QUIET, NULL);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017147 if (p != NULL)
17148 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017149 if (builtin_function(p))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017150 n = (find_internal_func(p) >= 0);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017151 else
17152 n = (find_func(p) != NULL);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017153 vim_free(p);
17154 }
17155 return n;
17156}
17157
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017158/*
17159 * Return TRUE if "name" looks like a builtin function name: starts with a
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017160 * lower case letter and doesn't contain a ':' or AUTOLOAD_CHAR.
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017161 */
17162 static int
17163builtin_function(name)
17164 char_u *name;
17165{
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017166 return ASCII_ISLOWER(name[0]) && vim_strchr(name, ':') == NULL
17167 && vim_strchr(name, AUTOLOAD_CHAR) == NULL;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017168}
17169
Bram Moolenaar05159a02005-02-26 23:04:13 +000017170#if defined(FEAT_PROFILE) || defined(PROTO)
17171/*
17172 * Start profiling function "fp".
17173 */
17174 static void
17175func_do_profile(fp)
17176 ufunc_T *fp;
17177{
17178 fp->uf_tm_count = 0;
17179 profile_zero(&fp->uf_tm_self);
17180 profile_zero(&fp->uf_tm_total);
17181 if (fp->uf_tml_count == NULL)
17182 fp->uf_tml_count = (int *)alloc_clear((unsigned)
17183 (sizeof(int) * fp->uf_lines.ga_len));
17184 if (fp->uf_tml_total == NULL)
17185 fp->uf_tml_total = (proftime_T *)alloc_clear((unsigned)
17186 (sizeof(proftime_T) * fp->uf_lines.ga_len));
17187 if (fp->uf_tml_self == NULL)
17188 fp->uf_tml_self = (proftime_T *)alloc_clear((unsigned)
17189 (sizeof(proftime_T) * fp->uf_lines.ga_len));
17190 fp->uf_tml_idx = -1;
17191 if (fp->uf_tml_count == NULL || fp->uf_tml_total == NULL
17192 || fp->uf_tml_self == NULL)
17193 return; /* out of memory */
17194
17195 fp->uf_profiling = TRUE;
17196}
17197
17198/*
17199 * Dump the profiling results for all functions in file "fd".
17200 */
17201 void
17202func_dump_profile(fd)
17203 FILE *fd;
17204{
17205 hashitem_T *hi;
17206 int todo;
17207 ufunc_T *fp;
17208 int i;
Bram Moolenaar73830342005-02-28 22:48:19 +000017209 ufunc_T **sorttab;
17210 int st_len = 0;
Bram Moolenaar05159a02005-02-26 23:04:13 +000017211
17212 todo = func_hashtab.ht_used;
Bram Moolenaar73830342005-02-28 22:48:19 +000017213 sorttab = (ufunc_T **)alloc((unsigned)(sizeof(ufunc_T) * todo));
17214
Bram Moolenaar05159a02005-02-26 23:04:13 +000017215 for (hi = func_hashtab.ht_array; todo > 0; ++hi)
17216 {
17217 if (!HASHITEM_EMPTY(hi))
17218 {
17219 --todo;
17220 fp = HI2UF(hi);
17221 if (fp->uf_profiling)
17222 {
Bram Moolenaar73830342005-02-28 22:48:19 +000017223 if (sorttab != NULL)
17224 sorttab[st_len++] = fp;
17225
Bram Moolenaar05159a02005-02-26 23:04:13 +000017226 if (fp->uf_name[0] == K_SPECIAL)
17227 fprintf(fd, "FUNCTION <SNR>%s()\n", fp->uf_name + 3);
17228 else
17229 fprintf(fd, "FUNCTION %s()\n", fp->uf_name);
17230 if (fp->uf_tm_count == 1)
17231 fprintf(fd, "Called 1 time\n");
17232 else
17233 fprintf(fd, "Called %d times\n", fp->uf_tm_count);
17234 fprintf(fd, "Total time: %s\n", profile_msg(&fp->uf_tm_total));
17235 fprintf(fd, " Self time: %s\n", profile_msg(&fp->uf_tm_self));
17236 fprintf(fd, "\n");
17237 fprintf(fd, "count total (s) self (s)\n");
17238
17239 for (i = 0; i < fp->uf_lines.ga_len; ++i)
17240 {
Bram Moolenaar73830342005-02-28 22:48:19 +000017241 prof_func_line(fd, fp->uf_tml_count[i],
17242 &fp->uf_tml_total[i], &fp->uf_tml_self[i], TRUE);
Bram Moolenaar05159a02005-02-26 23:04:13 +000017243 fprintf(fd, "%s\n", FUNCLINE(fp, i));
17244 }
17245 fprintf(fd, "\n");
17246 }
17247 }
17248 }
Bram Moolenaar73830342005-02-28 22:48:19 +000017249
17250 if (sorttab != NULL && st_len > 0)
17251 {
17252 qsort((void *)sorttab, (size_t)st_len, sizeof(ufunc_T *),
17253 prof_total_cmp);
17254 prof_sort_list(fd, sorttab, st_len, "TOTAL", FALSE);
17255 qsort((void *)sorttab, (size_t)st_len, sizeof(ufunc_T *),
17256 prof_self_cmp);
17257 prof_sort_list(fd, sorttab, st_len, "SELF", TRUE);
17258 }
Bram Moolenaar05159a02005-02-26 23:04:13 +000017259}
Bram Moolenaar73830342005-02-28 22:48:19 +000017260
17261 static void
17262prof_sort_list(fd, sorttab, st_len, title, prefer_self)
17263 FILE *fd;
17264 ufunc_T **sorttab;
17265 int st_len;
17266 char *title;
17267 int prefer_self; /* when equal print only self time */
17268{
17269 int i;
17270 ufunc_T *fp;
17271
17272 fprintf(fd, "FUNCTIONS SORTED ON %s TIME\n", title);
17273 fprintf(fd, "count total (s) self (s) function\n");
17274 for (i = 0; i < 20 && i < st_len; ++i)
17275 {
17276 fp = sorttab[i];
17277 prof_func_line(fd, fp->uf_tm_count, &fp->uf_tm_total, &fp->uf_tm_self,
17278 prefer_self);
17279 if (fp->uf_name[0] == K_SPECIAL)
17280 fprintf(fd, " <SNR>%s()\n", fp->uf_name + 3);
17281 else
17282 fprintf(fd, " %s()\n", fp->uf_name);
17283 }
17284 fprintf(fd, "\n");
17285}
17286
17287/*
17288 * Print the count and times for one function or function line.
17289 */
17290 static void
17291prof_func_line(fd, count, total, self, prefer_self)
17292 FILE *fd;
17293 int count;
17294 proftime_T *total;
17295 proftime_T *self;
17296 int prefer_self; /* when equal print only self time */
17297{
17298 if (count > 0)
17299 {
17300 fprintf(fd, "%5d ", count);
17301 if (prefer_self && profile_equal(total, self))
17302 fprintf(fd, " ");
17303 else
17304 fprintf(fd, "%s ", profile_msg(total));
17305 if (!prefer_self && profile_equal(total, self))
17306 fprintf(fd, " ");
17307 else
17308 fprintf(fd, "%s ", profile_msg(self));
17309 }
17310 else
17311 fprintf(fd, " ");
17312}
17313
17314/*
17315 * Compare function for total time sorting.
17316 */
17317 static int
17318#ifdef __BORLANDC__
17319_RTLENTRYF
17320#endif
17321prof_total_cmp(s1, s2)
17322 const void *s1;
17323 const void *s2;
17324{
17325 ufunc_T *p1, *p2;
17326
17327 p1 = *(ufunc_T **)s1;
17328 p2 = *(ufunc_T **)s2;
17329 return profile_cmp(&p1->uf_tm_total, &p2->uf_tm_total);
17330}
17331
17332/*
17333 * Compare function for self time sorting.
17334 */
17335 static int
17336#ifdef __BORLANDC__
17337_RTLENTRYF
17338#endif
17339prof_self_cmp(s1, s2)
17340 const void *s1;
17341 const void *s2;
17342{
17343 ufunc_T *p1, *p2;
17344
17345 p1 = *(ufunc_T **)s1;
17346 p2 = *(ufunc_T **)s2;
17347 return profile_cmp(&p1->uf_tm_self, &p2->uf_tm_self);
17348}
17349
Bram Moolenaar05159a02005-02-26 23:04:13 +000017350#endif
17351
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017352/*
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017353 * If "name" has a package name try autoloading the script for it.
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017354 * Return TRUE if a package was loaded.
17355 */
17356 static int
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017357script_autoload(name)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017358 char_u *name;
17359{
17360 char_u *p;
17361 char_u *scriptname;
17362 int ret = FALSE;
17363
17364 /* If there is no colon after name[1] there is no package name. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017365 p = vim_strchr(name, AUTOLOAD_CHAR);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017366 if (p == NULL || p <= name + 2)
17367 return FALSE;
17368
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017369 /* Try loading the package from $VIMRUNTIME/autoload/<name>.vim */
17370 scriptname = autoload_name(name);
17371 if (cmd_runtime(scriptname, FALSE) == OK)
17372 ret = TRUE;
17373
17374 vim_free(scriptname);
17375 return ret;
17376}
17377
17378/*
17379 * Return the autoload script name for a function or variable name.
17380 * Returns NULL when out of memory.
17381 */
17382 static char_u *
17383autoload_name(name)
17384 char_u *name;
17385{
17386 char_u *p;
17387 char_u *scriptname;
17388
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017389 /* Get the script file name: replace '#' with '/', append ".vim". */
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017390 scriptname = alloc((unsigned)(STRLEN(name) + 14));
17391 if (scriptname == NULL)
17392 return FALSE;
17393 STRCPY(scriptname, "autoload/");
17394 STRCAT(scriptname, name);
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017395 *vim_strrchr(scriptname, AUTOLOAD_CHAR) = NUL;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017396 STRCAT(scriptname, ".vim");
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017397 while ((p = vim_strchr(scriptname, AUTOLOAD_CHAR)) != NULL)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017398 *p = '/';
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017399 return scriptname;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017400}
17401
Bram Moolenaar071d4272004-06-13 20:20:40 +000017402#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
17403
17404/*
17405 * Function given to ExpandGeneric() to obtain the list of user defined
17406 * function names.
17407 */
17408 char_u *
17409get_user_func_name(xp, idx)
17410 expand_T *xp;
17411 int idx;
17412{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017413 static long_u done;
17414 static hashitem_T *hi;
17415 ufunc_T *fp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017416
17417 if (idx == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017418 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017419 done = 0;
17420 hi = func_hashtab.ht_array;
17421 }
17422 if (done < func_hashtab.ht_used)
17423 {
17424 if (done++ > 0)
17425 ++hi;
17426 while (HASHITEM_EMPTY(hi))
17427 ++hi;
17428 fp = HI2UF(hi);
17429
17430 if (STRLEN(fp->uf_name) + 4 >= IOSIZE)
17431 return fp->uf_name; /* prevents overflow */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017432
17433 cat_func_name(IObuff, fp);
17434 if (xp->xp_context != EXPAND_USER_FUNC)
17435 {
17436 STRCAT(IObuff, "(");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017437 if (!fp->uf_varargs && fp->uf_args.ga_len == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017438 STRCAT(IObuff, ")");
17439 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017440 return IObuff;
17441 }
17442 return NULL;
17443}
17444
17445#endif /* FEAT_CMDL_COMPL */
17446
17447/*
17448 * Copy the function name of "fp" to buffer "buf".
17449 * "buf" must be able to hold the function name plus three bytes.
17450 * Takes care of script-local function names.
17451 */
17452 static void
17453cat_func_name(buf, fp)
17454 char_u *buf;
17455 ufunc_T *fp;
17456{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017457 if (fp->uf_name[0] == K_SPECIAL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017458 {
17459 STRCPY(buf, "<SNR>");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017460 STRCAT(buf, fp->uf_name + 3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017461 }
17462 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017463 STRCPY(buf, fp->uf_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017464}
17465
17466/*
17467 * ":delfunction {name}"
17468 */
17469 void
17470ex_delfunction(eap)
17471 exarg_T *eap;
17472{
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017473 ufunc_T *fp = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017474 char_u *p;
17475 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000017476 funcdict_T fudi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017477
17478 p = eap->arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017479 name = trans_function_name(&p, eap->skip, 0, &fudi);
17480 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017481 if (name == NULL)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017482 {
17483 if (fudi.fd_dict != NULL && !eap->skip)
17484 EMSG(_(e_funcref));
Bram Moolenaar071d4272004-06-13 20:20:40 +000017485 return;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017486 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017487 if (!ends_excmd(*skipwhite(p)))
17488 {
17489 vim_free(name);
17490 EMSG(_(e_trailing));
17491 return;
17492 }
17493 eap->nextcmd = check_nextcmd(p);
17494 if (eap->nextcmd != NULL)
17495 *p = NUL;
17496
17497 if (!eap->skip)
17498 fp = find_func(name);
17499 vim_free(name);
17500
17501 if (!eap->skip)
17502 {
17503 if (fp == NULL)
17504 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000017505 EMSG2(_(e_nofunc), eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017506 return;
17507 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017508 if (fp->uf_calls > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017509 {
17510 EMSG2(_("E131: Cannot delete function %s: It is in use"), eap->arg);
17511 return;
17512 }
17513
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017514 if (fudi.fd_dict != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017515 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017516 /* Delete the dict item that refers to the function, it will
17517 * invoke func_unref() and possibly delete the function. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000017518 dictitem_remove(fudi.fd_dict, fudi.fd_di);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017519 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017520 else
17521 func_free(fp);
17522 }
17523}
17524
17525/*
17526 * Free a function and remove it from the list of functions.
17527 */
17528 static void
17529func_free(fp)
17530 ufunc_T *fp;
17531{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017532 hashitem_T *hi;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017533
17534 /* clear this function */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017535 ga_clear_strings(&(fp->uf_args));
17536 ga_clear_strings(&(fp->uf_lines));
Bram Moolenaar05159a02005-02-26 23:04:13 +000017537#ifdef FEAT_PROFILE
17538 vim_free(fp->uf_tml_count);
17539 vim_free(fp->uf_tml_total);
17540 vim_free(fp->uf_tml_self);
17541#endif
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017542
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017543 /* remove the function from the function hashtable */
17544 hi = hash_find(&func_hashtab, UF2HIKEY(fp));
17545 if (HASHITEM_EMPTY(hi))
17546 EMSG2(_(e_intern2), "func_free()");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017547 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017548 hash_remove(&func_hashtab, hi);
17549
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017550 vim_free(fp);
17551}
17552
17553/*
17554 * Unreference a Function: decrement the reference count and free it when it
17555 * becomes zero. Only for numbered functions.
17556 */
17557 static void
17558func_unref(name)
17559 char_u *name;
17560{
17561 ufunc_T *fp;
17562
17563 if (name != NULL && isdigit(*name))
17564 {
17565 fp = find_func(name);
17566 if (fp == NULL)
17567 EMSG2(_(e_intern2), "func_unref()");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017568 else if (--fp->uf_refcount <= 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017569 {
17570 /* Only delete it when it's not being used. Otherwise it's done
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017571 * when "uf_calls" becomes zero. */
17572 if (fp->uf_calls == 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017573 func_free(fp);
17574 }
17575 }
17576}
17577
17578/*
17579 * Count a reference to a Function.
17580 */
17581 static void
17582func_ref(name)
17583 char_u *name;
17584{
17585 ufunc_T *fp;
17586
17587 if (name != NULL && isdigit(*name))
17588 {
17589 fp = find_func(name);
17590 if (fp == NULL)
17591 EMSG2(_(e_intern2), "func_ref()");
17592 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017593 ++fp->uf_refcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017594 }
17595}
17596
17597/*
17598 * Call a user function.
17599 */
17600 static void
Bram Moolenaare9a41262005-01-15 22:18:47 +000017601call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017602 ufunc_T *fp; /* pointer to function */
17603 int argcount; /* nr of args */
Bram Moolenaar33570922005-01-25 22:26:29 +000017604 typval_T *argvars; /* arguments */
17605 typval_T *rettv; /* return value */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017606 linenr_T firstline; /* first line of range */
17607 linenr_T lastline; /* last line of range */
Bram Moolenaar33570922005-01-25 22:26:29 +000017608 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017609{
Bram Moolenaar33570922005-01-25 22:26:29 +000017610 char_u *save_sourcing_name;
17611 linenr_T save_sourcing_lnum;
17612 scid_T save_current_SID;
17613 funccall_T fc;
Bram Moolenaar33570922005-01-25 22:26:29 +000017614 int save_did_emsg;
17615 static int depth = 0;
17616 dictitem_T *v;
17617 int fixvar_idx = 0; /* index in fixvar[] */
17618 int i;
17619 int ai;
17620 char_u numbuf[NUMBUFLEN];
17621 char_u *name;
Bram Moolenaar05159a02005-02-26 23:04:13 +000017622#ifdef FEAT_PROFILE
17623 proftime_T wait_start;
17624#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000017625
17626 /* If depth of calling is getting too high, don't execute the function */
17627 if (depth >= p_mfd)
17628 {
17629 EMSG(_("E132: Function call depth is higher than 'maxfuncdepth'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017630 rettv->v_type = VAR_NUMBER;
17631 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017632 return;
17633 }
17634 ++depth;
17635
17636 line_breakcheck(); /* check for CTRL-C hit */
17637
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000017638 fc.caller = current_funccal;
Bram Moolenaar33570922005-01-25 22:26:29 +000017639 current_funccal = &fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017640 fc.func = fp;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017641 fc.rettv = rettv;
17642 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017643 fc.linenr = 0;
17644 fc.returned = FALSE;
17645 fc.level = ex_nesting_level;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017646 /* Check if this function has a breakpoint. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017647 fc.breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017648 fc.dbg_tick = debug_tick;
17649
Bram Moolenaar33570922005-01-25 22:26:29 +000017650 /*
17651 * Note about using fc.fixvar[]: This is an array of FIXVAR_CNT variables
17652 * with names up to VAR_SHORT_LEN long. This avoids having to alloc/free
17653 * each argument variable and saves a lot of time.
17654 */
17655 /*
17656 * Init l: variables.
17657 */
17658 init_var_dict(&fc.l_vars, &fc.l_vars_var);
Bram Moolenaara7043832005-01-21 11:56:39 +000017659 if (selfdict != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000017660 {
Bram Moolenaar33570922005-01-25 22:26:29 +000017661 /* Set l:self to "selfdict". */
17662 v = &fc.fixvar[fixvar_idx++].var;
17663 STRCPY(v->di_key, "self");
17664 v->di_flags = DI_FLAGS_RO + DI_FLAGS_FIX;
17665 hash_add(&fc.l_vars.dv_hashtab, DI2HIKEY(v));
17666 v->di_tv.v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017667 v->di_tv.v_lock = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000017668 v->di_tv.vval.v_dict = selfdict;
17669 ++selfdict->dv_refcount;
17670 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000017671
Bram Moolenaar33570922005-01-25 22:26:29 +000017672 /*
17673 * Init a: variables.
17674 * Set a:0 to "argcount".
17675 * Set a:000 to a list with room for the "..." arguments.
17676 */
17677 init_var_dict(&fc.l_avars, &fc.l_avars_var);
17678 add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "0",
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017679 (varnumber_T)(argcount - fp->uf_args.ga_len));
Bram Moolenaar33570922005-01-25 22:26:29 +000017680 v = &fc.fixvar[fixvar_idx++].var;
17681 STRCPY(v->di_key, "000");
17682 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
17683 hash_add(&fc.l_avars.dv_hashtab, DI2HIKEY(v));
17684 v->di_tv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017685 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000017686 v->di_tv.vval.v_list = &fc.l_varlist;
17687 vim_memset(&fc.l_varlist, 0, sizeof(list_T));
17688 fc.l_varlist.lv_refcount = 99999;
17689
17690 /*
17691 * Set a:firstline to "firstline" and a:lastline to "lastline".
17692 * Set a:name to named arguments.
17693 * Set a:N to the "..." arguments.
17694 */
17695 add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "firstline",
17696 (varnumber_T)firstline);
17697 add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "lastline",
17698 (varnumber_T)lastline);
17699 for (i = 0; i < argcount; ++i)
17700 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017701 ai = i - fp->uf_args.ga_len;
Bram Moolenaar33570922005-01-25 22:26:29 +000017702 if (ai < 0)
17703 /* named argument a:name */
17704 name = FUNCARG(fp, i);
17705 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000017706 {
Bram Moolenaar33570922005-01-25 22:26:29 +000017707 /* "..." argument a:1, a:2, etc. */
17708 sprintf((char *)numbuf, "%d", ai + 1);
17709 name = numbuf;
17710 }
17711 if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN)
17712 {
17713 v = &fc.fixvar[fixvar_idx++].var;
17714 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
17715 }
17716 else
17717 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017718 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
17719 + STRLEN(name)));
Bram Moolenaar33570922005-01-25 22:26:29 +000017720 if (v == NULL)
17721 break;
17722 v->di_flags = DI_FLAGS_RO;
17723 }
17724 STRCPY(v->di_key, name);
17725 hash_add(&fc.l_avars.dv_hashtab, DI2HIKEY(v));
17726
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017727 /* Note: the values are copied directly to avoid alloc/free.
17728 * "argvars" must have VAR_FIXED for v_lock. */
Bram Moolenaar33570922005-01-25 22:26:29 +000017729 v->di_tv = argvars[i];
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017730 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000017731
17732 if (ai >= 0 && ai < MAX_FUNC_ARGS)
17733 {
17734 list_append(&fc.l_varlist, &fc.l_listitems[ai]);
17735 fc.l_listitems[ai].li_tv = argvars[i];
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017736 fc.l_listitems[ai].li_tv.v_lock = VAR_FIXED;
Bram Moolenaare9a41262005-01-15 22:18:47 +000017737 }
17738 }
17739
Bram Moolenaar071d4272004-06-13 20:20:40 +000017740 /* Don't redraw while executing the function. */
17741 ++RedrawingDisabled;
17742 save_sourcing_name = sourcing_name;
17743 save_sourcing_lnum = sourcing_lnum;
17744 sourcing_lnum = 1;
17745 sourcing_name = alloc((unsigned)((save_sourcing_name == NULL ? 0
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017746 : STRLEN(save_sourcing_name)) + STRLEN(fp->uf_name) + 13));
Bram Moolenaar071d4272004-06-13 20:20:40 +000017747 if (sourcing_name != NULL)
17748 {
17749 if (save_sourcing_name != NULL
17750 && STRNCMP(save_sourcing_name, "function ", 9) == 0)
17751 sprintf((char *)sourcing_name, "%s..", save_sourcing_name);
17752 else
17753 STRCPY(sourcing_name, "function ");
17754 cat_func_name(sourcing_name + STRLEN(sourcing_name), fp);
17755
17756 if (p_verbose >= 12)
17757 {
17758 ++no_wait_return;
Bram Moolenaar54ee7752005-05-31 22:22:17 +000017759 verbose_enter_scroll();
17760
Bram Moolenaar555b2802005-05-19 21:08:39 +000017761 smsg((char_u *)_("calling %s"), sourcing_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017762 if (p_verbose >= 14)
17763 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000017764 char_u buf[MSG_BUF_LEN];
Bram Moolenaar758711c2005-02-02 23:11:38 +000017765 char_u numbuf[NUMBUFLEN];
17766 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017767
17768 msg_puts((char_u *)"(");
17769 for (i = 0; i < argcount; ++i)
17770 {
17771 if (i > 0)
17772 msg_puts((char_u *)", ");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017773 if (argvars[i].v_type == VAR_NUMBER)
17774 msg_outnum((long)argvars[i].vval.v_number);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017775 else
17776 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000017777 trunc_string(tv2string(&argvars[i], &tofree, numbuf),
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017778 buf, MSG_BUF_CLEN);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017779 msg_puts(buf);
Bram Moolenaar758711c2005-02-02 23:11:38 +000017780 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017781 }
17782 }
17783 msg_puts((char_u *)")");
17784 }
17785 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaar54ee7752005-05-31 22:22:17 +000017786
17787 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000017788 --no_wait_return;
17789 }
17790 }
Bram Moolenaar05159a02005-02-26 23:04:13 +000017791#ifdef FEAT_PROFILE
17792 if (do_profiling)
17793 {
17794 if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL))
17795 func_do_profile(fp);
17796 if (fp->uf_profiling
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000017797 || (fc.caller != NULL && &fc.caller->func->uf_profiling))
Bram Moolenaar05159a02005-02-26 23:04:13 +000017798 {
17799 ++fp->uf_tm_count;
17800 profile_start(&fp->uf_tm_start);
17801 profile_zero(&fp->uf_tm_children);
17802 }
17803 script_prof_save(&wait_start);
17804 }
17805#endif
17806
Bram Moolenaar071d4272004-06-13 20:20:40 +000017807 save_current_SID = current_SID;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017808 current_SID = fp->uf_script_ID;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017809 save_did_emsg = did_emsg;
17810 did_emsg = FALSE;
17811
17812 /* call do_cmdline() to execute the lines */
17813 do_cmdline(NULL, get_func_line, (void *)&fc,
17814 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
17815
17816 --RedrawingDisabled;
17817
17818 /* when the function was aborted because of an error, return -1 */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017819 if ((did_emsg && (fp->uf_flags & FC_ABORT)) || rettv->v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017820 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017821 clear_tv(rettv);
17822 rettv->v_type = VAR_NUMBER;
17823 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017824 }
17825
Bram Moolenaar05159a02005-02-26 23:04:13 +000017826#ifdef FEAT_PROFILE
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000017827 if (fp->uf_profiling || (fc.caller != NULL && &fc.caller->func->uf_profiling))
Bram Moolenaar05159a02005-02-26 23:04:13 +000017828 {
17829 profile_end(&fp->uf_tm_start);
17830 profile_sub_wait(&wait_start, &fp->uf_tm_start);
17831 profile_add(&fp->uf_tm_total, &fp->uf_tm_start);
17832 profile_add(&fp->uf_tm_self, &fp->uf_tm_start);
17833 profile_sub(&fp->uf_tm_self, &fp->uf_tm_children);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000017834 if (fc.caller != NULL && &fc.caller->func->uf_profiling)
Bram Moolenaar05159a02005-02-26 23:04:13 +000017835 {
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000017836 profile_add(&fc.caller->func->uf_tm_children, &fp->uf_tm_start);
17837 profile_add(&fc.caller->func->uf_tml_children, &fp->uf_tm_start);
Bram Moolenaar05159a02005-02-26 23:04:13 +000017838 }
17839 }
17840#endif
17841
Bram Moolenaar071d4272004-06-13 20:20:40 +000017842 /* when being verbose, mention the return value */
17843 if (p_verbose >= 12)
17844 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000017845 ++no_wait_return;
Bram Moolenaar54ee7752005-05-31 22:22:17 +000017846 verbose_enter_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000017847
Bram Moolenaar071d4272004-06-13 20:20:40 +000017848 if (aborting())
Bram Moolenaar555b2802005-05-19 21:08:39 +000017849 smsg((char_u *)_("%s aborted"), sourcing_name);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017850 else if (fc.rettv->v_type == VAR_NUMBER)
Bram Moolenaar555b2802005-05-19 21:08:39 +000017851 smsg((char_u *)_("%s returning #%ld"), sourcing_name,
17852 (long)fc.rettv->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +000017853 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000017854 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000017855 char_u buf[MSG_BUF_LEN];
17856 char_u numbuf[NUMBUFLEN];
17857 char_u *tofree;
17858
Bram Moolenaar555b2802005-05-19 21:08:39 +000017859 /* The value may be very long. Skip the middle part, so that we
17860 * have some idea how it starts and ends. smsg() would always
17861 * truncate it at the end. */
Bram Moolenaar758711c2005-02-02 23:11:38 +000017862 trunc_string(tv2string(fc.rettv, &tofree, numbuf),
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017863 buf, MSG_BUF_CLEN);
Bram Moolenaar555b2802005-05-19 21:08:39 +000017864 smsg((char_u *)_("%s returning %s"), sourcing_name, buf);
Bram Moolenaar758711c2005-02-02 23:11:38 +000017865 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017866 }
17867 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaar54ee7752005-05-31 22:22:17 +000017868
17869 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000017870 --no_wait_return;
17871 }
17872
17873 vim_free(sourcing_name);
17874 sourcing_name = save_sourcing_name;
17875 sourcing_lnum = save_sourcing_lnum;
17876 current_SID = save_current_SID;
Bram Moolenaar05159a02005-02-26 23:04:13 +000017877#ifdef FEAT_PROFILE
17878 if (do_profiling)
17879 script_prof_restore(&wait_start);
17880#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000017881
17882 if (p_verbose >= 12 && sourcing_name != NULL)
17883 {
17884 ++no_wait_return;
Bram Moolenaar54ee7752005-05-31 22:22:17 +000017885 verbose_enter_scroll();
17886
Bram Moolenaar555b2802005-05-19 21:08:39 +000017887 smsg((char_u *)_("continuing in %s"), sourcing_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017888 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaar54ee7752005-05-31 22:22:17 +000017889
17890 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000017891 --no_wait_return;
17892 }
17893
17894 did_emsg |= save_did_emsg;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000017895 current_funccal = fc.caller;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017896
Bram Moolenaar33570922005-01-25 22:26:29 +000017897 /* The a: variables typevals were not alloced, only free the allocated
17898 * variables. */
17899 vars_clear_ext(&fc.l_avars.dv_hashtab, FALSE);
17900
17901 vars_clear(&fc.l_vars.dv_hashtab); /* free all l: variables */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017902 --depth;
17903}
17904
17905/*
Bram Moolenaar33570922005-01-25 22:26:29 +000017906 * Add a number variable "name" to dict "dp" with value "nr".
17907 */
17908 static void
17909add_nr_var(dp, v, name, nr)
17910 dict_T *dp;
17911 dictitem_T *v;
17912 char *name;
17913 varnumber_T nr;
17914{
17915 STRCPY(v->di_key, name);
17916 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
17917 hash_add(&dp->dv_hashtab, DI2HIKEY(v));
17918 v->di_tv.v_type = VAR_NUMBER;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017919 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000017920 v->di_tv.vval.v_number = nr;
17921}
17922
17923/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000017924 * ":return [expr]"
17925 */
17926 void
17927ex_return(eap)
17928 exarg_T *eap;
17929{
17930 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000017931 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017932 int returning = FALSE;
17933
17934 if (current_funccal == NULL)
17935 {
17936 EMSG(_("E133: :return not inside a function"));
17937 return;
17938 }
17939
17940 if (eap->skip)
17941 ++emsg_skip;
17942
17943 eap->nextcmd = NULL;
17944 if ((*arg != NUL && *arg != '|' && *arg != '\n')
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017945 && eval0(arg, &rettv, &eap->nextcmd, !eap->skip) != FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017946 {
17947 if (!eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017948 returning = do_return(eap, FALSE, TRUE, &rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017949 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017950 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017951 }
17952 /* It's safer to return also on error. */
17953 else if (!eap->skip)
17954 {
17955 /*
17956 * Return unless the expression evaluation has been cancelled due to an
17957 * aborting error, an interrupt, or an exception.
17958 */
17959 if (!aborting())
17960 returning = do_return(eap, FALSE, TRUE, NULL);
17961 }
17962
17963 /* When skipping or the return gets pending, advance to the next command
17964 * in this line (!returning). Otherwise, ignore the rest of the line.
17965 * Following lines will be ignored by get_func_line(). */
17966 if (returning)
17967 eap->nextcmd = NULL;
17968 else if (eap->nextcmd == NULL) /* no argument */
17969 eap->nextcmd = check_nextcmd(arg);
17970
17971 if (eap->skip)
17972 --emsg_skip;
17973}
17974
17975/*
17976 * Return from a function. Possibly makes the return pending. Also called
17977 * for a pending return at the ":endtry" or after returning from an extra
17978 * do_cmdline(). "reanimate" is used in the latter case. "is_cmd" is set
Bram Moolenaar33570922005-01-25 22:26:29 +000017979 * when called due to a ":return" command. "rettv" may point to a typval_T
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017980 * with the return rettv. Returns TRUE when the return can be carried out,
Bram Moolenaar071d4272004-06-13 20:20:40 +000017981 * FALSE when the return gets pending.
17982 */
17983 int
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017984do_return(eap, reanimate, is_cmd, rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017985 exarg_T *eap;
17986 int reanimate;
17987 int is_cmd;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017988 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017989{
17990 int idx;
17991 struct condstack *cstack = eap->cstack;
17992
17993 if (reanimate)
17994 /* Undo the return. */
17995 current_funccal->returned = FALSE;
17996
17997 /*
17998 * Cleanup (and inactivate) conditionals, but stop when a try conditional
17999 * not in its finally clause (which then is to be executed next) is found.
18000 * In this case, make the ":return" pending for execution at the ":endtry".
18001 * Otherwise, return normally.
18002 */
18003 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
18004 if (idx >= 0)
18005 {
18006 cstack->cs_pending[idx] = CSTP_RETURN;
18007
18008 if (!is_cmd && !reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018009 /* A pending return again gets pending. "rettv" points to an
18010 * allocated variable with the rettv of the original ":return"'s
Bram Moolenaar071d4272004-06-13 20:20:40 +000018011 * argument if present or is NULL else. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018012 cstack->cs_rettv[idx] = rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018013 else
18014 {
18015 /* When undoing a return in order to make it pending, get the stored
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018016 * return rettv. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018017 if (reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018018 rettv = current_funccal->rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018019
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018020 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018021 {
18022 /* Store the value of the pending return. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018023 if ((cstack->cs_rettv[idx] = alloc_tv()) != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000018024 *(typval_T *)cstack->cs_rettv[idx] = *(typval_T *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018025 else
18026 EMSG(_(e_outofmem));
18027 }
18028 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018029 cstack->cs_rettv[idx] = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018030
18031 if (reanimate)
18032 {
18033 /* The pending return value could be overwritten by a ":return"
18034 * without argument in a finally clause; reset the default
18035 * return value. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018036 current_funccal->rettv->v_type = VAR_NUMBER;
18037 current_funccal->rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018038 }
18039 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018040 report_make_pending(CSTP_RETURN, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018041 }
18042 else
18043 {
18044 current_funccal->returned = TRUE;
18045
18046 /* If the return is carried out now, store the return value. For
18047 * a return immediately after reanimation, the value is already
18048 * there. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018049 if (!reanimate && rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018050 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018051 clear_tv(current_funccal->rettv);
Bram Moolenaar33570922005-01-25 22:26:29 +000018052 *current_funccal->rettv = *(typval_T *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018053 if (!is_cmd)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018054 vim_free(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018055 }
18056 }
18057
18058 return idx < 0;
18059}
18060
18061/*
18062 * Free the variable with a pending return value.
18063 */
18064 void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018065discard_pending_return(rettv)
18066 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018067{
Bram Moolenaar33570922005-01-25 22:26:29 +000018068 free_tv((typval_T *)rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018069}
18070
18071/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018072 * Generate a return command for producing the value of "rettv". The result
Bram Moolenaar071d4272004-06-13 20:20:40 +000018073 * is an allocated string. Used by report_pending() for verbose messages.
18074 */
18075 char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018076get_return_cmd(rettv)
18077 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018078{
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018079 char_u *s = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018080 char_u *tofree = NULL;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000018081 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000018082
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018083 if (rettv != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000018084 s = echo_string((typval_T *)rettv, &tofree, numbuf);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018085 if (s == NULL)
18086 s = (char_u *)"";
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018087
18088 STRCPY(IObuff, ":return ");
18089 STRNCPY(IObuff + 8, s, IOSIZE - 8);
18090 if (STRLEN(s) + 8 >= IOSIZE)
18091 STRCPY(IObuff + IOSIZE - 4, "...");
18092 vim_free(tofree);
18093 return vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018094}
18095
18096/*
18097 * Get next function line.
18098 * Called by do_cmdline() to get the next line.
18099 * Returns allocated string, or NULL for end of function.
18100 */
18101/* ARGSUSED */
18102 char_u *
18103get_func_line(c, cookie, indent)
18104 int c; /* not used */
18105 void *cookie;
18106 int indent; /* not used */
18107{
Bram Moolenaar33570922005-01-25 22:26:29 +000018108 funccall_T *fcp = (funccall_T *)cookie;
Bram Moolenaar05159a02005-02-26 23:04:13 +000018109 ufunc_T *fp = fcp->func;
18110 char_u *retval;
18111 garray_T *gap; /* growarray with function lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018112
18113 /* If breakpoints have been added/deleted need to check for it. */
18114 if (fcp->dbg_tick != debug_tick)
18115 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000018116 fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
Bram Moolenaar071d4272004-06-13 20:20:40 +000018117 sourcing_lnum);
18118 fcp->dbg_tick = debug_tick;
18119 }
Bram Moolenaar05159a02005-02-26 23:04:13 +000018120#ifdef FEAT_PROFILE
18121 if (do_profiling)
18122 func_line_end(cookie);
18123#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000018124
Bram Moolenaar05159a02005-02-26 23:04:13 +000018125 gap = &fp->uf_lines;
18126 if ((fp->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
Bram Moolenaar071d4272004-06-13 20:20:40 +000018127 retval = NULL;
18128 else if (fcp->returned || fcp->linenr >= gap->ga_len)
18129 retval = NULL;
18130 else
18131 {
18132 retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]);
18133 sourcing_lnum = fcp->linenr;
Bram Moolenaar05159a02005-02-26 23:04:13 +000018134#ifdef FEAT_PROFILE
18135 if (do_profiling)
18136 func_line_start(cookie);
18137#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000018138 }
18139
18140 /* Did we encounter a breakpoint? */
18141 if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum)
18142 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000018143 dbg_breakpoint(fp->uf_name, sourcing_lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018144 /* Find next breakpoint. */
Bram Moolenaar05159a02005-02-26 23:04:13 +000018145 fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
Bram Moolenaar071d4272004-06-13 20:20:40 +000018146 sourcing_lnum);
18147 fcp->dbg_tick = debug_tick;
18148 }
18149
18150 return retval;
18151}
18152
Bram Moolenaar05159a02005-02-26 23:04:13 +000018153#if defined(FEAT_PROFILE) || defined(PROTO)
18154/*
18155 * Called when starting to read a function line.
18156 * "sourcing_lnum" must be correct!
18157 * When skipping lines it may not actually be executed, but we won't find out
18158 * until later and we need to store the time now.
18159 */
18160 void
18161func_line_start(cookie)
18162 void *cookie;
18163{
18164 funccall_T *fcp = (funccall_T *)cookie;
18165 ufunc_T *fp = fcp->func;
18166
18167 if (fp->uf_profiling && sourcing_lnum >= 1
18168 && sourcing_lnum <= fp->uf_lines.ga_len)
18169 {
18170 fp->uf_tml_idx = sourcing_lnum - 1;
18171 fp->uf_tml_execed = FALSE;
18172 profile_start(&fp->uf_tml_start);
18173 profile_zero(&fp->uf_tml_children);
18174 profile_get_wait(&fp->uf_tml_wait);
18175 }
18176}
18177
18178/*
18179 * Called when actually executing a function line.
18180 */
18181 void
18182func_line_exec(cookie)
18183 void *cookie;
18184{
18185 funccall_T *fcp = (funccall_T *)cookie;
18186 ufunc_T *fp = fcp->func;
18187
18188 if (fp->uf_profiling && fp->uf_tml_idx >= 0)
18189 fp->uf_tml_execed = TRUE;
18190}
18191
18192/*
18193 * Called when done with a function line.
18194 */
18195 void
18196func_line_end(cookie)
18197 void *cookie;
18198{
18199 funccall_T *fcp = (funccall_T *)cookie;
18200 ufunc_T *fp = fcp->func;
18201
18202 if (fp->uf_profiling && fp->uf_tml_idx >= 0)
18203 {
18204 if (fp->uf_tml_execed)
18205 {
18206 ++fp->uf_tml_count[fp->uf_tml_idx];
18207 profile_end(&fp->uf_tml_start);
18208 profile_sub_wait(&fp->uf_tml_wait, &fp->uf_tml_start);
18209 profile_add(&fp->uf_tml_self[fp->uf_tml_idx], &fp->uf_tml_start);
18210 profile_add(&fp->uf_tml_total[fp->uf_tml_idx], &fp->uf_tml_start);
18211 profile_sub(&fp->uf_tml_self[fp->uf_tml_idx], &fp->uf_tml_children);
18212 }
18213 fp->uf_tml_idx = -1;
18214 }
18215}
18216#endif
18217
Bram Moolenaar071d4272004-06-13 20:20:40 +000018218/*
18219 * Return TRUE if the currently active function should be ended, because a
18220 * return was encountered or an error occured. Used inside a ":while".
18221 */
18222 int
18223func_has_ended(cookie)
18224 void *cookie;
18225{
Bram Moolenaar33570922005-01-25 22:26:29 +000018226 funccall_T *fcp = (funccall_T *)cookie;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018227
18228 /* Ignore the "abort" flag if the abortion behavior has been changed due to
18229 * an error inside a try conditional. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018230 return (((fcp->func->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
Bram Moolenaar071d4272004-06-13 20:20:40 +000018231 || fcp->returned);
18232}
18233
18234/*
18235 * return TRUE if cookie indicates a function which "abort"s on errors.
18236 */
18237 int
18238func_has_abort(cookie)
18239 void *cookie;
18240{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018241 return ((funccall_T *)cookie)->func->uf_flags & FC_ABORT;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018242}
18243
18244#if defined(FEAT_VIMINFO) || defined(FEAT_SESSION)
18245typedef enum
18246{
18247 VAR_FLAVOUR_DEFAULT,
18248 VAR_FLAVOUR_SESSION,
18249 VAR_FLAVOUR_VIMINFO
18250} var_flavour_T;
18251
18252static var_flavour_T var_flavour __ARGS((char_u *varname));
18253
18254 static var_flavour_T
18255var_flavour(varname)
18256 char_u *varname;
18257{
18258 char_u *p = varname;
18259
18260 if (ASCII_ISUPPER(*p))
18261 {
18262 while (*(++p))
18263 if (ASCII_ISLOWER(*p))
18264 return VAR_FLAVOUR_SESSION;
18265 return VAR_FLAVOUR_VIMINFO;
18266 }
18267 else
18268 return VAR_FLAVOUR_DEFAULT;
18269}
18270#endif
18271
18272#if defined(FEAT_VIMINFO) || defined(PROTO)
18273/*
18274 * Restore global vars that start with a capital from the viminfo file
18275 */
18276 int
18277read_viminfo_varlist(virp, writing)
18278 vir_T *virp;
18279 int writing;
18280{
18281 char_u *tab;
18282 int is_string = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +000018283 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018284
18285 if (!writing && (find_viminfo_parameter('!') != NULL))
18286 {
18287 tab = vim_strchr(virp->vir_line + 1, '\t');
18288 if (tab != NULL)
18289 {
18290 *tab++ = '\0'; /* isolate the variable name */
18291 if (*tab == 'S') /* string var */
18292 is_string = TRUE;
18293
18294 tab = vim_strchr(tab, '\t');
18295 if (tab != NULL)
18296 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000018297 if (is_string)
18298 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000018299 tv.v_type = VAR_STRING;
18300 tv.vval.v_string = viminfo_readstring(virp,
Bram Moolenaar071d4272004-06-13 20:20:40 +000018301 (int)(tab - virp->vir_line + 1), TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018302 }
18303 else
18304 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000018305 tv.v_type = VAR_NUMBER;
18306 tv.vval.v_number = atol((char *)tab + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018307 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000018308 set_var(virp->vir_line + 1, &tv, FALSE);
18309 if (is_string)
18310 vim_free(tv.vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018311 }
18312 }
18313 }
18314
18315 return viminfo_readline(virp);
18316}
18317
18318/*
18319 * Write global vars that start with a capital to the viminfo file
18320 */
18321 void
18322write_viminfo_varlist(fp)
18323 FILE *fp;
18324{
Bram Moolenaar33570922005-01-25 22:26:29 +000018325 hashitem_T *hi;
18326 dictitem_T *this_var;
Bram Moolenaara7043832005-01-21 11:56:39 +000018327 int todo;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018328 char *s;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018329 char_u *p;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018330 char_u *tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000018331 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000018332
18333 if (find_viminfo_parameter('!') == NULL)
18334 return;
18335
18336 fprintf(fp, _("\n# global variables:\n"));
Bram Moolenaara7043832005-01-21 11:56:39 +000018337
Bram Moolenaar33570922005-01-25 22:26:29 +000018338 todo = globvarht.ht_used;
18339 for (hi = globvarht.ht_array; todo > 0; ++hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018340 {
Bram Moolenaara7043832005-01-21 11:56:39 +000018341 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar071d4272004-06-13 20:20:40 +000018342 {
Bram Moolenaara7043832005-01-21 11:56:39 +000018343 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000018344 this_var = HI2DI(hi);
18345 if (var_flavour(this_var->di_key) == VAR_FLAVOUR_VIMINFO)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018346 {
Bram Moolenaar33570922005-01-25 22:26:29 +000018347 switch (this_var->di_tv.v_type)
Bram Moolenaara7043832005-01-21 11:56:39 +000018348 {
18349 case VAR_STRING: s = "STR"; break;
18350 case VAR_NUMBER: s = "NUM"; break;
18351 default: continue;
18352 }
Bram Moolenaar33570922005-01-25 22:26:29 +000018353 fprintf(fp, "!%s\t%s\t", this_var->di_key, s);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018354 p = echo_string(&this_var->di_tv, &tofree, numbuf);
18355 if (p != NULL)
18356 viminfo_writestring(fp, p);
Bram Moolenaara7043832005-01-21 11:56:39 +000018357 vim_free(tofree);
18358 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018359 }
18360 }
18361}
18362#endif
18363
18364#if defined(FEAT_SESSION) || defined(PROTO)
18365 int
18366store_session_globals(fd)
18367 FILE *fd;
18368{
Bram Moolenaar33570922005-01-25 22:26:29 +000018369 hashitem_T *hi;
18370 dictitem_T *this_var;
Bram Moolenaara7043832005-01-21 11:56:39 +000018371 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018372 char_u *p, *t;
18373
Bram Moolenaar33570922005-01-25 22:26:29 +000018374 todo = globvarht.ht_used;
18375 for (hi = globvarht.ht_array; todo > 0; ++hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018376 {
Bram Moolenaara7043832005-01-21 11:56:39 +000018377 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar071d4272004-06-13 20:20:40 +000018378 {
Bram Moolenaara7043832005-01-21 11:56:39 +000018379 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000018380 this_var = HI2DI(hi);
18381 if ((this_var->di_tv.v_type == VAR_NUMBER
18382 || this_var->di_tv.v_type == VAR_STRING)
18383 && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000018384 {
Bram Moolenaara7043832005-01-21 11:56:39 +000018385 /* Escape special characters with a backslash. Turn a LF and
18386 * CR into \n and \r. */
Bram Moolenaar33570922005-01-25 22:26:29 +000018387 p = vim_strsave_escaped(get_tv_string(&this_var->di_tv),
Bram Moolenaara7043832005-01-21 11:56:39 +000018388 (char_u *)"\\\"\n\r");
18389 if (p == NULL) /* out of memory */
18390 break;
18391 for (t = p; *t != NUL; ++t)
18392 if (*t == '\n')
18393 *t = 'n';
18394 else if (*t == '\r')
18395 *t = 'r';
18396 if ((fprintf(fd, "let %s = %c%s%c",
Bram Moolenaar33570922005-01-25 22:26:29 +000018397 this_var->di_key,
18398 (this_var->di_tv.v_type == VAR_STRING) ? '"'
18399 : ' ',
18400 p,
18401 (this_var->di_tv.v_type == VAR_STRING) ? '"'
18402 : ' ') < 0)
Bram Moolenaara7043832005-01-21 11:56:39 +000018403 || put_eol(fd) == FAIL)
18404 {
18405 vim_free(p);
18406 return FAIL;
18407 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018408 vim_free(p);
18409 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018410 }
18411 }
18412 return OK;
18413}
18414#endif
18415
18416#endif /* FEAT_EVAL */
18417
18418#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
18419
18420
18421#ifdef WIN3264
18422/*
18423 * Functions for ":8" filename modifier: get 8.3 version of a filename.
18424 */
18425static int get_short_pathname __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
18426static int shortpath_for_invalid_fname __ARGS((char_u **fname, char_u **bufp, int *fnamelen));
18427static int shortpath_for_partial __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
18428
18429/*
18430 * Get the short pathname of a file.
18431 * Returns 1 on success. *fnamelen is 0 for nonexistant path.
18432 */
18433 static int
18434get_short_pathname(fnamep, bufp, fnamelen)
18435 char_u **fnamep;
18436 char_u **bufp;
18437 int *fnamelen;
18438{
18439 int l,len;
18440 char_u *newbuf;
18441
18442 len = *fnamelen;
18443
18444 l = GetShortPathName(*fnamep, *fnamep, len);
18445 if (l > len - 1)
18446 {
18447 /* If that doesn't work (not enough space), then save the string
18448 * and try again with a new buffer big enough
18449 */
18450 newbuf = vim_strnsave(*fnamep, l);
18451 if (newbuf == NULL)
18452 return 0;
18453
18454 vim_free(*bufp);
18455 *fnamep = *bufp = newbuf;
18456
18457 l = GetShortPathName(*fnamep,*fnamep,l+1);
18458
18459 /* Really should always succeed, as the buffer is big enough */
18460 }
18461
18462 *fnamelen = l;
18463 return 1;
18464}
18465
18466/*
18467 * Create a short path name. Returns the length of the buffer it needs.
18468 * Doesn't copy over the end of the buffer passed in.
18469 */
18470 static int
18471shortpath_for_invalid_fname(fname, bufp, fnamelen)
18472 char_u **fname;
18473 char_u **bufp;
18474 int *fnamelen;
18475{
18476 char_u *s, *p, *pbuf2, *pbuf3;
18477 char_u ch;
Bram Moolenaar75c50c42005-06-04 22:06:24 +000018478 int len, len2, plen, slen;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018479
18480 /* Make a copy */
18481 len2 = *fnamelen;
18482 pbuf2 = vim_strnsave(*fname, len2);
18483 pbuf3 = NULL;
18484
18485 s = pbuf2 + len2 - 1; /* Find the end */
18486 slen = 1;
18487 plen = len2;
18488
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000018489 if (after_pathsep(pbuf2, s + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +000018490 {
18491 --s;
18492 ++slen;
18493 --plen;
18494 }
18495
18496 do
18497 {
18498 /* Go back one path-seperator */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000018499 while (s > pbuf2 && !after_pathsep(pbuf2, s + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +000018500 {
18501 --s;
18502 ++slen;
18503 --plen;
18504 }
18505 if (s <= pbuf2)
18506 break;
18507
18508 /* Remeber the character that is about to be blatted */
18509 ch = *s;
18510 *s = 0; /* get_short_pathname requires a null-terminated string */
18511
18512 /* Try it in situ */
18513 p = pbuf2;
18514 if (!get_short_pathname(&p, &pbuf3, &plen))
18515 {
18516 vim_free(pbuf2);
18517 return -1;
18518 }
18519 *s = ch; /* Preserve the string */
18520 } while (plen == 0);
18521
18522 if (plen > 0)
18523 {
18524 /* Remeber the length of the new string. */
18525 *fnamelen = len = plen + slen;
18526 vim_free(*bufp);
18527 if (len > len2)
18528 {
18529 /* If there's not enough space in the currently allocated string,
18530 * then copy it to a buffer big enough.
18531 */
18532 *fname= *bufp = vim_strnsave(p, len);
18533 if (*fname == NULL)
18534 return -1;
18535 }
18536 else
18537 {
18538 /* Transfer pbuf2 to being the main buffer (it's big enough) */
18539 *fname = *bufp = pbuf2;
18540 if (p != pbuf2)
18541 strncpy(*fname, p, plen);
18542 pbuf2 = NULL;
18543 }
18544 /* Concat the next bit */
18545 strncpy(*fname + plen, s, slen);
18546 (*fname)[len] = '\0';
18547 }
18548 vim_free(pbuf3);
18549 vim_free(pbuf2);
18550 return 0;
18551}
18552
18553/*
18554 * Get a pathname for a partial path.
18555 */
18556 static int
18557shortpath_for_partial(fnamep, bufp, fnamelen)
18558 char_u **fnamep;
18559 char_u **bufp;
18560 int *fnamelen;
18561{
18562 int sepcount, len, tflen;
18563 char_u *p;
18564 char_u *pbuf, *tfname;
18565 int hasTilde;
18566
18567 /* Count up the path seperators from the RHS.. so we know which part
18568 * of the path to return.
18569 */
18570 sepcount = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000018571 for (p = *fnamep; p < *fnamep + *fnamelen; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000018572 if (vim_ispathsep(*p))
18573 ++sepcount;
18574
18575 /* Need full path first (use expand_env() to remove a "~/") */
18576 hasTilde = (**fnamep == '~');
18577 if (hasTilde)
18578 pbuf = tfname = expand_env_save(*fnamep);
18579 else
18580 pbuf = tfname = FullName_save(*fnamep, FALSE);
18581
18582 len = tflen = STRLEN(tfname);
18583
18584 if (!get_short_pathname(&tfname, &pbuf, &len))
18585 return -1;
18586
18587 if (len == 0)
18588 {
18589 /* Don't have a valid filename, so shorten the rest of the
18590 * path if we can. This CAN give us invalid 8.3 filenames, but
18591 * there's not a lot of point in guessing what it might be.
18592 */
18593 len = tflen;
18594 if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == -1)
18595 return -1;
18596 }
18597
18598 /* Count the paths backward to find the beginning of the desired string. */
18599 for (p = tfname + len - 1; p >= tfname; --p)
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000018600 {
18601#ifdef FEAT_MBYTE
18602 if (has_mbyte)
18603 p -= mb_head_off(tfname, p);
18604#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000018605 if (vim_ispathsep(*p))
18606 {
18607 if (sepcount == 0 || (hasTilde && sepcount == 1))
18608 break;
18609 else
18610 sepcount --;
18611 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000018612 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018613 if (hasTilde)
18614 {
18615 --p;
18616 if (p >= tfname)
18617 *p = '~';
18618 else
18619 return -1;
18620 }
18621 else
18622 ++p;
18623
18624 /* Copy in the string - p indexes into tfname - allocated at pbuf */
18625 vim_free(*bufp);
18626 *fnamelen = (int)STRLEN(p);
18627 *bufp = pbuf;
18628 *fnamep = p;
18629
18630 return 0;
18631}
18632#endif /* WIN3264 */
18633
18634/*
18635 * Adjust a filename, according to a string of modifiers.
18636 * *fnamep must be NUL terminated when called. When returning, the length is
18637 * determined by *fnamelen.
18638 * Returns valid flags.
18639 * When there is an error, *fnamep is set to NULL.
18640 */
18641 int
18642modify_fname(src, usedlen, fnamep, bufp, fnamelen)
18643 char_u *src; /* string with modifiers */
18644 int *usedlen; /* characters after src that are used */
18645 char_u **fnamep; /* file name so far */
18646 char_u **bufp; /* buffer for allocated file name or NULL */
18647 int *fnamelen; /* length of fnamep */
18648{
18649 int valid = 0;
18650 char_u *tail;
18651 char_u *s, *p, *pbuf;
18652 char_u dirname[MAXPATHL];
18653 int c;
18654 int has_fullname = 0;
18655#ifdef WIN3264
18656 int has_shortname = 0;
18657#endif
18658
18659repeat:
18660 /* ":p" - full path/file_name */
18661 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p')
18662 {
18663 has_fullname = 1;
18664
18665 valid |= VALID_PATH;
18666 *usedlen += 2;
18667
18668 /* Expand "~/path" for all systems and "~user/path" for Unix and VMS */
18669 if ((*fnamep)[0] == '~'
18670#if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME))
18671 && ((*fnamep)[1] == '/'
18672# ifdef BACKSLASH_IN_FILENAME
18673 || (*fnamep)[1] == '\\'
18674# endif
18675 || (*fnamep)[1] == NUL)
18676
18677#endif
18678 )
18679 {
18680 *fnamep = expand_env_save(*fnamep);
18681 vim_free(*bufp); /* free any allocated file name */
18682 *bufp = *fnamep;
18683 if (*fnamep == NULL)
18684 return -1;
18685 }
18686
18687 /* When "/." or "/.." is used: force expansion to get rid of it. */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000018688 for (p = *fnamep; *p != NUL; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000018689 {
18690 if (vim_ispathsep(*p)
18691 && p[1] == '.'
18692 && (p[2] == NUL
18693 || vim_ispathsep(p[2])
18694 || (p[2] == '.'
18695 && (p[3] == NUL || vim_ispathsep(p[3])))))
18696 break;
18697 }
18698
18699 /* FullName_save() is slow, don't use it when not needed. */
18700 if (*p != NUL || !vim_isAbsName(*fnamep))
18701 {
18702 *fnamep = FullName_save(*fnamep, *p != NUL);
18703 vim_free(*bufp); /* free any allocated file name */
18704 *bufp = *fnamep;
18705 if (*fnamep == NULL)
18706 return -1;
18707 }
18708
18709 /* Append a path separator to a directory. */
18710 if (mch_isdir(*fnamep))
18711 {
18712 /* Make room for one or two extra characters. */
18713 *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2);
18714 vim_free(*bufp); /* free any allocated file name */
18715 *bufp = *fnamep;
18716 if (*fnamep == NULL)
18717 return -1;
18718 add_pathsep(*fnamep);
18719 }
18720 }
18721
18722 /* ":." - path relative to the current directory */
18723 /* ":~" - path relative to the home directory */
18724 /* ":8" - shortname path - postponed till after */
18725 while (src[*usedlen] == ':'
18726 && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8'))
18727 {
18728 *usedlen += 2;
18729 if (c == '8')
18730 {
18731#ifdef WIN3264
18732 has_shortname = 1; /* Postpone this. */
18733#endif
18734 continue;
18735 }
18736 pbuf = NULL;
18737 /* Need full path first (use expand_env() to remove a "~/") */
18738 if (!has_fullname)
18739 {
18740 if (c == '.' && **fnamep == '~')
18741 p = pbuf = expand_env_save(*fnamep);
18742 else
18743 p = pbuf = FullName_save(*fnamep, FALSE);
18744 }
18745 else
18746 p = *fnamep;
18747
18748 has_fullname = 0;
18749
18750 if (p != NULL)
18751 {
18752 if (c == '.')
18753 {
18754 mch_dirname(dirname, MAXPATHL);
18755 s = shorten_fname(p, dirname);
18756 if (s != NULL)
18757 {
18758 *fnamep = s;
18759 if (pbuf != NULL)
18760 {
18761 vim_free(*bufp); /* free any allocated file name */
18762 *bufp = pbuf;
18763 pbuf = NULL;
18764 }
18765 }
18766 }
18767 else
18768 {
18769 home_replace(NULL, p, dirname, MAXPATHL, TRUE);
18770 /* Only replace it when it starts with '~' */
18771 if (*dirname == '~')
18772 {
18773 s = vim_strsave(dirname);
18774 if (s != NULL)
18775 {
18776 *fnamep = s;
18777 vim_free(*bufp);
18778 *bufp = s;
18779 }
18780 }
18781 }
18782 vim_free(pbuf);
18783 }
18784 }
18785
18786 tail = gettail(*fnamep);
18787 *fnamelen = (int)STRLEN(*fnamep);
18788
18789 /* ":h" - head, remove "/file_name", can be repeated */
18790 /* Don't remove the first "/" or "c:\" */
18791 while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h')
18792 {
18793 valid |= VALID_HEAD;
18794 *usedlen += 2;
18795 s = get_past_head(*fnamep);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000018796 while (tail > s && after_pathsep(s, tail))
Bram Moolenaar071d4272004-06-13 20:20:40 +000018797 --tail;
18798 *fnamelen = (int)(tail - *fnamep);
18799#ifdef VMS
18800 if (*fnamelen > 0)
18801 *fnamelen += 1; /* the path separator is part of the path */
18802#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000018803 while (tail > s && !after_pathsep(s, tail))
18804 mb_ptr_back(*fnamep, tail);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018805 }
18806
18807 /* ":8" - shortname */
18808 if (src[*usedlen] == ':' && src[*usedlen + 1] == '8')
18809 {
18810 *usedlen += 2;
18811#ifdef WIN3264
18812 has_shortname = 1;
18813#endif
18814 }
18815
18816#ifdef WIN3264
18817 /* Check shortname after we have done 'heads' and before we do 'tails'
18818 */
18819 if (has_shortname)
18820 {
18821 pbuf = NULL;
18822 /* Copy the string if it is shortened by :h */
18823 if (*fnamelen < (int)STRLEN(*fnamep))
18824 {
18825 p = vim_strnsave(*fnamep, *fnamelen);
18826 if (p == 0)
18827 return -1;
18828 vim_free(*bufp);
18829 *bufp = *fnamep = p;
18830 }
18831
18832 /* Split into two implementations - makes it easier. First is where
18833 * there isn't a full name already, second is where there is.
18834 */
18835 if (!has_fullname && !vim_isAbsName(*fnamep))
18836 {
18837 if (shortpath_for_partial(fnamep, bufp, fnamelen) == -1)
18838 return -1;
18839 }
18840 else
18841 {
18842 int l;
18843
18844 /* Simple case, already have the full-name
18845 * Nearly always shorter, so try first time. */
18846 l = *fnamelen;
18847 if (!get_short_pathname(fnamep, bufp, &l))
18848 return -1;
18849
18850 if (l == 0)
18851 {
18852 /* Couldn't find the filename.. search the paths.
18853 */
18854 l = *fnamelen;
18855 if (shortpath_for_invalid_fname(fnamep, bufp, &l ) == -1)
18856 return -1;
18857 }
18858 *fnamelen = l;
18859 }
18860 }
18861#endif /* WIN3264 */
18862
18863 /* ":t" - tail, just the basename */
18864 if (src[*usedlen] == ':' && src[*usedlen + 1] == 't')
18865 {
18866 *usedlen += 2;
18867 *fnamelen -= (int)(tail - *fnamep);
18868 *fnamep = tail;
18869 }
18870
18871 /* ":e" - extension, can be repeated */
18872 /* ":r" - root, without extension, can be repeated */
18873 while (src[*usedlen] == ':'
18874 && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r'))
18875 {
18876 /* find a '.' in the tail:
18877 * - for second :e: before the current fname
18878 * - otherwise: The last '.'
18879 */
18880 if (src[*usedlen + 1] == 'e' && *fnamep > tail)
18881 s = *fnamep - 2;
18882 else
18883 s = *fnamep + *fnamelen - 1;
18884 for ( ; s > tail; --s)
18885 if (s[0] == '.')
18886 break;
18887 if (src[*usedlen + 1] == 'e') /* :e */
18888 {
18889 if (s > tail)
18890 {
18891 *fnamelen += (int)(*fnamep - (s + 1));
18892 *fnamep = s + 1;
18893#ifdef VMS
18894 /* cut version from the extension */
18895 s = *fnamep + *fnamelen - 1;
18896 for ( ; s > *fnamep; --s)
18897 if (s[0] == ';')
18898 break;
18899 if (s > *fnamep)
18900 *fnamelen = s - *fnamep;
18901#endif
18902 }
18903 else if (*fnamep <= tail)
18904 *fnamelen = 0;
18905 }
18906 else /* :r */
18907 {
18908 if (s > tail) /* remove one extension */
18909 *fnamelen = (int)(s - *fnamep);
18910 }
18911 *usedlen += 2;
18912 }
18913
18914 /* ":s?pat?foo?" - substitute */
18915 /* ":gs?pat?foo?" - global substitute */
18916 if (src[*usedlen] == ':'
18917 && (src[*usedlen + 1] == 's'
18918 || (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's')))
18919 {
18920 char_u *str;
18921 char_u *pat;
18922 char_u *sub;
18923 int sep;
18924 char_u *flags;
18925 int didit = FALSE;
18926
18927 flags = (char_u *)"";
18928 s = src + *usedlen + 2;
18929 if (src[*usedlen + 1] == 'g')
18930 {
18931 flags = (char_u *)"g";
18932 ++s;
18933 }
18934
18935 sep = *s++;
18936 if (sep)
18937 {
18938 /* find end of pattern */
18939 p = vim_strchr(s, sep);
18940 if (p != NULL)
18941 {
18942 pat = vim_strnsave(s, (int)(p - s));
18943 if (pat != NULL)
18944 {
18945 s = p + 1;
18946 /* find end of substitution */
18947 p = vim_strchr(s, sep);
18948 if (p != NULL)
18949 {
18950 sub = vim_strnsave(s, (int)(p - s));
18951 str = vim_strnsave(*fnamep, *fnamelen);
18952 if (sub != NULL && str != NULL)
18953 {
18954 *usedlen = (int)(p + 1 - src);
18955 s = do_string_sub(str, pat, sub, flags);
18956 if (s != NULL)
18957 {
18958 *fnamep = s;
18959 *fnamelen = (int)STRLEN(s);
18960 vim_free(*bufp);
18961 *bufp = s;
18962 didit = TRUE;
18963 }
18964 }
18965 vim_free(sub);
18966 vim_free(str);
18967 }
18968 vim_free(pat);
18969 }
18970 }
18971 /* after using ":s", repeat all the modifiers */
18972 if (didit)
18973 goto repeat;
18974 }
18975 }
18976
18977 return valid;
18978}
18979
18980/*
18981 * Perform a substitution on "str" with pattern "pat" and substitute "sub".
18982 * "flags" can be "g" to do a global substitute.
18983 * Returns an allocated string, NULL for error.
18984 */
18985 char_u *
18986do_string_sub(str, pat, sub, flags)
18987 char_u *str;
18988 char_u *pat;
18989 char_u *sub;
18990 char_u *flags;
18991{
18992 int sublen;
18993 regmatch_T regmatch;
18994 int i;
18995 int do_all;
18996 char_u *tail;
18997 garray_T ga;
18998 char_u *ret;
18999 char_u *save_cpo;
19000
19001 /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */
19002 save_cpo = p_cpo;
19003 p_cpo = (char_u *)"";
19004
19005 ga_init2(&ga, 1, 200);
19006
19007 do_all = (flags[0] == 'g');
19008
19009 regmatch.rm_ic = p_ic;
19010 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
19011 if (regmatch.regprog != NULL)
19012 {
19013 tail = str;
19014 while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
19015 {
19016 /*
19017 * Get some space for a temporary buffer to do the substitution
19018 * into. It will contain:
19019 * - The text up to where the match is.
19020 * - The substituted text.
19021 * - The text after the match.
19022 */
19023 sublen = vim_regsub(&regmatch, sub, tail, FALSE, TRUE, FALSE);
19024 if (ga_grow(&ga, (int)(STRLEN(tail) + sublen -
19025 (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
19026 {
19027 ga_clear(&ga);
19028 break;
19029 }
19030
19031 /* copy the text up to where the match is */
19032 i = (int)(regmatch.startp[0] - tail);
19033 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
19034 /* add the substituted text */
19035 (void)vim_regsub(&regmatch, sub, (char_u *)ga.ga_data
19036 + ga.ga_len + i, TRUE, TRUE, FALSE);
19037 ga.ga_len += i + sublen - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019038 /* avoid getting stuck on a match with an empty string */
19039 if (tail == regmatch.endp[0])
19040 {
19041 if (*tail == NUL)
19042 break;
19043 *((char_u *)ga.ga_data + ga.ga_len) = *tail++;
19044 ++ga.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019045 }
19046 else
19047 {
19048 tail = regmatch.endp[0];
19049 if (*tail == NUL)
19050 break;
19051 }
19052 if (!do_all)
19053 break;
19054 }
19055
19056 if (ga.ga_data != NULL)
19057 STRCPY((char *)ga.ga_data + ga.ga_len, tail);
19058
19059 vim_free(regmatch.regprog);
19060 }
19061
19062 ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data);
19063 ga_clear(&ga);
19064 p_cpo = save_cpo;
19065
19066 return ret;
19067}
19068
19069#endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */